From af927ddf1c4377d54918956a4f841db3167134be Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Fri, 15 Mar 2024 13:57:23 -0300 Subject: [PATCH 01/10] Add HPOS compatibility notice for WooCommerce Orders --- .../classes/Feature/WooCommerce/Orders.php | 43 +++++++++++++++++++ .../WooCommerce/TestWooCommerceOrders.php | 41 ++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/includes/classes/Feature/WooCommerce/Orders.php b/includes/classes/Feature/WooCommerce/Orders.php index dd3a7d3c93..5e8a1fc1f1 100644 --- a/includes/classes/Feature/WooCommerce/Orders.php +++ b/includes/classes/Feature/WooCommerce/Orders.php @@ -45,6 +45,7 @@ public function setup() { add_action( 'parse_query', [ $this, 'maybe_hook_woocommerce_search_fields' ], 1 ); add_action( 'parse_query', [ $this, 'search_order' ], 11 ); add_action( 'pre_get_posts', [ $this, 'translate_args' ], 11, 1 ); + add_filter( 'ep_admin_notices', [ $this, 'hpos_compatibility_notice' ] ); } /** @@ -335,6 +336,48 @@ public function get_supported_post_types() : array { return $supported_post_types; } + /** + * Display a notice if WooCommerce Orders are not compatible with ElasticPress + * + * If the user has WooCommerce, Protected Content, and HPOS enabled, orders will not go through ElasticPress. + * + * @param array $notices Current EP notices + * @return array + */ + public function hpos_compatibility_notice( array $notices ) : array { + $current_screen = \get_current_screen(); + if ( empty( $current_screen->id ) || 'woocommerce_page_wc-orders' !== $current_screen->id ) { + return $notices; + } + + if ( \ElasticPress\Utils\get_option( 'ep_hide_wc_orders_incompatible_notice' ) ) { + return $notices; + } + + $protected_content = \ElasticPress\Features::factory()->get_registered_feature( 'protected_content' ); + if ( ! $protected_content->is_active() ) { + return $notices; + } + + if ( + ! class_exists( '\Automattic\WooCommerce\Utilities\OrderUtil' ) + || ! method_exists( '\Automattic\WooCommerce\Utilities\OrderUtil', 'custom_orders_table_usage_is_enabled' ) ) { + return $notices; + } + + if ( ! \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ) { + return $notices; + } + + $notices['wc_orders_incompatible'] = [ + 'html' => esc_html__( "Although the WooCommerce and Protected Content features are enabled, ElasticPress will not integrate with the WooCommerce Orders list if WooCommerce's High-performance order storage is enabled.", 'elasticpress' ), + 'type' => 'warning', + 'dismiss' => true, + ]; + + return $notices; + } + /** * If the query has a search term, add the order fields that need to be searched. * diff --git a/tests/php/features/WooCommerce/TestWooCommerceOrders.php b/tests/php/features/WooCommerce/TestWooCommerceOrders.php index 8be8e86c31..b224728bfb 100644 --- a/tests/php/features/WooCommerce/TestWooCommerceOrders.php +++ b/tests/php/features/WooCommerce/TestWooCommerceOrders.php @@ -329,4 +329,45 @@ public function ordersAutosuggestMethodsDataProvider() : array { [ 'set_search_fields', [] ], ]; } + + /** + * Test the `hpos_compatibility_notice` method + * + * @group woocommerce + * @group woocommerce-orders + */ + public function test_hpos_compatibility_notice() { + $notices = [ + 'test' => [], + ]; + $this->assertCount( 1, $this->orders->hpos_compatibility_notice( $notices ) ); + + \set_current_screen( 'woocommerce_page_wc-orders' ); + $this->assertCount( 1, $this->orders->hpos_compatibility_notice( $notices ) ); + + ElasticPress\Features::factory()->activate_feature( 'protected_content' ); + $this->assertCount( 1, $this->orders->hpos_compatibility_notice( $notices ) ); + + $option_name = \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION; + $change_value = function() { + return 'yes'; + }; + add_filter( 'pre_option_' . $option_name, $change_value ); + + $new_notices = $this->orders->hpos_compatibility_notice( $notices ); + $this->assertCount( 2, $new_notices ); + $this->assertArrayHasKey( 'wc_orders_incompatible', $new_notices ); + + /** + * Test if the notice is hidden when the user already dismissed it + */ + $change_hide_option = function() { + return 1; + }; + add_filter( 'pre_option_ep_hide_wc_orders_incompatible_notice', $change_hide_option ); + add_filter( 'pre_site_option_ep_hide_wc_orders_incompatible_notice', $change_hide_option ); + $new_notices = $this->orders->hpos_compatibility_notice( $notices ); + $this->assertCount( 1, $new_notices ); + $this->assertArrayNotHasKey( 'wc_orders_incompatible', $new_notices ); + } } From 54a79d26923b406ae223a9fba35aa863c4eb58ba Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Fri, 15 Mar 2024 14:01:59 -0300 Subject: [PATCH 02/10] Lint fix --- tests/php/features/WooCommerce/TestWooCommerceOrders.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/php/features/WooCommerce/TestWooCommerceOrders.php b/tests/php/features/WooCommerce/TestWooCommerceOrders.php index b224728bfb..2f5a3257ce 100644 --- a/tests/php/features/WooCommerce/TestWooCommerceOrders.php +++ b/tests/php/features/WooCommerce/TestWooCommerceOrders.php @@ -348,7 +348,7 @@ public function test_hpos_compatibility_notice() { ElasticPress\Features::factory()->activate_feature( 'protected_content' ); $this->assertCount( 1, $this->orders->hpos_compatibility_notice( $notices ) ); - $option_name = \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION; + $option_name = \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION; $change_value = function() { return 'yes'; }; From 41d9dcf9a7560b388a69dfba5d1b489600ea1a42 Mon Sep 17 00:00:00 2001 From: Jacob Peattie Date: Sun, 17 Mar 2024 22:43:04 +1100 Subject: [PATCH 03/10] Don't open instant results modal if an autosuggest suggestion is selected. --- assets/js/autosuggest/index.js | 6 ++++++ assets/js/instant-results/apps/modal.js | 9 +++++++++ tests/cypress/integration/features/autosuggest.cy.js | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/assets/js/autosuggest/index.js b/assets/js/autosuggest/index.js index 7b8cad072c..cd035ac25b 100644 --- a/assets/js/autosuggest/index.js +++ b/assets/js/autosuggest/index.js @@ -362,6 +362,8 @@ function updateAutosuggestBox(options, input) { } }); + setInputActiveDescendant('', input); + return true; } @@ -373,6 +375,7 @@ function updateAutosuggestBox(options, input) { function hideAutosuggestBox() { const lists = document.querySelectorAll('.autosuggest-list'); const containers = document.querySelectorAll('.ep-autosuggest'); + const inputs = document.querySelectorAll('.ep-autosuggest-container [aria-activedescendant]'); // empty all EP results lists lists.forEach((list) => { @@ -387,6 +390,9 @@ function hideAutosuggestBox() { container.style = 'display: none;'; }); + // Remove active descendant attribute from all inputs + inputs.forEach((input) => setInputActiveDescendant('', input)); + return true; } diff --git a/assets/js/instant-results/apps/modal.js b/assets/js/instant-results/apps/modal.js index 69aef353ad..11e5ed82e9 100644 --- a/assets/js/instant-results/apps/modal.js +++ b/assets/js/instant-results/apps/modal.js @@ -49,6 +49,15 @@ export default () => { inputRef.current = event.target.s; + /** + * Don't open the modal if an autosuggest suggestion is selected. + */ + const activeDescendant = inputRef.current.getAttribute('aria-activedescendant'); + + if (activeDescendant) { + return; + } + const { value } = inputRef.current; const post_type = getPostTypesFromForm(inputRef.current.form); diff --git a/tests/cypress/integration/features/autosuggest.cy.js b/tests/cypress/integration/features/autosuggest.cy.js index f766dd08ea..3e4e248b08 100644 --- a/tests/cypress/integration/features/autosuggest.cy.js +++ b/tests/cypress/integration/features/autosuggest.cy.js @@ -4,6 +4,7 @@ describe('Autosuggest Feature', () => { }); beforeEach(() => { + cy.maybeDisableFeature('instant-results'); cy.deactivatePlugin('custom-headers-for-autosuggest', 'wpCli'); }); @@ -102,4 +103,11 @@ describe('Autosuggest Feature', () => { cy.get('.ep-autosuggest li a').first().click(); cy.url().should('include', 'cypress=foobar'); }); + + it('Can select an Autosuggest suggestion even if Instant Results is active', () => { + cy.maybeEnableFeature('instant-results'); + cy.visit('/'); + cy.get('.wp-block-search__input').type('blog{downArrow}{enter}'); + cy.url().should('include', 'blog'); + }); }); From 7aadce058037418c5f71c0d36a59e7d8231ca720 Mon Sep 17 00:00:00 2001 From: Jacob Peattie Date: Sun, 17 Mar 2024 23:02:42 +1100 Subject: [PATCH 04/10] Add tooltips for meta keys to the weighting screen. --- assets/js/weighting/components/field.js | 15 ++++++++++++--- assets/js/weighting/components/group.js | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/assets/js/weighting/components/field.js b/assets/js/weighting/components/field.js index 8477456aa9..814542eb53 100644 --- a/assets/js/weighting/components/field.js +++ b/assets/js/weighting/components/field.js @@ -1,7 +1,7 @@ /** * WordPress Dependencies. */ -import { Button, CheckboxControl, RangeControl } from '@wordpress/components'; +import { Button, CheckboxControl, RangeControl, Tooltip } from '@wordpress/components'; import { WPElement } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { trash } from '@wordpress/icons'; @@ -14,9 +14,10 @@ import { trash } from '@wordpress/icons'; * @param {Function} props.onChange Change handler. * @param {Function} props.onDelete Delete handler. * @param {object} props.value Values. + * @param {boolean} props.showTooltip Whether to show field name tooltip. * @returns {WPElement} Component element. */ -export default ({ label, onChange, onDelete, value }) => { +export default ({ label, onChange, onDelete, value, showTooltip }) => { const { enabled = false, weight = 0 } = value; /** @@ -45,7 +46,15 @@ export default ({ label, onChange, onDelete, value }) => { return (
- {label} + + {showTooltip ? ( + + {label} + + ) : ( + label + )} +
{ onDelete={() => { onDelete(key); }} + showTooltip /> ))} From 2c61cd5e98f7932efafa4d96e126b96a29f42ffb Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 18 Mar 2024 17:10:18 -0300 Subject: [PATCH 05/10] Better isolate Orders Autosuggest + message about compatibility --- .../Feature/WooCommerce/OrdersAutosuggest.php | 144 +++++++++++++++- .../Feature/WooCommerce/WooCommerce.php | 159 +++++++----------- 2 files changed, 202 insertions(+), 101 deletions(-) diff --git a/includes/classes/Feature/WooCommerce/OrdersAutosuggest.php b/includes/classes/Feature/WooCommerce/OrdersAutosuggest.php index 25ae2fa50a..ad4a76cca8 100644 --- a/includes/classes/Feature/WooCommerce/OrdersAutosuggest.php +++ b/includes/classes/Feature/WooCommerce/OrdersAutosuggest.php @@ -9,6 +9,7 @@ namespace ElasticPress\Feature\WooCommerce; use ElasticPress\Elasticsearch; +use ElasticPress\Features; use ElasticPress\Indexables; use ElasticPress\REST; use ElasticPress\Utils; @@ -36,12 +37,23 @@ class OrdersAutosuggest { protected $search_template; /** - * Initialize feature. + * WooCommerce feature object instance * - * @return void + * @since 5.1.0 + * @var WooCommerce */ - public function __construct() { - $this->index = Indexables::factory()->get( 'post' )->get_index_name(); + protected $woocommerce; + + /** + * Class constructor + * + * @param WooCommerce|null $woocommerce WooCommerce feature object instance + */ + public function __construct( WooCommerce $woocommerce = null ) { + $this->index = Indexables::factory()->get( 'post' )->get_index_name(); + $this->woocommerce = $woocommerce ? + $woocommerce : + Features::factory()->get_registered_feature( 'woocommerce' ); } /** @@ -50,6 +62,13 @@ public function __construct() { * @return void */ public function setup() { + add_filter( 'ep_woocommerce_settings_schema', [ $this, 'add_settings_schema' ] ); + + // Orders Autosuggest feature. + if ( ! $this->is_enabled() ) { + return; + } + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_assets' ] ); add_filter( 'ep_after_update_feature', [ $this, 'after_update_feature' ], 10, 3 ); add_filter( 'ep_after_sync_index', [ $this, 'epio_save_search_template' ] ); @@ -548,4 +567,121 @@ public function maybe_set_posts_where( $where, $query ) { return $where; } + + /** + * Whether orders autosuggest is available or not + * + * @since 5.1.0 + * @return boolean + */ + public function is_available() : bool { + /** + * Whether the autosuggest feature is available for non + * ElasticPress.io customers. + * + * @since 4.5.0 + * @hook ep_woocommerce_orders_autosuggest_available + * @param {boolean} $available Whether the feature is available. + */ + return apply_filters( 'ep_woocommerce_orders_autosuggest_available', Utils\is_epio() && $this->is_hpos_compatible() ); + } + + /** + * Whether orders autosuggest is enabled or not + * + * @since 5.1.0 + * @return boolean + */ + public function is_enabled() : bool { + return $this->is_available() && '1' === $this->woocommerce->get_setting( 'orders' ); + } + + /** + * Whether the current setup is compatible with WooCommerce's HPOS or not + * + * @since 5.1.0 + * @return boolean + */ + public function is_hpos_compatible() { + if ( + ! class_exists( '\Automattic\WooCommerce\Utilities\OrderUtil' ) + || ! method_exists( '\Automattic\WooCommerce\Utilities\OrderUtil', 'custom_orders_table_usage_is_enabled' ) ) { + return true; + } + + if ( ! \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ) { + return true; + } + + if ( wc_get_container()->get( \Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer::class )->data_sync_is_enabled() ) { + return true; + } + + return false; + } + + /** + * Add the orders autosuggest field to the WooCommerce feature schema + * + * @since 5.1.0 + * @param array $settings_schema Current settings schema + * @return array + */ + public function add_settings_schema( array $settings_schema ) : array { + $available = $this->is_available(); + + $settings_schema[] = [ + 'default' => '0', + 'disabled' => ! $available, + 'help' => $this->get_setting_help_message(), + 'key' => 'orders', + 'label' => __( 'Show suggestions when searching for Orders', 'elasticpress' ), + 'requires_sync' => true, + 'type' => 'checkbox', + ]; + + return $settings_schema; + } + + /** + * Return the help message for the setting schema field + * + * @since 5.1.0 + * @return string + */ + protected function get_setting_help_message() : string { + $available = $this->is_available(); + + $epio_autosuggest_kb_link = 'https://elasticpress.zendesk.com/hc/en-us/articles/13374461690381-Configuring-ElasticPress-io-Order-Autosuggest'; + + if ( $available ) { + /* translators: 1: tag (ElasticPress.io); 2. ; 3: tag (KB article); 4. ; */ + $message = __( 'You are directly connected to %1$sElasticPress.io%2$s! Enable autosuggest for Orders to enhance Dashboard results and quickly find WooCommerce Orders. %3$sLearn More%4$s.', 'elasticpress' ); + + return sprintf( + wp_kses( $message, 'ep-html' ), + '', + '', + '', + '' + ); + } + + if ( ! $this->is_hpos_compatible() ) { + return esc_html__( 'Currently, autosuggest for orders is only available if WooCommerce order data storage is set in legacy or compatibility mode.', 'elasticpress' ); + } + + /* translators: 1: tag (ElasticPress.io); 2. ; 3: tag (KB article); 4. ; */ + $message = __( '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' ); + + $message = sprintf( + wp_kses( $message, 'ep-html' ), + '', + '', + '', + '' + ); + + return $message; + } } diff --git a/includes/classes/Feature/WooCommerce/WooCommerce.php b/includes/classes/Feature/WooCommerce/WooCommerce.php index 839a46dcb4..85f8a2a7b3 100644 --- a/includes/classes/Feature/WooCommerce/WooCommerce.php +++ b/includes/classes/Feature/WooCommerce/WooCommerce.php @@ -72,7 +72,7 @@ public function __construct() { $this->orders = new Orders( $this ); $this->products = new Products( $this ); - $this->orders_autosuggest = new OrdersAutosuggest(); + $this->orders_autosuggest = new OrdersAutosuggest( $this ); parent::__construct(); } @@ -93,11 +93,7 @@ public function setup() { $this->products->setup(); $this->orders->setup(); - - // Orders Autosuggest feature. - if ( $this->is_orders_autosuggest_enabled() ) { - $this->orders_autosuggest->setup(); - } + $this->orders_autosuggest->setup(); } /** @@ -128,11 +124,7 @@ public function tear_down() { $this->products->tear_down(); $this->orders->tear_down(); - - // Orders Autosuggest feature. - if ( $this->is_orders_autosuggest_enabled() ) { - $this->orders_autosuggest->tear_down(); - } + $this->orders_autosuggest->tear_down(); } /** @@ -180,44 +172,6 @@ public function output_feature_box_long() { is_orders_autosuggest_available(); - $enabled = $this->is_orders_autosuggest_enabled(); - ?> -
-
-
-
- -

- tag (ElasticPress.io); 2. ; 3: tag (KB article); 4. ; */ - __( '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' ) : - /* translators: 1: tag (ElasticPress.io); 2. ; 3: tag (KB article); 4. ; */ - __( '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' ); - - printf( - wp_kses( $message, 'ep-html' ), - '', - '', - '', - '' - ); - ?> -

-
-
- settings_schema = apply_filters( 'ep_woocommerce_settings_schema', $this->settings_schema ); } /** - * Whether orders autosuggest is enabled or not + * DEPRECATED. Dashboard WooCommerce settings * * @since 4.5.0 - * @return boolean + * @deprecated 5.1.0 */ - public function is_orders_autosuggest_enabled() : bool { - return $this->is_orders_autosuggest_available() && '1' === $this->get_setting( 'orders' ); + public function output_feature_box_settings() { + _doing_it_wrong( + __METHOD__, + esc_html__( 'Settings are now generated via the set_settings_schema() method.', 'elasticpress' ), + '5.0.0' + ); } /** - * Set the `settings_schema` attribute + * DEPRECATED. Whether orders autosuggest is available or not * - * @since 5.0.0 + * @since 4.5.0 + * @deprecated 5.1.0 + * @return boolean */ - protected function set_settings_schema() { - $available = $this->is_orders_autosuggest_available(); - - $epio_autosuggest_kb_link = 'https://elasticpress.zendesk.com/hc/en-us/articles/13374461690381-Configuring-ElasticPress-io-Order-Autosuggest'; - - $message = ( $available ) ? - /* translators: 1: tag (ElasticPress.io); 2. ; 3: tag (KB article); 4. ; */ - __( 'You are directly connected to %1$sElasticPress.io%2$s! Enable autosuggest for Orders to enhance Dashboard results and quickly find WooCommerce Orders. %3$sLearn More%4$s.', 'elasticpress' ) : - /* translators: 1: tag (ElasticPress.io); 2. ; 3: tag (KB article); 4. ; */ - __( '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' ); - - $message = sprintf( - wp_kses( $message, 'ep-html' ), - '', - '', - '', - '' - ); + public function is_orders_autosuggest_available() : bool { + _deprecated_function( __METHOD__, '5.1.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders_autosuggest->is_available()" ); + return $this->orders_autosuggest->is_available(); + } - $this->settings_schema = [ - [ - 'default' => '0', - 'disabled' => ! $available, - 'help' => $message, - 'key' => 'orders', - 'label' => __( 'Show suggestions when searching for Orders', 'elasticpress' ), - 'requires_sync' => true, - 'type' => 'checkbox', - ], - ]; + /** + * DEPRECATED. Whether orders autosuggest is enabled or not + * + * @since 4.5.0 + * @deprecated 5.1.0 + * @return boolean + */ + public function is_orders_autosuggest_enabled() : bool { + _deprecated_function( __METHOD__, '5.1.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders_autosuggest->is_enabled()" ); + return $this->orders_autosuggest->is_enabled(); } /** @@ -368,6 +312,7 @@ protected function set_settings_schema() { * * @param \WP_Query $query WP Query * @since 2.1 + * @deprecated 4.7.0 */ public function translate_args( $query ) { _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()" ); @@ -380,6 +325,7 @@ public function translate_args( $query ) { * * @param array $meta_key The meta key to get the mapping for. * @since 2.1 + * @deprecated 4.7.0 * @return string The mapped meta key. */ public function get_orderby_meta_mapping( $meta_key ) { @@ -392,6 +338,7 @@ public function get_orderby_meta_mapping( $meta_key ) { * * @param array $search_fields Array of search fields. * @since 3.0 + * @deprecated 4.7.0 * @return array */ public function remove_author( $search_fields ) { @@ -404,6 +351,7 @@ public function remove_author( $search_fields ) { * * @param array $meta Existing post meta. * @param array $post Post arguments array. + * @deprecated 4.7.0 * @since 2.1 * @return array */ @@ -422,6 +370,7 @@ public function whitelist_meta_keys( $meta, $post ) { * * @param array $taxonomies Index taxonomies array. * @param array $post Post properties array. + * @deprecated 4.7.0 * @since 2.1 * @return array */ @@ -434,6 +383,7 @@ public function whitelist_taxonomies( $taxonomies, $post ) { * DEPRECATED. Returns the WooCommerce-oriented post types in admin that EP will search * * @since 4.4.0 + * @deprecated 4.7.0 * @return mixed|void */ public function get_admin_searchable_post_types() { @@ -447,6 +397,7 @@ public function get_admin_searchable_post_types() { * @param bool $enabled Coupons enabled or not * @param WP_Query $query WP Query * @since 2.1 + * @deprecated 4.7.0 * @return bool */ public function blacklist_coupons( $enabled, $query ) { @@ -459,6 +410,7 @@ public function blacklist_coupons( $enabled, $query ) { * * @since 2.1 * @param bool $override Original order perms check value + * @deprecated 4.7.0 * @param int $post_id Post ID * @return bool */ @@ -475,6 +427,7 @@ public function bypass_order_permissions_check( $override, $post_id ) { * If we were to always return array() on this filter, we'd break admin searches when WooCommerce module is activated * without the Protected Content Module * + * @deprecated 4.7.0 * @param \WP_Query $query Current query */ public function maybe_hook_woocommerce_search_fields( $query ) { @@ -490,6 +443,7 @@ public function maybe_hook_woocommerce_search_fields( $query ) { * 3. If the search key is integer but not an order id ( might be phone number ), use ES to find it * * @param WP_Query $wp WP Query + * @deprecated 4.7.0 * @since 2.3 */ public function search_order( $wp ) { @@ -508,7 +462,7 @@ public function search_order( $wp ) { * * @param array $post_args Post arguments * @param string|int $post_id Post id - * + * @deprecated 4.7.0 * @return array */ public function add_order_items_search( $post_args, $post_id ) { @@ -520,6 +474,7 @@ public function add_order_items_search( $post_args, $post_id ) { * DEPRECATED. Add WooCommerce Product Attributes to EP Facets. * * @param array $taxonomies Taxonomies array + * @deprecated 4.7.0 * @return array */ public function add_product_attributes( $taxonomies = [] ) { @@ -531,7 +486,7 @@ public function add_product_attributes( $taxonomies = [] ) { * DEPRECATED. Add WooCommerce Fields to the Weighting Dashboard. * * @since 3.x - * + * @deprecated 4.7.0 * @param array $fields Current weighting fields. * @param string $post_type Current post type. * @return array New fields. @@ -545,7 +500,7 @@ public function add_product_attributes_to_weighting( $fields, $post_type ) { * DEPRECATED. Add WooCommerce Fields to the default values of the Weighting Dashboard. * * @since 3.x - * + * @deprecated 4.7.0 * @param array $defaults Default values for the post type. * @param string $post_type Current post type. * @return array @@ -560,6 +515,7 @@ public function add_product_default_post_type_weights( $defaults, $post_type ) { * * @param array $post_types Array of post types (e.g. post, page). * @since 2.6 + * @deprecated 4.7.0 * @return array */ public function suggest_wc_add_post_type( $post_types ) { @@ -574,6 +530,7 @@ public function suggest_wc_add_post_type( $post_types ) { * @param array $query_args WP_Query args * @param WP_Query $query WP_Query object * @since 3.2 + * @deprecated 4.7.0 * @return array */ public function price_filter( $args, $query_args, $query ) { @@ -590,6 +547,7 @@ public function price_filter( $args, $query_args, $query ) { * @see https://github.com/10up/ElasticPress/issues/2726 * * @since 4.2.0 + * @deprecated 4.7.0 * @param bool $skip Whether the password protected content should have their content, and meta removed * @param array $post_args Post arguments * @return bool @@ -603,6 +561,7 @@ public function keep_order_fields( $skip, $post_args ) { * DEPRECATED. Add a new `_variations_skus` meta field to the product to be indexed in Elasticsearch. * * @since 4.2.0 + * @deprecated 4.7.0 * @param array $post_meta Post meta * @param WP_Post $post Post object * @return array @@ -622,6 +581,7 @@ public function add_variations_skus_meta( $post_meta, $post ) { * by ElasticPress. * * @since 4.2.0 + * @deprecated 4.7.0 * @param array $query_vars Query vars. * @return array */ @@ -634,6 +594,7 @@ public function admin_product_list_request_query( $query_vars ) { * DEPRECATED. Apply the necessary changes to WP_Query in WooCommerce Admin Product List. * * @param WP_Query $query The WP Query being executed. + * @deprecated 4.7.0 */ public function translate_args_admin_products_list( $query ) { _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->price_filter()" ); @@ -644,6 +605,7 @@ public function translate_args_admin_products_list( $query ) { * DEPRECATED. Depending on the number of products display an admin notice in the custom sort screen for WooCommerce Products * * @since 4.4.0 + * @deprecated 4.7.0 * @param array $notices Current ElasticPress admin notices * @return array */ @@ -656,6 +618,7 @@ public function maybe_display_notice_about_product_ordering( $notices ) { * DEPRECATED. Conditionally resync products after applying a custom order. * * @since 4.4.0 + * @deprecated 4.7.0 * @param int $sorting_id ID of post dragged and dropped * @param array $menu_orders Post IDs and their new menu_order value */ @@ -668,6 +631,7 @@ public function action_sync_on_woocommerce_sort_single( $sorting_id, $menu_order * DEPRECATED. Add weight by date settings related to WooCommerce * * @since 4.6.0 + * @deprecated 4.7.0 * @param array $settings Current settings. */ public function add_weight_settings_search( $settings ) { @@ -679,6 +643,7 @@ public function add_weight_settings_search( $settings ) { * DEPRECATED. Conditionally disable decaying by date based on WooCommerce Decay settings. * * @since 4.6.0 + * @deprecated 4.7.0 * @param bool $is_decaying_enabled Whether decay by date is enabled or not * @param array $settings Settings * @param array $args WP_Query args From 9a10d00fd6bf082223cf9d5095fd45b239ee1ff5 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Tue, 19 Mar 2024 09:48:25 -0300 Subject: [PATCH 06/10] Fix unit tests --- .../classes/Feature/WooCommerce/Orders.php | 2 +- .../features/WooCommerce/TestWooCommerce.php | 4 +- .../TestWooCommerceOrdersAutosuggest.php | 56 +++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/includes/classes/Feature/WooCommerce/Orders.php b/includes/classes/Feature/WooCommerce/Orders.php index 5e8a1fc1f1..849820c4bd 100644 --- a/includes/classes/Feature/WooCommerce/Orders.php +++ b/includes/classes/Feature/WooCommerce/Orders.php @@ -520,7 +520,7 @@ public function __call( $method_name, $arguments ) { "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders_autosuggest->{$method_name}()" // phpcs:ignore ); - if ( $this->woocommerce->is_orders_autosuggest_enabled() && method_exists( $this->woocommerce->orders_autosuggest, $method_name ) ) { + if ( $this->woocommerce->orders_autosuggest->is_enabled() && method_exists( $this->woocommerce->orders_autosuggest, $method_name ) ) { call_user_func_array( [ $this->woocommerce->orders_autosuggest, $method_name ], $arguments ); } } diff --git a/tests/php/features/WooCommerce/TestWooCommerce.php b/tests/php/features/WooCommerce/TestWooCommerce.php index 93ea0fe491..05e8d7aa60 100644 --- a/tests/php/features/WooCommerce/TestWooCommerce.php +++ b/tests/php/features/WooCommerce/TestWooCommerce.php @@ -153,6 +153,7 @@ public function testSearchQueryForCouponWhenProtectedContentIsNotEnable() { * * @since 4.5.0 * @group woocommerce + * @expectedDeprecated ElasticPress\Feature\WooCommerce\WooCommerce::is_orders_autosuggest_available */ public function testIsOrdersAutosuggestAvailable() { $woocommerce_feature = ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' ); @@ -170,10 +171,11 @@ public function testIsOrdersAutosuggestAvailable() { } /** - * Test the `is_orders_autosuggest_available` method + * Test the `is_orders_autosuggest_enabled` method * * @since 4.5.0 * @group woocommerce + * @expectedDeprecated ElasticPress\Feature\WooCommerce\WooCommerce::is_orders_autosuggest_enabled */ public function testIsOrdersAutosuggestEnabled() { $woocommerce_feature = ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' ); diff --git a/tests/php/features/WooCommerce/TestWooCommerceOrdersAutosuggest.php b/tests/php/features/WooCommerce/TestWooCommerceOrdersAutosuggest.php index de3682e8d6..81c2728d2a 100644 --- a/tests/php/features/WooCommerce/TestWooCommerceOrdersAutosuggest.php +++ b/tests/php/features/WooCommerce/TestWooCommerceOrdersAutosuggest.php @@ -294,4 +294,60 @@ public function testSetSearchFields() { $this->assertSame( $expected_fields, $changed_search_fields ); } + + /** + * Test the `is_available` method + * + * @since 5.1.0 + * @group woocommerce + * @group woocommerce-orders-autosuggest + */ + public function test_is_available() { + $this->assertSame( $this->orders_autosuggest->is_available(), \ElasticPress\Utils\is_epio() ); + + /** + * Test the `ep_woocommerce_orders_autosuggest_available` filter + */ + add_filter( 'ep_woocommerce_orders_autosuggest_available', '__return_true' ); + $this->assertTrue( $this->orders_autosuggest->is_available() ); + + add_filter( 'ep_woocommerce_orders_autosuggest_available', '__return_false' ); + $this->assertFalse( $this->orders_autosuggest->is_available() ); + } + + /** + * Test the `is_enabled` method + * + * @since 5.1.0 + * @group woocommerce + */ + public function test_is_enabled() { + $this->assertFalse( $this->orders_autosuggest->is_enabled() ); + + /** + * Make it available but it won't be enabled + */ + add_filter( 'ep_woocommerce_orders_autosuggest_available', '__return_true' ); + $this->assertFalse( $this->orders_autosuggest->is_enabled() ); + + /** + * Enable it + */ + $filter = function() { + return [ + 'woocommerce' => [ + 'orders' => '1', + ], + ]; + }; + add_filter( 'pre_site_option_ep_feature_settings', $filter ); + add_filter( 'pre_option_ep_feature_settings', $filter ); + $this->assertTrue( $this->orders_autosuggest->is_enabled() ); + + /** + * Make it unavailable. Even activated, it should not be considered enabled if not available anymore. + */ + remove_filter( 'ep_woocommerce_orders_autosuggest_available', '__return_true' ); + $this->assertFalse( $this->orders_autosuggest->is_enabled() ); + } } From 5c664ee31f6f20526452fe6cdfea14bf2f3823ec Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Tue, 19 Mar 2024 10:14:50 -0300 Subject: [PATCH 07/10] New unit tests --- .../TestWooCommerceOrdersAutosuggest.php | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/tests/php/features/WooCommerce/TestWooCommerceOrdersAutosuggest.php b/tests/php/features/WooCommerce/TestWooCommerceOrdersAutosuggest.php index 81c2728d2a..f7c917bc01 100644 --- a/tests/php/features/WooCommerce/TestWooCommerceOrdersAutosuggest.php +++ b/tests/php/features/WooCommerce/TestWooCommerceOrdersAutosuggest.php @@ -320,6 +320,7 @@ public function test_is_available() { * * @since 5.1.0 * @group woocommerce + * @group woocommerce-orders-autosuggest */ public function test_is_enabled() { $this->assertFalse( $this->orders_autosuggest->is_enabled() ); @@ -350,4 +351,91 @@ public function test_is_enabled() { remove_filter( 'ep_woocommerce_orders_autosuggest_available', '__return_true' ); $this->assertFalse( $this->orders_autosuggest->is_enabled() ); } + + /** + * Test the `is_hpos_compatible` method + * + * @since 5.1.0 + * @group woocommerce + * @group woocommerce-orders-autosuggest + */ + public function test_is_hpos_compatible() { + $this->assertTrue( $this->orders_autosuggest->is_hpos_compatible() ); + + // Turn HPOS on + $custom_orders_table = \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION; + $change_custom_orders_table = function() { + return 'yes'; + }; + add_filter( 'pre_option_' . $custom_orders_table, $change_custom_orders_table ); + + // Disable legacy mode + $legacy_mode = \Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer::ORDERS_DATA_SYNC_ENABLED_OPTION; + $change_legacy_mode = function() { + return 'no'; + }; + add_filter( 'pre_option_' . $legacy_mode, $change_legacy_mode ); + + $this->assertFalse( $this->orders_autosuggest->is_hpos_compatible() ); + } + + /** + * Test the `add_settings_schema` method + * + * @since 5.1.0 + * @group woocommerce + * @group woocommerce-orders-autosuggest + */ + public function test_add_settings_schema() { + $new_settings_schema = $this->orders_autosuggest->add_settings_schema( [] ); + $this->assertSame( 'orders', $new_settings_schema[0]['key'] ); + } + + /** + * Test the `get_setting_help_message` method when the feature is available + * + * @since 5.1.0 + * @group woocommerce + * @group woocommerce-orders-autosuggest + */ + public function test_get_setting_help_message_feature_available() { + /** + * Make it available but it won't be enabled + */ + add_filter( 'ep_woocommerce_orders_autosuggest_available', '__return_true' ); + + $new_settings_schema = $this->orders_autosuggest->add_settings_schema( [] ); + $this->assertStringContainsString( 'You are directly connected to', $new_settings_schema[0]['help'] ); + } + + /** + * Test the `get_setting_help_message` method when incompatible with HPOS + * + * @since 5.1.0 + * @group woocommerce + * @group woocommerce-orders-autosuggest + */ + public function test_get_setting_help_message_feature_hpos_incompatible() { + // Turn HPOS on + $custom_orders_table = \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION; + $change_custom_orders_table = function() { + return 'yes'; + }; + add_filter( 'pre_option_' . $custom_orders_table, $change_custom_orders_table ); + + $new_settings_schema = $this->orders_autosuggest->add_settings_schema( [] ); + $this->assertStringContainsString( 'Currently, autosuggest for orders is only available', $new_settings_schema[0]['help'] ); + } + + /** + * Test the `get_setting_help_message` method when the feature is not available + * + * @since 5.1.0 + * @group woocommerce + * @group woocommerce-orders-autosuggest + */ + public function test_get_setting_help_message_feature_not_available() { + $new_settings_schema = $this->orders_autosuggest->add_settings_schema( [] ); + $this->assertStringContainsString( 'Due to the sensitive nature of orders', $new_settings_schema[0]['help'] ); + } } From a4221df79341debdf4688e9d75942e2244d55cb9 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Tue, 19 Mar 2024 10:28:43 -0300 Subject: [PATCH 08/10] Fix linting --- .../WooCommerce/TestWooCommerceOrdersAutosuggest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/php/features/WooCommerce/TestWooCommerceOrdersAutosuggest.php b/tests/php/features/WooCommerce/TestWooCommerceOrdersAutosuggest.php index f7c917bc01..b183c90a08 100644 --- a/tests/php/features/WooCommerce/TestWooCommerceOrdersAutosuggest.php +++ b/tests/php/features/WooCommerce/TestWooCommerceOrdersAutosuggest.php @@ -363,14 +363,14 @@ public function test_is_hpos_compatible() { $this->assertTrue( $this->orders_autosuggest->is_hpos_compatible() ); // Turn HPOS on - $custom_orders_table = \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION; + $custom_orders_table = \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION; $change_custom_orders_table = function() { return 'yes'; }; add_filter( 'pre_option_' . $custom_orders_table, $change_custom_orders_table ); // Disable legacy mode - $legacy_mode = \Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer::ORDERS_DATA_SYNC_ENABLED_OPTION; + $legacy_mode = \Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer::ORDERS_DATA_SYNC_ENABLED_OPTION; $change_legacy_mode = function() { return 'no'; }; @@ -417,7 +417,7 @@ public function test_get_setting_help_message_feature_available() { */ public function test_get_setting_help_message_feature_hpos_incompatible() { // Turn HPOS on - $custom_orders_table = \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION; + $custom_orders_table = \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION; $change_custom_orders_table = function() { return 'yes'; }; From 53334504f0c2e175c2085d17caabb9873f85eac0 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Tue, 19 Mar 2024 13:10:32 -0300 Subject: [PATCH 09/10] Add $context to get_capability() --- includes/classes/Feature/Search/Synonyms.php | 4 +- .../Feature/SearchOrdering/SearchOrdering.php | 4 +- includes/classes/REST/SearchOrdering.php | 2 +- includes/utils.php | 41 ++++++++++++++----- tests/php/TestUtils.php | 40 +++++++++++++++--- 5 files changed, 69 insertions(+), 22 deletions(-) diff --git a/includes/classes/Feature/Search/Synonyms.php b/includes/classes/Feature/Search/Synonyms.php index de26fec2f9..6f7745411e 100644 --- a/includes/classes/Feature/Search/Synonyms.php +++ b/includes/classes/Feature/Search/Synonyms.php @@ -171,7 +171,7 @@ public function admin_menu() { 'elasticpress', esc_html__( 'ElasticPress Synonyms', 'elasticpress' ), esc_html__( 'Synonyms', 'elasticpress' ), - Utils\get_capability(), + Utils\get_capability( 'synonyms' ), 'elasticpress-synonyms', [ $this, 'admin_page' ] ); @@ -248,7 +248,7 @@ public function register_post_type() { 'show_ui' => false, 'show_in_menu' => false, 'query_var' => true, - 'capabilities' => Utils\get_post_map_capabilities(), + 'capabilities' => Utils\get_post_map_capabilities( 'synonyms' ), 'has_archive' => false, 'hierarchical' => false, 'menu_position' => 100, diff --git a/includes/classes/Feature/SearchOrdering/SearchOrdering.php b/includes/classes/Feature/SearchOrdering/SearchOrdering.php index 833991dc1a..be4931d9e6 100644 --- a/includes/classes/Feature/SearchOrdering/SearchOrdering.php +++ b/includes/classes/Feature/SearchOrdering/SearchOrdering.php @@ -215,7 +215,7 @@ public function admin_menu() { 'elasticpress', esc_html__( 'Custom Results', 'elasticpress' ), esc_html__( 'Custom Results', 'elasticpress' ), - Utils\get_capability(), + Utils\get_capability( 'search-ordering' ), 'edit.php?post_type=' . self::POST_TYPE_NAME ); } @@ -294,7 +294,7 @@ public function register_post_type() { 'show_in_menu' => false, 'query_var' => true, 'rewrite' => array( 'slug' => 'ep-pointer' ), - 'capabilities' => Utils\get_post_map_capabilities(), + 'capabilities' => Utils\get_post_map_capabilities( 'search-ordering' ), 'has_archive' => false, 'hierarchical' => false, 'menu_position' => 100, diff --git a/includes/classes/REST/SearchOrdering.php b/includes/classes/REST/SearchOrdering.php index 3420137474..48d02c61ed 100644 --- a/includes/classes/REST/SearchOrdering.php +++ b/includes/classes/REST/SearchOrdering.php @@ -71,7 +71,7 @@ public function get_args() { * @return boolean */ public function check_permission() { - $capability = Utils\get_capability(); + $capability = Utils\get_capability( 'search-ordering' ); return current_user_can( $capability ); } diff --git a/includes/utils.php b/includes/utils.php index 59d338d49c..1d6d5aa535 100644 --- a/includes/utils.php +++ b/includes/utils.php @@ -54,47 +54,66 @@ function get_epio_credentials() { /** * Get WP capability needed for a user to interact with ElasticPress in the admin * - * @since 4.5.0 + * @since 4.5.0, 5.1.0 added $context + * @param string $context Context for the capability. Defaults to empty string. * @return string */ -function get_capability() : string { +function get_capability( string $context = '' ) : string { /** * Filter the WP capability needed to interact with ElasticPress in the admin * - * @since 4.5.0 + * Example: + * ``` + * add_filter( + * 'ep_capability', + * function ( $cacapability, $context ) { + * return ( 'synonyms' === $context ) ? + * 'manage_elasticpress_synonyms' : + * $cacapability; + * }, + * 10, + * 2 + * ); + * ``` + * + * @since 4.5.0, 5.1.0 added $context * @hook ep_capability * @param {string} $capability Capability name. Defaults to `'manage_elasticpress'` + * @param {string} $context Additional context * @return {string} New capability value */ - return apply_filters( 'ep_capability', 'manage_elasticpress' ); + return apply_filters( 'ep_capability', 'manage_elasticpress', $context ); } /** * Get WP capability needed for a user to interact with ElasticPress in the network admin * - * @since 4.5.0 + * @since 4.5.0, 5.1.0 added $context + * @param string $context Context for the capability. Defaults to empty string. * @return string */ -function get_network_capability() : string { +function get_network_capability( string $context = '' ) : string { /** * Filter the WP capability needed to interact with ElasticPress in the network admin * - * @since 4.5.0 + * @since 4.5.0, 5.1.0 added $context * @hook ep_network_capability * @param {string} $capability Capability name. Defaults to `'manage_network_elasticpress'` + * @param {string} $context Additional context * @return {string} New capability value */ - return apply_filters( 'ep_network_capability', 'manage_network_elasticpress' ); + return apply_filters( 'ep_network_capability', 'manage_network_elasticpress', $context ); } /** * Get mapped capabilities for post types * - * @since 4.5.0 + * @since 4.5.0, 5.1.0 added $context + * @param string $context Context for the capability. Defaults to empty string. * @return array */ -function get_post_map_capabilities() : array { - $capability = get_capability(); +function get_post_map_capabilities( string $context = '' ) : array { + $capability = get_capability( $context ); return [ 'edit_post' => $capability, diff --git a/tests/php/TestUtils.php b/tests/php/TestUtils.php index 6328ba51ba..67ab8d6ca3 100644 --- a/tests/php/TestUtils.php +++ b/tests/php/TestUtils.php @@ -276,13 +276,14 @@ public function testGetCapability() { /** * Test the `ep_capability` filter. */ - $change_cap_name = function( $cap ) { + $change_cap_name = function( $cap, $context ) { $this->assertSame( 'manage_elasticpress', $cap ); + $this->assertSame( 'context', $context ); return 'custom_manage_ep'; }; - add_filter( 'ep_capability', $change_cap_name ); + add_filter( 'ep_capability', $change_cap_name, 10, 2 ); - $this->assertSame( 'custom_manage_ep', Utils\get_capability() ); + $this->assertSame( 'custom_manage_ep', Utils\get_capability( 'context' ) ); } /** @@ -296,13 +297,14 @@ public function testGetNetworkCapability() { /** * Test the `ep_network_capability` filter. */ - $change_cap_name = function( $cap ) { + $change_cap_name = function( $cap, $context ) { $this->assertSame( 'manage_network_elasticpress', $cap ); + $this->assertSame( 'context', $context ); return 'custom_manage_network_ep'; }; - add_filter( 'ep_network_capability', $change_cap_name ); + add_filter( 'ep_network_capability', $change_cap_name, 10, 2 ); - $this->assertSame( 'custom_manage_network_ep', Utils\get_network_capability() ); + $this->assertSame( 'custom_manage_network_ep', Utils\get_network_capability( 'context' ) ); } /** @@ -324,6 +326,32 @@ public function testGetPostMapCapabilities() { $this->assertSame( $expected, Utils\get_post_map_capabilities() ); } + /** + * Test the `get_post_map_capabilities` function passing context + * + * @since 5.1.0 + */ + public function test_get_post_map_capabilities_with_context() { + $change_cap_name = function( $cap, $context ) { + $this->assertSame( 'manage_elasticpress', $cap ); + $this->assertSame( 'context', $context ); + return 'custom_manage_ep'; + }; + add_filter( 'ep_capability', $change_cap_name, 10, 2 ); + + $expected = [ + 'edit_post' => 'custom_manage_ep', + 'edit_posts' => 'custom_manage_ep', + 'edit_others_posts' => 'custom_manage_ep', + 'publish_posts' => 'custom_manage_ep', + 'read_post' => 'custom_manage_ep', + 'read_private_posts' => 'custom_manage_ep', + 'delete_post' => 'custom_manage_ep', + ]; + + $this->assertSame( $expected, Utils\get_post_map_capabilities( 'context' ) ); + } + /** * Test the `get_elasticsearch_error_reason` function * From a3dc817214c4279a003c825ee1906e558edf7d76 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Tue, 19 Mar 2024 15:58:55 -0300 Subject: [PATCH 10/10] Modernize ep_highlight_excerpt to deal with block content --- includes/classes/Feature/Search/Search.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/includes/classes/Feature/Search/Search.php b/includes/classes/Feature/Search/Search.php index 0e7ea785a1..1d9f7c7868 100644 --- a/includes/classes/Feature/Search/Search.php +++ b/includes/classes/Feature/Search/Search.php @@ -285,14 +285,18 @@ public function allow_excerpt_html() { * @return string $text the new excerpt */ public function ep_highlight_excerpt( $text, $post ) { - $settings = $this->get_settings(); // reproduces wp_trim_excerpt filter, preserving the excerpt_more and excerpt_length filters if ( '' === $text ) { $text = get_the_content( '', false, $post ); + + $text = strip_shortcodes( $text ); + $text = excerpt_remove_blocks( $text ); + $text = apply_filters( 'the_content', $text ); $text = str_replace( '\]\]\>', ']]>', $text ); + $text = strip_tags( $text, '<' . esc_html( $settings['highlight_tag'] ) . '>' ); // use the defined length, if already applied... @@ -300,9 +304,12 @@ public function ep_highlight_excerpt( $text, $post ) { // use defined excerpt_more filter if it is used $excerpt_more = apply_filters( 'excerpt_more', $text ); - $excerpt_more = $excerpt_more !== $text ? $excerpt_more : '[…]'; + /** + * WordPress would handle this using `wp_trim_words` but that removes all tags, + * including the one used to highlight the search term. + */ $words = explode( ' ', $text, $excerpt_length + 1 ); if ( count( $words ) > $excerpt_length ) { array_pop( $words );