From 2a49eaac02ab537a97709128683854cf3bab5b7c Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Fri, 5 Dec 2014 15:46:49 -0500 Subject: [PATCH 01/41] Add property to integration post object for debugging --- classes/class-ep-wp-query-integration.php | 1 + 1 file changed, 1 insertion(+) diff --git a/classes/class-ep-wp-query-integration.php b/classes/class-ep-wp-query-integration.php index b9d51a0ff6..26bbab3c3a 100644 --- a/classes/class-ep-wp-query-integration.php +++ b/classes/class-ep-wp-query-integration.php @@ -177,6 +177,7 @@ public function filter_the_posts( $posts, &$query ) { $post->post_date_gmt = $post_array['post_date_gmt']; $post->post_modified = $post_array['post_modified']; $post->post_modified_gmt = $post_array['post_modified_gmt']; + $post->elasticsearch = true; // Super useful for debugging // Run through get_post() to add all expected properties (even if they're empty) $post = get_post( $post ); From a2f4f8fdae90057a39f6e355961c90af9e29a44a Mon Sep 17 00:00:00 2001 From: Elliott Stocks Date: Wed, 17 Dec 2014 12:12:19 +0000 Subject: [PATCH 02/41] Check if failed post exists Fixes PHP notice - Notice: Trying to get property of non-object in /elasticpress/bin/wp-cli.php on line 431 --- bin/wp-cli.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bin/wp-cli.php b/bin/wp-cli.php index bb8ca301d9..3c247cb2e5 100644 --- a/bin/wp-cli.php +++ b/bin/wp-cli.php @@ -428,7 +428,10 @@ private function send_bulk_errors() { if ( ! empty( $this->failed_posts ) ) { $email_text = __( "The following posts failed to index:\r\n\r\n", 'elasticpress' ); foreach ( $this->failed_posts as $failed ) { - $email_text .= "- {$failed}: " . get_post( $failed )->post_title . "\r\n"; + $failed_post = get_post( $failed ); + if ( $failed_post ) { + $email_text .= "- {$failed}: " . get_post( $failed )->post_title . "\r\n"; + } } $send_mail = wp_mail( get_option( 'admin_email' ), wp_specialchars_decode( get_option( 'blogname' ) ) . __( ': ElasticPress Index Errors', 'elasticpress' ), $email_text ); From 7d5d6f5d1e286ec11b6ab2492488efff06816c9f Mon Sep 17 00:00:00 2001 From: Elliott Stocks Date: Wed, 17 Dec 2014 12:14:12 +0000 Subject: [PATCH 03/41] Check 'setup' isset in $assoc_args Fixes PHP notice - Notice: Undefined index: setup in /elasticpress/bin/wp-cli.php on line 193 --- bin/wp-cli.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/wp-cli.php b/bin/wp-cli.php index bb8ca301d9..c1c46288c1 100644 --- a/bin/wp-cli.php +++ b/bin/wp-cli.php @@ -190,7 +190,7 @@ public function index( $args, $assoc_args ) { timer_start(); // Run setup if flag was passed - if ( true === $assoc_args['setup'] ) { + if ( isset( $assoc_args['setup'] ) && true === $assoc_args['setup'] ) { // Right now setup is just the put_mapping command, as this also deletes the index(s) first $this->put_mapping( $args, $assoc_args ); From f6f37508b2b930f9768a961337ccf6e0f5a06f4b Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Thu, 18 Dec 2014 11:46:49 -0500 Subject: [PATCH 04/41] Use ep_integrate instead of ep_match_all - see #169 --- classes/class-ep-api.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/classes/class-ep-api.php b/classes/class-ep-api.php index b7407d8b9a..7ca4f70174 100644 --- a/classes/class-ep-api.php +++ b/classes/class-ep-api.php @@ -883,11 +883,19 @@ public function format_args( $args ) { ), ), ); - if ( ! empty( $args['s'] ) && ! isset( $args['ep_match_all'] ) ) { + + /** + * We are using ep_integrate instead of ep_match_all. ep_match_all will be + * supported for legacy code but may be deprecated and removed eventually. + * + * @since 1.3 + */ + + if ( ! empty( $args['s'] ) && empty( $args['ep_match_all'] ) && empty( $args['ep_integrate'] ) ) { $query['bool']['should'][1]['fuzzy_like_this']['like_text'] = $args['s']; $query['bool']['should'][0]['multi_match']['query'] = $args['s']; $formatted_args['query'] = $query; - } else if ( isset( $args['ep_match_all'] ) && true === $args['ep_match_all'] ) { + } else if ( ! empty( $args['ep_match_all'] ) || ! empty( $args['ep_integrate'] ) ) { $formatted_args['query']['match_all'] = array(); } @@ -987,7 +995,9 @@ public function elasticpress_enabled( $query ) { if ( $query->is_search() ) { $enabled = true; - } else if ( isset( $query->query['ep_match_all'] ) && true === $query->query['ep_match_all'] ) { + } elseif ( ! empty( $query->query['ep_match_all'] ) ) { // ep_match_all is supported for legacy reasons + $enabled = true; + } elseif ( ! empty( $query->query['ep_integrate'] ) ) { $enabled = true; } From d2d4339c0d37259fa870e498e9455e04194cfb7f Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Thu, 18 Dec 2014 13:01:27 -0500 Subject: [PATCH 05/41] Default to any post_type if none is specified. Require post post_type to be specified. Tests and docs included. --- README.md | 2 +- classes/class-ep-api.php | 33 +++++++---- tests/test-multisite.php | 118 ++++++++++++++++++++++++++++++++++++- tests/test-single-site.php | 99 ++++++++++++++++++++++++++++++- 4 files changed, 233 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index ddd7dbfea2..33e8ed98e8 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ After running an index, ElasticPress integrates with WP_Query. The end goal is t * ```post_type``` (*string*/*array*) - Filter posts by post type. ```any``` wil search all public post types. + Filter posts by post type. ```any``` wil search all public post types. `WP_Query` defaults to either `post` or `any` if no `post_type` is provided depending on the context of the query. This is confusing. ElasticPress will ALWAYS default to `any` if no `post_type` is provided. If you want to search for `post` posts, you MUST specify `post` as the `post_type`. * ```offset``` (*int*) diff --git a/classes/class-ep-api.php b/classes/class-ep-api.php index 7ca4f70174..c6627e5be8 100644 --- a/classes/class-ep-api.php +++ b/classes/class-ep-api.php @@ -899,20 +899,29 @@ public function format_args( $args ) { $formatted_args['query']['match_all'] = array(); } - if ( isset( $args['post_type'] ) ) { - $post_types = (array) $args['post_type']; - $terms_map_name = 'terms'; - if ( count( $post_types ) < 2 ) { - $terms_map_name = 'term'; - } + /** + * Like WP_Query in search context, if no post_type is specified we default to "any". To + * be safe you should ALWAYS specify the post_type parameter UNLIKE with WP_Query. + * + * @since 1.3 + */ + if ( ! empty( $args['post_type'] ) ) { + // should NEVER be "any" but just in case + if ( 'any' !== $args['post_type'] ) { + $post_types = (array) $args['post_type']; + $terms_map_name = 'terms'; + if ( count( $post_types ) < 2 ) { + $terms_map_name = 'term'; + } - $filter['and'][] = array( - $terms_map_name => array( - 'post_type.raw' => $post_types, - ), - ); + $filter['and'][] = array( + $terms_map_name => array( + 'post_type.raw' => $post_types, + ), + ); - $use_filters = true; + $use_filters = true; + } } if ( isset( $args['offset'] ) ) { diff --git a/tests/test-multisite.php b/tests/test-multisite.php index 29aba11e6a..8db19643a4 100644 --- a/tests/test-multisite.php +++ b/tests/test-multisite.php @@ -463,11 +463,11 @@ public function testTaxQuery() { } /** - * Test a post type query search + * Test a post type query search for pages * - * @since 1.0 + * @since 1.3 */ - public function testPostTypeQuery() { + public function testPostTypeSearchQueryPage() { $sites = ep_get_sites(); $i = 0; @@ -500,6 +500,118 @@ public function testPostTypeQuery() { $this->assertEquals( $query->found_posts, 2 ); } + /** + * Test a post type query search for posts + * + * @since 1.3 + */ + public function testPostTypeSearchQueryPost() { + $sites = ep_get_sites(); + + $i = 0; + + foreach ( $sites as $site ) { + switch_to_blog( $site['blog_id'] ); + + ep_create_and_sync_post( array( 'post_content' => 'findme', 'post_type' => 'page' ) ); + + if ( $i > 0 ) { + ep_create_and_sync_post( array( 'post_content' => 'findme' ) ); + } + + ep_refresh_index(); + + restore_current_blog(); + + $i++; + } + + $args = array( + 's' => 'findme', + 'sites' => 'all', + 'post_type' => 'post', + ); + + $query = new WP_Query( $args ); + + $this->assertEquals( $query->post_count, 2 ); + $this->assertEquals( $query->found_posts, 2 ); + } + + /** + * Test a post type query search where no post type is specified + * + * @since 1.3 + */ + public function testNoPostTypeSearchQuery() { + $sites = ep_get_sites(); + + $i = 0; + + foreach ( $sites as $site ) { + switch_to_blog( $site['blog_id'] ); + + ep_create_and_sync_post( array( 'post_content' => 'findme', 'post_type' => 'page' ) ); + + if ( $i > 0 ) { + ep_create_and_sync_post( array( 'post_content' => 'findme' ) ); + } + + ep_refresh_index(); + + restore_current_blog(); + + $i++; + } + + $args = array( + 's' => 'findme', + 'sites' => 'all', + ); + + $query = new WP_Query( $args ); + + $this->assertEquals( $query->post_count, 5 ); + $this->assertEquals( $query->found_posts, 5 ); + } + + /** + * Test a post type query non-search where no post type is specified + * + * @since 1.3 + */ + public function testNoPostTypeNoSearchQuery() { + $sites = ep_get_sites(); + + $i = 0; + + foreach ( $sites as $site ) { + switch_to_blog( $site['blog_id'] ); + + ep_create_and_sync_post( array( 'post_content' => 'findme', 'post_type' => 'page' ) ); + + if ( $i > 0 ) { + ep_create_and_sync_post( array( 'post_content' => 'findme' ) ); + } + + ep_refresh_index(); + + restore_current_blog(); + + $i++; + } + + $args = array( + 'ep_integrate' => true, + 'sites' => 'all', + ); + + $query = new WP_Query( $args ); + + $this->assertEquals( $query->post_count, 5 ); + $this->assertEquals( $query->found_posts, 5 ); + } + /** * Test an author ID query * diff --git a/tests/test-single-site.php b/tests/test-single-site.php index 2d1a9a6254..61473a8e20 100644 --- a/tests/test-single-site.php +++ b/tests/test-single-site.php @@ -409,11 +409,11 @@ public function testAuthorNameQuery() { } /** - * Test a post type query + * Test a post type query for pages * - * @since 1.0 + * @since 1.3 */ - public function testPostTypeQuery() { + public function testPostTypeQueryPage() { ep_create_and_sync_post( array( 'post_content' => 'findme test 1', 'post_type' => 'page' ) ); ep_create_and_sync_post( array( 'post_content' => 'findme test 2' ) ); ep_create_and_sync_post( array( 'post_content' => 'findme test 3', 'post_type' => 'page' ) ); @@ -431,6 +431,99 @@ public function testPostTypeQuery() { $this->assertEquals( 2, $query->found_posts ); } + + /** + * Test a post type query for posts + * + * @since 1.3 + */ + public function testPostTypeQueryPost() { + ep_create_and_sync_post( array( 'post_content' => 'findme test 1', 'post_type' => 'page' ) ); + ep_create_and_sync_post( array( 'post_content' => 'findme test 2' ) ); + ep_create_and_sync_post( array( 'post_content' => 'findme test 3', 'post_type' => 'page' ) ); + + ep_refresh_index(); + + $args = array( + 's' => 'findme', + 'post_type' => 'post', + ); + + $query = new WP_Query( $args ); + + $this->assertEquals( 1, $query->post_count ); + $this->assertEquals( 1, $query->found_posts ); + } + + /** + * Test a query with no post type + * + * @since 1.3 + */ + public function testNoPostTypeSearchQuery() { + ep_create_and_sync_post( array( 'post_content' => 'findme test 1', 'post_type' => 'page' ) ); + ep_create_and_sync_post( array( 'post_content' => 'findme test 2' ) ); + ep_create_and_sync_post( array( 'post_content' => 'findme test 3' ) ); + + ep_refresh_index(); + + // post_type defaults to "any" + $args = array( + 's' => 'findme', + ); + + $query = new WP_Query( $args ); + + $this->assertEquals( 3, $query->post_count ); + $this->assertEquals( 3, $query->found_posts ); + } + + /** + * Test a query with no post type on non-search query + * + * @since 1.3 + */ + public function testNoPostTypeNonSearchQuery() { + ep_create_and_sync_post( array( 'post_content' => 'findme test 1', 'post_type' => 'page' ) ); + ep_create_and_sync_post( array( 'post_content' => 'findme test 2' ) ); + ep_create_and_sync_post( array( 'post_content' => 'findme test 3' ) ); + + ep_refresh_index(); + + // post_type defaults to "any" + $args = array( + 'ep_integrate' => true, + ); + + $query = new WP_Query( $args ); + + $this->assertEquals( 3, $query->post_count ); + $this->assertEquals( 3, $query->found_posts ); + } + + /** + * Test a query with "any" post type + * + * @since 1.3 + */ + public function testAnyPostTypeQuery() { + ep_create_and_sync_post( array( 'post_content' => 'findme test 1', 'post_type' => 'page' ) ); + ep_create_and_sync_post( array( 'post_content' => 'findme test 2' ) ); + ep_create_and_sync_post( array( 'post_content' => 'findme test 3', 'post_type' => 'page' ) ); + + ep_refresh_index(); + + $args = array( + 's' => 'findme', + 'post_type' => 'any', + ); + + $query = new WP_Query( $args ); + + $this->assertEquals( 3, $query->post_count ); + $this->assertEquals( 3, $query->found_posts ); + } + /** * Test a query that fuzzy searches meta * From 40e0839a461e18a4321fb06fad15f44df44120b3 Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Mon, 22 Dec 2014 16:59:20 -0500 Subject: [PATCH 06/41] Support . --- classes/class-ep-api.php | 93 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/classes/class-ep-api.php b/classes/class-ep-api.php index c6627e5be8..0b6f26ce31 100644 --- a/classes/class-ep-api.php +++ b/classes/class-ep-api.php @@ -817,6 +817,99 @@ public function format_args( $args ) { $use_filters = true; } + /** + * 'meta_query' arg support. + * + * Relation supports 'AND' and 'OR'. 'AND' is the default. For each individual query, the + * following 'compare' values are supported: =, !=, EXISTS, NOT EXISTS. '=' is the default. + * 'type' is NOT support at this time. + * + * @since 1.3 + */ + if ( ! empty( $args['meta_query'] ) ) { + $meta_filter = array(); + + $relation = 'must'; + if ( ! empty( $args['meta_query']['relation'] ) && 'or' === strtolower( $args['meta_query']['relation'] ) ) { + $relation = 'should'; + } + + foreach( $args['meta_query'] as $single_meta_query ) { + if ( ! empty( $single_meta_query['key'] ) ) { + + $terms_obj = false; + + $compare = '='; + if ( ! empty( $single_meta_query['compare'] ) ) { + $compare = strtolower( $single_meta_query['compare'] ); + } + + switch ( $compare ) { + case '!=': + if ( isset( $single_meta_query['value'] ) ) { + $terms_obj = array( + 'bool' => array( + 'must_not' => array( + array( + 'terms' => array( + 'post_meta.' . $single_meta_query['key'] . '.raw' => (array) $single_meta_query['value'], + ), + ), + ), + ), + ); + } + + break; + case 'exists': + $terms_obj = array( + 'exists' => array( + 'field' => 'post_meta.' . $single_meta_query['key'], + ), + ); + + break; + case 'not exists': + $terms_obj = array( + 'bool' => array( + 'must_not' => array( + array( + 'exists' => array( + 'field' => 'post_meta.' . $single_meta_query['key'], + ), + ), + ), + ), + ); + + break; + case '=': + default: + if ( isset( $single_meta_query['value'] ) ) { + $terms_obj = array( + 'terms' => array( + 'post_meta.' . $single_meta_query['key'] . '.raw' => (array) $single_meta_query['value'], + ), + ); + } + + break; + } + + // Add the meta query filter + if ( false !== $terms_obj ) { + $meta_filter[] = $terms_obj; + } + } + } + + if ( ! empty( $meta_filter ) ) { + $filter['and'][]['bool'][$relation] = $meta_filter; + } + + $use_filters = true; + } + /** * Allow for search field specification * From ac2f91c476aa1e502ba0a4c8b499a02a565e98e7 Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Mon, 22 Dec 2014 17:16:08 -0500 Subject: [PATCH 07/41] Tests for meta filter; need more MS tests --- tests/test-multisite.php | 52 +++++++++++ tests/test-single-site.php | 179 +++++++++++++++++++++++++++++++++++++ 2 files changed, 231 insertions(+) diff --git a/tests/test-multisite.php b/tests/test-multisite.php index 8db19643a4..b1e4d6958e 100644 --- a/tests/test-multisite.php +++ b/tests/test-multisite.php @@ -735,6 +735,58 @@ public function testSearchMetaQuery() { $this->assertEquals( $query->found_posts, 2 ); } + /** + * Test a search with a filter on meta + * + * @since 1.3 + */ + public function testFilterMetaQuery() { + $sites = ep_get_sites(); + + $i = 0; + + foreach ( $sites as $site ) { + switch_to_blog( $site['blog_id'] ); + + ep_create_and_sync_post( array( 'post_content' => 'post content findme' ), array( 'test_key' => 'findme', 'test_key2' => 'findme3', ) ); + + if ( $i > 0 ) { + ep_create_and_sync_post( array( 'post_content' => 'post content findme' ), array( 'test_key2' => 'findme', 'test_key' => 'value2', 'test_key3' => 'findme' ) ); + } + + ep_refresh_index(); + + restore_current_blog(); + + $i++; + } + + $args = array( + 's' => 'findme', + 'sites' => 'all', + 'meta_query' => array( + array( + 'key' => 'test_key', + 'value' => 'value2' + ), + array( + 'key' => 'test_key2', + 'value' => 'findme3', + 'compare' => '!=', + ), + array( + 'key' => 'test_key3', + 'compare' => 'exists', + ) + ) + ); + + $query = new WP_Query( $args ); + + $this->assertEquals( $query->post_count, 2 ); + $this->assertEquals( $query->found_posts, 2 ); + } + /** * Test a fuzzy search on taxonomy terms * diff --git a/tests/test-single-site.php b/tests/test-single-site.php index 61473a8e20..a2a0ddc7c9 100644 --- a/tests/test-single-site.php +++ b/tests/test-single-site.php @@ -962,4 +962,183 @@ public function testEmptySearchString() { $this->assertEquals( 2, $query->post_count ); $this->assertEquals( 2, $query->found_posts ); } + + /** + * Test a query that searches and filters by a meta equal query + * + * @since 1.3 + */ + public function testMetaQueryEquals() { + ep_create_and_sync_post( array( 'post_content' => 'the post content' ) ); + ep_create_and_sync_post( array( 'post_content' => 'the post content findme' ) ); + ep_create_and_sync_post( array( 'post_content' => 'post content findme' ), array( 'test_key' => 'value' ) ); + + ep_refresh_index(); + $args = array( + 's' => 'findme', + 'meta_query' => array( + array( + 'key' => 'test_key', + 'value' => 'value', + ) + ), + ); + + $query = new WP_Query( $args ); + + $this->assertEquals( 1, $query->post_count ); + $this->assertEquals( 1, $query->found_posts ); + } + + /** + * Test a query that searches and filters by a meta not equal query + * + * @since 1.3 + */ + public function testMetaQueryNotEquals() { + ep_create_and_sync_post( array( 'post_content' => 'the post content findme' ) ); + ep_create_and_sync_post( array( 'post_content' => 'the post content findme' ) ); + ep_create_and_sync_post( array( 'post_content' => 'post content findme' ), array( 'test_key' => 'value' ) ); + + ep_refresh_index(); + $args = array( + 's' => 'findme', + 'meta_query' => array( + array( + 'key' => 'test_key', + 'value' => 'value', + 'compare' => '!=', + ) + ), + ); + + $query = new WP_Query( $args ); + + $this->assertEquals( 2, $query->post_count ); + $this->assertEquals( 2, $query->found_posts ); + } + + /** + * Test a query that searches and filters by a meta exists query + * + * @since 1.3 + */ + public function testMetaQueryExists() { + ep_create_and_sync_post( array( 'post_content' => 'the post content findme' ) ); + ep_create_and_sync_post( array( 'post_content' => 'the post content findme' ) ); + ep_create_and_sync_post( array( 'post_content' => 'post content findme' ), array( 'test_key' => 'value' ) ); + + ep_refresh_index(); + $args = array( + 's' => 'findme', + 'meta_query' => array( + array( + 'key' => 'test_key', + 'compare' => 'exists', + ) + ), + ); + + $query = new WP_Query( $args ); + + $this->assertEquals( 1, $query->post_count ); + $this->assertEquals( 1, $query->found_posts ); + } + + /** + * Test a query that searches and filters by a meta not exists query + * + * @since 1.3 + */ + public function testMetaQueryNotExists() { + ep_create_and_sync_post( array( 'post_content' => 'the post content findme' ) ); + ep_create_and_sync_post( array( 'post_content' => 'the post content findme' ) ); + ep_create_and_sync_post( array( 'post_content' => 'post content findme' ), array( 'test_key' => 'value' ) ); + + ep_refresh_index(); + $args = array( + 's' => 'findme', + 'meta_query' => array( + array( + 'key' => 'test_key', + 'compare' => 'not exists', + ) + ), + ); + + $query = new WP_Query( $args ); + + $this->assertEquals( 2, $query->post_count ); + $this->assertEquals( 2, $query->found_posts ); + } + + /** + * Test an advanced meta filter query + * + * @since 1.3 + */ + public function testMetaQueryOrRelation() { + ep_create_and_sync_post( array( 'post_content' => 'the post content findme' ), array( 'test_key5' => 'value1' ) ); + ep_create_and_sync_post( array( 'post_content' => 'the post content findme' ), array( 'test_key' => 'value1', 'test_key2' => 'value' ) ); + ep_create_and_sync_post( array( 'post_content' => 'post content findme' ), array( 'test_key6' => 'value', 'test_key2' => 'value2', 'test_key3' => 'value' ) ); + + ep_refresh_index(); + $args = array( + 's' => 'findme', + 'meta_query' => array( + array( + 'key' => 'test_key5', + 'compare' => 'exists', + ), + array( + 'key' => 'test_key6', + 'value' => 'value', + 'compare' => '=', + ), + 'relation' => 'or', + ), + ); + + $query = new WP_Query( $args ); + + $this->assertEquals( 2, $query->post_count ); + $this->assertEquals( 2, $query->found_posts ); + } + + /** + * Test an advanced meta filter query + * + * @since 1.3 + */ + public function testMetaQueryAdvanced() { + ep_create_and_sync_post( array( 'post_content' => 'the post content findme' ), array( 'test_key' => 'value1' ) ); + ep_create_and_sync_post( array( 'post_content' => 'the post content findme' ), array( 'test_key' => 'value1', 'test_key2' => 'value' ) ); + ep_create_and_sync_post( array( 'post_content' => 'post content findme' ), array( 'test_key' => 'value', 'test_key2' => 'value2', 'test_key3' => 'value' ) ); + + ep_refresh_index(); + $args = array( + 's' => 'findme', + 'meta_query' => array( + array( + 'key' => 'test_key3', + 'compare' => 'exists', + ), + array( + 'key' => 'test_key2', + 'value' => 'value2', + 'compare' => '=', + ), + array( + 'key' => 'test_key', + 'value' => 'value1', + 'compare' => '!=', + ) + ), + ); + + $query = new WP_Query( $args ); + + $this->assertEquals( 1, $query->post_count ); + $this->assertEquals( 1, $query->found_posts ); + } } \ No newline at end of file From 7204c6d09f563d0e95e996d68bed5cabbc5188b8 Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Mon, 22 Dec 2014 17:25:05 -0500 Subject: [PATCH 08/41] Documentation --- README.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/README.md b/README.md index 33e8ed98e8..4cc99276c8 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,51 @@ After running an index, ElasticPress integrates with WP_Query. The end goal is t ```tax_query``` accepts an array of arrays where each inner array *only* supports ```taxonomy``` (string) and ```terms``` (string|array) parameters. ```terms``` is a slug, either in string or array form. +* ```meta_query``` (*array*) + + Filter posts by post meta conditions. Takes an array of form: + + ```php + new WP_Query( array( + 's' => 'search phrase', + 'meta_query' => array( + array( + 'key' => 'key_name', + 'value' => 'meta value', + 'compare' => '=', + ), + ), + ) ); + ``` + + ```tax_query``` accepts an array of arrays where each inner array *only* supports ```key``` (string), ```value``` (string|array|int), and ```compare``` (string) parameters. ```compare``` supports the following: + * ```=``` - Posts will be returned that have a post meta key corresponding to ```key``` and a value that equals the value passed to ```value```. + * ```!=``` - Posts will be returned that have a post meta key corresponding to ```key``` and a value that does NOT equal the value passed to ```value```. + * ```EXISTS``` - Posts will be returned that have a post meta key corresponding to ```key```. + * ```NOT EXISTS``` - Posts will be returned that do not have a post meta key corresponding to ```key```. + + The outer array also supports a ```relation``` (string) parameter. By default ```relation``` is set to ```AND```: + ```php + new WP_Query( array( + 's' => 'search phrase', + 'meta_query' => array( + array( + 'key' => 'key_name', + 'value' => 'meta value', + 'compare' => '=', + ), + array( + 'key' => 'key_name2', + 'value' => 'meta value', + 'compare' => '!=', + ), + 'relation' => 'AND', + ), + ) ); + ``` + + Possible values for ```relation``` are ```OR``` and ```AND```. If ```relation``` is set to ```AND```, all inner queries must be true for a post to be returned. If ```relation``` is set to ```OR```, only one of the inner meta queries must be true for the post to be returned. + * ```post_type``` (*string*/*array*) Filter posts by post type. ```any``` wil search all public post types. `WP_Query` defaults to either `post` or `any` if no `post_type` is provided depending on the context of the query. This is confusing. ElasticPress will ALWAYS default to `any` if no `post_type` is provided. If you want to search for `post` posts, you MUST specify `post` as the `post_type`. From 7e491e343ec1902d4872b9e502d3c9b55fc90bb3 Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Mon, 22 Dec 2014 17:29:41 -0500 Subject: [PATCH 09/41] Cleanup docs --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4cc99276c8..f3842ceca1 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,8 @@ After running an index, ElasticPress integrates with WP_Query. The end goal is t ) ); ``` - ```tax_query``` accepts an array of arrays where each inner array *only* supports ```key``` (string), ```value``` (string|array|int), and ```compare``` (string) parameters. ```compare``` supports the following: + ```meta_query``` accepts an array of arrays where each inner array *only* supports ```key``` (string), ```value``` (string|array|int), and ```compare``` (string) parameters. ```compare``` supports the following: + * ```=``` - Posts will be returned that have a post meta key corresponding to ```key``` and a value that equals the value passed to ```value```. * ```!=``` - Posts will be returned that have a post meta key corresponding to ```key``` and a value that does NOT equal the value passed to ```value```. * ```EXISTS``` - Posts will be returned that have a post meta key corresponding to ```key```. From 5af123968b9b7f945fd8a6d328e84861e213dfb0 Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Mon, 22 Dec 2014 17:31:15 -0500 Subject: [PATCH 10/41] Cleanup markdown for compare option list --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f3842ceca1..70975d2c0d 100644 --- a/README.md +++ b/README.md @@ -120,10 +120,10 @@ After running an index, ElasticPress integrates with WP_Query. The end goal is t ```meta_query``` accepts an array of arrays where each inner array *only* supports ```key``` (string), ```value``` (string|array|int), and ```compare``` (string) parameters. ```compare``` supports the following: - * ```=``` - Posts will be returned that have a post meta key corresponding to ```key``` and a value that equals the value passed to ```value```. - * ```!=``` - Posts will be returned that have a post meta key corresponding to ```key``` and a value that does NOT equal the value passed to ```value```. - * ```EXISTS``` - Posts will be returned that have a post meta key corresponding to ```key```. - * ```NOT EXISTS``` - Posts will be returned that do not have a post meta key corresponding to ```key```. + * ```=``` - Posts will be returned that have a post meta key corresponding to ```key``` and a value that equals the value passed to ```value```. + * ```!=``` - Posts will be returned that have a post meta key corresponding to ```key``` and a value that does NOT equal the value passed to ```value```. + * ```EXISTS``` - Posts will be returned that have a post meta key corresponding to ```key```. + * ```NOT EXISTS``` - Posts will be returned that do not have a post meta key corresponding to ```key```. The outer array also supports a ```relation``` (string) parameter. By default ```relation``` is set to ```AND```: ```php From c039f8b709a23c8ae6d492fa872e49a1f9adcab5 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 22 Dec 2014 16:22:44 -0700 Subject: [PATCH 11/41] Add WAdd WP_Query integration on init, not plugin loadP_Query integration on init, not plugin load Switches the integration setup to fire on init, once WordPress is loaded and any potential theme filters have a chance to load. Corrects an issue where it was not possible to use the ep_admin_wp_query_integration filter to enable admin side ES enhanced queries during an ajax callback (or possibly at all). Because the ep_admin_wp_query_integration filter was applied duting class instantiation (at plugin load), the returned value was always false.Switches the integration setup to fire on init, once WordPress is loaded and any potential theme filters have a chance to load. Corrects an issue where it was not possible to use the ep_admin_wp_query_integration filter to enable admin side ES enhanced queries during an ajax callback (or possibly at all). Because the ep_admin_wp_query_integration filter was applied duting class instantiation (at plugin load), the returned value was always false. --- classes/class-ep-wp-query-integration.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/classes/class-ep-wp-query-integration.php b/classes/class-ep-wp-query-integration.php index b9d51a0ff6..0fcc57e1e7 100644 --- a/classes/class-ep-wp-query-integration.php +++ b/classes/class-ep-wp-query-integration.php @@ -17,7 +17,10 @@ class EP_WP_Query_Integration { public function __construct() { } public function setup() { + add_action( 'init', array( $this, 'setup_wp_query_integration' ) ); + } + public function setup_wp_query_integration() { // Ensure we aren't on the admin (unless overridden) if ( is_admin() && ! apply_filters( 'ep_admin_wp_query_integration', false ) ) { return; From 2532b79beff6bbf2914293f20e66825d7f4505a6 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 22 Dec 2014 22:40:44 -0700 Subject: [PATCH 12/41] Update test setup to call new integration function Corrects test setup issue. --- tests/test-multisite.php | 2 +- tests/test-single-site.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test-multisite.php b/tests/test-multisite.php index 29aba11e6a..bafe526292 100644 --- a/tests/test-multisite.php +++ b/tests/test-multisite.php @@ -37,7 +37,7 @@ public function setUp() { wp_set_current_user( $admin_id ); - EP_WP_Query_Integration::factory()->setup(); + EP_WP_Query_Integration::factory()->setup_wp_query_integration(); $this->setup_test_post_type(); diff --git a/tests/test-single-site.php b/tests/test-single-site.php index 2d1a9a6254..ca08df5f93 100644 --- a/tests/test-single-site.php +++ b/tests/test-single-site.php @@ -21,7 +21,7 @@ public function setUp() { ep_activate(); - EP_WP_Query_Integration::factory()->setup(); + EP_WP_Query_Integration::factory()->setup_wp_query_integration(); $this->setup_test_post_type(); } From 90378646b69507d9ebc04589dbdda843c9285f1c Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Mon, 29 Dec 2014 15:47:20 -0500 Subject: [PATCH 13/41] Only use filters if we have an existent meta filter --- classes/class-ep-api.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/class-ep-api.php b/classes/class-ep-api.php index 0b6f26ce31..3cada99470 100644 --- a/classes/class-ep-api.php +++ b/classes/class-ep-api.php @@ -905,9 +905,9 @@ public function format_args( $args ) { if ( ! empty( $meta_filter ) ) { $filter['and'][]['bool'][$relation] = $meta_filter; - } - $use_filters = true; + $use_filters = true; + } } /** From 5f046a25222e682a5bb9b7342d62515df46f8db5 Mon Sep 17 00:00:00 2001 From: Aaron Holbrook Date: Tue, 30 Dec 2014 10:45:41 -0600 Subject: [PATCH 14/41] Revert "Add WP_Query integration on init, not plugin load" --- classes/class-ep-wp-query-integration.php | 3 --- tests/test-multisite.php | 2 +- tests/test-single-site.php | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/classes/class-ep-wp-query-integration.php b/classes/class-ep-wp-query-integration.php index 0fcc57e1e7..b9d51a0ff6 100644 --- a/classes/class-ep-wp-query-integration.php +++ b/classes/class-ep-wp-query-integration.php @@ -17,10 +17,7 @@ class EP_WP_Query_Integration { public function __construct() { } public function setup() { - add_action( 'init', array( $this, 'setup_wp_query_integration' ) ); - } - public function setup_wp_query_integration() { // Ensure we aren't on the admin (unless overridden) if ( is_admin() && ! apply_filters( 'ep_admin_wp_query_integration', false ) ) { return; diff --git a/tests/test-multisite.php b/tests/test-multisite.php index bafe526292..29aba11e6a 100644 --- a/tests/test-multisite.php +++ b/tests/test-multisite.php @@ -37,7 +37,7 @@ public function setUp() { wp_set_current_user( $admin_id ); - EP_WP_Query_Integration::factory()->setup_wp_query_integration(); + EP_WP_Query_Integration::factory()->setup(); $this->setup_test_post_type(); diff --git a/tests/test-single-site.php b/tests/test-single-site.php index ca08df5f93..2d1a9a6254 100644 --- a/tests/test-single-site.php +++ b/tests/test-single-site.php @@ -21,7 +21,7 @@ public function setUp() { ep_activate(); - EP_WP_Query_Integration::factory()->setup_wp_query_integration(); + EP_WP_Query_Integration::factory()->setup(); $this->setup_test_post_type(); } From 9c3ffed1a6864ee01776961667a92656be6fb556 Mon Sep 17 00:00:00 2001 From: Aaron Holbrook Date: Tue, 30 Dec 2014 11:17:27 -0600 Subject: [PATCH 15/41] Change setup to happen on init --- classes/class-ep-wp-query-integration.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/classes/class-ep-wp-query-integration.php b/classes/class-ep-wp-query-integration.php index 26bbab3c3a..1c2e3188d6 100644 --- a/classes/class-ep-wp-query-integration.php +++ b/classes/class-ep-wp-query-integration.php @@ -16,8 +16,11 @@ class EP_WP_Query_Integration { */ public function __construct() { } + /** + * Checks to see if we should be integrating and if so, sets up the appropriate actions and filters. + * @since 0.9 + */ public function setup() { - // Ensure we aren't on the admin (unless overridden) if ( is_admin() && ! apply_filters( 'ep_admin_wp_query_integration', false ) ) { return; @@ -54,6 +57,12 @@ public function setup() { add_action( 'the_post', array( $this, 'action_the_post' ), 10, 1 ); } + /** + * Disables cache_results + * + * @param $query + * @since 0.9 + */ public function action_pre_get_posts( $query ) { if ( ! ep_elasticpress_enabled( $query ) || apply_filters( 'ep_skip_query_integration', false, $query ) ) { return; @@ -237,7 +246,7 @@ public static function factory() { if ( ! $instance ) { $instance = new self(); - $instance->setup(); + add_action( 'init', array( $instance, 'setup' ) ); } return $instance; From 162771cc7a0b625c4c001327b9dce7d704baf5f6 Mon Sep 17 00:00:00 2001 From: Aaron Holbrook Date: Wed, 31 Dec 2014 06:09:27 -0600 Subject: [PATCH 16/41] Add composer file and travis modifications to support code climate. Adding directly to master --- .travis.yml | 8 +++++++- composer.json | 28 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 composer.json diff --git a/.travis.yml b/.travis.yml index 7fab69336a..464af842ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,13 @@ services: - elasticsearch before_script: + - mkdir -p build/logs + - if [ "$(phpenv version-name)" != "5.2" ]; then composer install --dev; fi; - bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION - sleep 5 -script: phpunit \ No newline at end of file +script: + - if [ "$(phpenv version-name)" != "5.2" ]; then phpunit --coverage-clover build/logs/clover.xml; else phpunit; fi; + +after_script: + - if [ "$(phpenv version-name) != "5.2" ]; then php vendor/bin/coveralls; ./vendor/bin/test-reporter; fi; diff --git a/composer.json b/composer.json new file mode 100644 index 0000000000..e276215b0f --- /dev/null +++ b/composer.json @@ -0,0 +1,28 @@ +{ + "name": "10up/ElasticPress", + "description": "Integrate Elasticsearch with WordPress.", + "type": "wordpress-plugin", + "keywords": ["wordpress", "plugin", "elasticsearch", "elasticpress", "search"], + "license": ["MIT"], + "authors": [ + { + "name": "Aaron Holbrook", + "email": "aaron@10up.com", + "homepage": "http://aaronjholbrook.com" + }, + { + "name": "Taylor Lovett", + "email": "taylorl@get10up.com" + }, + { + "name": "10up", + "homepage": "http://10up.com" + } + ], + "require": { + "php": ">=5.2" + }, + "require-dev": { + "codeclimate/php-test-reporter": "dev-master" + } +} From a9cb385a386458e5b44e7343315dd9a9ebb67d27 Mon Sep 17 00:00:00 2001 From: Aaron Holbrook Date: Wed, 31 Dec 2014 06:26:35 -0600 Subject: [PATCH 17/41] Added .coveralls.yml config file. Believe this is needed for the test-reporter and coveralls script --- .coveralls.yml | 5 + composer.lock | 581 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 586 insertions(+) create mode 100644 .coveralls.yml create mode 100644 composer.lock diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 0000000000..aef325a99c --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1,5 @@ +service_name: travis-ci + +src_dir: ./ +coverage_clover: build/logs/clover.xml +json_path: build/logs/coveralls-upload.json diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000000..ab9b320469 --- /dev/null +++ b/composer.lock @@ -0,0 +1,581 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "332f73e3674c21dc09f838e8b7fff5b8", + "packages": [], + "packages-dev": [ + { + "name": "codeclimate/php-test-reporter", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/codeclimate/php-test-reporter.git", + "reference": "2dd8395f81874333d15de3a598f722997ba42fb5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/codeclimate/php-test-reporter/zipball/2dd8395f81874333d15de3a598f722997ba42fb5", + "reference": "2dd8395f81874333d15de3a598f722997ba42fb5", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.3", + "satooshi/php-coveralls": "0.6.*", + "symfony/console": ">=2.0" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*@stable" + }, + "bin": [ + "composer/bin/test-reporter" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.1.x-dev" + } + }, + "autoload": { + "psr-0": { + "CodeClimate\\Component": "src/", + "CodeClimate\\Bundle": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Code Climate", + "email": "hello@codeclimate.com", + "homepage": "https://codeclimate.com" + } + ], + "description": "PHP client for reporting test coverage to Code Climate", + "homepage": "https://github.com/codeclimate/php-test-reporter", + "keywords": [ + "codeclimate", + "coverage" + ], + "time": "2014-12-29 16:17:04" + }, + { + "name": "guzzle/guzzle", + "version": "v3.9.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle3.git", + "reference": "54991459675c1a2924122afbb0e5609ade581155" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/54991459675c1a2924122afbb0e5609ade581155", + "reference": "54991459675c1a2924122afbb0e5609ade581155", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.3.3", + "symfony/event-dispatcher": "~2.1" + }, + "replace": { + "guzzle/batch": "self.version", + "guzzle/cache": "self.version", + "guzzle/common": "self.version", + "guzzle/http": "self.version", + "guzzle/inflection": "self.version", + "guzzle/iterator": "self.version", + "guzzle/log": "self.version", + "guzzle/parser": "self.version", + "guzzle/plugin": "self.version", + "guzzle/plugin-async": "self.version", + "guzzle/plugin-backoff": "self.version", + "guzzle/plugin-cache": "self.version", + "guzzle/plugin-cookie": "self.version", + "guzzle/plugin-curlauth": "self.version", + "guzzle/plugin-error-response": "self.version", + "guzzle/plugin-history": "self.version", + "guzzle/plugin-log": "self.version", + "guzzle/plugin-md5": "self.version", + "guzzle/plugin-mock": "self.version", + "guzzle/plugin-oauth": "self.version", + "guzzle/service": "self.version", + "guzzle/stream": "self.version" + }, + "require-dev": { + "doctrine/cache": "~1.3", + "monolog/monolog": "~1.0", + "phpunit/phpunit": "3.7.*", + "psr/log": "~1.0", + "symfony/class-loader": "~2.1", + "zendframework/zend-cache": "2.*,<2.3", + "zendframework/zend-log": "2.*,<2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.9-dev" + } + }, + "autoload": { + "psr-0": { + "Guzzle": "src/", + "Guzzle\\Tests": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Guzzle Community", + "homepage": "https://github.com/guzzle/guzzle/contributors" + } + ], + "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2014-08-11 04:32:36" + }, + { + "name": "psr/log", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2012-12-21 11:40:51" + }, + { + "name": "satooshi/php-coveralls", + "version": "v0.6.1", + "source": { + "type": "git", + "url": "https://github.com/satooshi/php-coveralls.git", + "reference": "dd0df95bd37a7cf5c5c50304dfe260ffe4b50760" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/dd0df95bd37a7cf5c5c50304dfe260ffe4b50760", + "reference": "dd0df95bd37a7cf5c5c50304dfe260ffe4b50760", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-simplexml": "*", + "guzzle/guzzle": ">=3.0", + "php": ">=5.3", + "psr/log": "1.0.0", + "symfony/config": ">=2.0", + "symfony/console": ">=2.0", + "symfony/stopwatch": ">=2.2", + "symfony/yaml": ">=2.0" + }, + "require-dev": { + "apigen/apigen": "2.8.*@stable", + "pdepend/pdepend": "dev-master", + "phpmd/phpmd": "dev-master", + "phpunit/php-invoker": ">=1.1.0,<1.2.0", + "phpunit/phpunit": "3.7.*@stable", + "sebastian/finder-facade": "dev-master", + "sebastian/phpcpd": "1.4.*@stable", + "squizlabs/php_codesniffer": "1.4.*@stable", + "theseer/fdomdocument": "dev-master" + }, + "bin": [ + "composer/bin/coveralls" + ], + "type": "library", + "autoload": { + "psr-0": { + "Contrib\\Component": "src/", + "Contrib\\Bundle": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kitamura Satoshi", + "email": "with.no.parachute@gmail.com", + "homepage": "https://www.facebook.com/satooshi.jp" + } + ], + "description": "PHP client library for Coveralls API", + "homepage": "https://github.com/satooshi/php-coveralls", + "keywords": [ + "ci", + "coverage", + "github", + "test" + ], + "time": "2013-05-04 08:07:33" + }, + { + "name": "symfony/config", + "version": "v2.6.1", + "target-dir": "Symfony/Component/Config", + "source": { + "type": "git", + "url": "https://github.com/symfony/Config.git", + "reference": "84c0c150c1520995f09ea9e47e817068b353cb0f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Config/zipball/84c0c150c1520995f09ea9e47e817068b353cb0f", + "reference": "84c0c150c1520995f09ea9e47e817068b353cb0f", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/filesystem": "~2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Config\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Config Component", + "homepage": "http://symfony.com", + "time": "2014-12-02 20:19:20" + }, + { + "name": "symfony/console", + "version": "v2.6.1", + "target-dir": "Symfony/Component/Console", + "source": { + "type": "git", + "url": "https://github.com/symfony/Console.git", + "reference": "ef825fd9f809d275926547c9e57cbf14968793e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Console/zipball/ef825fd9f809d275926547c9e57cbf14968793e8", + "reference": "ef825fd9f809d275926547c9e57cbf14968793e8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.1", + "symfony/process": "~2.1" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Console\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Console Component", + "homepage": "http://symfony.com", + "time": "2014-12-02 20:19:20" + }, + { + "name": "symfony/event-dispatcher", + "version": "v2.6.1", + "target-dir": "Symfony/Component/EventDispatcher", + "source": { + "type": "git", + "url": "https://github.com/symfony/EventDispatcher.git", + "reference": "720fe9bca893df7ad1b4546649473b5afddf0216" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/720fe9bca893df7ad1b4546649473b5afddf0216", + "reference": "720fe9bca893df7ad1b4546649473b5afddf0216", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.0", + "symfony/dependency-injection": "~2.6", + "symfony/expression-language": "~2.6", + "symfony/stopwatch": "~2.2" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "http://symfony.com", + "time": "2014-12-02 20:19:20" + }, + { + "name": "symfony/filesystem", + "version": "v2.6.1", + "target-dir": "Symfony/Component/Filesystem", + "source": { + "type": "git", + "url": "https://github.com/symfony/Filesystem.git", + "reference": "ff6efc95256cb33031933729e68b01d720b5436b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/ff6efc95256cb33031933729e68b01d720b5436b", + "reference": "ff6efc95256cb33031933729e68b01d720b5436b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Filesystem\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "http://symfony.com", + "time": "2014-12-02 20:19:20" + }, + { + "name": "symfony/stopwatch", + "version": "v2.6.1", + "target-dir": "Symfony/Component/Stopwatch", + "source": { + "type": "git", + "url": "https://github.com/symfony/Stopwatch.git", + "reference": "261abd360cfb6ac65ea93ffd82073e2011d034fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/261abd360cfb6ac65ea93ffd82073e2011d034fc", + "reference": "261abd360cfb6ac65ea93ffd82073e2011d034fc", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Stopwatch\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Stopwatch Component", + "homepage": "http://symfony.com", + "time": "2014-12-02 20:19:20" + }, + { + "name": "symfony/yaml", + "version": "v2.6.1", + "target-dir": "Symfony/Component/Yaml", + "source": { + "type": "git", + "url": "https://github.com/symfony/Yaml.git", + "reference": "3346fc090a3eb6b53d408db2903b241af51dcb20" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/3346fc090a3eb6b53d408db2903b241af51dcb20", + "reference": "3346fc090a3eb6b53d408db2903b241af51dcb20", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Yaml\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Yaml Component", + "homepage": "http://symfony.com", + "time": "2014-12-02 20:19:20" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "codeclimate/php-test-reporter": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.2" + }, + "platform-dev": [] +} From 40f0b1f7c7b5570d2034bcf4027c863876d487b2 Mon Sep 17 00:00:00 2001 From: Aaron Holbrook Date: Wed, 31 Dec 2014 06:58:36 -0600 Subject: [PATCH 18/41] Remove coveralls.yml - update travis.yml; Manually send test coverage to code climate via curl. --- .coveralls.yml | 5 ----- .travis.yml | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) delete mode 100644 .coveralls.yml diff --git a/.coveralls.yml b/.coveralls.yml deleted file mode 100644 index aef325a99c..0000000000 --- a/.coveralls.yml +++ /dev/null @@ -1,5 +0,0 @@ -service_name: travis-ci - -src_dir: ./ -coverage_clover: build/logs/clover.xml -json_path: build/logs/coveralls-upload.json diff --git a/.travis.yml b/.travis.yml index 464af842ea..378d62b80f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,4 +23,4 @@ script: - if [ "$(phpenv version-name)" != "5.2" ]; then phpunit --coverage-clover build/logs/clover.xml; else phpunit; fi; after_script: - - if [ "$(phpenv version-name) != "5.2" ]; then php vendor/bin/coveralls; ./vendor/bin/test-reporter; fi; + - if [ "$(phpenv version-name) != "5.2" ]; then php ./vendor/bin/test-reporter --stdout > codeclimate.json; ./vendor/bin/test-reporter; "curl -X POST -d @codeclimate.json -H 'Content-Type: application/json' -H 'User-Agent: Code Climate (PHP Test Reporter v0.1.1)' https://codeclimate.com/test_reports"; fi; From 4de580ebe0aed1f9fd24a73435acdb31f15c46fb Mon Sep 17 00:00:00 2001 From: Aaron Holbrook Date: Wed, 31 Dec 2014 07:11:28 -0600 Subject: [PATCH 19/41] Fix double escaping, invalid travis.yml file. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 378d62b80f..6a7e88279f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,4 +23,5 @@ script: - if [ "$(phpenv version-name)" != "5.2" ]; then phpunit --coverage-clover build/logs/clover.xml; else phpunit; fi; after_script: - - if [ "$(phpenv version-name) != "5.2" ]; then php ./vendor/bin/test-reporter --stdout > codeclimate.json; ./vendor/bin/test-reporter; "curl -X POST -d @codeclimate.json -H 'Content-Type: application/json' -H 'User-Agent: Code Climate (PHP Test Reporter v0.1.1)' https://codeclimate.com/test_reports"; fi; + - ./vendor/bin/test-reporter --stdout > codeclimate.json + - "if [ \"$(phpenv version-name)\" != \"5.2\" ]; then curl -X POST -d @codeclimate.json -H 'Content-Type: application/json' -H 'User-Agent: Code Climate (PHP Test Reporter v0.1.1)' https://codeclimate.com/test_reports; fi;" \ No newline at end of file From 8834bfb28ca88d499b6788886642c3b94e443d0b Mon Sep 17 00:00:00 2001 From: Aaron Holbrook Date: Wed, 31 Dec 2014 07:31:25 -0600 Subject: [PATCH 20/41] Add coverage badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ddd7dbfea2..f4d1cf3c38 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -ElasticPress [![Build Status](https://travis-ci.org/10up/ElasticPress.svg?branch=master)](https://travis-ci.org/10up/ElasticPress) +ElasticPress [![Build Status](https://travis-ci.org/10up/ElasticPress.svg?branch=master)](https://travis-ci.org/10up/ElasticPress) [![Code Climate](https://img.shields.io/codeclimate/coverage/github/10up/ElasticPress.svg?style=flat)](https://codeclimate.com/github/10up/ElasticPress) ============= Integrate [Elasticsearch](http://www.elasticsearch.org/) with [WordPress](http://wordpress.org/). From 9c74c0a380c9da238f66cdc9f60ab9f07d05edce Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Wed, 7 Jan 2015 10:04:01 -0500 Subject: [PATCH 21/41] Remove index exists check; move search to posts request filter; save searched posts in assoc array with query hash as key --- classes/class-ep-api.php | 2 +- classes/class-ep-wp-query-integration.php | 89 ++++++++++++----------- 2 files changed, 48 insertions(+), 43 deletions(-) diff --git a/classes/class-ep-api.php b/classes/class-ep-api.php index c6627e5be8..c453c37f9a 100644 --- a/classes/class-ep-api.php +++ b/classes/class-ep-api.php @@ -138,7 +138,7 @@ public function search( $args, $scope = 'current' ) { return array( 'found_posts' => $response['hits']['total'], 'posts' => $posts ); } - return array( 'found_posts' => 0, 'posts' => array() ); + return false; } /** diff --git a/classes/class-ep-wp-query-integration.php b/classes/class-ep-wp-query-integration.php index 26bbab3c3a..d7b3800599 100644 --- a/classes/class-ep-wp-query-integration.php +++ b/classes/class-ep-wp-query-integration.php @@ -9,6 +9,8 @@ class EP_WP_Query_Integration { */ private $query_stack = array(); + private $posts_by_query = array(); + /** * Placeholder method * @@ -28,11 +30,6 @@ public function setup() { return; } - // If we can't reach the Elasticsearch service, don't bother with the rest of this - if ( ! ep_index_exists() ) { - return; - } - // Make sure we return nothing for MySQL posts query add_filter( 'posts_request', array( $this, 'filter_posts_request' ), 10, 2 ); @@ -128,17 +125,52 @@ public function action_loop_end( $query ) { } /** - * Filter the posts array to contain ES search results in EP_Post form. + * Filter the posts array to contain ES search results in EP_Post form. Pull previously search posts. * * @param array $posts * @param object &$query * @return array */ public function filter_the_posts( $posts, &$query ) { - if ( ! ep_elasticpress_enabled( $query ) || apply_filters( 'ep_skip_query_integration', false, $query ) ) { + if ( ! ep_elasticpress_enabled( $query ) || apply_filters( 'ep_skip_query_integration', false, $query ) || ! isset( $this->posts_by_query[spl_object_hash( $query )] ) ) { return $posts; } + $new_posts = $this->posts_by_query[spl_object_hash( $query )]; + + return $new_posts; + } + + /** + * Remove the found_rows from the SQL Query + * + * @param string $sql + * @param object $query + * @since 0.9 + * @return string + */ + public function filter_found_posts_query( $sql, $query ) { + if ( ! ep_elasticpress_enabled( $query ) || apply_filters( 'ep_skip_query_integration', false, $query ) ) { + return $sql; + } + + return ''; + } + + /** + * Filter query string used for get_posts(). Search for posts and save for later. + * Return a query that will return nothing. + * + * @param string $request + * @param object $query + * @since 0.9 + * @return string + */ + public function filter_posts_request( $request, $query ) { + if ( ! ep_elasticpress_enabled( $query ) || apply_filters( 'ep_skip_query_integration', false, $query ) ) { + return $request; + } + $query_vars = $query->query_vars; if ( 'any' == $query_vars['post_type'] ) { unset( $query_vars['post_type'] ); @@ -153,10 +185,14 @@ public function filter_the_posts( $posts, &$query ) { $search = ep_search( $formatted_args, $scope ); + if ( false === $search ) { + return $request; + } + $query->found_posts = $search['found_posts']; $query->max_num_pages = ceil( $search['found_posts'] / $query->get( 'posts_per_page' ) ); - $posts = array(); + $new_posts = array(); foreach ( $search['posts'] as $post_array ) { $post = new stdClass(); @@ -183,43 +219,12 @@ public function filter_the_posts( $posts, &$query ) { $post = get_post( $post ); if ( $post ) { - $posts[] = $post; + $new_posts[] = $post; } } + $this->posts_by_query[spl_object_hash( $query )] = $new_posts; - do_action( 'ep_wp_query_search', $posts, $search, $query ); - - return $posts; - } - - /** - * Remove the found_rows from the SQL Query - * - * @param string $sql - * @param object $query - * @since 0.9 - * @return string - */ - public function filter_found_posts_query( $sql, $query ) { - if ( ! ep_elasticpress_enabled( $query ) || apply_filters( 'ep_skip_query_integration', false, $query ) ) { - return $sql; - } - - return ''; - } - - /** - * Filter query string used for get_posts(). Return a query that will return nothing. - * - * @param string $request - * @param object $query - * @since 0.9 - * @return string - */ - public function filter_posts_request( $request, $query ) { - if ( ! ep_elasticpress_enabled( $query ) || apply_filters( 'ep_skip_query_integration', false, $query ) ) { - return $request; - } + do_action( 'ep_wp_query_search', $new_posts, $search, $query ); global $wpdb; From f6cee6a32e0247b3579892c45867d312ed139196 Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Thu, 8 Jan 2015 09:38:52 -0500 Subject: [PATCH 22/41] Remove unneeded index exists function --- classes/class-ep-api.php | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/classes/class-ep-api.php b/classes/class-ep-api.php index c453c37f9a..b17528fb43 100644 --- a/classes/class-ep-api.php +++ b/classes/class-ep-api.php @@ -1134,32 +1134,6 @@ public function elasticsearch_alive() { return $elasticsearch_alive; } - - /** - * Ensures that this index exists - * - * @param null $index - * - * @return bool - * @since 1.1.0 - */ - public function index_exists( $index = null ) { - $index_exists = false; - - $index_url = ep_get_index_url( $index ); - - $url = $index_url . '/_status'; - - $request = wp_remote_request( $url ); - - if ( ! is_wp_error( $request ) ) { - if ( isset( $request['response']['code'] ) && 200 === $request['response']['code'] ) { - $index_exists = true; - } - } - - return $index_exists; - } } EP_API::factory(); From 29f8c6874c03d8128544522e0eb6c6bcc1a9cb62 Mon Sep 17 00:00:00 2001 From: Ivan Kruchkoff Date: Mon, 12 Jan 2015 14:19:06 +1100 Subject: [PATCH 23/41] Network wide operations only work on multisite installs --- bin/wp-cli.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/wp-cli.php b/bin/wp-cli.php index 7e21675aa8..62b5713f82 100644 --- a/bin/wp-cli.php +++ b/bin/wp-cli.php @@ -34,7 +34,7 @@ class ElasticPress_CLI_Command extends WP_CLI_Command { public function put_mapping( $args, $assoc_args ) { $this->_connect_check(); - if ( ! empty( $assoc_args['network-wide'] ) ) { + if ( ! empty( $assoc_args['network-wide'] ) && is_multisite() ) { $sites = ep_get_sites(); foreach ( $sites as $site ) { @@ -85,7 +85,7 @@ public function put_mapping( $args, $assoc_args ) { public function delete_index( $args, $assoc_args ) { $this->_connect_check(); - if ( ! empty( $assoc_args['network-wide'] ) ) { + if ( ! empty( $assoc_args['network-wide'] ) && is_multisite() ) { $sites = ep_get_sites(); foreach ( $sites as $site ) { @@ -196,7 +196,7 @@ public function index( $args, $assoc_args ) { $this->put_mapping( $args, $assoc_args ); } - if ( ! empty( $assoc_args['network-wide'] ) ) { + if ( ! empty( $assoc_args['network-wide'] ) && is_multisite() ) { WP_CLI::log( __( 'Indexing posts network-wide...', 'elasticpress' ) ); From 512974f7c2753165802ff133389f56035eb33ddd Mon Sep 17 00:00:00 2001 From: Ivan Kruchkoff Date: Wed, 14 Jan 2015 14:31:22 +1100 Subject: [PATCH 24/41] Resolve #136: Output header indicating if ES is being used for results --- classes/class-ep-wp-query-integration.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/classes/class-ep-wp-query-integration.php b/classes/class-ep-wp-query-integration.php index 1c2e3188d6..1d8c603b3a 100644 --- a/classes/class-ep-wp-query-integration.php +++ b/classes/class-ep-wp-query-integration.php @@ -39,6 +39,7 @@ public function setup() { // Make sure we return nothing for MySQL posts query add_filter( 'posts_request', array( $this, 'filter_posts_request' ), 10, 2 ); + // Add header add_action( 'pre_get_posts', array( $this, 'action_pre_get_posts' ), 5 ); // Nukes the FOUND_ROWS() database query @@ -58,7 +59,7 @@ public function setup() { } /** - * Disables cache_results + * Disables cache_results, adds header. * * @param $query * @since 0.9 @@ -69,6 +70,14 @@ public function action_pre_get_posts( $query ) { } $query->set( 'cache_results', false ); + + if ( ! headers_sent() ) { + /** + * Manually setting a header as $wp_query isn't yet initialized + * when we call: add_filter('wp_headers', 'filter_wp_headers'); + */ + header( 'X-ElasticPress-Search: true' ); + } } /** From 00f2d3174d33735729b0f107a71e545362ceee8f Mon Sep 17 00:00:00 2001 From: Ivan Kruchkoff Date: Thu, 15 Jan 2015 15:44:15 +1100 Subject: [PATCH 25/41] Cleaned up indentation --- bin/wp-cli.php | 4 ++-- classes/class-ep-wp-query-integration.php | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bin/wp-cli.php b/bin/wp-cli.php index 62b5713f82..bd84b57b1d 100644 --- a/bin/wp-cli.php +++ b/bin/wp-cli.php @@ -34,7 +34,7 @@ class ElasticPress_CLI_Command extends WP_CLI_Command { public function put_mapping( $args, $assoc_args ) { $this->_connect_check(); - if ( ! empty( $assoc_args['network-wide'] ) && is_multisite() ) { + if ( ! empty( $assoc_args['network-wide'] ) && is_multisite() ) { $sites = ep_get_sites(); foreach ( $sites as $site ) { @@ -196,7 +196,7 @@ public function index( $args, $assoc_args ) { $this->put_mapping( $args, $assoc_args ); } - if ( ! empty( $assoc_args['network-wide'] ) && is_multisite() ) { + if ( ! empty( $assoc_args['network-wide'] ) && is_multisite() ) { WP_CLI::log( __( 'Indexing posts network-wide...', 'elasticpress' ) ); diff --git a/classes/class-ep-wp-query-integration.php b/classes/class-ep-wp-query-integration.php index 1d8c603b3a..91b2ed0c8f 100644 --- a/classes/class-ep-wp-query-integration.php +++ b/classes/class-ep-wp-query-integration.php @@ -39,7 +39,7 @@ public function setup() { // Make sure we return nothing for MySQL posts query add_filter( 'posts_request', array( $this, 'filter_posts_request' ), 10, 2 ); - // Add header + // Add header add_action( 'pre_get_posts', array( $this, 'action_pre_get_posts' ), 5 ); // Nukes the FOUND_ROWS() database query @@ -71,13 +71,13 @@ public function action_pre_get_posts( $query ) { $query->set( 'cache_results', false ); - if ( ! headers_sent() ) { - /** - * Manually setting a header as $wp_query isn't yet initialized - * when we call: add_filter('wp_headers', 'filter_wp_headers'); - */ - header( 'X-ElasticPress-Search: true' ); - } + if ( ! headers_sent() ) { + /** + * Manually setting a header as $wp_query isn't yet initialized + * when we call: add_filter('wp_headers', 'filter_wp_headers'); + */ + header( 'X-ElasticPress-Search: true' ); + } } /** From 370c4633e76cf3fc35832608861be569a79ff9c3 Mon Sep 17 00:00:00 2001 From: Jonathan Bardo Date: Tue, 20 Jan 2015 13:08:57 -0500 Subject: [PATCH 26/41] issue-190 --- bin/wp-cli.php | 2 +- classes/class-ep-api.php | 4 ++-- classes/class-ep-config.php | 14 ++++++++++++++ classes/class-ep-sync-manager.php | 6 ++++-- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/bin/wp-cli.php b/bin/wp-cli.php index bd84b57b1d..209633c672 100644 --- a/bin/wp-cli.php +++ b/bin/wp-cli.php @@ -264,7 +264,7 @@ private function _index_helper( $no_bulk = false, $posts_per_page) { $args = apply_filters( 'ep_index_posts_args', array( 'posts_per_page' => $posts_per_page, 'post_type' => ep_get_indexable_post_types(), - 'post_status' => 'publish', + 'post_status' => ep_get_indexable_post_status(), 'offset' => $offset, 'ignore_sticky_posts' => true ) ); diff --git a/classes/class-ep-api.php b/classes/class-ep-api.php index 40dd748f0d..fd784734a0 100644 --- a/classes/class-ep-api.php +++ b/classes/class-ep-api.php @@ -447,7 +447,7 @@ public function put_mapping() { ), 'post_status' => array( 'type' => 'string', - 'index' => 'no' + 'index' => 'not_analyzed' ), 'post_name' => array( 'type' => 'multi_field', @@ -583,7 +583,7 @@ public function prepare_post( $post_id ) { 'post_title' => get_the_title( $post_id ), 'post_excerpt' => $post->post_excerpt, 'post_content' => apply_filters( 'the_content', $post->post_content ), - 'post_status' => 'publish', + 'post_status' => $post->post_status, 'post_name' => $post->post_name, 'post_modified' => $post_modified, 'post_modified_gmt' => $post_modified_gmt, diff --git a/classes/class-ep-config.php b/classes/class-ep-config.php index 435187ed80..ca4ec482c2 100644 --- a/classes/class-ep-config.php +++ b/classes/class-ep-config.php @@ -71,6 +71,16 @@ public function get_indexable_post_types() { return apply_filters( 'ep_indexable_post_types', $post_types ); } + /** + * Return indexable post_status for the current site + * + * @since 1.3 + * @return array + */ + public function get_indexable_post_status() { + return apply_filters( 'ep_indexable_post_status', array( 'publish' ) ); + } + /** * Generate network index name for alias * @@ -106,6 +116,10 @@ function ep_get_indexable_post_types() { return EP_Config::factory()->get_indexable_post_types(); } +function ep_get_indexable_post_status() { + return EP_Config::factory()->get_indexable_post_status(); +} + function ep_get_network_alias() { return EP_Config::factory()->get_network_alias(); } diff --git a/classes/class-ep-sync-manager.php b/classes/class-ep-sync-manager.php index 3ed5d7758d..315b4a536a 100644 --- a/classes/class-ep-sync-manager.php +++ b/classes/class-ep-sync-manager.php @@ -52,7 +52,9 @@ public function action_sync_on_transition( $new_status, $old_status, $post ) { return; } - if ( 'publish' !== $new_status && 'publish' !== $old_status ) { + $indexable_post_statuses = ep_get_indexable_post_status(); + + if ( ! in_array( $new_status, $indexable_post_statuses ) && ! in_array( $old_status, $indexable_post_statuses ) ) { return; } @@ -61,7 +63,7 @@ public function action_sync_on_transition( $new_status, $old_status, $post ) { } // Our post was published, but is no longer, so let's remove it from the Elasticsearch index - if ( 'publish' !== $new_status ) { + if ( ! in_array( $new_status, $indexable_post_statuses ) ) { $this->action_delete_post( $post->ID ); } else { $post_type = get_post_type( $post->ID ); From 028546f6e251e51da8cfe11ba44538b572b1a0ff Mon Sep 17 00:00:00 2001 From: Jonathan Bardo Date: Mon, 26 Jan 2015 15:24:39 -0500 Subject: [PATCH 27/41] Add post type to return post --- classes/class-ep-wp-query-integration.php | 1 + 1 file changed, 1 insertion(+) diff --git a/classes/class-ep-wp-query-integration.php b/classes/class-ep-wp-query-integration.php index 599570485b..827cc2dd3a 100644 --- a/classes/class-ep-wp-query-integration.php +++ b/classes/class-ep-wp-query-integration.php @@ -222,6 +222,7 @@ public function filter_posts_request( $request, $query ) { $post->site_id = $post_array['site_id']; } + $post->post_type = $post_array['post_type']; $post->post_name = $post_array['post_name']; $post->post_status = $post_array['post_status']; $post->post_title = $post_array['post_title']; From f9365f738924a79fd8ff8f8cdf74c0ea27ffb155 Mon Sep 17 00:00:00 2001 From: Ryan Boswell Date: Wed, 28 Jan 2015 11:42:14 -0800 Subject: [PATCH 28/41] Abide by the 'exclude_from_search' flag when running search queries. For other queries, continue to allow searches across all post types. --- classes/class-ep-wp-query-integration.php | 25 ++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/classes/class-ep-wp-query-integration.php b/classes/class-ep-wp-query-integration.php index 599570485b..b5c740c243 100644 --- a/classes/class-ep-wp-query-integration.php +++ b/classes/class-ep-wp-query-integration.php @@ -191,7 +191,30 @@ public function filter_posts_request( $request, $query ) { $query_vars = $query->query_vars; if ( 'any' == $query_vars['post_type'] ) { - unset( $query_vars['post_type'] ); + + if( $query->is_search() ) { + + /* + * This is a search query + * To follow WordPress conventions, + * make sure we only search 'searchable' post types + */ + $searchable_post_types = get_post_types( array( 'exclude_from_search' => false ) ); + + // Conform the post types array to an acceptable format for ES + $post_types = array(); + foreach( $searchable_post_types as $type ) { + $post_types[] = $type; + } + $query_vars['post_type'] = $post_types; + } else { + + /* + * This is not a search query + * so unset the post_type query var + */ + unset( $query_vars['post_type'] ); + } } $scope = 'current'; From b132518f6ed32e48942b86d19c5b12782cb8e1a3 Mon Sep 17 00:00:00 2001 From: Ryan Boswell Date: Thu, 29 Jan 2015 08:00:56 -0800 Subject: [PATCH 29/41] If we don't end up with any searchable post types, don't continue. Changes courtesy of @AaronHolbrook. --- classes/class-ep-wp-query-integration.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/classes/class-ep-wp-query-integration.php b/classes/class-ep-wp-query-integration.php index b5c740c243..6832f091f7 100644 --- a/classes/class-ep-wp-query-integration.php +++ b/classes/class-ep-wp-query-integration.php @@ -192,23 +192,30 @@ public function filter_posts_request( $request, $query ) { $query_vars = $query->query_vars; if ( 'any' == $query_vars['post_type'] ) { - if( $query->is_search() ) { - + if ( $query->is_search() ) { + /* * This is a search query * To follow WordPress conventions, * make sure we only search 'searchable' post types */ $searchable_post_types = get_post_types( array( 'exclude_from_search' => false ) ); - + + // If we have no searchable post types, there's no point going any further + if ( empty( $searchable_post_types ) ) { + return; + } + // Conform the post types array to an acceptable format for ES $post_types = array(); foreach( $searchable_post_types as $type ) { $post_types[] = $type; } + + // These are now the only post types we will search $query_vars['post_type'] = $post_types; } else { - + /* * This is not a search query * so unset the post_type query var From 1aa15400479066c14da49e62e24b1f809db872c6 Mon Sep 17 00:00:00 2001 From: Ryan Boswell Date: Thu, 29 Jan 2015 08:03:19 -0800 Subject: [PATCH 30/41] Make sure we do a strict check for the post_type. Changes courtesy of @AaronHolbrook. --- classes/class-ep-wp-query-integration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/class-ep-wp-query-integration.php b/classes/class-ep-wp-query-integration.php index 6832f091f7..f44ccd3096 100644 --- a/classes/class-ep-wp-query-integration.php +++ b/classes/class-ep-wp-query-integration.php @@ -190,7 +190,7 @@ public function filter_posts_request( $request, $query ) { } $query_vars = $query->query_vars; - if ( 'any' == $query_vars['post_type'] ) { + if ( 'any' === $query_vars['post_type'] ) { if ( $query->is_search() ) { From 56cebeb5a81b2f61802cdc3ead03d88342db4895 Mon Sep 17 00:00:00 2001 From: Aaron Holbrook Date: Fri, 30 Jan 2015 11:53:15 -0600 Subject: [PATCH 31/41] Add tests for excluding post types from search. Fix for returning early to ensure found_posts is properly calculated --- classes/class-ep-wp-query-integration.php | 4 +- tests/test-single-site.php | 84 +++++++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/classes/class-ep-wp-query-integration.php b/classes/class-ep-wp-query-integration.php index f44ccd3096..a55c3f5cf5 100644 --- a/classes/class-ep-wp-query-integration.php +++ b/classes/class-ep-wp-query-integration.php @@ -203,7 +203,9 @@ public function filter_posts_request( $request, $query ) { // If we have no searchable post types, there's no point going any further if ( empty( $searchable_post_types ) ) { - return; + + // Have to return something or it improperly calculates the found_posts + return "WHERE 0 = 1"; } // Conform the post types array to an acceptable format for ES diff --git a/tests/test-single-site.php b/tests/test-single-site.php index a2a0ddc7c9..97ef274bb2 100644 --- a/tests/test-single-site.php +++ b/tests/test-single-site.php @@ -1141,4 +1141,88 @@ public function testMetaQueryAdvanced() { $this->assertEquals( 1, $query->post_count ); $this->assertEquals( 1, $query->found_posts ); } + + /** + * Test exclude_from_search post type flag + * Ensure that we do not search that post type when all post types are searched + * + * @since 0.9 + */ + public function testExcludeFromSearch() { + $post_ids = array(); + + $post_ids[0] = ep_create_and_sync_post(); + $post_ids[1] = ep_create_and_sync_post(); + $post_ids[2] = ep_create_and_sync_post( array( 'post_content' => 'findme' ) ); + $post_ids[3] = ep_create_and_sync_post(); + $post_ids[4] = ep_create_and_sync_post( array( 'post_content' => 'findme' ) ); + + register_post_type( 'exclude-me', array( + 'public' => true, + 'exclude_from_search' => true, + ) ); + + $post_ids[5] = ep_create_and_sync_post( array( 'post_type' => 'exclude-me', 'post_content' => 'findme' ) ); + + ep_refresh_index(); + + $args = array( + 's' => 'findme', + ); + + add_action( 'ep_wp_query_search', array( $this, 'action_wp_query_search' ), 10, 0 ); + + $query = new WP_Query( $args ); + + $this->assertTrue( ! empty( $this->fired_actions['ep_wp_query_search'] ) ); + + $this->assertEquals( $query->post_count, 2 ); + $this->assertEquals( $query->found_posts, 2 ); + + wp_reset_postdata(); + } + + /** + * Test what happens when no post types are available to be searched + * + * @since 0.9 + */ + public function testNoAvailablePostTypesToSearch() { + $post_ids = array(); + + $post_ids[0] = ep_create_and_sync_post(); + $post_ids[1] = ep_create_and_sync_post(); + $post_ids[2] = ep_create_and_sync_post( array( 'post_content' => 'findme' ) ); + $post_ids[3] = ep_create_and_sync_post(); + $post_ids[4] = ep_create_and_sync_post( array( 'post_content' => 'findme' ) ); + + $GLOBALS['wp_post_types']; + + $backup_post_types = $GLOBALS['wp_post_types']; + + // Set all post types to be excluded from search + foreach ( $GLOBALS['wp_post_types'] as $post_type ) { + $post_type->exclude_from_search = true; + } + + ep_refresh_index(); + + $args = array( + 's' => 'findme', + ); + + add_action( 'ep_wp_query_search', array( $this, 'action_wp_query_search' ), 10, 0 ); + + $query = new WP_Query( $args ); + + $this->assertTrue( empty( $this->fired_actions['ep_wp_query_search'] ) ); + + $this->assertEquals( $query->post_count, 0 ); + $this->assertEquals( $query->found_posts, 0 ); + + wp_reset_postdata(); + + // Reset the main $wp_post_types item + $GLOBALS['wp_post_types'] = $backup_post_types; + } } \ No newline at end of file From f7dd3ac60987b9685dd28c75fd9111138e2712e7 Mon Sep 17 00:00:00 2001 From: Aaron Holbrook Date: Fri, 30 Jan 2015 11:55:57 -0600 Subject: [PATCH 32/41] Fix version numbers --- tests/test-single-site.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test-single-site.php b/tests/test-single-site.php index 97ef274bb2..821bfa8794 100644 --- a/tests/test-single-site.php +++ b/tests/test-single-site.php @@ -1146,7 +1146,7 @@ public function testMetaQueryAdvanced() { * Test exclude_from_search post type flag * Ensure that we do not search that post type when all post types are searched * - * @since 0.9 + * @since 1.3 */ public function testExcludeFromSearch() { $post_ids = array(); @@ -1185,7 +1185,7 @@ public function testExcludeFromSearch() { /** * Test what happens when no post types are available to be searched * - * @since 0.9 + * @since 1.3 */ public function testNoAvailablePostTypesToSearch() { $post_ids = array(); From 04d1d57120e60ee5c1bd1205912ad0a047082c3c Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Mon, 2 Feb 2015 15:55:28 -0500 Subject: [PATCH 33/41] Cleanup documentation; document additional WP-CLI params; add documentation for each WP-CLI command --- README.md | 43 +++++++++++++++++++++++++++++++++++++++++-- bin/wp-cli.php | 3 ++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 722b85ed9b..0d542e6b3e 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ The proceeding sets depend on whether you are configuring for single site or mul ### Single Site 2. Activate the plugin. -3. Using wp-cli, do an initial sync (with mapping) with your ES server by running the following commands: +3. Using WP-CLI, do an initial sync (with mapping) with your ES server by running the following commands: ```bash wp elasticpress index --setup @@ -57,7 +57,7 @@ wp elasticpress index --setup ### Multisite Cross-site Search 2. Network activate the plugin -3. Using wp-cli, do an initial sync (with mapping) with your ES server by running the following commands: +3. Using WP-CLI, do an initial sync (with mapping) with your ES server by running the following commands: ```bash wp elasticpress index --setup --network-wide @@ -325,6 +325,45 @@ The following are special parameters that are only supported by ElasticPress. ) ); ``` +### Supported WP-CLI Commands + +The following commands are supported by ElasticPress: + +* `wp elasticpress index [--setup] [--network-wide] [--posts-per-page] [--no-bulk]` + + Index all posts in the current blog. `--network-wide` will force indexing on all the blogs in the network. `--setup` will clear the index first and re-send the put mapping. `--posts-per-page` let's you determine the amount of posts to be indexed per bulk index (or cycle). `--no-bulk` let's you disable bulk indexing. + +* `wp elasticpress activate` + + Turns on ElasticPress integration. Integration is automatically deactivated during indexing. + +* `wp elasticpress deactivate` + + Turns off ElasticPress integration. Integration is automatically deactivated during indexing. + +* `wp elasticpress delete-index [--network-wide]` + + Deletes the current blog index. `--network-wide` will force every index on the network to be deleted. + +* `wp elasticpress is-active` + + Checks whether ElasticPress is currently integration active. This is different than whether the plugin is WordPress active or not. During indexing, integration will be deactivated automatically. + +* `wp elasticpress put-mapping [--network-wide]` + + Sends plugin put mapping to the current blog index. `--network-wide` will force mappings to be sent for every index in the network. + +* `wp elasticpress recreate-network-alias` + + Recreates the alias index which points to every index in the network. + +* `wp elasticpress stats` + + Returns basic stats on Elasticsearch instance i.e. number of documents in current index as well as disk space used. + +* `wp elasticpress status` + + ## Development ### Setup diff --git a/bin/wp-cli.php b/bin/wp-cli.php index 209633c672..be5f0820af 100644 --- a/bin/wp-cli.php +++ b/bin/wp-cli.php @@ -166,7 +166,7 @@ private function _create_network_alias() { /** * Index all posts for a site or network wide * - * @synopsis [--setup] [--network-wide] [--posts-per-page] + * @synopsis [--setup] [--network-wide] [--posts-per-page] [--no-bulk] * @param array $args * * @since 0.1.2 @@ -249,6 +249,7 @@ public function index( $args, $assoc_args ) { * Helper method for indexing posts * * @param bool $no_bulk disable bulk indexing + * @param int $posts_per_page * * @since 0.9 * @return array From 419e7602032bc50d5eb0d8e66ff8f83bfc442842 Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Mon, 2 Feb 2015 17:43:28 -0500 Subject: [PATCH 34/41] Remove improperly documented args from status WP-CLI command --- bin/wp-cli.php | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/wp-cli.php b/bin/wp-cli.php index be5f0820af..414bfa623c 100644 --- a/bin/wp-cli.php +++ b/bin/wp-cli.php @@ -449,7 +449,6 @@ private function send_bulk_errors() { /** * Ping the Elasticsearch server and retrieve a status. * - * @synopsis [--raw] [--index=] * @since 0.9.1 */ public function status() { From ad87ca4f5587286a3cd21ce0156057484964590f Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Mon, 2 Feb 2015 17:47:56 -0500 Subject: [PATCH 35/41] ep_integrate param documentation --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0d542e6b3e..5a9ad16cd1 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Creating indices is handled automatically by ElasticPress. Index names are autom ## Usage -After running an index, ElasticPress integrates with WP_Query. The end goal is to support all the parameters available to WP_Query so the transition is completely transparent. Right now, our WP_Query integration supports *many* of the relevant WP_Query parameters and adds a couple special ones. +After running an index, ElasticPress integrates with `WP_Query` if and only if the query is a search or the `ep_integrate` parameter is passed (see below). The end goal is to support all the parameters available to WP_Query so the transition is completely transparent. Right now, our WP_Query integration supports *many* of the relevant WP_Query parameters and adds a couple special ones. ### Supported WP_Query Parameters @@ -302,14 +302,14 @@ The following are special parameters that are only supported by ElasticPress. _Note:_ Nesting cross-site `WP_Query` loops can result in unexpected behavior. -* ```ep_match_all``` (*bool*) +* ```ep_integrate``` (*bool*) - Allows you to perform queries without passing a search parameter. For example: + Allows you to perform queries without passing a search parameter. This is pretty powerful as you can leverage Elasticsearch to retrieve queries that are too complex for MySQL (such as a 5-dimensional taxonomy query). For example: Get 20 of the lastest posts ```php new WP_Query( array( - 'ep_match_all' => true, + 'ep_integrate' => true, 'post_type' => 'post', 'posts_per_page' => 20, ) ); @@ -318,7 +318,7 @@ The following are special parameters that are only supported by ElasticPress. Get all posts with a specific category ```php new WP_Query( array( - 'ep_match_all' => true, + 'ep_integrate' => true, 'post_type' => 'post', 'posts_per_page' => -1, 'category' => 5, From 65df011444c1b45940930922317fb7d335288b7d Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Mon, 2 Feb 2015 17:48:47 -0500 Subject: [PATCH 36/41] GPLv2 license --- README.md | 5 +++++ readme.txt | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5a9ad16cd1..e55f88a110 100644 --- a/README.md +++ b/README.md @@ -403,3 +403,8 @@ EP_HOST="http://192.168.50.4:9200" phpunit ### Issues If you identify any errors or have an idea for improving the plugin, please [open an issue](https://github.com/10up/ElasticPress/issues?state=open). We're excited to see what the community thinks of this project, and we would love your input! + + +## License + +ElasticPress is free software; you can redistribute it and/or modify it under the terms of the [GNU General Public License](http://www.gnu.org/licenses/gpl-2.0.html) as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. \ No newline at end of file diff --git a/readme.txt b/readme.txt index d8d9a39291..25d20763d8 100644 --- a/readme.txt +++ b/readme.txt @@ -6,8 +6,8 @@ Tags: search, elasticsearch, fuzzy, facet, searching, autosuggest, suggest, elas Requires at least: 3.7.1 Tested up to: 4.1 Stable tag: 1.2 -License: MIT -License URI: http://opensource.org/licenses/MIT +License: GPLv2 or later +License URI: http://www.gnu.org/licenses/gpl-2.0.html Integrate Elasticsearch with WordPress. From 6b37d0e97d5d67339d394ba425ece966963fe569 Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Mon, 2 Feb 2015 17:49:15 -0500 Subject: [PATCH 37/41] Increment version to 1.3; GPLv2 or later --- elasticpress.php | 4 ++-- readme.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/elasticpress.php b/elasticpress.php index fa7126bac5..87611c5b3b 100644 --- a/elasticpress.php +++ b/elasticpress.php @@ -3,10 +3,10 @@ /** * Plugin Name: ElasticPress * Description: Integrate WordPress search with Elasticsearch - * Version: 1.2 + * Version: 1.3 * Author: Aaron Holbrook, Taylor Lovett, Matt Gross, 10up * Author URI: http://10up.com - * License: MIT + * License: GPLv2 or later * * This program derives work from Alley Interactive's SearchPress * and Automattic's VIP search plugin: diff --git a/readme.txt b/readme.txt index 25d20763d8..c2a27b3218 100644 --- a/readme.txt +++ b/readme.txt @@ -5,7 +5,7 @@ Plugin URI: https://github.com/10up/ElasticPress Tags: search, elasticsearch, fuzzy, facet, searching, autosuggest, suggest, elastic, advanced search Requires at least: 3.7.1 Tested up to: 4.1 -Stable tag: 1.2 +Stable tag: 1.3 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html From b691885edb315a3736f736482aebe044fc642593 Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Tue, 3 Feb 2015 09:41:33 -0500 Subject: [PATCH 38/41] Pass original args to formatted args filter - see 158 --- classes/class-ep-api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/class-ep-api.php b/classes/class-ep-api.php index fd784734a0..eec4ee44bb 100644 --- a/classes/class-ep-api.php +++ b/classes/class-ep-api.php @@ -1058,7 +1058,7 @@ public function format_args( $args ) { } } - return apply_filters( 'ep_formatted_args', $formatted_args ); + return apply_filters( 'ep_formatted_args', $formatted_args, $args ); } /** From 48445e2f3279b6b833c82989029b8ae654ef71d4 Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Tue, 3 Feb 2015 10:13:59 -0500 Subject: [PATCH 39/41] Make analyzer language and put mapping request easily filterable --- classes/class-ep-api.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/classes/class-ep-api.php b/classes/class-ep-api.php index eec4ee44bb..92ab37c918 100644 --- a/classes/class-ep-api.php +++ b/classes/class-ep-api.php @@ -292,7 +292,7 @@ public function put_mapping() { 'default' => array( 'tokenizer' => 'standard', 'filter' => array( 'standard', 'ewp_word_delimiter', 'lowercase', 'stop', 'ewp_snowball' ), - 'language' => 'English' + 'language' => apply_filters( 'ep_analyzer_language', 'English' ), ), 'shingle_analyzer' => array( 'type' => 'custom', @@ -515,6 +515,8 @@ public function put_mapping() { $request = wp_remote_request( $index_url, array( 'body' => json_encode( $mapping ), 'method' => 'PUT' ) ); + $request = apply_filters( 'ep_config_mapping_request', $request, $index_url, $mapping ); + if ( ! is_wp_error( $request ) && 200 === wp_remote_retrieve_response_code( $request ) ) { $response_body = wp_remote_retrieve_body( $request ); From d55f43d8251368a725daababe45029709aa0a971 Mon Sep 17 00:00:00 2001 From: Aaron Holbrook Date: Tue, 3 Feb 2015 10:41:02 -0600 Subject: [PATCH 40/41] Add missing filter for snowball --- classes/class-ep-api.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/class-ep-api.php b/classes/class-ep-api.php index 92ab37c918..09dc2d97ca 100644 --- a/classes/class-ep-api.php +++ b/classes/class-ep-api.php @@ -312,8 +312,8 @@ public function put_mapping() { ), 'ewp_snowball' => array( 'type' => 'snowball', - 'language' => 'English' - ), + 'language' => apply_filters( 'ep_analyzer_language', 'English' ), + ), 'edge_ngram' => array( 'side' => 'front', 'max_gram' => 10, From b57d9e1f23f3024b6504d217d76ab75e1d39f766 Mon Sep 17 00:00:00 2001 From: Taylor Lovett Date: Tue, 3 Feb 2015 12:05:12 -0500 Subject: [PATCH 41/41] Add 1.3 props --- readme.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/readme.txt b/readme.txt index c2a27b3218..8c04349882 100644 --- a/readme.txt +++ b/readme.txt @@ -58,6 +58,18 @@ configuring single site and multi-site cross-site search are slightly different. == Changelog == += 1.3 = +* Support `meta_query` in WP_Query integration +* Improved documentation. Each WP-CLI command has been documented +* Add `elasticsearch` property to global post object to assist in debugging +* `ep_integrate` param added to allow for WP_Query integration without search. (Formally called ep_match_all) +* Bug fix: check if failed post exists in indexing. Props [elliot-stocks](https://github.com/elliott-stocks) +* Bug fix: properly check if setup is defined in indexing. Props [elliot-stocks](https://github.com/elliott-stocks) +* Bug fix: add WP_Query integration on init rather than plugins loaded. Props [adamsilverstein](https://github.com/adamsilverstein) +* Bug fix: Properly set global post object post type in loop. Props [tott](https://github.com/tott) +* Bug fix: Do not check if index exists on every page load. Refactor so we can revert to MySQL after failed ES ping. +* Bug fix: Make sure we check `is_multisite()` if `--network-wide` is provided [ivankruchkoff](https://github.com/ivankruchkoff) + = 1.2 = * Allow number of shards and replicas to be configurable. * Improved searching algorithm. Favor exact matches over fuzzy matches.