Skip to content

Commit

Permalink
Merge branch 'develop' into fix/3855
Browse files Browse the repository at this point in the history
  • Loading branch information
felipeelia authored Mar 20, 2024
2 parents 025d6e9 + b7d2afa commit 9c247a7
Show file tree
Hide file tree
Showing 17 changed files with 548 additions and 130 deletions.
6 changes: 6 additions & 0 deletions assets/js/autosuggest/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,8 @@ function updateAutosuggestBox(options, input) {
}
});

setInputActiveDescendant('', input);

return true;
}

Expand All @@ -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) => {
Expand All @@ -387,6 +390,9 @@ function hideAutosuggestBox() {
container.style = 'display: none;';
});

// Remove active descendant attribute from all inputs
inputs.forEach((input) => setInputActiveDescendant('', input));

return true;
}

Expand Down
9 changes: 9 additions & 0 deletions assets/js/instant-results/apps/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
15 changes: 12 additions & 3 deletions assets/js/weighting/components/field.js
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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;

/**
Expand Down Expand Up @@ -45,7 +46,15 @@ export default ({ label, onChange, onDelete, value }) => {
return (
<div className="ep-weighting-field">
<fieldset>
<legend className="ep-weighting-field__name">{label}</legend>
<legend className="ep-weighting-field__name">
{showTooltip ? (
<Tooltip text={label}>
<span>{label}</span>
</Tooltip>
) : (
label
)}
</legend>
<div className="ep-weighting-field__searchable">
<CheckboxControl
checked={enabled}
Expand Down
1 change: 1 addition & 0 deletions assets/js/weighting/components/group.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export default ({ group, postType }) => {
onDelete={() => {
onDelete(key);
}}
showTooltip
/>
</PanelRow>
))}
Expand Down
11 changes: 9 additions & 2 deletions includes/classes/Feature/Search/Search.php
Original file line number Diff line number Diff line change
Expand Up @@ -285,24 +285,31 @@ 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( '\]\]\>', ']]&gt;', $text );

$text = strip_tags( $text, '<' . esc_html( $settings['highlight_tag'] ) . '>' );

// use the defined length, if already applied...
$excerpt_length = apply_filters( 'excerpt_length', 55 );

// use defined excerpt_more filter if it is used
$excerpt_more = apply_filters( 'excerpt_more', $text );

$excerpt_more = $excerpt_more !== $text ? $excerpt_more : '[&hellip;]';

/**
* 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 );
Expand Down
4 changes: 2 additions & 2 deletions includes/classes/Feature/Search/Synonyms.php
Original file line number Diff line number Diff line change
Expand Up @@ -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' ]
);
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions includes/classes/Feature/SearchOrdering/SearchOrdering.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
}
Expand Down Expand Up @@ -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,
Expand Down
45 changes: 44 additions & 1 deletion includes/classes/Feature/WooCommerce/Orders.php
Original file line number Diff line number Diff line change
Expand Up @@ -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' ] );
}

/**
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -477,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 );
}
}
Expand Down
144 changes: 140 additions & 4 deletions includes/classes/Feature/WooCommerce/OrdersAutosuggest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace ElasticPress\Feature\WooCommerce;

use ElasticPress\Elasticsearch;
use ElasticPress\Features;
use ElasticPress\Indexables;
use ElasticPress\REST;
use ElasticPress\Utils;
Expand Down Expand Up @@ -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' );
}

/**
Expand All @@ -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' ] );
Expand Down Expand Up @@ -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: <a> tag (ElasticPress.io); 2. </a>; 3: <a> tag (KB article); 4. </a>; */
$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' ),
'<a href="https://elasticpress.io/" target="_blank">',
'</a>',
'<a href="' . esc_url( $epio_autosuggest_kb_link ) . '" target="_blank">',
'</a>'
);
}

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: <a> tag (ElasticPress.io); 2. </a>; 3: <a> tag (KB article); 4. </a>; */
$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' ),
'<a href="https://elasticpress.io/" target="_blank">',
'</a>',
'<a href="' . esc_url( $epio_autosuggest_kb_link ) . '" target="_blank">',
'</a>'
);

return $message;
}
}
Loading

0 comments on commit 9c247a7

Please sign in to comment.