From a1a7e4f687784adc59337d0b6a660b5c7b7aa724 Mon Sep 17 00:00:00 2001 From: Ayebare Date: Wed, 29 Jan 2020 13:28:55 +0300 Subject: [PATCH 01/52] added a function to return related posts query --- .../Feature/RelatedPosts/RelatedPosts.php | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/includes/classes/Feature/RelatedPosts/RelatedPosts.php b/includes/classes/Feature/RelatedPosts/RelatedPosts.php index 9dd24f3b98..643b0a8692 100644 --- a/includes/classes/Feature/RelatedPosts/RelatedPosts.php +++ b/includes/classes/Feature/RelatedPosts/RelatedPosts.php @@ -110,10 +110,10 @@ public function formatted_args( $formatted_args, $args ) { * * @param int $post_id Post ID * @param int $return Return code - * @since 2.1 - * @return array|bool + * @since 3.4 + * @return WP_Query */ - public function find_related( $post_id, $return = 5 ) { + public function get_related_query( $post_id, $return = 5 ) { $args = array( 'more_like' => $post_id, 'posts_per_page' => $return, @@ -129,7 +129,22 @@ public function find_related( $post_id, $return = 5 ) { * @since 2.1 * @return {array} New arguments */ - $query = new WP_Query( apply_filters( 'ep_find_related_args', $args ) ); + return new WP_Query( apply_filters( 'ep_find_related_args', $args ) ); + } + + /** + * Search Elasticsearch for related content + * + * @param int $post_id Post ID + * @param int $return Return code + * + * @since 2.1 + * @uses get_related_query + * + * @return array|bool + */ + public function find_related( $post_id, $return = 5 ) { + $query = $this->get_related_query( $post_id, $return = 5 ); if ( ! $query->have_posts() ) { return false; From 72c81f53a09caedcec11b429d34d11f5a66fd558 Mon Sep 17 00:00:00 2001 From: Ayebare Date: Wed, 5 Feb 2020 17:23:04 +0300 Subject: [PATCH 02/52] added unit tests for related post query --- tests/php/features/TestRelatedPosts.php | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/php/features/TestRelatedPosts.php b/tests/php/features/TestRelatedPosts.php index eac3135877..903f509d3a 100644 --- a/tests/php/features/TestRelatedPosts.php +++ b/tests/php/features/TestRelatedPosts.php @@ -93,6 +93,32 @@ public function testFindRelatedPostFilter() { remove_filter( 'ep_find_related_args', array( $this, 'find_related_posts_filter' ), 10, 1 ); } + /** + * Test for related posts query + * + * @group related_posts + */ + public function testGetRelatedQuery() { + $post_id = Functions\create_and_sync_post( array( 'post_content' => 'findme test 1' ) ); + + $related_post_title = 'related post test'; + Functions\create_and_sync_post( array( + 'post_title' => $related_post_title, + 'post_content' => 'findme test 2' + ) + ); + + ElasticPress\Elasticsearch::factory()->refresh_indices(); + ElasticPress\Features::factory()->activate_feature( 'related_posts' ); + ElasticPress\Features::factory()->setup_features(); + + $query = ElasticPress\Features::factory()->get_registered_feature( 'related_posts' )->get_related_query( $post_id, 1 ); + + $this->assertTrue( ! empty( $query->posts ) ); + $this->assertEquals( '1', $query->post_count ); + $this->assertEquals( $related_post_title, $query->posts[0]->post_title ); + } + /** * Detect EP fire * From da8671e79c90b1d745ce7b9b120124379393b4db Mon Sep 17 00:00:00 2001 From: Volodymyr Kolesnykov Date: Fri, 17 Dec 2021 01:54:35 +0200 Subject: [PATCH 03/52] Replace deprecated FILTER_SANITIZE_STRING --- includes/classes/Feature/Search/Synonyms.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/includes/classes/Feature/Search/Synonyms.php b/includes/classes/Feature/Search/Synonyms.php index 05d823138e..2051fabf4a 100644 --- a/includes/classes/Feature/Search/Synonyms.php +++ b/includes/classes/Feature/Search/Synonyms.php @@ -187,7 +187,7 @@ public function admin_notices() { return; } - $update = filter_input( INPUT_GET, 'ep_synonym_update', FILTER_SANITIZE_STRING ); + $update = filter_input( INPUT_GET, 'ep_synonym_update', FILTER_SANITIZE_SPECIAL_CHARS ); if ( ! in_array( $update, [ 'success', 'error-update-post', 'error-update-index' ], true ) ) { return; @@ -327,7 +327,7 @@ public function validate_synonym( $synonym ) { return false; } - return filter_var( trim( $synonym ), FILTER_SANITIZE_STRING ); + return sanitize_text_field( $synonym, true ); } /** @@ -386,13 +386,13 @@ public function add_search_synonyms( $mapping, $index ) { * @return void */ public function handle_update_synonyms() { - $nonce = filter_input( INPUT_POST, $this->get_nonce_field(), FILTER_SANITIZE_STRING ); - $referer = filter_input( INPUT_POST, '_wp_http_referer', FILTER_SANITIZE_STRING ); + $nonce = filter_input( INPUT_POST, $this->get_nonce_field(), FILTER_SANITIZE_SPECIAL_CHARS ); + $referer = filter_input( INPUT_POST, '_wp_http_referer', FILTER_SANITIZE_URL ); $post_id = false; if ( wp_verify_nonce( $nonce, $this->get_nonce_action() ) ) { - $synonyms = filter_input( INPUT_POST, $this->get_synonym_field(), FILTER_SANITIZE_STRING ); - $mode = filter_input( INPUT_POST, 'synonyms_editor_mode', FILTER_SANITIZE_STRING ); + $synonyms = filter_input( INPUT_POST, $this->get_synonym_field(), FILTER_SANITIZE_SPECIAL_CHARS ); + $mode = filter_input( INPUT_POST, 'synonyms_editor_mode', FILTER_SANITIZE_SPECIAL_CHARS ); $content = trim( sanitize_textarea_field( $synonyms ) ); // Content can't be empty. From 43ab996c1aef89aecf17767d1db70776ecc1ecd1 Mon Sep 17 00:00:00 2001 From: Volodymyr Kolesnykov Date: Tue, 18 Jan 2022 19:25:01 +0200 Subject: [PATCH 04/52] Fix overzealous filtering - see Automattic/ElasticPress#142 --- includes/classes/Feature/Search/Synonyms.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/classes/Feature/Search/Synonyms.php b/includes/classes/Feature/Search/Synonyms.php index 2051fabf4a..2dc3cbede6 100644 --- a/includes/classes/Feature/Search/Synonyms.php +++ b/includes/classes/Feature/Search/Synonyms.php @@ -391,7 +391,7 @@ public function handle_update_synonyms() { $post_id = false; if ( wp_verify_nonce( $nonce, $this->get_nonce_action() ) ) { - $synonyms = filter_input( INPUT_POST, $this->get_synonym_field(), FILTER_SANITIZE_SPECIAL_CHARS ); + $synonyms = filter_input( INPUT_POST, $this->get_synonym_field(), FILTER_CALLBACK, [ 'options' => 'wp_strip_all_tags' ] ); $mode = filter_input( INPUT_POST, 'synonyms_editor_mode', FILTER_SANITIZE_SPECIAL_CHARS ); $content = trim( sanitize_textarea_field( $synonyms ) ); From 499cf5ac0b8fd5c9982ed66aee09cfea8220fb9c Mon Sep 17 00:00:00 2001 From: Daniel Kudwien Date: Tue, 1 Feb 2022 16:28:06 +0100 Subject: [PATCH 05/52] Fixed PHP warning Trying to access array offset on value of type int in get_index_names(). --- includes/classes/Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/classes/Command.php b/includes/classes/Command.php index e4e113433a..778ba5a27f 100644 --- a/includes/classes/Command.php +++ b/includes/classes/Command.php @@ -411,7 +411,7 @@ public function get_indexes( $args, $assoc_args ) { * @return array */ protected function get_index_names() { - $sites = ( is_multisite() ) ? Utils\get_sites() : array( 'blog_id' => get_current_blog_id() ); + $sites = ( is_multisite() ) ? Utils\get_sites() : array( array( 'blog_id' => get_current_blog_id() ) ); $all_indexables = Indexables::factory()->get_all(); From efafd00c9ae8e41f93b6a98d8ca1ad77f1fbe2ee Mon Sep 17 00:00:00 2001 From: Rebecca Hum <16962021+rebeccahum@users.noreply.github.com> Date: Mon, 7 Mar 2022 10:01:29 -0700 Subject: [PATCH 06/52] Add generate_mapping --- includes/classes/Indexable.php | 7 +++ .../classes/Indexable/Comment/Comment.php | 20 ++++++-- includes/classes/Indexable/Post/Post.php | 50 ++++++++++++------- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/includes/classes/Indexable.php b/includes/classes/Indexable.php index 6c06bffe54..6e1bc23bbe 100644 --- a/includes/classes/Indexable.php +++ b/includes/classes/Indexable.php @@ -1107,4 +1107,11 @@ abstract public function prepare_document( $object_id ); * @return boolean */ abstract public function query_db( $args ); + + /** + * Must implement a method that generates the mapping array. + * + * @return array + */ + abstract public function generate_mapping(); } diff --git a/includes/classes/Indexable/Comment/Comment.php b/includes/classes/Indexable/Comment/Comment.php index d6ca3297ec..87bc504525 100644 --- a/includes/classes/Indexable/Comment/Comment.php +++ b/includes/classes/Indexable/Comment/Comment.php @@ -750,12 +750,12 @@ public function format_args( $query_vars ) { } /** - * Put mapping for comments + * Generate the mapping array * - * @since 3.6.0 - * @return boolean + * @since 4.0.0 + * @return array */ - public function put_mapping() { + public function generate_mapping() { $es_version = Elasticsearch::factory()->get_elasticsearch_version(); if ( empty( $es_version ) ) { @@ -797,6 +797,18 @@ public function put_mapping() { */ $mapping = apply_filters( 'ep_comment_mapping', $mapping ); + return $mapping; + } + + /** + * Put mapping for comments + * + * @since 3.6.0 + * @return boolean + */ + public function put_mapping() { + $mapping = $this->generate_mapping(); + return Elasticsearch::factory()->put_mapping( $this->get_index_name(), $mapping ); } diff --git a/includes/classes/Indexable/Post/Post.php b/includes/classes/Indexable/Post/Post.php index 50c1ab1efb..e0ac085d8e 100644 --- a/includes/classes/Indexable/Post/Post.php +++ b/includes/classes/Indexable/Post/Post.php @@ -308,6 +308,36 @@ public function get_mapping_name() { return apply_filters( 'ep_post_mapping_version', $mapping_file ); } + /** + * Generate the mapping array + * + * @since 4.0.0 + * @return array + */ + public function generate_mapping() { + $mapping_file = $this->get_mapping_name(); + + /** + * Filter post indexable mapping file + * + * @hook ep_post_mapping_file + * @param {string} $file Path to file + * @return {string} New file path + */ + $mapping = require apply_filters( 'ep_post_mapping_file', __DIR__ . '/../../../mappings/post/' . $mapping_file ); + + /** + * Filter post indexable mapping + * + * @hook ep_post_mapping + * @param {array} $mapping Mapping + * @return {array} New mapping + */ + $mapping = apply_filters( 'ep_post_mapping', $mapping ); + + return $mapping; + } + /** * Determine version of mapping currently on the post index. * @@ -364,25 +394,7 @@ public function determine_mapping_version() { * @return array */ public function put_mapping() { - $mapping_file = $this->get_mapping_name(); - - /** - * Filter post indexable mapping file - * - * @hook ep_post_mapping_file - * @param {string} $file Path to file - * @return {string} New file path - */ - $mapping = require apply_filters( 'ep_post_mapping_file', __DIR__ . '/../../../mappings/post/' . $mapping_file ); - - /** - * Filter post indexable mapping - * - * @hook ep_post_mapping - * @param {array} $mapping Mapping - * @return {array} New mapping - */ - $mapping = apply_filters( 'ep_post_mapping', $mapping ); + $mapping = $this->generate_mapping(); delete_transient( 'ep_post_mapping_version' ); From ed73984c59c5c75e7e419b2a39f3f84d0caa0f4e Mon Sep 17 00:00:00 2001 From: Rebecca Hum <16962021+rebeccahum@users.noreply.github.com> Date: Mon, 7 Mar 2022 11:50:50 -0700 Subject: [PATCH 07/52] Add shim generate_mapping to Indexable class and move put_mapping into it --- includes/classes/Indexable.php | 16 ++++++++++++---- includes/classes/Indexable/Comment/Comment.php | 12 ------------ includes/classes/Indexable/Post/Post.php | 16 ++-------------- includes/classes/Indexable/Term/Term.php | 12 ------------ includes/classes/Indexable/User/User.php | 12 ------------ 5 files changed, 14 insertions(+), 54 deletions(-) diff --git a/includes/classes/Indexable.php b/includes/classes/Indexable.php index 6e1bc23bbe..e27a5d3e5c 100644 --- a/includes/classes/Indexable.php +++ b/includes/classes/Indexable.php @@ -1083,11 +1083,15 @@ public function is_full_reindexing( $blog_id = null ) { } /** - * Must implement a method that handles sending mapping to ES + * Send mapping to Elasticsearch * * @return boolean */ - abstract public function put_mapping(); + public function put_mapping() { + $mapping = $this->generate_mapping(); + + return Elasticsearch::factory()->put_mapping( $this->get_index_name(), $mapping ); + } /** * Must implement a method that given an object ID, returns a formatted Elasticsearch @@ -1109,9 +1113,13 @@ abstract public function prepare_document( $object_id ); abstract public function query_db( $args ); /** - * Must implement a method that generates the mapping array. + * Shim function for backwards-compatibility on custom Indexables. * * @return array */ - abstract public function generate_mapping(); + public function generate_mapping() { + _doing_it_wrong( __METHOD__, 'The Indexable class should not call generate_mapping() directly.', 'ElasticPress 4.0' ); + + return []; + } } diff --git a/includes/classes/Indexable/Comment/Comment.php b/includes/classes/Indexable/Comment/Comment.php index 87bc504525..e4803edd7b 100644 --- a/includes/classes/Indexable/Comment/Comment.php +++ b/includes/classes/Indexable/Comment/Comment.php @@ -800,18 +800,6 @@ public function generate_mapping() { return $mapping; } - /** - * Put mapping for comments - * - * @since 3.6.0 - * @return boolean - */ - public function put_mapping() { - $mapping = $this->generate_mapping(); - - return Elasticsearch::factory()->put_mapping( $this->get_index_name(), $mapping ); - } - /** * Returns indexable comment types * diff --git a/includes/classes/Indexable/Post/Post.php b/includes/classes/Indexable/Post/Post.php index e0ac085d8e..e0f43575f6 100644 --- a/includes/classes/Indexable/Post/Post.php +++ b/includes/classes/Indexable/Post/Post.php @@ -335,6 +335,8 @@ public function generate_mapping() { */ $mapping = apply_filters( 'ep_post_mapping', $mapping ); + delete_transient( 'ep_post_mapping_version' ); + return $mapping; } @@ -387,20 +389,6 @@ public function determine_mapping_version() { return apply_filters( 'ep_post_mapping_version_determined', $version ); } - /** - * Send mapping to Elasticsearch - * - * @since 3.0 - * @return array - */ - public function put_mapping() { - $mapping = $this->generate_mapping(); - - delete_transient( 'ep_post_mapping_version' ); - - return Elasticsearch::factory()->put_mapping( $this->get_index_name(), $mapping ); - } - /** * Prepare a post for syncing * diff --git a/includes/classes/Indexable/Term/Term.php b/includes/classes/Indexable/Term/Term.php index 8621596144..49103a13c5 100644 --- a/includes/classes/Indexable/Term/Term.php +++ b/includes/classes/Indexable/Term/Term.php @@ -622,18 +622,6 @@ public function generate_mapping() { return $mapping; } - /** - * Put mapping for terms - * - * @since 3.1 - * @return boolean - */ - public function put_mapping() { - $mapping = $this->generate_mapping(); - - return Elasticsearch::factory()->put_mapping( $this->get_index_name(), $mapping ); - } - /** * Prepare a term document for indexing * diff --git a/includes/classes/Indexable/User/User.php b/includes/classes/Indexable/User/User.php index 3ceb7afe09..c72b0110f0 100644 --- a/includes/classes/Indexable/User/User.php +++ b/includes/classes/Indexable/User/User.php @@ -794,18 +794,6 @@ public function generate_mapping() { return $mapping; } - /** - * Put mapping for users - * - * @since 3.0 - * @return boolean - */ - public function put_mapping() { - $mapping = $this->generate_mapping(); - - return Elasticsearch::factory()->put_mapping( $this->get_index_name(), $mapping ); - } - /** * Prepare a user document for indexing * From bcc35f62abca08eb85af38ce0c2bf44b7429f2a4 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 14 Mar 2022 08:41:08 -0300 Subject: [PATCH 08/52] Add a --pretty flag to WP-CLI get-mapping + docs --- includes/classes/Command.php | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/includes/classes/Command.php b/includes/classes/Command.php index 249b450dcc..0eea02bdd9 100644 --- a/includes/classes/Command.php +++ b/includes/classes/Command.php @@ -364,11 +364,14 @@ private function put_mapping_helper( $args, $assoc_args ) { * * ## OPTIONS * - * [--index-name] + * [--index-name=] * : The name of the index for which to return the mapping. If not passed, all mappings will be returned * + * [--pretty] + * : Use this flag to render a pretty-printed version of the JSON response. + * * @subcommand get-mapping - * @since 3.6.4 + * @since 3.6.4, `--pretty` introduced in 4.1.0 * @param array $args Positional CLI args. * @param array $assoc_args Associative CLI args. */ @@ -379,9 +382,16 @@ public function get_mapping( $args, $assoc_args ) { $response = Elasticsearch::factory()->remote_request( $path ); - $body = wp_remote_retrieve_body( $response ); + $response_body = wp_remote_retrieve_body( $response ); - WP_CLI::line( $body ); + if ( ! empty( $assoc_args['pretty'] ) ) { + $content_type = wp_remote_retrieve_header( $response, 'Content-Type' ); + if ( preg_match( '/json/', $content_type ) ) { + // Re-encode the JSON to add space formatting + $response_body = wp_json_encode( json_decode( $response_body ), JSON_PRETTY_PRINT ); + } + } + WP_CLI::line( $response_body ); } /** From 69da8decc44b9bd513ffb2b97864b3c3250fbebe Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Tue, 15 Mar 2022 17:33:16 -0300 Subject: [PATCH 09/52] Synonyms: Initial commit for e2e tests --- .../features/search/synonyms.spec.js | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 tests/cypress/integration/features/search/synonyms.spec.js diff --git a/tests/cypress/integration/features/search/synonyms.spec.js b/tests/cypress/integration/features/search/synonyms.spec.js new file mode 100644 index 0000000000..2818f16df8 --- /dev/null +++ b/tests/cypress/integration/features/search/synonyms.spec.js @@ -0,0 +1,58 @@ +describe('Post Search Feature - Synonyms Functionality', () => { + before(() => { + cy.wpCli("wp post list --post_type='ep-synonym' --format=ids", true).then( + (wpCliResponse) => { + if (wpCliResponse.code === 0) { + cy.wpCli(`wp post delete ${wpCliResponse.stdout} --force`, true); + } + }, + ); + cy.wpCli( + "wp post list --s='Testing Synonyms' --ep_integrate='false' --format=ids", + true, + ).then((wpCliResponse) => { + if (wpCliResponse.code === 0) { + cy.wpCli(`wp post delete ${wpCliResponse.stdout} --force`, true); + } + }); + + cy.login(); + + const postsData = [ + { + title: 'Testing Synonyms - Shoes', + }, + { + title: 'Testing Synonyms - Sneakers', + }, + ]; + postsData.forEach((postData) => { + cy.publishPost(postData); + }); + }); + it('Can create, search, and delete synonyms sets', () => { + cy.login(); + + // Add the set + cy.visitAdminPage('admin.php?page=elasticpress-synonyms'); + cy.get('.synonym-sets-editor .synonym__remove').click(); + cy.contains('.synonym-sets-editor .button', 'Add Set').as('addset').click(); + cy.get('.synonym-sets-editor .ep-synonyms__linked-multi-input').type( + 'sneakers{enter}shoes{enter}', + ); + cy.get('#synonym-root .button-primary').click(); + + // Check if it works + cy.visit('/?s=sneakers'); + cy.contains('.site-content article h2', 'Shoes').should('exist'); + + // Remove the set + cy.visitAdminPage('admin.php?page=elasticpress-synonyms'); + cy.get('.synonym-sets-editor .synonym__remove').click(); + cy.get('#synonym-root .button-primary').click(); + + // Check if it works + cy.visit('/?s=sneakers'); + cy.contains('.site-content article h2', 'Shoes').should('not.exist'); + }); +}); From e486debd0c6603bff8e9a90ecfb6ce6ae4053240 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Thu, 17 Mar 2022 15:16:42 -0300 Subject: [PATCH 10/52] Synonyms: tests for alternatives --- .../features/search/synonyms.spec.js | 56 ++++++++++++++----- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/tests/cypress/integration/features/search/synonyms.spec.js b/tests/cypress/integration/features/search/synonyms.spec.js index 2818f16df8..08714df588 100644 --- a/tests/cypress/integration/features/search/synonyms.spec.js +++ b/tests/cypress/integration/features/search/synonyms.spec.js @@ -1,4 +1,7 @@ describe('Post Search Feature - Synonyms Functionality', () => { + const word1 = 'authenticity'; + const word2 = 'credibility'; + before(() => { cy.wpCli("wp post list --post_type='ep-synonym' --format=ids", true).then( (wpCliResponse) => { @@ -20,31 +23,32 @@ describe('Post Search Feature - Synonyms Functionality', () => { const postsData = [ { - title: 'Testing Synonyms - Shoes', + title: `Testing Synonyms - ${word1}`, }, { - title: 'Testing Synonyms - Sneakers', + title: `Testing Synonyms - ${word2}`, }, ]; postsData.forEach((postData) => { cy.publishPost(postData); }); }); - it('Can create, search, and delete synonyms sets', () => { + beforeEach(() => { cy.login(); - + }); + it('Can create, search, and delete synonyms sets', () => { // Add the set cy.visitAdminPage('admin.php?page=elasticpress-synonyms'); - cy.get('.synonym-sets-editor .synonym__remove').click(); - cy.contains('.synonym-sets-editor .button', 'Add Set').as('addset').click(); - cy.get('.synonym-sets-editor .ep-synonyms__linked-multi-input').type( - 'sneakers{enter}shoes{enter}', - ); + cy.get('.synonym-sets-editor').within(() => { + cy.get('.synonym__remove').click(); + cy.contains('.button', 'Add Set').as('addset').click(); + cy.get('.ep-synonyms__linked-multi-input').type(`${word1}{enter}${word2}{enter}`); + }); cy.get('#synonym-root .button-primary').click(); // Check if it works - cy.visit('/?s=sneakers'); - cy.contains('.site-content article h2', 'Shoes').should('exist'); + cy.visit(`/?s=${word2}`); + cy.contains('.site-content article h2', word1).should('exist'); // Remove the set cy.visitAdminPage('admin.php?page=elasticpress-synonyms'); @@ -52,7 +56,33 @@ describe('Post Search Feature - Synonyms Functionality', () => { cy.get('#synonym-root .button-primary').click(); // Check if it works - cy.visit('/?s=sneakers'); - cy.contains('.site-content article h2', 'Shoes').should('not.exist'); + cy.visit(`/?s=${word2}`); + cy.contains('.site-content article h2', word1).should('not.exist'); + }); + it('Can create, search, and delete synonyms alternatives', () => { + // Add the set + cy.visitAdminPage('admin.php?page=elasticpress-synonyms'); + cy.get('.synonym-alternatives-editor').within(() => { + cy.get('.synonym__remove').click(); + cy.contains('.button', 'Add Alternative').as('addset').click(); + cy.get('.ep-synonyms__input').type(word1); + cy.get('.ep-synonyms__linked-multi-input').type(`${word2}{enter}`); + }); + cy.get('#synonym-root .button-primary').click(); + + // Check if it works + cy.visit(`/?s=${word1}`); + cy.contains('.site-content article h2', word2).should('exist'); + cy.visit(`/?s=${word2}`); + cy.contains('.site-content article h2', word1).should('not.exist'); + + // Remove the set + cy.visitAdminPage('admin.php?page=elasticpress-synonyms'); + cy.get('.synonym-alternatives-editor .synonym__remove').click(); + cy.get('#synonym-root .button-primary').click(); + + // Check if it works + cy.visit(`/?s=${word1}`); + cy.contains('.site-content article h2', word2).should('not.exist'); }); }); From 6e63fb297cbafd75ed57f8f032fcefe24d0c2861 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Thu, 17 Mar 2022 15:33:14 -0300 Subject: [PATCH 11/52] Synonyms: Test the Advanced Text Editor --- .../features/search/synonyms.spec.js | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/tests/cypress/integration/features/search/synonyms.spec.js b/tests/cypress/integration/features/search/synonyms.spec.js index 08714df588..5f6c027b2a 100644 --- a/tests/cypress/integration/features/search/synonyms.spec.js +++ b/tests/cypress/integration/features/search/synonyms.spec.js @@ -41,7 +41,7 @@ describe('Post Search Feature - Synonyms Functionality', () => { cy.visitAdminPage('admin.php?page=elasticpress-synonyms'); cy.get('.synonym-sets-editor').within(() => { cy.get('.synonym__remove').click(); - cy.contains('.button', 'Add Set').as('addset').click(); + cy.contains('.button', 'Add Set').click(); cy.get('.ep-synonyms__linked-multi-input').type(`${word1}{enter}${word2}{enter}`); }); cy.get('#synonym-root .button-primary').click(); @@ -64,7 +64,7 @@ describe('Post Search Feature - Synonyms Functionality', () => { cy.visitAdminPage('admin.php?page=elasticpress-synonyms'); cy.get('.synonym-alternatives-editor').within(() => { cy.get('.synonym__remove').click(); - cy.contains('.button', 'Add Alternative').as('addset').click(); + cy.contains('.button', 'Add Alternative').click(); cy.get('.ep-synonyms__input').type(word1); cy.get('.ep-synonyms__linked-multi-input').type(`${word2}{enter}`); }); @@ -85,4 +85,44 @@ describe('Post Search Feature - Synonyms Functionality', () => { cy.visit(`/?s=${word1}`); cy.contains('.site-content article h2', word2).should('not.exist'); }); + it('Can use the Advanced Text Editor', () => { + cy.visitAdminPage('admin.php?page=elasticpress-synonyms'); + cy.contains('.page-title-action', 'Switch to Advanced Text Editor').click(); + cy.get('#ep-synonym-input').clearThenType(`{enter} + {enter} + {enter} + {enter} + {enter} + {enter} + {enter} + {enter} + {enter} + {enter} + {enter} + foo => bar + test => + list,of,words + `); + cy.get('#synonym-root .button-primary').click(); + + cy.contains( + '.synonym-solr-editor__validation', + 'Alternatives must have both a primary term and at least one alternative term.', + ).should('exist'); + + cy.get('#ep-synonym-input').clearThenType('foo => bar{enter}list,of,words'); + cy.get('#synonym-root .button-primary').click(); + cy.contains('.notice-success', 'Successfully updated synonym filter.').should('exist'); + + cy.contains('.page-title-action', 'Switch to Visual Editor').click(); + cy.contains('.synonym-set-editor div', 'list').should('exist'); + cy.contains('.synonym-set-editor div', 'of').should('exist'); + cy.contains('.synonym-set-editor div', 'words').should('exist'); + + cy.get('.synonym-alternative-editor input[value="foo"]').should('exist'); + cy.contains( + '.synonym-alternative-editor .ep-synonyms__linked-multi-input div', + 'bar', + ).should('exist'); + }); }); From 4f54f3b3943aab55062f0a8488f3ae18fd5b2288 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Thu, 17 Mar 2022 15:48:32 -0300 Subject: [PATCH 12/52] Synonyms tests: wp-cli --- .../features/search/synonyms.spec.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/cypress/integration/features/search/synonyms.spec.js b/tests/cypress/integration/features/search/synonyms.spec.js index 5f6c027b2a..b4922b4603 100644 --- a/tests/cypress/integration/features/search/synonyms.spec.js +++ b/tests/cypress/integration/features/search/synonyms.spec.js @@ -125,4 +125,22 @@ describe('Post Search Feature - Synonyms Functionality', () => { 'bar', ).should('exist'); }); + it('Can preserve synonyms if a sync is performed', () => { + cy.visitAdminPage('admin.php?page=elasticpress-synonyms'); + cy.get('.page-title-action').then(($button) => { + if ($button.text() === 'Switch to Advanced Text Editor') { + $button.click(); + } + }); + + cy.get('#ep-synonym-input').clearThenType('foo => bar{enter}list,of,words'); + cy.get('#synonym-root .button-primary').click(); + + cy.wpCli('elasticpress index --setup --yes'); + + cy.visitAdminPage('admin.php?page=elasticpress-synonyms'); + cy.get('#ep-synonym-input') + .should('contain', 'foo => bar') + .should('contain', 'list, of, words'); + }); }); From 9523dc83db82298ff8361f012df510f07630feb2 Mon Sep 17 00:00:00 2001 From: Jacob Peattie Date: Fri, 18 Mar 2022 16:46:31 +1100 Subject: [PATCH 13/52] Refactor weighting JavaScript without jQuery. --- assets/js/weighting.js | 74 +++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/assets/js/weighting.js b/assets/js/weighting.js index 732f5bad65..d107459bdd 100644 --- a/assets/js/weighting.js +++ b/assets/js/weighting.js @@ -1,20 +1,64 @@ -import jQuery from 'jquery'; +/** + * WordPress dependencies. + */ +import domReady from '@wordpress/dom-ready'; -jQuery('.weighting-settings input[type=range]').on('input', function () { - const el = jQuery(this); +/** + * Initialize. + * + * @returns {void} + */ +const init = () => { + /** + * Update the value in the range input label. + * + * @param {Element} el Range input element. + */ + const updateSliderValue = (el) => { + el.labels[0].querySelector('.weighting-value').textContent = el.disabled ? '0' : el.value; + }; - el.prev('label').find('.weighting-value').text(el.val()); -}); + /** + * Handle range slider input. + * + * @param {Event} event Input event. + */ + const onSliderInput = (event) => { + updateSliderValue(event.currentTarget); + }; -jQuery('.weighting-settings .searchable input[type=checkbox]').change(function () { - const $checkbox = jQuery(this); - const $rangeInput = $checkbox.parent().next('.weighting').find('input[type=range]'); - const $weightDisplay = $rangeInput.prev('label').find('.weighting-value'); + /** + * Handle checkbox change. + * + * @param {Event} event Change event. + */ + const onCheckboxChange = (event) => { + const el = event.currentTarget.closest('fieldset').querySelector('input[type="range"]'); - // toggle range input - $rangeInput.prop('disabled', !this.checked); + el.disabled = !event.currentTarget.checked; - // get new weight display value, and set it - const newWeightDisplay = !this.checked ? '0' : $rangeInput.val(); - $weightDisplay.text(newWeightDisplay); -}); + updateSliderValue(el); + }; + + /** + * Bind events. + */ + const sliders = document.querySelectorAll('.weighting-settings input[type=range]'); + + for (const slider of sliders) { + slider.addEventListener('input', onSliderInput); + } + + const checkboxes = document.querySelectorAll( + '.weighting-settings .searchable input[type=checkbox]', + ); + + for (const checkbox of checkboxes) { + checkbox.addEventListener('change', onCheckboxChange); + } +}; + +/** + * Initialize. + */ +domReady(init); From a15ce1e3c61441cc752a182e84d836ea49e9fa5c Mon Sep 17 00:00:00 2001 From: Jacob Peattie Date: Fri, 18 Mar 2022 16:46:58 +1100 Subject: [PATCH 14/52] Refactor notice JavaScript without jQuery. --- assets/js/notice.js | 73 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 15 deletions(-) diff --git a/assets/js/notice.js b/assets/js/notice.js index 035d9c57cc..d7fd55fe49 100644 --- a/assets/js/notice.js +++ b/assets/js/notice.js @@ -1,21 +1,64 @@ -import jQuery from 'jquery'; +/** + * WordPress dependencies. + */ +import apiFetch from '@wordpress/api-fetch'; +import domReady from '@wordpress/dom-ready'; +/** + * Window dependencies. + */ const { epAdmin, ajaxurl } = window; -jQuery('.notice').on('click', '.notice-dismiss', (event) => { - const notice = event.delegateTarget.getAttribute('data-ep-notice'); +/** + * Initialize. + * + * @returns {void} + */ +const init = () => { + const notices = document.querySelectorAll('.notice[data-ep-notice]'); - if (!notice) { - return; + /** + * Handle clicking in an ElasticPress notice. + * + * If the click target is the dismiss button send an AJAX request to remember + * the dismissal. + * + * @param {Event} event Click event. + * @returns {void} + */ + const onClick = (event) => { + /** + * Only proceed if we're clicking dismiss. + */ + if (!event.target.classList.contains('notice-dismiss')) { + return; + } + + /** + * Handler is admin-ajax.php, so the body needs to be form data. + */ + const formData = new FormData(); + + formData.append('action', 'ep_notice_dismiss'); + formData.append('notice', event.currentTarget.dataset.epNotice); + formData.append('nonce', epAdmin.nonce); + + apiFetch({ + method: 'POST', + url: ajaxurl, + body: formData, + }); + }; + + /** + * Bind click events to notices. + */ + for (const notice of notices) { + notice.addEventListener('click', onClick); } +}; - jQuery.ajax({ - method: 'post', - data: { - nonce: epAdmin.nonce, - action: 'ep_notice_dismiss', - notice, - }, - url: ajaxurl, - }); -}); +/** + * Initialize. + */ +domReady(init); From c030cef43be825df7a18a9c67a70510542dc91a8 Mon Sep 17 00:00:00 2001 From: Jacob Peattie Date: Fri, 18 Mar 2022 16:49:11 +1100 Subject: [PATCH 15/52] Refactor network admin script without jQuery. --- assets/css/sites-admin.css | 65 ----------------------- assets/js/sites-admin.js | 102 ++++++++++++++++++++++++++++--------- includes/dashboard.php | 25 +++------ package-lock.json | 25 +++++---- package.json | 4 +- 5 files changed, 104 insertions(+), 117 deletions(-) delete mode 100644 assets/css/sites-admin.css diff --git a/assets/css/sites-admin.css b/assets/css/sites-admin.css deleted file mode 100644 index 8b987d1482..0000000000 --- a/assets/css/sites-admin.css +++ /dev/null @@ -1,65 +0,0 @@ -/* Switch toggle on network admin sites page. */ -.switch { - display: inline-block; - height: 34px; - position: relative; - width: 60px; -} - -.switch input { - height: 0; - opacity: 0; - width: 0; -} - -.slider { - background-color: #ccc; - bottom: 0; - cursor: pointer; - left: 0; - position: absolute; - right: 0; - top: 0; - -webkit-transition: 0.4s; - transition: 0.4s; -} - -.slider::before { - background-color: #fff; - bottom: 4px; - content: ""; - height: 26px; - left: 4px; - position: absolute; - -webkit-transition: 0.4s; - transition: 0.4s; - width: 26px; -} - -input:checked + .slider { - background-color: #2196f3; -} - -input:focus + .slider { - box-shadow: 0 0 1px #2196f3; -} - -input:checked + .slider::before { - -webkit-transform: translateX(26px); - -ms-transform: translateX(26px); - transform: translateX(26px); -} - -/* Rounded sliders */ -.slider.round { - border-radius: 34px; -} - -.slider.round::before { - border-radius: 50%; -} - -.switch-label { - padding-left: 20px; - padding-top: 20px; -} diff --git a/assets/js/sites-admin.js b/assets/js/sites-admin.js index e97da24f3c..0869f0489e 100644 --- a/assets/js/sites-admin.js +++ b/assets/js/sites-admin.js @@ -1,28 +1,82 @@ -import jQuery from 'jquery'; +/** + * WordPress dependencies. + */ +import apiFetch from '@wordpress/api-fetch'; +import { ToggleControl } from '@wordpress/components'; +import domReady from '@wordpress/dom-ready'; +import { render, useState, WPElement } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; -const { epsa } = window; +/** + * Window dependencies. + */ +const { ajaxurl, epsa } = window; -window.addEventListener('load', function () { - const toggles = document.getElementsByClassName('index-toggle'); - for (let i = 0; i < toggles.length; i++) { - toggles[i].addEventListener('click', function () { - const checked = this.checked ? 'yes' : 'no'; - - jQuery.get( - epsa.ajax_url, - { - action: 'ep_site_admin', - blog_id: this.dataset.blogid, - nonce: epsa.nonce, - checked, - }, - () => { - document.getElementById(`switch-label-${this.dataset.blogid}`).innerHTML = this - .checked - ? 'On' - : 'Off'; - }, - ); +/** + * Toggle component. + * + * @param {object} props Component props. + * @param {string} props.blogId Blog ID. + * @param {boolean} props.isDefaultChecked Whether checked by default. + * @returns {WPElement} Toggle component. + */ +const ElasticPressToggleControl = ({ blogId, isDefaultChecked }) => { + const [isChecked, setIsChecked] = useState(isDefaultChecked); + const [isLoading, setIsLoading] = useState(false); + + /** + * Handle toggle change. + * + * @param {boolean} isChecked New checked state. + * @returns {void} + */ + const onChange = async (isChecked) => { + setIsChecked(isChecked); + setIsLoading(true); + + const formData = new FormData(); + + formData.append('action', 'ep_site_admin'); + formData.append('blog_id', blogId); + formData.append('checked', isChecked ? 'yes' : 'no'); + formData.append('nonce', epsa.nonce); + + await apiFetch({ + method: 'POST', + url: ajaxurl, + body: formData, }); + + setIsLoading(false); + }; + + return ( + + ); +}; + +/** + * Initialize. + * + * @returns {void} + */ +const init = () => { + const toggles = document.getElementsByClassName('index-toggle'); + + for (const toggle of toggles) { + render( + , + toggle.parentElement, + ); } -}); +}; + +domReady(init); diff --git a/includes/dashboard.php b/includes/dashboard.php index beb4c02ccf..dbcbd445dc 100644 --- a/includes/dashboard.php +++ b/includes/dashboard.php @@ -436,12 +436,7 @@ function action_wp_ajax_ep_save_feature() { */ function action_admin_enqueue_dashboard_scripts() { if ( isset( get_current_screen()->id ) && strpos( get_current_screen()->id, 'sites-network' ) !== false ) { - wp_enqueue_style( - 'ep_admin_sites_styles', - EP_URL . 'dist/css/sites-admin-styles.min.css', - Utils\get_asset_info( 'sites-admin-styles', 'dependencies' ), - Utils\get_asset_info( 'sites-admin-styles', 'version' ) - ); + wp_enqueue_style( 'wp-components' ); wp_enqueue_script( 'ep_admin_sites_scripts', @@ -825,16 +820,12 @@ function add_blogs_column( $column_name, $blog_id ) { } if ( 'elasticpress' === $column_name ) { $is_indexable = get_blog_option( $blog_id, 'ep_indexable', 'yes' ); - $checked = ( 'yes' === $is_indexable ) ? 'checked' : ''; - echo ''; - echo ''; - if ( 'yes' === $is_indexable ) { - esc_html_e( 'On', 'elasticpress' ); - } else { - esc_html_e( 'Off', 'elasticpress' ); - } - echo ''; + printf( + '', + checked( $is_indexable, 'yes', false ), + esc_attr( $blog_id ) + ); } return $column_name; @@ -844,8 +835,8 @@ function add_blogs_column( $column_name, $blog_id ) { * AJAX callback to update ep_indexable site option. */ function action_wp_ajax_ep_site_admin() { - $blog_id = ( ! empty( $_GET['blog_id'] ) ) ? absint( wp_unslash( $_GET['blog_id'] ) ) : - 1; - $checked = ( ! empty( $_GET['checked'] ) ) ? sanitize_text_field( wp_unslash( $_GET['checked'] ) ) : 'no'; + $blog_id = ( ! empty( $_POST['blog_id'] ) ) ? absint( wp_unslash( $_POST['blog_id'] ) ) : - 1; + $checked = ( ! empty( $_POST['checked'] ) ) ? sanitize_text_field( wp_unslash( $_POST['checked'] ) ) : 'no'; if ( - 1 === $blog_id || ! check_ajax_referer( 'epsa', 'nonce', false ) ) { return wp_send_json_error(); diff --git a/package-lock.json b/package-lock.json index 222c782435..abc2b2b33d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +10,10 @@ "license": "GPL-2.0-or-later", "dependencies": { "@10up/component-tooltip": "^2.0.0", - "@wordpress/api-fetch": "^5.2.6", + "@wordpress/api-fetch": "^5.2.7", "@wordpress/components": "^18.0.0", "@wordpress/date": "^4.2.3", + "@wordpress/dom-ready": "^3.4.1", "@wordpress/element": "^4.0.4", "@wordpress/i18n": "^3.20.0", "@wordpress/icons": "^6.1.1", @@ -4237,12 +4238,13 @@ } }, "node_modules/@wordpress/api-fetch": { - "version": "5.2.6", - "license": "GPL-2.0-or-later", + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@wordpress/api-fetch/-/api-fetch-5.2.7.tgz", + "integrity": "sha512-r8dxJ8ScyKJ9yqHqwybJe2ANAyEZTKcjalp8bdMIZc7lJXgRa5f9kTvulE6hItkSVgBe38u6rx0T7UrlXNrUTw==", "dependencies": { "@babel/runtime": "^7.16.0", "@wordpress/i18n": "^4.2.4", - "@wordpress/url": "^3.3.1" + "@wordpress/url": "^3.3.2" }, "engines": { "node": ">=12" @@ -4436,8 +4438,9 @@ } }, "node_modules/@wordpress/dom-ready": { - "version": "3.3.1", - "license": "GPL-2.0-or-later", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@wordpress/dom-ready/-/dom-ready-3.4.1.tgz", + "integrity": "sha512-w6DVKKpNwX0XUp0Cuh1OyFyGXLabr47k/ecRHKmQkQh9LdjRew7QvxUHYDN1rejRvq5GqcDb7Gnkz4E6hWIo4Q==", "dependencies": { "@babel/runtime": "^7.16.0" }, @@ -22794,11 +22797,13 @@ } }, "@wordpress/api-fetch": { - "version": "5.2.6", + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@wordpress/api-fetch/-/api-fetch-5.2.7.tgz", + "integrity": "sha512-r8dxJ8ScyKJ9yqHqwybJe2ANAyEZTKcjalp8bdMIZc7lJXgRa5f9kTvulE6hItkSVgBe38u6rx0T7UrlXNrUTw==", "requires": { "@babel/runtime": "^7.16.0", "@wordpress/i18n": "^4.2.4", - "@wordpress/url": "^3.3.1" + "@wordpress/url": "^3.3.2" }, "dependencies": { "@wordpress/i18n": { @@ -22936,7 +22941,9 @@ } }, "@wordpress/dom-ready": { - "version": "3.3.1", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@wordpress/dom-ready/-/dom-ready-3.4.1.tgz", + "integrity": "sha512-w6DVKKpNwX0XUp0Cuh1OyFyGXLabr47k/ecRHKmQkQh9LdjRew7QvxUHYDN1rejRvq5GqcDb7Gnkz4E6hWIo4Q==", "requires": { "@babel/runtime": "^7.16.0" } diff --git a/package.json b/package.json index 8e90b195a4..b0000cb7ca 100644 --- a/package.json +++ b/package.json @@ -69,16 +69,16 @@ "ordering-styles.min": "./assets/css/ordering.css", "related-posts-block-styles.min": "./assets/css/related-posts-block.css", "sync-styles.min": "./assets/css/sync.css", - "sites-admin-styles.min": "./assets/css/sites-admin.css", "synonyms-styles.min": "./assets/css/synonyms.css" }, "wpDependencyExternals": true }, "dependencies": { "@10up/component-tooltip": "^2.0.0", - "@wordpress/api-fetch": "^5.2.6", + "@wordpress/api-fetch": "^5.2.7", "@wordpress/components": "^18.0.0", "@wordpress/date": "^4.2.3", + "@wordpress/dom-ready": "^3.4.1", "@wordpress/element": "^4.0.4", "@wordpress/i18n": "^3.20.0", "@wordpress/icons": "^6.1.1", From 23e7e25fb93e6169a15dcc3ee035cb1b31bb13df Mon Sep 17 00:00:00 2001 From: Jacob Peattie Date: Fri, 18 Mar 2022 17:33:39 +1100 Subject: [PATCH 16/52] Refactor setting script without JavaScript. --- assets/js/settings.js | 155 ++++++++++++++++++++-------- includes/partials/settings-page.php | 43 ++++---- 2 files changed, 134 insertions(+), 64 deletions(-) diff --git a/assets/js/settings.js b/assets/js/settings.js index 5fd35919fe..b20ecb8372 100644 --- a/assets/js/settings.js +++ b/assets/js/settings.js @@ -1,46 +1,115 @@ -import jQuery from 'jquery'; - -const $epCredentialsTab = jQuery(document.getElementsByClassName('ep-credentials-tab')); -const $epCredentialsHostLabel = jQuery('.ep-host-row label'); -const $epCredentialsHostLegend = jQuery(document.getElementsByClassName('ep-host-legend')); -const $epCredentialsAdditionalFields = jQuery( - document.getElementsByClassName('ep-additional-fields'), -); -const epHostField = document.getElementById('ep_host'); -const epHost = epHostField ? epHostField.value : null; -let epHostNewValue = ''; - -if (epHostField) { - epHostField.addEventListener('input', (e) => { - epHostNewValue = e.target.value; - }); -} - -$epCredentialsTab.on('click', (e) => { - const epio = e.currentTarget.getAttribute('data-epio') !== null; - const $target = jQuery(e.currentTarget); - const initial = $target.hasClass('initial'); - - e.preventDefault(); - - if (initial && !epHostField.disabled) { - epHostField.value = epHost; - } else { - epHostField.value = epHostNewValue; +/** + * WordPress dependencies. + */ +import domReady from '@wordpress/dom-ready'; +import { __ } from '@wordpress/i18n'; + +/** + * Initialize. + * + * @returns {void} + */ +const init = () => { + const tabs = document.querySelectorAll('.ep-credentials-tab'); + const host = document.getElementById('ep_host'); + const hostLabel = host.labels[0]; + const hostDescription = host.nextElementSibling; + const additionalFields = document.getElementsByClassName('ep-additional-fields'); + + let activeTab = document.querySelector('.nav-tab-active'); + + /** + * Is the current tab the ElasticPress.io tab? + * + * @returns {boolean} Whether the current tab is for ElasticPress.io. + */ + const isEpio = () => { + return 'epio' in activeTab.dataset; + }; + + let epioHost = isEpio() ? host.value : ''; + let esHost = isEpio() ? '' : host.value; + + /** + * Handle input on the host field. + * + * @param {Event} event Input event. + * @returns {void} + */ + const onInput = (event) => { + if (isEpio()) { + epioHost = event.currentTarget.value; + } else { + esHost = event.currentTarget.value; + } + }; + + /** + * Handle clicking on a tab. + * + * @param {Event} event Click event. + * @returns {void} + */ + const onClick = (event) => { + activeTab = event.currentTarget; + + /** + * Set active tab. + */ + for (const tab of tabs) { + tab.classList.toggle('nav-tab-active', tab === activeTab); + } + + /** + * Hide or show additional fields. + */ + for (const additionalField of additionalFields) { + additionalField.classList.toggle('hidden', !isEpio()); + } + + /** + * Update field label. + */ + hostLabel.innerText = isEpio() + ? __('ElasticPress.io Host URL', 'elasticpress') + : __('Elasticsearch Host URL', 'elasticpress'); + + /** + * If the host field is disabled, we're done. + */ + if (host.disabled) { + return; + } + + /** + * Restore field value for the current tab. + */ + host.value = isEpio() ? epioHost : esHost; + + /** + * Update host field description. + */ + hostDescription.innerText = isEpio() + ? __('Plug in your ElasticPress.io server here!', 'elasticpress') + : __('Plug in your Elasticsearch server here!', 'elasticpress'); + }; + + /** + * Bind input event to host field. + */ + if (host) { + host.addEventListener('input', onInput); } - $epCredentialsTab.removeClass('nav-tab-active'); - $target.addClass('nav-tab-active'); - - if (epio) { - $epCredentialsHostLabel.text('ElasticPress.io Host URL'); - $epCredentialsHostLegend.text('Plug in your ElasticPress.io server here!'); - $epCredentialsAdditionalFields.show(); - $epCredentialsAdditionalFields.attr('aria-hidden', 'false'); - } else { - $epCredentialsHostLabel.text('Elasticsearch Host URL'); - $epCredentialsHostLegend.text('Plug in your Elasticsearch server here!'); - $epCredentialsAdditionalFields.hide(); - $epCredentialsAdditionalFields.attr('aria-hidden', 'true'); + /** + * Bind click events to tabs. + */ + for (const tab of tabs) { + tab.addEventListener('click', onClick); } -}); +}; + +/** + * Initialize. + */ +domReady(init); diff --git a/includes/partials/settings-page.php b/includes/partials/settings-page.php index 0ff019beba..4230d4142e 100644 --- a/includes/partials/settings-page.php +++ b/includes/partials/settings-page.php @@ -49,11 +49,11 @@
@@ -86,23 +86,24 @@ * @param {boolean} $show True to show * @return {boolean} New value */ - if ( apply_filters( 'ep_admin_show_host', true ) ) : - ?> - disabled placeholder="http://" type="text" value="" name="ep_host" id="ep_host"> - - - - - - + $show_host = apply_filters( 'ep_admin_show_host', true ); + $disabled = $wpconfig || ! $show_host; + $value = $show_host ? esc_url( $host ) : __( '••••••••••••••••', 'elasticpress' ); + ?> + placeholder="http://" type="text" value="" name="ep_host" id="ep_host"> + + +

+ +

- +

- + @@ -120,9 +121,9 @@ disabled type="text" value="" name="ep_prefix" id="ep_prefix"> - +

- +

@@ -145,9 +146,9 @@ disabled type="text" value="" name="ep_credentials[username]" id="ep_username"> - +

- +

@@ -169,9 +170,9 @@ disabled type="text" value="" name="ep_credentials[token]" id="ep_token"> - +

- +

@@ -199,12 +200,12 @@ ] ); ?> - +

- + From 1b0c95a887fdb6552bd343a39c6822cdac3e0976 Mon Sep 17 00:00:00 2001 From: Jacob Peattie Date: Fri, 18 Mar 2022 17:36:12 +1100 Subject: [PATCH 17/52] Remove jQuery as a dependency and from eslint config. --- .eslintrc.js | 3 --- package-lock.json | 8 -------- package.json | 1 - 3 files changed, 12 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index d9c294f9d3..ceca853366 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,7 +2,4 @@ const defaultEslintrc = require('10up-toolkit/config/.eslintrc'); module.exports = { ...defaultEslintrc, - globals: { - jQuery: true, - }, }; diff --git a/package-lock.json b/package-lock.json index abc2b2b33d..ab79d038d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,6 @@ "chart.js": "^2.9.4", "element-closest": "^3.0.2", "focus-trap-react": "^8.8.2", - "jquery": "^3.6.0", "promise-polyfill": "^8.2.1", "react": "^16.14.0", "react-beautiful-dnd": "^11.0.5", @@ -12814,10 +12813,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jquery": { - "version": "3.6.0", - "license": "MIT" - }, "node_modules/js-tokens": { "version": "4.0.0", "license": "MIT" @@ -28273,9 +28268,6 @@ } } }, - "jquery": { - "version": "3.6.0" - }, "js-tokens": { "version": "4.0.0" }, diff --git a/package.json b/package.json index b0000cb7ca..1fa8158d85 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,6 @@ "chart.js": "^2.9.4", "element-closest": "^3.0.2", "focus-trap-react": "^8.8.2", - "jquery": "^3.6.0", "promise-polyfill": "^8.2.1", "react": "^16.14.0", "react-beautiful-dnd": "^11.0.5", From 04d2d1d8af1cf962c1b085bf2a7bdbfe7afd1cf3 Mon Sep 17 00:00:00 2001 From: Jacob Peattie Date: Fri, 18 Mar 2022 18:42:51 +1100 Subject: [PATCH 18/52] Fix failing test. --- assets/js/sites-admin.js | 1 + tests/cypress/integration/wp-cli.spec.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/js/sites-admin.js b/assets/js/sites-admin.js index 0869f0489e..d6c4a3e91e 100644 --- a/assets/js/sites-admin.js +++ b/assets/js/sites-admin.js @@ -53,6 +53,7 @@ const ElasticPressToggleControl = ({ blogId, isDefaultChecked }) => { return ( { cy.activatePlugin('elasticpress', 'wpCli', 'network'); cy.visitAdminPage('network/sites.php'); - cy.get('.index-toggle').check(); + cy.get('.index-toggle input').click(); }); after(() => { From ad2518dbd3d4a63f38414aec4e4b92c9933a3913 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Fri, 18 Mar 2022 09:02:31 -0300 Subject: [PATCH 19/52] Only use advanced pagination for supported indexables --- includes/classes/IndexHelper.php | 2 +- includes/classes/Indexable.php | 9 +++++++++ includes/classes/Indexable/Post/Post.php | 9 +++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/includes/classes/IndexHelper.php b/includes/classes/IndexHelper.php index 3421c97366..e56bdd2d95 100644 --- a/includes/classes/IndexHelper.php +++ b/includes/classes/IndexHelper.php @@ -482,7 +482,7 @@ protected function get_objects_to_index() { 'per_page' => absint( $per_page ), ]; - if ( 'offset' === $this->index_meta['pagination_method'] ) { + if ( ! $indexable->support_indexing_advanced_pagination || 'offset' === $this->index_meta['pagination_method'] ) { $args['offset'] = $this->index_meta['offset']; } diff --git a/includes/classes/Indexable.php b/includes/classes/Indexable.php index 62c03e00c6..5b9d7514e4 100644 --- a/includes/classes/Indexable.php +++ b/includes/classes/Indexable.php @@ -54,6 +54,15 @@ abstract class Indexable { */ public $query_integration; + /** + * Flag to indicate if the indexable has support for + * `id_range` pagination method during a sync. + * + * @var boolean + * @since 4.0.2 + */ + public $support_indexing_advanced_pagination = false; + /** * Get number of bulk items to index per page * diff --git a/includes/classes/Indexable/Post/Post.php b/includes/classes/Indexable/Post/Post.php index e8344ea8c8..1d3f881825 100644 --- a/includes/classes/Indexable/Post/Post.php +++ b/includes/classes/Indexable/Post/Post.php @@ -32,6 +32,15 @@ class Post extends Indexable { */ public $slug = 'post'; + /** + * Flag to indicate if the indexable has support for + * `id_range` pagination method during a sync. + * + * @var boolean + * @since 4.0.2 + */ + public $support_indexing_advanced_pagination = true; + /** * Create indexable and initialize dependencies * From ca13468db5a68227d1e23cc417e6f32e0c93dd38 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Fri, 18 Mar 2022 09:32:17 -0300 Subject: [PATCH 20/52] WC Orders: properly add ID to fields when searching for digits --- includes/classes/Feature/WooCommerce/WooCommerce.php | 2 +- tests/php/features/TestWooCommerce.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/classes/Feature/WooCommerce/WooCommerce.php b/includes/classes/Feature/WooCommerce/WooCommerce.php index d02318d91a..91ffce7148 100644 --- a/includes/classes/Feature/WooCommerce/WooCommerce.php +++ b/includes/classes/Feature/WooCommerce/WooCommerce.php @@ -392,7 +392,7 @@ public function translate_args( $query ) { // Search query if ( 'shop_order' === $post_type ) { $default_search_fields = array( 'post_title', 'post_content', 'post_excerpt' ); - if ( is_int( $s ) ) { + if ( ctype_digit( $s ) ) { $default_search_fields[] = 'ID'; } $search_fields = $query->get( 'search_fields', $default_search_fields ); diff --git a/tests/php/features/TestWooCommerce.php b/tests/php/features/TestWooCommerce.php index c943e8f69b..35c8974b66 100644 --- a/tests/php/features/TestWooCommerce.php +++ b/tests/php/features/TestWooCommerce.php @@ -172,7 +172,7 @@ public function testSearchShopOrderById() { ElasticPress\Elasticsearch::factory()->refresh_indices(); $args = array( - 's' => $shop_order_id, + 's' => (string) $shop_order_id, 'post_type' => 'shop_order', ); @@ -215,7 +215,7 @@ public function testSearchShopOrderByMetaFieldAndId() { ElasticPress\Elasticsearch::factory()->refresh_indices(); $args = array( - 's' => $shop_order_id_1, + 's' => (string) $shop_order_id_1, 'post_type' => 'shop_order', ); From 807a24383a2120f38d43b690a00f0713728bece5 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 21 Mar 2022 09:57:14 -0300 Subject: [PATCH 21/52] Utilitary command to create zip packages --- .gitignore | 3 +-- bin/build-zip.sh | 10 ++++++++++ package.json | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) create mode 100755 bin/build-zip.sh diff --git a/.gitignore b/.gitignore index 3649138eed..8773d27fb8 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,4 @@ test-coverage-html/ screenshots .DS_Store -/tests/wpa/test-mu-plugins/custom-ep-credentials.php -wpa-elasticsearch.yml \ No newline at end of file +payload \ No newline at end of file diff --git a/bin/build-zip.sh b/bin/build-zip.sh new file mode 100755 index 0000000000..1fe5aefd81 --- /dev/null +++ b/bin/build-zip.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +npm ci +npm run build + +rm -r ./payload + +TMP_DIR="./payload/elasticpress" +mkdir -p $TMP_DIR +rsync -rc --exclude-from=".distignore" --exclude="payload" . "$TMP_DIR/" && cd $TMP_DIR/.. && zip -r "./elasticpress.zip" . diff --git a/package.json b/package.json index 4613f0379f..fb0c178251 100644 --- a/package.json +++ b/package.json @@ -18,13 +18,13 @@ "start": "composer install --ignore-platform-reqs && npm install && npm run build", "build": "10up-toolkit build", "watch": "10up-toolkit start", - "build-release": "npm install && composer install --no-dev -o && npm run build", "lint-release": "npm install && composer install && npm run lint", "lint-js": "10up-toolkit lint-js assets/js tests/cypress", "lint-php": "composer run lint", "format-js": "10up-toolkit format-js assets/js", "lint": "npm run lint-style && npm run lint-js && npm run lint-php", "build:docs": "rm -rf hook_docs && jsdoc -c hookdoc-conf.json elasticpress.php includes", + "build:zip": "./bin/build-zip.sh", "lint-style": "10up-toolkit lint-style", "env": "wp-env", "env:start": "wp-env start && cd bin/es-docker/ && docker-compose up -d", From 1235348cda758eb38d2815716cfebbc3f3c23eff Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 21 Mar 2022 11:15:46 -0300 Subject: [PATCH 22/52] Limit users to the current site Based on 8f41dc92ea7b469a3413e91b2a239154bf8150b4 (#2601) Co-authored-by: Thorsten Frommen --- includes/classes/Indexable/User/User.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/includes/classes/Indexable/User/User.php b/includes/classes/Indexable/User/User.php index 3ceb7afe09..094b453457 100644 --- a/includes/classes/Indexable/User/User.php +++ b/includes/classes/Indexable/User/User.php @@ -173,6 +173,22 @@ public function format_args( $query_vars, $query ) { $use_filters = true; } + + // If there are no specific roles named, make sure the user is a member of the site. + if ( ! $use_filters ) { + $filter['bool']['must'][] = array( + 'exists' => array( + 'field' => 'capabilities.' . $blog_id . '.roles', + ), + ); + $filter['bool']['must_not'][] = array( + 'term' => array( + 'capabilities.' . $blog_id . '.roles' => 0, + ), + ); + + $use_filters = true; + } } } @@ -876,7 +892,7 @@ public function prepare_capabilities( $user_id ) { if ( ! empty( $roles ) ) { $prepared_roles[ (int) $site['blog_id'] ] = [ - 'roles' => array_keys( $roles ), + 'roles' => array_keys( (array) $roles ), ]; } } From e68a69b45fc90c81562dad5a330c8fccfa7ea38a Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 21 Mar 2022 14:45:34 -0300 Subject: [PATCH 23/52] Unit tests --- tests/php/indexables/TestUser.php | 54 +++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tests/php/indexables/TestUser.php b/tests/php/indexables/TestUser.php index 7cfacfb101..464a3e7a0d 100644 --- a/tests/php/indexables/TestUser.php +++ b/tests/php/indexables/TestUser.php @@ -1439,4 +1439,58 @@ public function testIntegrateSearchQueries() { $this->assertTrue( $this->get_feature()->integrate_search_queries( false, $query ) ); } + + /** + * Test users that does not belong to any blog. + * + * @since 4.1.0 + */ + public function testUserSearchLimitedToOneBlog() { + // This user does not belong to any blog. + Functions\create_and_sync_user( + [ + 'user_login' => 'users-and-blogs-1', + 'role' => '', + 'first_name' => 'No Blog', + 'last_name' => 'User', + 'user_email' => 'no-blog@test.com', + 'user_url' => 'http://domain.test', + ] + ); + Functions\create_and_sync_user( + [ + 'user_login' => 'users-and-blogs-2', + 'role' => 'contributor', + 'first_name' => 'Blog', + 'last_name' => 'User', + 'user_email' => 'blog@test.com', + 'user_url' => 'http://domain.test', + ] + ); + + ElasticPress\Elasticsearch::factory()->refresh_indices(); + + // Here `blog_id` defaults to `get_current_blog_id()`. + $query = new \WP_User_Query( [ + 'search' => 'users-and-blogs' + ] ); + + $this->assertTrue( $this->get_feature()->integrate_search_queries( false, $query ) ); + $this->assertEquals( 1, $query->total_users ); + foreach ( $query->results as $user ) { + $this->assertTrue( $user->elasticsearch ); + } + + // Search accross all blogs. + $query = new \WP_User_Query( [ + 'search' => 'users-and-blogs', + 'blog_id' => 0, + ] ); + + $this->assertTrue( $this->get_feature()->integrate_search_queries( false, $query ) ); + $this->assertEquals( 2, $query->total_users ); + foreach ( $query->results as $user ) { + $this->assertTrue( $user->elasticsearch ); + } + } } From eba243b6f7d8d01147f18ed310df5d4a440f20f3 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 21 Mar 2022 15:02:41 -0300 Subject: [PATCH 24/52] e2e tests --- .../integration/indexables/user.spec.js | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tests/cypress/integration/indexables/user.spec.js b/tests/cypress/integration/indexables/user.spec.js index 1e33486084..b4e8c45119 100644 --- a/tests/cypress/integration/indexables/user.spec.js +++ b/tests/cypress/integration/indexables/user.spec.js @@ -104,4 +104,49 @@ describe('User Indexable', () => { expect(text).to.contain('"value": "Doe"'); }); }); + + it('Only returns users from the current blog', () => { + cy.login(); + + cy.maybeEnableFeature('users'); + + const newUserData = { + userLogin: 'nobloguser', + userEmail: 'no-blog-user@example.com', + }; + + cy.wpCli(`wp user get ${newUserData.userLogin} --field=ID`, true).then((wpCliResponse) => { + if (wpCliResponse.code === 0) { + cy.wpCli(`wp user delete ${newUserData.userLogin} --yes --network`); + cy.wpCli('wp elasticpress index --setup --yes'); + } + }); + + // Create a user without a blog. + cy.visitAdminPage('network/user-new.php'); + cy.get('#username').clearThenType(newUserData.userLogin); + cy.get('#email').clearThenType(newUserData.userEmail); + cy.get('#add-user').click(); + cy.get('#message.updated').should('be.visible'); + + // Searching for it should not return anything. + searchUser('nobloguser'); + cy.get('.wp-list-table').should('contain.text', 'No users found.'); + cy.getTotal(0); + cy.get('.ep-query-debug').should('contain.text', 'Query Response Code: HTTP 200'); + + // Add user to the blog. + cy.visitAdminPage('user-new.php'); + cy.get('#adduser-email').clearThenType(newUserData.userLogin); + cy.get('#adduser-noconfirmation').check(); + cy.get('#addusersub').click(); + cy.get('#message.updated').should('be.visible'); + + // Searching for it should return it. + searchUser('nobloguser'); + cy.get('.wp-list-table').should('contain.text', 'nobloguser'); + cy.getTotal(1); + cy.get('.ep-query-debug').should('contain.text', 'Query Response Code: HTTP 200'); + cy.get('.query-results').should('contain.text', '"user_email": "no-blog-user@example.com"'); + }); }); From 995e639430265018f9a4d784acae6477c48a02a6 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 21 Mar 2022 17:56:23 -0300 Subject: [PATCH 25/52] Don't uncheck site to be indexed --- tests/cypress/integration/wp-cli.spec.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/cypress/integration/wp-cli.spec.js b/tests/cypress/integration/wp-cli.spec.js index 328fa53a49..412cab7c5d 100644 --- a/tests/cypress/integration/wp-cli.spec.js +++ b/tests/cypress/integration/wp-cli.spec.js @@ -195,12 +195,7 @@ describe('WP-CLI Commands', () => { context('multisite parameters', () => { before(() => { - cy.login(); - cy.activatePlugin('elasticpress', 'wpCli', 'network'); - - cy.visitAdminPage('network/sites.php'); - cy.get('.index-toggle input').click(); }); after(() => { From 64ac517fe490832eb06e04c7f52bfd2bec5af802 Mon Sep 17 00:00:00 2001 From: Jacob Peattie Date: Tue, 22 Mar 2022 17:59:44 +1100 Subject: [PATCH 26/52] Generate search template as anonymous user. --- .../Feature/InstantResults/InstantResults.php | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/includes/classes/Feature/InstantResults/InstantResults.php b/includes/classes/Feature/InstantResults/InstantResults.php index 63ffb8d54a..beac89c6f1 100644 --- a/includes/classes/Feature/InstantResults/InstantResults.php +++ b/includes/classes/Feature/InstantResults/InstantResults.php @@ -374,10 +374,29 @@ public function get_search_template() { ] ); + /** + * The ID of the current user when generating the Instant Results + * search template. + * + * By default Instant Results sets the current user as anomnymous when + * generating the search template, so that any filters applied to + * queries for logged-in or specific users are not applied to the + * template. This filter supports setting a specific user as the + * current user while the template is generated. + * + * @hook ep_search_template_user_id + * @param int|WP $user_id User ID to use. + * + * @since 4.1.0 + */ + $template_user_id = apply_filters( 'ep_search_template_user_id', 0 ); + $original_user_id = get_current_user_id(); + + wp_set_current_user( $template_user_id ); + add_filter( 'ep_intercept_remote_request', '__return_true' ); add_filter( 'ep_do_intercept_request', [ $this, 'intercept_search_request' ], 10, 4 ); add_filter( 'ep_is_integrated_request', [ $this, 'is_integrated_request' ], 10, 2 ); - add_filter( 'ep_exclude_password_protected_from_search', '__return_true' ); $query = new \WP_Query( array( @@ -392,7 +411,8 @@ public function get_search_template() { remove_filter( 'ep_intercept_remote_request', '__return_true' ); remove_filter( 'ep_do_intercept_request', [ $this, 'intercept_search_request' ], 10 ); remove_filter( 'ep_is_integrated_request', [ $this, 'is_integrated_request' ], 10 ); - remove_filter( 'ep_exclude_password_protected_from_search', '__return_true' ); + + wp_set_current_user( $original_user_id ); return $this->search_template; } From 3658f041891d071740777d47055512a53652e9aa Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Tue, 22 Mar 2022 09:44:12 -0300 Subject: [PATCH 27/52] Small refactor of the code --- includes/classes/Indexable/User/User.php | 42 +++++++++++------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/includes/classes/Indexable/User/User.php b/includes/classes/Indexable/User/User.php index 094b453457..e991146998 100644 --- a/includes/classes/Indexable/User/User.php +++ b/includes/classes/Indexable/User/User.php @@ -129,7 +129,25 @@ public function format_args( $query_vars, $query ) { * Support `role` query arg */ if ( ! empty( $blog_id ) ) { - if ( ! empty( $query_vars['role'] ) ) { + // If a blog id is set, we will apply at least one filter for roles. + $use_filters = true; + + // If there are no specific roles named, make sure the user is a member of the site. + if ( empty( $query_vars['role'] ) && empty( $query_vars['role__in'] ) && empty( $query_vars['role__not_in'] ) ) { + $filter['bool']['must'][] = array( + 'exists' => array( + 'field' => 'capabilities.' . $blog_id . '.roles', + ), + ); + /** + * EP versions prior to 4.1.0 set non-existent roles as `0`. + */ + $filter['bool']['must_not'][] = array( + 'term' => array( + 'capabilities.' . $blog_id . '.roles' => 0, + ), + ); + } elseif ( ! empty( $query_vars['role'] ) ) { $roles = (array) $query_vars['role']; foreach ( $roles as $role ) { @@ -141,8 +159,6 @@ public function format_args( $query_vars, $query ) { ), ); } - - $use_filters = true; } else { if ( ! empty( $query_vars['role__in'] ) ) { $roles_in = (array) $query_vars['role__in']; @@ -154,8 +170,6 @@ public function format_args( $query_vars, $query ) { 'capabilities.' . $blog_id . '.roles' => $roles_in, ), ); - - $use_filters = true; } if ( ! empty( $query_vars['role__not_in'] ) ) { @@ -170,24 +184,6 @@ public function format_args( $query_vars, $query ) { ), ); } - - $use_filters = true; - } - - // If there are no specific roles named, make sure the user is a member of the site. - if ( ! $use_filters ) { - $filter['bool']['must'][] = array( - 'exists' => array( - 'field' => 'capabilities.' . $blog_id . '.roles', - ), - ); - $filter['bool']['must_not'][] = array( - 'term' => array( - 'capabilities.' . $blog_id . '.roles' => 0, - ), - ); - - $use_filters = true; } } } From 2ebb3e1009996b6cbcdea32d67f3be4bb24a0d14 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Tue, 22 Mar 2022 10:33:23 -0300 Subject: [PATCH 28/52] Weighting: truthy values for 'enabled' --- includes/classes/Feature/Search/Weighting.php | 14 ++++--- tests/php/features/TestWeighting.php | 39 +++++++++++++++++++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/includes/classes/Feature/Search/Weighting.php b/includes/classes/Feature/Search/Weighting.php index 95902a8ea4..0d24ec9291 100644 --- a/includes/classes/Feature/Search/Weighting.php +++ b/includes/classes/Feature/Search/Weighting.php @@ -546,15 +546,17 @@ public function post_type_has_fields( $post_type, $args = [] ) { $weights = $weight_config[ $post_type ]; } - $weights = array_diff_key( $weights, $ignore_keys ); + $fields = array_diff_key( $weights, $ignore_keys ); - $found_enabled = array_search( true, array_column( $weights, 'enabled' ), true ); - - if ( false !== $found_enabled ) { - return true; + $found_enabled = false; + foreach ( $fields as $field ) { + if ( filter_var( $field['enabled'], FILTER_VALIDATE_BOOLEAN ) ) { + $found_enabled = true; + break; + } } - return false; + return $found_enabled; } /** diff --git a/tests/php/features/TestWeighting.php b/tests/php/features/TestWeighting.php index 295b5e38ff..3defa972f9 100644 --- a/tests/php/features/TestWeighting.php +++ b/tests/php/features/TestWeighting.php @@ -303,6 +303,45 @@ public function testPostTypeHasFieldsWithCustomConfig() { $this->assertFalse( $this->get_weighting_feature()->post_type_has_fields( 'page' ) ); } + /** + * Check if `post_type_has_fields()` behaves correctly when using the `ep_weighting_configuration_for_search` filter. + * + * @since 4.1.0 + */ + public function testPostTypeHasFieldsWithCustomConfigViaFilter() { + $function = function() { + return [ + 'page' => [], + 'post' => [ + 'post_title' => [ + 'enabled' => 'on', + 'weight' => 1 + ] + ], + 'test' => [ + 'post_title' => [ + 'enabled' => true, + 'weight' => 1 + ] + ], + 'test-2' => [ + 'post_title' => [ + 'enabled' => 10, // This is not considered a "truthy" value + 'weight' => 1 + ] + ], + ]; + }; + add_filter( 'ep_weighting_configuration_for_search', $function ); + + $this->assertTrue( $this->get_weighting_feature()->post_type_has_fields( 'post' ) ); + $this->assertFalse( $this->get_weighting_feature()->post_type_has_fields( 'page' ) ); + $this->assertTrue( $this->get_weighting_feature()->post_type_has_fields( 'test' ) ); + $this->assertFalse( $this->get_weighting_feature()->post_type_has_fields( 'test-2' ) ); + + remove_filter( 'ep_weighting_configuration_for_search', $function ); + } + public function testDoWeightingWithQueryContainsSearchFields() { // Test search fields are set on the query. $this->assertSame( ['do', 'nothing'], $this->get_weighting_feature()->do_weighting( ['do', 'nothing'], ['search_fields' => [ 'post_title' ] ] ) ); From bc6e5fdc4bf463be7a2cf7127b7ff088d4e13530 Mon Sep 17 00:00:00 2001 From: Darshan Sawardekar Date: Thu, 24 Mar 2022 18:48:29 +0530 Subject: [PATCH 29/52] Shows a sync error if the server returned invalid json --- assets/js/sync.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/assets/js/sync.js b/assets/js/sync.js index a0389af091..62da139d92 100644 --- a/assets/js/sync.js +++ b/assets/js/sync.js @@ -303,6 +303,25 @@ function updateSyncDash() { if (isSyncing) { progressBar.classList.remove('ep-sync-box__progressbar_complete'); + } else if (syncStatus === 'error') { + const progressInfoElement = activeBox.querySelector('.ep-sync-box__progress-info'); + + progressInfoElement.innerText = __('Sync failed', 'elasticpress'); + + updateStartDateTime(new Date()); + updateDisabledAttribute(deleteAndSyncButton, false); + updateDisabledAttribute(syncButton, false); + + hidePauseStopButtons(); + hideResumeButton(); + + syncButton.style.display = 'flex'; + + const learnMoreLink = activeBox.querySelector('.ep-sync-box__learn-more-link'); + + if (learnMoreLink?.style) { + learnMoreLink.style.display = 'block'; + } } else if (syncStatus === 'interrupt') { const progressInfoElement = activeBox.querySelector('.ep-sync-box__progress-info'); @@ -662,6 +681,13 @@ function sync(putMapping = false) { sync(putMapping); }) .catch((response) => { + if (response && response.code === 'invalid_json') { + syncStatus = 'error'; + updateSyncDash(); + cancelSync(); + addErrorToOutput(response.message); + } + if ( response && response.status && From 7c6c817bd8c8d23f27f8baa91f0fe102dd2dd83e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Mar 2022 19:07:13 +0000 Subject: [PATCH 30/52] Bump node-forge from 1.2.1 to 1.3.0 Bumps [node-forge](https://github.com/digitalbazaar/forge) from 1.2.1 to 1.3.0. - [Release notes](https://github.com/digitalbazaar/forge/releases) - [Changelog](https://github.com/digitalbazaar/forge/blob/main/CHANGELOG.md) - [Commits](https://github.com/digitalbazaar/forge/compare/v1.2.1...v1.3.0) --- updated-dependencies: - dependency-name: node-forge dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e3c3d32da5..e95713ad55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14041,9 +14041,10 @@ } }, "node_modules/node-forge": { - "version": "1.2.1", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz", + "integrity": "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==", "dev": true, - "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" } @@ -29045,7 +29046,9 @@ } }, "node-forge": { - "version": "1.2.1", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz", + "integrity": "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==", "dev": true }, "node-int64": { From 4b0961e3944dfd95098e54ae41927f2e7a6fe294 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Fri, 25 Mar 2022 08:50:46 -0300 Subject: [PATCH 31/52] Automatic update using npm audit --fix --- package-lock.json | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index e95713ad55..07e20aba16 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4493,9 +4493,10 @@ } }, "node_modules/@wordpress/env": { - "version": "4.2.2", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@wordpress/env/-/env-4.4.0.tgz", + "integrity": "sha512-qRkomr/URmfLrgVKnq+54l4+J0l6ZXJYKhUnfBbAxGIQKM73vQNFJyEiI2gfEaWcRYtlgPolYtIuwoy/QPz31g==", "dev": true, - "license": "GPL-2.0-or-later", "dependencies": { "chalk": "^4.0.0", "copy-dir": "^1.3.0", @@ -13920,8 +13921,9 @@ } }, "node_modules/minimist": { - "version": "1.2.5", - "license": "MIT" + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "node_modules/minimist-options": { "version": "4.1.0", @@ -22979,7 +22981,9 @@ } }, "@wordpress/env": { - "version": "4.2.2", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@wordpress/env/-/env-4.4.0.tgz", + "integrity": "sha512-qRkomr/URmfLrgVKnq+54l4+J0l6ZXJYKhUnfBbAxGIQKM73vQNFJyEiI2gfEaWcRYtlgPolYtIuwoy/QPz31g==", "dev": true, "requires": { "chalk": "^4.0.0", @@ -28968,7 +28972,9 @@ } }, "minimist": { - "version": "1.2.5" + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "minimist-options": { "version": "4.1.0", From a2f0cf4484bc7983a839e23db5e23fd6c88ac6aa Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Fri, 25 Mar 2022 10:49:12 -0300 Subject: [PATCH 32/52] Update `@since` tags --- includes/classes/Indexable.php | 1 + includes/classes/Indexable/Comment/Comment.php | 2 +- includes/classes/Indexable/Post/Post.php | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/includes/classes/Indexable.php b/includes/classes/Indexable.php index e27a5d3e5c..ff2e3fb521 100644 --- a/includes/classes/Indexable.php +++ b/includes/classes/Indexable.php @@ -1115,6 +1115,7 @@ abstract public function query_db( $args ); /** * Shim function for backwards-compatibility on custom Indexables. * + * @since 4.1.0 * @return array */ public function generate_mapping() { diff --git a/includes/classes/Indexable/Comment/Comment.php b/includes/classes/Indexable/Comment/Comment.php index e4803edd7b..eb5312e6e5 100644 --- a/includes/classes/Indexable/Comment/Comment.php +++ b/includes/classes/Indexable/Comment/Comment.php @@ -752,7 +752,7 @@ public function format_args( $query_vars ) { /** * Generate the mapping array * - * @since 4.0.0 + * @since 4.1.0 * @return array */ public function generate_mapping() { diff --git a/includes/classes/Indexable/Post/Post.php b/includes/classes/Indexable/Post/Post.php index e0f43575f6..62ff2b2b95 100644 --- a/includes/classes/Indexable/Post/Post.php +++ b/includes/classes/Indexable/Post/Post.php @@ -311,7 +311,7 @@ public function get_mapping_name() { /** * Generate the mapping array * - * @since 4.0.0 + * @since 4.1.0 * @return array */ public function generate_mapping() { From 42a62f58f05e60bc32e9234094182ef47120a83c Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Fri, 25 Mar 2022 10:57:11 -0300 Subject: [PATCH 33/52] Update tests and `@since` tag --- includes/classes/Feature/RelatedPosts/RelatedPosts.php | 2 +- tests/php/features/TestRelatedPosts.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/includes/classes/Feature/RelatedPosts/RelatedPosts.php b/includes/classes/Feature/RelatedPosts/RelatedPosts.php index fb8547de3e..d59f32e77a 100644 --- a/includes/classes/Feature/RelatedPosts/RelatedPosts.php +++ b/includes/classes/Feature/RelatedPosts/RelatedPosts.php @@ -114,7 +114,7 @@ public function formatted_args( $formatted_args, $args ) { * * @param int $post_id Post ID * @param int $return Return code - * @since 3.4 + * @since 4.1.0 * @return WP_Query */ public function get_related_query( $post_id, $return = 5 ) { diff --git a/tests/php/features/TestRelatedPosts.php b/tests/php/features/TestRelatedPosts.php index 903f509d3a..b84aa7c0de 100644 --- a/tests/php/features/TestRelatedPosts.php +++ b/tests/php/features/TestRelatedPosts.php @@ -114,7 +114,8 @@ public function testGetRelatedQuery() { $query = ElasticPress\Features::factory()->get_registered_feature( 'related_posts' )->get_related_query( $post_id, 1 ); - $this->assertTrue( ! empty( $query->posts ) ); + $this->assertTrue( $query->elasticsearch_success ); + $this->assertNotEmpty( $query->posts ); $this->assertEquals( '1', $query->post_count ); $this->assertEquals( $related_post_title, $query->posts[0]->post_title ); } From df327f45a3662a592aaccbc91b15f0ae26b587bb Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Fri, 25 Mar 2022 11:14:42 -0300 Subject: [PATCH 34/52] Update hook doc --- includes/classes/Feature/InstantResults/InstantResults.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/classes/Feature/InstantResults/InstantResults.php b/includes/classes/Feature/InstantResults/InstantResults.php index beac89c6f1..de90e026d1 100644 --- a/includes/classes/Feature/InstantResults/InstantResults.php +++ b/includes/classes/Feature/InstantResults/InstantResults.php @@ -385,8 +385,8 @@ public function get_search_template() { * current user while the template is generated. * * @hook ep_search_template_user_id - * @param int|WP $user_id User ID to use. - * + * @param {int} $user_id User ID to use. + * @return {int} New user ID to use. * @since 4.1.0 */ $template_user_id = apply_filters( 'ep_search_template_user_id', 0 ); From 87705ffc37ab404149d32e5e9ee9e6c7fca7ab59 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Fri, 25 Mar 2022 14:48:47 -0300 Subject: [PATCH 35/52] Add --pretty to other commands --- includes/classes/Command.php | 75 +++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 26 deletions(-) diff --git a/includes/classes/Command.php b/includes/classes/Command.php index a9c4e2192c..36da049c0d 100644 --- a/includes/classes/Command.php +++ b/includes/classes/Command.php @@ -382,23 +382,17 @@ public function get_mapping( $args, $assoc_args ) { $response = Elasticsearch::factory()->remote_request( $path ); - $response_body = wp_remote_retrieve_body( $response ); - - if ( ! empty( $assoc_args['pretty'] ) ) { - $content_type = wp_remote_retrieve_header( $response, 'Content-Type' ); - if ( preg_match( '/json/', $content_type ) ) { - // Re-encode the JSON to add space formatting - $response_body = wp_json_encode( json_decode( $response_body ), JSON_PRETTY_PRINT ); - } - } - WP_CLI::line( $response_body ); + $this->print_json_response( $response, ! empty( $assoc_args['pretty'] ) ); } /** * Return all indexes from the cluster as a JSON object. * + * [--pretty] + * : Use this flag to render a pretty-printed version of the JSON response. + * * @subcommand get-cluster-indexes - * @since 3.2 + * @since 3.2, `--pretty` introduced in 4.1.0 * @param array $args Positional CLI args. * @param array $assoc_args Associative CLI args. */ @@ -407,23 +401,26 @@ public function get_cluster_indexes( $args, $assoc_args ) { $response = Elasticsearch::factory()->remote_request( $path ); - $body = wp_remote_retrieve_body( $response ); - - WP_CLI::line( $body ); + $this->print_json_response( $response, ! empty( $assoc_args['pretty'] ) ); } /** * Return all index names as a JSON object. * + * [--pretty] + * : Use this flag to render a pretty-printed version of the JSON response. + * * @subcommand get-indexes - * @since 3.2 + * @since 3.2, `--pretty` introduced in 4.1.0 * @param array $args Positional CLI args. * @param array $assoc_args Associative CLI args. */ public function get_indexes( $args, $assoc_args ) { $index_names = $this->get_index_names(); - WP_CLI::line( wp_json_encode( $index_names ) ); + $flag = ( ! empty( $assoc_args['pretty'] ) ) ? JSON_PRETTY_PRINT : null; + + WP_CLI::line( wp_json_encode( $index_names, $flag ) ); } /** @@ -995,7 +992,11 @@ public function clear_index() { * items_indexed | integer | Total number of items indexed * total_items | integer | Total number of items indexed or -1 if not yet determined * + * [--pretty] + * : Use this flag to render a pretty-printed version of the JSON response. + * * @subcommand get-indexing-status + * @since 3.5.1, `--pretty` introduced in 4.1.0 */ public function get_indexing_status() { $indexing_status = Utils\get_indexing_status(); @@ -1009,7 +1010,9 @@ public function get_indexing_status() { ]; } - WP_CLI::line( wp_json_encode( $indexing_status ) ); + $flag = ( ! empty( $assoc_args['pretty'] ) ) ? JSON_PRETTY_PRINT : null; + + WP_CLI::line( wp_json_encode( $indexing_status, $flag ) ); } /** @@ -1020,8 +1023,11 @@ public function get_indexing_status() { * [--clear] * : Clear the `ep_last_cli_index` option. * - * @subcommand get-last-cli-index + * [--pretty] + * : Use this flag to render a pretty-printed version of the JSON response. * + * @subcommand get-last-cli-index + * @since 3.5.1, `--pretty` introduced in 4.1.0 * @param array $args Positional CLI args. * @param array $assoc_args Associative CLI args. */ @@ -1033,8 +1039,9 @@ public function get_last_cli_index( $args, $assoc_args ) { delete_site_option( 'ep_last_cli_index' ); } - WP_CLI::line( wp_json_encode( $last_sync ) ); + $flag = ( ! empty( $assoc_args['pretty'] ) ) ? JSON_PRETTY_PRINT : null; + WP_CLI::line( wp_json_encode( $last_sync, $flag ) ); } @@ -1371,9 +1378,12 @@ public function call_ep_cli_put_mapping( $index_meta, $indexable ) { * [--debug-http-request] * : Enable debugging * + * [--pretty] + * : Use this flag to render a pretty-printed version of the JSON response. + * * @subcommand request * - * @since 3.6.6 + * @since 3.6.6, `--pretty` introduced in 4.1.0 * * @param array $args Positional CLI args. * @param array $assoc_args Associative CLI args. @@ -1441,13 +1451,26 @@ function ( $response, $context, $transport, $request_args, $url ) { WP_CLI::error( $response->get_error_message() ); } + $this->print_json_response( $response, ! empty( $assoc_args['pretty'] ) ); + } + + /** + * Print an HTTP response. + * + * @since 4.1.0 + * @param array $response HTTP Response. + * @param boolean $pretty Whether the JSON response should be formatted or not. + */ + protected function print_json_response( $response, $pretty ) { $response_body = wp_remote_retrieve_body( $response ); - $content_type = wp_remote_retrieve_header( $response, 'Content-Type' ); - if ( preg_match( '/json/', $content_type ) ) { - // Re-encode the JSON to add space formatting - $response_body = wp_json_encode( json_decode( $response_body ), JSON_PRETTY_PRINT ); - } - WP_CLI::log( $response_body ); + if ( $pretty ) { + $content_type = wp_remote_retrieve_header( $response, 'Content-Type' ); + if ( preg_match( '/json/', $content_type ) ) { + // Re-encode the JSON to add space formatting + $response_body = wp_json_encode( json_decode( $response_body ), JSON_PRETTY_PRINT ); + } + } + WP_CLI::line( $response_body ); } } From 235fd7438a11cea97a5f9fde87cac5e2de422f03 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Sun, 27 Mar 2022 18:54:30 -0300 Subject: [PATCH 36/52] Add support for multiple aggregations --- includes/classes/Indexable/Post/Post.php | 56 +++++++++++++++++------- tests/php/indexables/TestPost.php | 32 ++++++++++++++ 2 files changed, 71 insertions(+), 17 deletions(-) diff --git a/includes/classes/Indexable/Post/Post.php b/includes/classes/Indexable/Post/Post.php index aabd88bbc1..9b34e8a974 100644 --- a/includes/classes/Indexable/Post/Post.php +++ b/includes/classes/Indexable/Post/Post.php @@ -1800,24 +1800,15 @@ public function format_args( $args, $wp_query ) { /** * Aggregations */ - if ( isset( $args['aggs'] ) && ! empty( $args['aggs']['aggs'] ) ) { - $agg_obj = $args['aggs']; - - // Add a name to the aggregation if it was passed through - if ( ! empty( $agg_obj['name'] ) ) { - $agg_name = $agg_obj['name']; - } else { - $agg_name = 'aggregation_name'; - } - - // Add/use the filter if warranted - if ( isset( $agg_obj['use-filter'] ) && false !== $agg_obj['use-filter'] && $use_filters ) { - - // If a filter is being used, use it on the aggregation as well to receive relevant information to the query - $formatted_args['aggs'][ $agg_name ]['filter'] = $filter; - $formatted_args['aggs'][ $agg_name ]['aggs'] = $agg_obj['aggs']; + if ( isset( $args['aggs'] ) ) { + // An array of aggregations. + if ( isset( $args['aggs'][0] ) ) { + foreach ( $args['aggs'] as $agg ) { + $formatted_args = $this->apply_aggregations( $formatted_args, $agg, $use_filters, $filter ); + } } else { - $formatted_args['aggs'][ $agg_name ] = $agg_obj['aggs']; + // Single aggregation. + $formatted_args = $this->apply_aggregations( $formatted_args, $args['aggs'], $use_filters, $filter ); } } @@ -2224,4 +2215,35 @@ protected function determine_mapping_version_based_on_existing( $mapping, $index return 'unknown'; } + + /** + * Given ES args, add aggregations to it. + * + * @since 4.1.0 + * @param array $formatted_args Formatted Elasticsearch query. + * @param array $agg Aggregation data. + * @param boolean $use_filters Whether filters should be used or not. + * @param array $filter Filters defined so far. + * @return array Formatted Elasticsearch query with the aggregation added. + */ + protected function apply_aggregations( $formatted_args, $agg, $use_filters, $filter ) { + if ( empty( $agg['aggs'] ) ) { + return $formatted_args; + } + + // Add a name to the aggregation if it was passed through + $agg_name = ( ! empty( $agg['name'] ) ) ? $agg['name'] : 'aggregation_name'; + + // Add/use the filter if warranted + if ( isset( $agg['use-filter'] ) && false !== $agg['use-filter'] && $use_filters ) { + + // If a filter is being used, use it on the aggregation as well to receive relevant information to the query + $formatted_args['aggs'][ $agg_name ]['filter'] = $filter; + $formatted_args['aggs'][ $agg_name ]['aggs'] = $agg['aggs']; + } else { + $formatted_args['aggs'][ $agg_name ] = $agg['aggs']; + } + + return $formatted_args; + } } diff --git a/tests/php/indexables/TestPost.php b/tests/php/indexables/TestPost.php index d936c80c16..691bc30010 100644 --- a/tests/php/indexables/TestPost.php +++ b/tests/php/indexables/TestPost.php @@ -5939,6 +5939,38 @@ public function testFormatArgsAggs() { ); $this->assertSame( 'terms.post_type', $args['aggs']['aggregation_name']['terms']['field'] ); + + // Multiple aggs. + $args = $post->format_args( + [ + // Triggers $use_filter to be true. + 'post_status' => 'publish', + + 'aggs' => [ + [ + 'name' => 'taxonomies', + 'use-filter' => true, + 'aggs' => [ + 'terms' => [ + 'field' => 'terms.category.slug', + ], + ], + ], + [ + 'aggs' => [ + 'terms' => [ + 'field' => 'terms.post_type', + ], + ], + ] + ], + ], + new \WP_Query() + ); + + $this->assertSame( 'publish', $args['aggs']['taxonomies']['filter']['bool']['must'][1]['term']['post_status'] ); + $this->assertSame( 'terms.category.slug', $args['aggs']['taxonomies']['aggs']['terms']['field'] ); + $this->assertSame( 'terms.post_type', $args['aggs']['aggregation_name']['terms']['field'] ); } /** From 8a23e2164fc3589ef6919d8e1362e7d2af25f6f3 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 28 Mar 2022 10:43:14 -0300 Subject: [PATCH 37/52] Partial update of changelog and credits --- CHANGELOG.md | 20 ++++++++++++++++++++ CREDITS.md | 3 +++ 2 files changed, 23 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 627e0dd379..4e4f5c1d19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,26 @@ All notable changes to this project will be documented in this file, per [the Ke ## [Unreleased] +### Added +- Utility command to create zip packages: `npm run build:zip`. Props [@felipeelia](https://github.com/felipeelia) via [#2669](https://github.com/10up/ElasticPress/pull/2669). +- E2e tests for the Synonyms feature. Props [@felipeelia](https://github.com/felipeelia) via [#2655](https://github.com/10up/ElasticPress/pull/2655). +- `generate_mapping()` to post and comment indexables. Props [@rebeccahum](https://github.com/rebeccahum) via [#2637](https://github.com/10up/ElasticPress/pull/2637). +- `get_related_query()` to the `RelatedPosts` class. Props [@ayebare](https://github.com/ayebare) via [#1653](https://github.com/10up/ElasticPress/pull/1653). + +### Changed +- Refactored remaining admin scripts to remove jQuery as a dependency. Props [@JakePT](https://github.com/JakePT) via [#2664](https://github.com/10up/ElasticPress/pull/2664). +- Generate Instant Results' search template as an anonymous user by default. Props [@JakePT](https://github.com/JakePT) via [#2672](https://github.com/10up/ElasticPress/pull/2672). + +### Fixed +- PHP warning Trying to access array offset on value of type int in `get_index_names()`. Props [@sun](https://github.com/sun) via [#2580](https://github.com/10up/ElasticPress/pull/2580). +- Searches by WooCommerce Order ID. Props [@felipeelia](https://github.com/felipeelia) via [#2666](https://github.com/10up/ElasticPress/pull/2666). +- Display and error message if syncing failed due to invalid JSON response from the server. Props [@dsawardekar](https://github.com/dsawardekar) via [#2677](https://github.com/10up/ElasticPress/pull/2677). +- Better compatibility with PHP 8.1 by replacing the deprecated `FILTER_SANITIZE_STRING`. Props [@sjinks](https://github.com/sjinks) via [#2529](https://github.com/10up/ElasticPress/pull/2529). + +## Security +- Bumped `node-forge` from 1.2.1 to 1.3.0. Props [@dependabot](https://github.com/dependabot) via [#2678](https://github.com/10up/ElasticPress/pull/2678). +- Bumped` @wordpress/env` from 4.2.2 to 4.4.0, and `minimist` from 1.2.5 to 1.2.6. Props [@felipeelia](https://github.com/felipeelia) via [#2680](https://github.com/10up/ElasticPress/pull/2680). + ## [4.0.1] - 2022-03-16 **This is a security release affecting users running ElasticPress 4.0 with both the WooCommerce and Protected Content Features activated. Please update to the latest version of ElasticPress if the WooCommerce and Protected Content features are activated and you're using ElasticPress 4.0.** diff --git a/CREDITS.md b/CREDITS.md index 98b3a7c76b..ecb9ae66f4 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -171,6 +171,9 @@ Thank you to all the people who have already contributed to this repository via [@beazuadmin](https://github.com/beazuadmin), [Jonathan Netek](https://www.linkedin.com/in/jonathan-netek/), [Tom Burtless (@tomburtless)](https://github.com/tomburtless), +[Daniel Kudwien (@sun)](https://github.com/sun), +[Darshan Sawardekar (@dsawardekar)](https://github.com/dsawardekar), +[Ayebare (@ayebare)](https://github.com/ayebare), and [@qazaqstan2025](https://github.com/qazaqstan2025). From 5defa4d25f6368dcc8f06b35b6422388a918e647 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 28 Mar 2022 14:04:48 -0300 Subject: [PATCH 38/52] IndexHelper: handle the output of an array of messages --- includes/classes/IndexHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/classes/IndexHelper.php b/includes/classes/IndexHelper.php index 3421c97366..9bb9bd0373 100644 --- a/includes/classes/IndexHelper.php +++ b/includes/classes/IndexHelper.php @@ -889,7 +889,7 @@ protected function output( $message_text, $type = 'info', $context = '' ) { } $message = [ - 'message' => $message_text, + 'message' => ( is_array( $message_text ) ) ? implode( "\n", $message_text ) : $message_text, 'index_meta' => $this->index_meta, 'totals' => $totals ?? [], 'status' => $type, From a827ce812279fe2cbe94239b3a345a1ec34143e6 Mon Sep 17 00:00:00 2001 From: Rebecca Hum <16962021+rebeccahum@users.noreply.github.com> Date: Mon, 28 Mar 2022 11:08:46 -0600 Subject: [PATCH 39/52] get_term_tree(): fix infinite loop for non-existent parent --- includes/utils.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/utils.php b/includes/utils.php index 3153269a7d..f48ddd6100 100644 --- a/includes/utils.php +++ b/includes/utils.php @@ -353,7 +353,7 @@ function get_term_tree( $all_terms, $orderby = 'count', $order = 'desc', $flat = $terms_map[ $term->term_id ] = $term; } - if ( empty( $term->parent ) ) { + if ( empty( $term->parent ) || ( ! empty( $term->parent ) && ! term_exists( $term->parent, $term->taxonomy ) ) ) { $term->level = 0; if ( empty( $orderby ) ) { From 849a60f97c0b26a029d81ce1b86ade09e500e227 Mon Sep 17 00:00:00 2001 From: Rebecca Hum <16962021+rebeccahum@users.noreply.github.com> Date: Mon, 28 Mar 2022 11:31:32 -0600 Subject: [PATCH 40/52] Remove first condition on second check --- includes/utils.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/utils.php b/includes/utils.php index f48ddd6100..c40452f992 100644 --- a/includes/utils.php +++ b/includes/utils.php @@ -353,7 +353,7 @@ function get_term_tree( $all_terms, $orderby = 'count', $order = 'desc', $flat = $terms_map[ $term->term_id ] = $term; } - if ( empty( $term->parent ) || ( ! empty( $term->parent ) && ! term_exists( $term->parent, $term->taxonomy ) ) ) { + if ( empty( $term->parent ) || ! term_exists( $term->parent, $term->taxonomy ) ) { $term->level = 0; if ( empty( $orderby ) ) { From 54d4ad0b26c72d578e0706299432f6c607a979ca Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 28 Mar 2022 14:50:51 -0300 Subject: [PATCH 41/52] Add the `pretty_json_encode` method --- includes/classes/Command.php | 45 ++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/includes/classes/Command.php b/includes/classes/Command.php index 36da049c0d..928758ac21 100644 --- a/includes/classes/Command.php +++ b/includes/classes/Command.php @@ -418,9 +418,7 @@ public function get_cluster_indexes( $args, $assoc_args ) { public function get_indexes( $args, $assoc_args ) { $index_names = $this->get_index_names(); - $flag = ( ! empty( $assoc_args['pretty'] ) ) ? JSON_PRETTY_PRINT : null; - - WP_CLI::line( wp_json_encode( $index_names, $flag ) ); + $this->pretty_json_encode( $index_names, ! empty( $assoc_args['pretty'] ) ); } /** @@ -997,8 +995,10 @@ public function clear_index() { * * @subcommand get-indexing-status * @since 3.5.1, `--pretty` introduced in 4.1.0 + * @param array $args Positional CLI args. + * @param array $assoc_args Associative CLI args. */ - public function get_indexing_status() { + public function get_indexing_status( $args, $assoc_args ) { $indexing_status = Utils\get_indexing_status(); if ( empty( $indexing_status ) ) { @@ -1010,9 +1010,7 @@ public function get_indexing_status() { ]; } - $flag = ( ! empty( $assoc_args['pretty'] ) ) ? JSON_PRETTY_PRINT : null; - - WP_CLI::line( wp_json_encode( $indexing_status, $flag ) ); + $this->pretty_json_encode( $indexing_status, ! empty( $assoc_args['pretty'] ) ); } /** @@ -1039,9 +1037,7 @@ public function get_last_cli_index( $args, $assoc_args ) { delete_site_option( 'ep_last_cli_index' ); } - $flag = ( ! empty( $assoc_args['pretty'] ) ) ? JSON_PRETTY_PRINT : null; - - WP_CLI::line( wp_json_encode( $last_sync, $flag ) ); + $this->pretty_json_encode( $last_sync, ! empty( $assoc_args['pretty'] ) ); } @@ -1464,13 +1460,28 @@ function ( $response, $context, $transport, $request_args, $url ) { protected function print_json_response( $response, $pretty ) { $response_body = wp_remote_retrieve_body( $response ); - if ( $pretty ) { - $content_type = wp_remote_retrieve_header( $response, 'Content-Type' ); - if ( preg_match( '/json/', $content_type ) ) { - // Re-encode the JSON to add space formatting - $response_body = wp_json_encode( json_decode( $response_body ), JSON_PRETTY_PRINT ); - } + $content_type = wp_remote_retrieve_header( $response, 'Content-Type' ); + + if ( ! $pretty || ! preg_match( '/json/', $content_type ) ) { + WP_CLI::line( $response_body ); + return; } - WP_CLI::line( $response_body ); + + // Re-encode the JSON to add space formatting + $response_body_obj = json_decode( $response_body ); + + $this->pretty_json_encode( $response_body_obj, JSON_PRETTY_PRINT ); + } + + /** + * Output a JSON object. Conditionally format it before doing so. + * + * @since 4.1.0 + * @param array $json_obj The JSON object or array. + * @param boolean $pretty_print_flag Whether it should or not be formatted. + */ + protected function pretty_json_encode( $json_obj, $pretty_print_flag ) { + $flag = $pretty_print_flag ? JSON_PRETTY_PRINT : null; + WP_CLI::line( wp_json_encode( $json_obj, $flag ) ); } } From 64457360c563f8fb40e4cff34c3f1d23965eebb8 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 28 Mar 2022 15:15:50 -0300 Subject: [PATCH 42/52] Adjust `@since` tags --- includes/classes/Indexable.php | 2 +- includes/classes/Indexable/Post/Post.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/classes/Indexable.php b/includes/classes/Indexable.php index adb07f95fd..3f9f882322 100644 --- a/includes/classes/Indexable.php +++ b/includes/classes/Indexable.php @@ -59,7 +59,7 @@ abstract class Indexable { * `id_range` pagination method during a sync. * * @var boolean - * @since 4.0.2 + * @since 4.1.0 */ public $support_indexing_advanced_pagination = false; diff --git a/includes/classes/Indexable/Post/Post.php b/includes/classes/Indexable/Post/Post.php index 78a04c0f5b..64b60fb856 100644 --- a/includes/classes/Indexable/Post/Post.php +++ b/includes/classes/Indexable/Post/Post.php @@ -37,7 +37,7 @@ class Post extends Indexable { * `id_range` pagination method during a sync. * * @var boolean - * @since 4.0.2 + * @since 4.1.0 */ public $support_indexing_advanced_pagination = true; From f3df048bfe711b830e4fa344b3d6332165b3e034 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Tue, 29 Mar 2022 11:06:47 -0300 Subject: [PATCH 43/52] Improve check for numeric array keys --- includes/classes/Indexable/Post/Post.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/includes/classes/Indexable/Post/Post.php b/includes/classes/Indexable/Post/Post.php index 9b34e8a974..15d9c89d13 100644 --- a/includes/classes/Indexable/Post/Post.php +++ b/includes/classes/Indexable/Post/Post.php @@ -1800,9 +1800,13 @@ public function format_args( $args, $wp_query ) { /** * Aggregations */ - if ( isset( $args['aggs'] ) ) { - // An array of aggregations. - if ( isset( $args['aggs'][0] ) ) { + if ( ! empty( $args['aggs'] ) && is_array( $args['aggs'] ) ) { + // Check if the array indexes are all numeric. + $agg_keys = array_keys( $args['aggs'] ); + $agg_num_keys = array_filter( $agg_keys, 'is_int' ); + $has_only_num_keys = count( $agg_num_keys ) === count( $args['aggs'] ); + + if ( $has_only_num_keys ) { foreach ( $args['aggs'] as $agg ) { $formatted_args = $this->apply_aggregations( $formatted_args, $agg, $use_filters, $filter ); } From 799227351428ad37204940e03afc76b7e5b59108 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Tue, 29 Mar 2022 11:22:27 -0300 Subject: [PATCH 44/52] Add most recent PRs --- CHANGELOG.md | 6 ++++++ CREDITS.md | 1 + 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e4f5c1d19..a95d168027 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file, per [the Ke - E2e tests for the Synonyms feature. Props [@felipeelia](https://github.com/felipeelia) via [#2655](https://github.com/10up/ElasticPress/pull/2655). - `generate_mapping()` to post and comment indexables. Props [@rebeccahum](https://github.com/rebeccahum) via [#2637](https://github.com/10up/ElasticPress/pull/2637). - `get_related_query()` to the `RelatedPosts` class. Props [@ayebare](https://github.com/ayebare) via [#1653](https://github.com/10up/ElasticPress/pull/1653). +- New `--pretty` flag to the WP-CLI commands that output a JSON. Props [@felipeelia](https://github.com/felipeelia) and [@oscarssanchez](https://github.com/oscarssanchez) via [#2653](https://github.com/10up/ElasticPress/pull/2653). ### Changed - Refactored remaining admin scripts to remove jQuery as a dependency. Props [@JakePT](https://github.com/JakePT) via [#2664](https://github.com/10up/ElasticPress/pull/2664). @@ -19,6 +20,11 @@ All notable changes to this project will be documented in this file, per [the Ke - Searches by WooCommerce Order ID. Props [@felipeelia](https://github.com/felipeelia) via [#2666](https://github.com/10up/ElasticPress/pull/2666). - Display and error message if syncing failed due to invalid JSON response from the server. Props [@dsawardekar](https://github.com/dsawardekar) via [#2677](https://github.com/10up/ElasticPress/pull/2677). - Better compatibility with PHP 8.1 by replacing the deprecated `FILTER_SANITIZE_STRING`. Props [@sjinks](https://github.com/sjinks) via [#2529](https://github.com/10up/ElasticPress/pull/2529). +- `get_term_tree()` no longer infinite loops when parent ID is non-existent. Props [@rebeccahum](https://github.com/rebeccahum) via [#2687](https://github.com/10up/ElasticPress/pull/2687). +- User search results include users who do not exist in the current site. Props [@tfrommen](https://github.com/tfrommen) and [@felipeelia](https://github.com/felipeelia) via [#2670](https://github.com/10up/ElasticPress/pull/2670). +- Pagination while syncing Indexables other than Posts. Props [@felipeelia](https://github.com/felipeelia) and [@derringer](https://github.com/derringer) via [#2665](https://github.com/10up/ElasticPress/pull/2665). +- Handle the output of an array of messages in sync processes. Props [@felipeelia](https://github.com/felipeelia) via [#2688](https://github.com/10up/ElasticPress/pull/2688). +- Truthy values for the `'enabled'` field's attribute while using the `ep_weighting_configuration_for_search` filter. Props [@felipeelia](https://github.com/felipeelia) and [@moritzlang](https://github.com/moritzlang) via [#2673](https://github.com/10up/ElasticPress/pull/2673). ## Security - Bumped `node-forge` from 1.2.1 to 1.3.0. Props [@dependabot](https://github.com/dependabot) via [#2678](https://github.com/10up/ElasticPress/pull/2678). diff --git a/CREDITS.md b/CREDITS.md index ecb9ae66f4..4f279e192a 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -174,6 +174,7 @@ Thank you to all the people who have already contributed to this repository via [Daniel Kudwien (@sun)](https://github.com/sun), [Darshan Sawardekar (@dsawardekar)](https://github.com/dsawardekar), [Ayebare (@ayebare)](https://github.com/ayebare), +[Michael Derringer (@derringer)](https://github.com/derringer), and [@qazaqstan2025](https://github.com/qazaqstan2025). From f88c79f73d29f2902c150d817c6af5e29aaf069f Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Wed, 30 Mar 2022 09:19:00 -0300 Subject: [PATCH 45/52] Added #2682 to the changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a95d168027..c08f946807 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file, per [the Ke - `generate_mapping()` to post and comment indexables. Props [@rebeccahum](https://github.com/rebeccahum) via [#2637](https://github.com/10up/ElasticPress/pull/2637). - `get_related_query()` to the `RelatedPosts` class. Props [@ayebare](https://github.com/ayebare) via [#1653](https://github.com/10up/ElasticPress/pull/1653). - New `--pretty` flag to the WP-CLI commands that output a JSON. Props [@felipeelia](https://github.com/felipeelia) and [@oscarssanchez](https://github.com/oscarssanchez) via [#2653](https://github.com/10up/ElasticPress/pull/2653). +- Support for an array of aggregations in the `aggs` parameter of `WP_Query`. Props [@felipeelia](https://github.com/felipeelia) and [@oscarssanchez](https://github.com/oscarssanchez) via [#2682](https://github.com/10up/ElasticPress/pull/2682). ### Changed - Refactored remaining admin scripts to remove jQuery as a dependency. Props [@JakePT](https://github.com/JakePT) via [#2664](https://github.com/10up/ElasticPress/pull/2664). From 72f1d2f9039dd2e6beeca3e212fe76b06f2d94d9 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Wed, 30 Mar 2022 10:17:05 -0300 Subject: [PATCH 46/52] Bump version numbers --- elasticpress.php | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- readme.txt | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/elasticpress.php b/elasticpress.php index 52794f850d..ab4d9490ea 100644 --- a/elasticpress.php +++ b/elasticpress.php @@ -3,7 +3,7 @@ * Plugin Name: ElasticPress * Plugin URI: https://github.com/10up/ElasticPress * Description: A fast and flexible search and query engine for WordPress. - * Version: 4.0.1 + * Version: 4.1.0 * Requires at least: 5.6 * Requires PHP: 7.0 * Author: 10up @@ -32,7 +32,7 @@ define( 'EP_URL', plugin_dir_url( __FILE__ ) ); define( 'EP_PATH', plugin_dir_path( __FILE__ ) ); define( 'EP_FILE', plugin_basename( __FILE__ ) ); -define( 'EP_VERSION', '4.0.1' ); +define( 'EP_VERSION', '4.1.0' ); /** * PSR-4-ish autoloading diff --git a/package-lock.json b/package-lock.json index 97ac341c2f..0392342d1d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "elasticpress", - "version": "4.0.1", + "version": "4.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "elasticpress", - "version": "4.0.1", + "version": "4.1.0", "license": "GPL-2.0-or-later", "dependencies": { "@10up/component-tooltip": "^2.0.0", diff --git a/package.json b/package.json index f504603700..2e5517091b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "elasticpress", - "version": "4.0.1", + "version": "4.1.0", "license": "GPL-2.0-or-later", "description": "A fast and flexible search and query engine for WordPress.", "devDependencies": { diff --git a/readme.txt b/readme.txt index 4acc1984fe..174c84aaeb 100644 --- a/readme.txt +++ b/readme.txt @@ -2,7 +2,7 @@ Contributors: 10up, tlovett1, vhauri, tott, oscarssanchez, cmmarslender Tags: performance, slow, search, elasticsearch, fuzzy, facet, aggregation, searching, autosuggest, suggest, elastic, advanced search, woocommerce, related posts, woocommerce Tested up to: 5.9.1 -Stable tag: 4.0.1 +Stable tag: 4.1.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html From f275aa0bd2ff1e3c8cc37d7e9ff4d8a9c663904e Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 4 Apr 2022 13:29:02 -0300 Subject: [PATCH 47/52] readme.txt changelog + release date --- CHANGELOG.md | 3 +++ readme.txt | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c08f946807..0c307bab15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file, per [the Ke ## [Unreleased] +## [4.1.0] - 2022-04-05 + ### Added - Utility command to create zip packages: `npm run build:zip`. Props [@felipeelia](https://github.com/felipeelia) via [#2669](https://github.com/10up/ElasticPress/pull/2669). - E2e tests for the Synonyms feature. Props [@felipeelia](https://github.com/felipeelia) via [#2655](https://github.com/10up/ElasticPress/pull/2655). @@ -1342,6 +1344,7 @@ This is a bug fix release with some filter additions. - Initial plugin release [Unreleased]: https://github.com/10up/ElasticPress/compare/trunk...develop +[4.1.0]: https://github.com/10up/ElasticPress/compare/4.0.1...4.1.0 [4.0.1]: https://github.com/10up/ElasticPress/compare/4.0.0...4.0.1 [4.0.0]: https://github.com/10up/ElasticPress/compare/3.6.6...4.0.0 [3.6.6]: https://github.com/10up/ElasticPress/compare/3.6.5...3.6.6 diff --git a/readme.txt b/readme.txt index 174c84aaeb..2ba27a655a 100644 --- a/readme.txt +++ b/readme.txt @@ -51,6 +51,35 @@ Please refer to [Github](https://github.com/10up/ElasticPress) for detailed usag == Changelog == += 4.1.0 - 2022-04-05 = + +Added +* Utility command to create zip packages: `npm run build:zip`. Props [@felipeelia](https://github.com/felipeelia). +* E2e tests for the Synonyms feature. Props [@felipeelia](https://github.com/felipeelia). +* `generate_mapping()` to post and comment indexables. Props [@rebeccahum](https://github.com/rebeccahum). +* `get_related_query()` to the `RelatedPosts` class. Props [@ayebare](https://github.com/ayebare). +* New `--pretty` flag to the WP-CLI commands that output a JSON. Props [@felipeelia](https://github.com/felipeelia) and [@oscarssanchez](https://github.com/oscarssanchez). +* Support for an array of aggregations in the `aggs` parameter of `WP_Query`. Props [@felipeelia](https://github.com/felipeelia) and [@oscarssanchez](https://github.com/oscarssanchez). + +Changed +* Refactored remaining admin scripts to remove jQuery as a dependency. Props [@JakePT](https://github.com/JakePT). +* Generate Instant Results' search template as an anonymous user by default. Props [@JakePT](https://github.com/JakePT). + +Fixed +* PHP warning Trying to access array offset on value of type int in `get_index_names()`. Props [@sun](https://github.com/sun). +* Searches by WooCommerce Order ID. Props [@felipeelia](https://github.com/felipeelia). +* Display and error message if syncing failed due to invalid JSON response from the server. Props [@dsawardekar](https://github.com/dsawardekar). +* Better compatibility with PHP 8.1 by replacing the deprecated `FILTER_SANITIZE_STRING`. Props [@sjinks](https://github.com/sjinks). +* `get_term_tree()` no longer infinite loops when parent ID is non-existent. Props [@rebeccahum](https://github.com/rebeccahum). +* User search results include users who do not exist in the current site. Props [@tfrommen](https://github.com/tfrommen) and [@felipeelia](https://github.com/felipeelia). +* Pagination while syncing Indexables other than Posts. Props [@felipeelia](https://github.com/felipeelia) and [@derringer](https://github.com/derringer). +* Handle the output of an array of messages in sync processes. Props [@felipeelia](https://github.com/felipeelia). +* Truthy values for the `'enabled'` field's attribute while using the `ep_weighting_configuration_for_search` filter. Props [@felipeelia](https://github.com/felipeelia) and [@moritzlang](https://github.com/moritzlang). + +Security +* Bumped `node-forge` from 1.2.1 to 1.3.0. Props [@dependabot](https://github.com/dependabot). +* Bumped` @wordpress/env` from 4.2.2 to 4.4.0, and `minimist` from 1.2.5 to 1.2.6. Props [@felipeelia](https://github.com/felipeelia). + = 4.0.1 - 2022-03-16 = **This is a security release affecting users running ElasticPress 4.0 with both the WooCommerce and Protected Content Features activated. Please update to the latest version of ElasticPress if the WooCommerce and Protected Content features are activated and you're using ElasticPress 4.0.** From c53b4bb4d2ec4c703923a0809452084338e8022e Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 4 Apr 2022 14:18:45 -0300 Subject: [PATCH 48/52] Add the learn more link --- includes/partials/sync-page.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/partials/sync-page.php b/includes/partials/sync-page.php index 3314931212..d3cafc7401 100644 --- a/includes/partials/sync-page.php +++ b/includes/partials/sync-page.php @@ -46,7 +46,7 @@ class="ep-last-sync__icon-status" - + From 5c7db0be8aea5c18af12161039671406ad40abeb Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 4 Apr 2022 14:35:53 -0300 Subject: [PATCH 49/52] Add #2699 to the changelog --- CHANGELOG.md | 1 + readme.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c307bab15..30034af517 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ All notable changes to this project will be documented in this file, per [the Ke - Pagination while syncing Indexables other than Posts. Props [@felipeelia](https://github.com/felipeelia) and [@derringer](https://github.com/derringer) via [#2665](https://github.com/10up/ElasticPress/pull/2665). - Handle the output of an array of messages in sync processes. Props [@felipeelia](https://github.com/felipeelia) via [#2688](https://github.com/10up/ElasticPress/pull/2688). - Truthy values for the `'enabled'` field's attribute while using the `ep_weighting_configuration_for_search` filter. Props [@felipeelia](https://github.com/felipeelia) and [@moritzlang](https://github.com/moritzlang) via [#2673](https://github.com/10up/ElasticPress/pull/2673). +- "Learn More" link on the Sync Page. Props [@felipeelia](https://github.com/felipeelia), [@JakePT](https://github.com/JakePT), and [@brandwaffle](https://github.com/brandwaffle) via [#2699](https://github.com/10up/ElasticPress/pull/2699). ## Security - Bumped `node-forge` from 1.2.1 to 1.3.0. Props [@dependabot](https://github.com/dependabot) via [#2678](https://github.com/10up/ElasticPress/pull/2678). diff --git a/readme.txt b/readme.txt index 2ba27a655a..1f6d7a1970 100644 --- a/readme.txt +++ b/readme.txt @@ -75,6 +75,7 @@ Fixed * Pagination while syncing Indexables other than Posts. Props [@felipeelia](https://github.com/felipeelia) and [@derringer](https://github.com/derringer). * Handle the output of an array of messages in sync processes. Props [@felipeelia](https://github.com/felipeelia). * Truthy values for the `'enabled'` field's attribute while using the `ep_weighting_configuration_for_search` filter. Props [@felipeelia](https://github.com/felipeelia) and [@moritzlang](https://github.com/moritzlang). +* "Learn More" link on the Sync Page. Props [@felipeelia](https://github.com/felipeelia), [@JakePT](https://github.com/JakePT), and [@brandwaffle](https://github.com/brandwaffle). Security * Bumped `node-forge` from 1.2.1 to 1.3.0. Props [@dependabot](https://github.com/dependabot). From 8b289e43206512e0c85075a805931363a3c6e085 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Tue, 5 Apr 2022 14:24:21 -0300 Subject: [PATCH 50/52] Icons alignment --- assets/css/dashboard.css | 8 ++++++-- assets/css/sync.css | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/assets/css/dashboard.css b/assets/css/dashboard.css index 7ed03b2053..3809da870c 100644 --- a/assets/css/dashboard.css +++ b/assets/css/dashboard.css @@ -80,8 +80,8 @@ h2.ep-list-features { .ep-header-menu .icons { display: inline-block; float: right; - height: 39px; - line-height: 39px; + height: 30px; + line-height: 34px; padding-right: 3px; } @@ -134,6 +134,10 @@ h2.ep-list-features { display: inline; } +.ep-header-menu .icons .dashicons-update { + top: 2px; +} + /** * Features */ diff --git a/assets/css/sync.css b/assets/css/sync.css index ad438b1c8c..f6cc9cd892 100644 --- a/assets/css/sync.css +++ b/assets/css/sync.css @@ -167,6 +167,11 @@ margin-bottom: 0.5em; } + & .ep-last-sync__icon-status { + margin-right: 5px; + vertical-align: text-bottom; + } + & .ep-last-sync__date { background-color: var(--ep-admin-color-grey-01); padding: 6px; From b1c84cd31ecdf77ff8bd8fdcba7aff7d5741df91 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Tue, 5 Apr 2022 14:41:09 -0300 Subject: [PATCH 51/52] Add #2701 --- CHANGELOG.md | 1 + readme.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30034af517..9140a17e36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ All notable changes to this project will be documented in this file, per [the Ke - Handle the output of an array of messages in sync processes. Props [@felipeelia](https://github.com/felipeelia) via [#2688](https://github.com/10up/ElasticPress/pull/2688). - Truthy values for the `'enabled'` field's attribute while using the `ep_weighting_configuration_for_search` filter. Props [@felipeelia](https://github.com/felipeelia) and [@moritzlang](https://github.com/moritzlang) via [#2673](https://github.com/10up/ElasticPress/pull/2673). - "Learn More" link on the Sync Page. Props [@felipeelia](https://github.com/felipeelia), [@JakePT](https://github.com/JakePT), and [@brandwaffle](https://github.com/brandwaffle) via [#2699](https://github.com/10up/ElasticPress/pull/2699). +- Icons alignment in the WP Dashboard. Props [@felipeelia](https://github.com/felipeelia), [@brandwaffle](https://github.com/brandwaffle), and [@tlovett1](https://github.com/tlovett1) via [#2701](https://github.com/10up/ElasticPress/pull/2701). ## Security - Bumped `node-forge` from 1.2.1 to 1.3.0. Props [@dependabot](https://github.com/dependabot) via [#2678](https://github.com/10up/ElasticPress/pull/2678). diff --git a/readme.txt b/readme.txt index 1f6d7a1970..3a45745b53 100644 --- a/readme.txt +++ b/readme.txt @@ -76,6 +76,7 @@ Fixed * Handle the output of an array of messages in sync processes. Props [@felipeelia](https://github.com/felipeelia). * Truthy values for the `'enabled'` field's attribute while using the `ep_weighting_configuration_for_search` filter. Props [@felipeelia](https://github.com/felipeelia) and [@moritzlang](https://github.com/moritzlang). * "Learn More" link on the Sync Page. Props [@felipeelia](https://github.com/felipeelia), [@JakePT](https://github.com/JakePT), and [@brandwaffle](https://github.com/brandwaffle). +* Icons alignment in the WP Dashboard. Props [@felipeelia](https://github.com/felipeelia), [@brandwaffle](https://github.com/brandwaffle), and [@tlovett1](https://github.com/tlovett1). Security * Bumped `node-forge` from 1.2.1 to 1.3.0. Props [@dependabot](https://github.com/dependabot). From 21b5e0a08870b74020769882dd460fc1d1da4d1c Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Tue, 5 Apr 2022 14:44:36 -0300 Subject: [PATCH 52/52] Props to `@jakemgold` --- CHANGELOG.md | 2 +- CREDITS.md | 1 + readme.txt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9140a17e36..33d0d02932 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,7 @@ All notable changes to this project will be documented in this file, per [the Ke - Handle the output of an array of messages in sync processes. Props [@felipeelia](https://github.com/felipeelia) via [#2688](https://github.com/10up/ElasticPress/pull/2688). - Truthy values for the `'enabled'` field's attribute while using the `ep_weighting_configuration_for_search` filter. Props [@felipeelia](https://github.com/felipeelia) and [@moritzlang](https://github.com/moritzlang) via [#2673](https://github.com/10up/ElasticPress/pull/2673). - "Learn More" link on the Sync Page. Props [@felipeelia](https://github.com/felipeelia), [@JakePT](https://github.com/JakePT), and [@brandwaffle](https://github.com/brandwaffle) via [#2699](https://github.com/10up/ElasticPress/pull/2699). -- Icons alignment in the WP Dashboard. Props [@felipeelia](https://github.com/felipeelia), [@brandwaffle](https://github.com/brandwaffle), and [@tlovett1](https://github.com/tlovett1) via [#2701](https://github.com/10up/ElasticPress/pull/2701). +- Icons alignment in the WP Dashboard. Props [@jakemgold](https://github.com/jakemgold), [@felipeelia](https://github.com/felipeelia), [@brandwaffle](https://github.com/brandwaffle), and [@tlovett1](https://github.com/tlovett1) via [#2701](https://github.com/10up/ElasticPress/pull/2701). ## Security - Bumped `node-forge` from 1.2.1 to 1.3.0. Props [@dependabot](https://github.com/dependabot) via [#2678](https://github.com/10up/ElasticPress/pull/2678). diff --git a/CREDITS.md b/CREDITS.md index 4f279e192a..19a744ed56 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -175,6 +175,7 @@ Thank you to all the people who have already contributed to this repository via [Darshan Sawardekar (@dsawardekar)](https://github.com/dsawardekar), [Ayebare (@ayebare)](https://github.com/ayebare), [Michael Derringer (@derringer)](https://github.com/derringer), +[Jake Goldman (@jakemgold)](https://github.com/jakemgold), and [@qazaqstan2025](https://github.com/qazaqstan2025). diff --git a/readme.txt b/readme.txt index 3a45745b53..caf3db6141 100644 --- a/readme.txt +++ b/readme.txt @@ -76,7 +76,7 @@ Fixed * Handle the output of an array of messages in sync processes. Props [@felipeelia](https://github.com/felipeelia). * Truthy values for the `'enabled'` field's attribute while using the `ep_weighting_configuration_for_search` filter. Props [@felipeelia](https://github.com/felipeelia) and [@moritzlang](https://github.com/moritzlang). * "Learn More" link on the Sync Page. Props [@felipeelia](https://github.com/felipeelia), [@JakePT](https://github.com/JakePT), and [@brandwaffle](https://github.com/brandwaffle). -* Icons alignment in the WP Dashboard. Props [@felipeelia](https://github.com/felipeelia), [@brandwaffle](https://github.com/brandwaffle), and [@tlovett1](https://github.com/tlovett1). +* Icons alignment in the WP Dashboard. Props [@jakemgold](https://github.com/jakemgold), [@felipeelia](https://github.com/felipeelia), [@brandwaffle](https://github.com/brandwaffle), and [@tlovett1](https://github.com/tlovett1). Security * Bumped `node-forge` from 1.2.1 to 1.3.0. Props [@dependabot](https://github.com/dependabot).