From 866983367c976be71dac57f579f0f471edd4ca19 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Fri, 28 Apr 2017 15:41:10 -0400 Subject: [PATCH 01/20] Adding in support for post_name__in --- class-es-wp-query-shoehorn.php | 2 +- class-es-wp-query-wrapper.php | 5 +++++ tests/query/query.php | 29 +++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/class-es-wp-query-shoehorn.php b/class-es-wp-query-shoehorn.php index 3d7c938..6818570 100644 --- a/class-es-wp-query-shoehorn.php +++ b/class-es-wp-query-shoehorn.php @@ -219,4 +219,4 @@ private function reboot_query_vars( &$query ) { $q['posts_per_page'] = get_option( 'posts_per_page' ); } } -} \ No newline at end of file +} diff --git a/class-es-wp-query-wrapper.php b/class-es-wp-query-wrapper.php index 5c64f0a..201bcb8 100644 --- a/class-es-wp-query-wrapper.php +++ b/class-es-wp-query-wrapper.php @@ -462,6 +462,9 @@ public function get_posts() { $q['attachment'] = sanitize_title_for_query( wp_basename( $q['attachment'] ) ); $q['name'] = $q['attachment']; $filter[] = $this->dsl_terms( $this->es_map( 'post_name' ), $q['attachment'] ); + } elseif ( ! empty( $q['post_name__in'] ) ) { + $post_name__in = $q['post_name__in']; + $filter[] = $this->dsl_terms( $this->es_map( 'post_name' ), $post_name__in ); } @@ -688,6 +691,8 @@ public function get_posts() { } elseif ( $q['orderby'] == 'post_parent__in' && ! empty( $post_parent__in ) ) { // (see above) // $orderby = "FIELD( {$wpdb->posts}.post_parent, $post_parent__in )"; + } elseif ( $q['orderby'] === 'post_name__in' && ! empty( $post_name__in ) ) { + // (see above) } else { if ( is_array( $q['orderby'] ) ) { foreach ( $q['orderby'] as $_orderby => $order ) { diff --git a/tests/query/query.php b/tests/query/query.php index d51f4bd..5d0223b 100644 --- a/tests/query/query.php +++ b/tests/query/query.php @@ -67,4 +67,33 @@ function test_orderby() { $q5 = new ES_WP_Query( array( 'orderby' => array() ) ); $this->assertFalse( isset( $q5->es_args['sort'] ) ); } + + function test_post_name__in() { + $post_a = $this->factory->post->create( [ 'post_name' => 'post-a' ] ); + $post_b = $this->factory->post->create( [ 'post_name' => 'post-b' ] ); + $post_c = $this->factory->post->create( [ 'post_name' => 'post-c' ] ); + es_wp_query_index_test_data(); + + $post_name__in = [ + 'post-c', + 'post-a', + 'post-b', + ]; + + $q = new ES_WP_Query( [ + 'post_name__in' => $post_name__in, + + 'orderby' => 'post_name__in', + 'order' => 'ASC', + ] ); + + $this->assertNotEmpty( $q->posts ); + + // Unable to verify the order at this time. + foreach ( $q->posts as $post ) { + // Verify that the post name is in the proper array. + $this->assertTrue( in_array( $post->post_name, $post_name__in, true ) ); + } + + } } From 33febe5d06ee40cf34887a83cbbcc01b32c47483 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Mon, 1 May 2017 15:46:53 -0400 Subject: [PATCH 02/20] Adding in post query sort handler --- class-es-wp-query-wrapper.php | 57 ++++++++++++++++++++++++++++++++--- tests/query/query.php | 8 +++-- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/class-es-wp-query-wrapper.php b/class-es-wp-query-wrapper.php index 201bcb8..1e26788 100644 --- a/class-es-wp-query-wrapper.php +++ b/class-es-wp-query-wrapper.php @@ -47,7 +47,7 @@ protected function set_posts( $q, $es_response ) { $post_id = (array) $hit['fields'][ $this->es_map( 'post_id' ) ]; $this->posts[] = reset( $post_id ); } - return; + break; case 'id=>parent' : foreach ( $es_response['hits']['hits'] as $hit ) { @@ -55,12 +55,11 @@ protected function set_posts( $q, $es_response ) { $post_parent = (array) $hit['fields'][ $this->es_map( 'post_parent' ) ]; $this->posts[ reset( $post_id ) ] = reset( $post_parent ); } - return; + break; default : if ( apply_filters( 'es_query_use_source', false ) ) { $this->posts = wp_list_pluck( $es_response['hits']['hits'], '_source' ); - return; } else { $post_ids = array(); foreach ( $es_response['hits']['hits'] as $hit ) { @@ -73,12 +72,62 @@ protected function set_posts( $q, $es_response ) { $post__in = implode( ',', $post_ids ); $this->posts = $wpdb->get_results( "SELECT $wpdb->posts.* FROM $wpdb->posts WHERE ID IN ($post__in) ORDER BY FIELD( {$wpdb->posts}.ID, $post__in )" ); } - return; } + break; } } else { $this->posts = array(); } + + $this->post_query_sort_handler( $q ); + } + + /** + * Post query sort handler + */ + protected function post_query_sort_handler( $query ) { + switch ( $query['orderby'] ) { + case 'post__in' : + + break; + + case 'post_parent__in' : + + break; + + case 'post_name__in' : + $order = array_flip( $query['post_name__in'] ); + usort( $this->posts, function( $a, $b ) use ( $order ) { + // Add support for a query of only post ID fields. + if ( ! ( $a instanceof WP_Post ) ) { + $a = get_post( $a ); + } + + if ( ! ( $b instanceof WP_Post ) ) { + $b = get_post( $b ); + } + + if ( ! isset( $order[ $a->post_name ] ) || ! isset( $order[ $b->post_name ] ) ) { + // If a post exists in the results but the post name doesn't exist in the query. + return 0; + } + + return $order[ $a->post_name ] < $order[ $b->post_name ] ? -1 : 1; + } ); + break; + } + + // } elseif ( 'none' == $q['orderby'] ) { + // // nothing to see here + // } elseif ( $q['orderby'] == 'post__in' && ! empty( $post__in ) ) { + // // @todo: Figure this out... Elasticsearch doesn't have an equivalent of this + // // $orderby = "FIELD( {$wpdb->posts}.ID, $post__in )"; + // } elseif ( $q['orderby'] == 'post_parent__in' && ! empty( $post_parent__in ) ) { + // // (see above) + // // $orderby = "FIELD( {$wpdb->posts}.post_parent, $post_parent__in )"; + // } elseif ( $q['orderby'] === 'post_name__in' && ! empty( $post_name__in ) ) { + // // (see above) + // } else { } // @todo: Core queries where 1=0 here, which probably happens for good reason. diff --git a/tests/query/query.php b/tests/query/query.php index 5d0223b..9e417dd 100644 --- a/tests/query/query.php +++ b/tests/query/query.php @@ -82,18 +82,20 @@ function test_post_name__in() { $q = new ES_WP_Query( [ 'post_name__in' => $post_name__in, - 'orderby' => 'post_name__in', 'order' => 'ASC', ] ); $this->assertNotEmpty( $q->posts ); - // Unable to verify the order at this time. + // Verify that the post name is in the proper array. foreach ( $q->posts as $post ) { - // Verify that the post name is in the proper array. $this->assertTrue( in_array( $post->post_name, $post_name__in, true ) ); } + // Assert that the order matches + foreach ( $post_name__in as $i => $post_name ) { + $this->assertEquals( $post_name, $q->posts[ $i ]->post_name ); + } } } From b51fe099fbf11259f2312b4625453aac6b6c8629 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Mon, 1 May 2017 16:16:01 -0400 Subject: [PATCH 03/20] Adding in post query sort handler --- class-es-wp-query-wrapper.php | 72 ++++++++++++++++++----------------- tests/query/query.php | 44 ++++++++++++++++++++- 2 files changed, 81 insertions(+), 35 deletions(-) diff --git a/class-es-wp-query-wrapper.php b/class-es-wp-query-wrapper.php index 1e26788..3e72ce4 100644 --- a/class-es-wp-query-wrapper.php +++ b/class-es-wp-query-wrapper.php @@ -47,6 +47,8 @@ protected function set_posts( $q, $es_response ) { $post_id = (array) $hit['fields'][ $this->es_map( 'post_id' ) ]; $this->posts[] = reset( $post_id ); } + + $this->posts = $this->post_query_sort_handler( $this->posts, $q ); break; case 'id=>parent' : @@ -72,62 +74,64 @@ protected function set_posts( $q, $es_response ) { $post__in = implode( ',', $post_ids ); $this->posts = $wpdb->get_results( "SELECT $wpdb->posts.* FROM $wpdb->posts WHERE ID IN ($post__in) ORDER BY FIELD( {$wpdb->posts}.ID, $post__in )" ); } + + $this->posts = $this->post_query_sort_handler( $this->posts, $q ); } break; } } else { $this->posts = array(); } - - $this->post_query_sort_handler( $q ); } /** * Post query sort handler + * Handle sorting by `post__in`, `post__in` and `post_parent__in`. + * + * @param array $posts Query result posts. + * @param array $query Initial query. + * @return array Sorted posts. */ - protected function post_query_sort_handler( $query ) { + protected function post_query_sort_handler( $posts, $query ) { + if ( empty( $query['orderby'] ) ) { + return $posts; + } + + // Determine the key to sort by. switch ( $query['orderby'] ) { case 'post__in' : + $key = 'ID'; + break; + case 'post_name__in' : + $key = 'post_name'; break; - case 'post_parent__in' : + default : + return $posts; + } - break; + // Flip the order to allow retrieval by index. + $order = array_flip( $query[ $query['orderby'] ] ); - case 'post_name__in' : - $order = array_flip( $query['post_name__in'] ); - usort( $this->posts, function( $a, $b ) use ( $order ) { - // Add support for a query of only post ID fields. - if ( ! ( $a instanceof WP_Post ) ) { - $a = get_post( $a ); - } + usort( $posts, function( $a, $b ) use ( $order, $key ) { + // Add support for a query of only post ID fields. + if ( ! ( $a instanceof WP_Post ) ) { + $a = get_post( $a ); + } - if ( ! ( $b instanceof WP_Post ) ) { - $b = get_post( $b ); - } + if ( ! ( $b instanceof WP_Post ) ) { + $b = get_post( $b ); + } - if ( ! isset( $order[ $a->post_name ] ) || ! isset( $order[ $b->post_name ] ) ) { - // If a post exists in the results but the post name doesn't exist in the query. - return 0; - } + if ( ! isset( $order[ $a->$key ] ) || ! isset( $order[ $b->$key ] ) ) { + return 0; + } - return $order[ $a->post_name ] < $order[ $b->post_name ] ? -1 : 1; - } ); - break; - } + return $order[ $a->$key ] < $order[ $b->$key ] ? -1 : 1; + } ); - // } elseif ( 'none' == $q['orderby'] ) { - // // nothing to see here - // } elseif ( $q['orderby'] == 'post__in' && ! empty( $post__in ) ) { - // // @todo: Figure this out... Elasticsearch doesn't have an equivalent of this - // // $orderby = "FIELD( {$wpdb->posts}.ID, $post__in )"; - // } elseif ( $q['orderby'] == 'post_parent__in' && ! empty( $post_parent__in ) ) { - // // (see above) - // // $orderby = "FIELD( {$wpdb->posts}.post_parent, $post_parent__in )"; - // } elseif ( $q['orderby'] === 'post_name__in' && ! empty( $post_name__in ) ) { - // // (see above) - // } else { + return $posts; } // @todo: Core queries where 1=0 here, which probably happens for good reason. diff --git a/tests/query/query.php b/tests/query/query.php index 9e417dd..b15eb60 100644 --- a/tests/query/query.php +++ b/tests/query/query.php @@ -68,6 +68,44 @@ function test_orderby() { $this->assertFalse( isset( $q5->es_args['sort'] ) ); } + function test_orderby_post__in() { + $p_a = $this->factory->post->create(); + $p_b = $this->factory->post->create(); + $p_c = $this->factory->post->create(); + $p_d = $this->factory->post->create(); + es_wp_query_index_test_data(); + + $post__in = [ + $p_c, + $p_a, + $p_d, + $p_b, + ]; + + $q = new ES_WP_Query( [ + 'post__in' => $post__in, + 'orderby' => 'post__in', + 'order' => 'ASC', + 'posts_per_page' => 4, + ] ); + + $this->assertNotEmpty( $q->posts ); + + // Verify that the post is in the proper array. + foreach ( $q->posts as $post ) { + $this->assertTrue( in_array( $post->ID, $post__in, true ) ); + } + + // Assert that the order matches + foreach ( $post__in as $i => $post_ID ) { + $this->assertEquals( + $post_ID, + $q->posts[ $i ]->ID, + 'Post not in expected order from `post__in`.' + ); + } + } + function test_post_name__in() { $post_a = $this->factory->post->create( [ 'post_name' => 'post-a' ] ); $post_b = $this->factory->post->create( [ 'post_name' => 'post-b' ] ); @@ -95,7 +133,11 @@ function test_post_name__in() { // Assert that the order matches foreach ( $post_name__in as $i => $post_name ) { - $this->assertEquals( $post_name, $q->posts[ $i ]->post_name ); + $this->assertEquals( + $post_name, + $q->posts[ $i ]->post_name, + 'Post not in expected order from `post_name__in`.' + ); } } } From ea8d1bc5f043ba6008583360acf52adbf066d7b1 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Mon, 1 May 2017 16:22:32 -0400 Subject: [PATCH 04/20] Adding support for post_parent__in, need test --- class-es-wp-query-wrapper.php | 10 +++++++++- tests/query/query.php | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/class-es-wp-query-wrapper.php b/class-es-wp-query-wrapper.php index 3e72ce4..e81bcc2 100644 --- a/class-es-wp-query-wrapper.php +++ b/class-es-wp-query-wrapper.php @@ -107,6 +107,10 @@ protected function post_query_sort_handler( $posts, $query ) { $key = 'post_name'; break; + case 'post_parent__in' : + $key = 'post_parent'; + break; + default : return $posts; } @@ -128,7 +132,11 @@ protected function post_query_sort_handler( $posts, $query ) { return 0; } - return $order[ $a->$key ] < $order[ $b->$key ] ? -1 : 1; + if ( $order[ $a->$key ] === $order[ $b->$key ] ) { + return 0; + } else { + return $order[ $a->$key ] < $order[ $b->$key ] ? -1 : 1; + } } ); return $posts; diff --git a/tests/query/query.php b/tests/query/query.php index b15eb60..712872f 100644 --- a/tests/query/query.php +++ b/tests/query/query.php @@ -140,4 +140,8 @@ function test_post_name__in() { ); } } + + public function test_orderby_post_parent__in() { + + } } From 1c602e89e840adea271dfd53197f711ce48a59a1 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Mon, 1 May 2017 16:24:01 -0400 Subject: [PATCH 05/20] Adding support for post_parent__in, need test --- tests/query/query.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/query/query.php b/tests/query/query.php index 712872f..6df89d5 100644 --- a/tests/query/query.php +++ b/tests/query/query.php @@ -142,6 +142,15 @@ function test_post_name__in() { } public function test_orderby_post_parent__in() { - + $parent_a = $this->factory->post->create(); + $parent_b = $this->factory->post->create(); + $parent_c = $this->factory->post->create(); + $children = []; + + foreach( [ $parent_a, $parent_b, $parent_c ] as $parent ) { + for ( $i = 0; $i < 2; $i += 1 ) { + var_dump($i); + } + } } } From 81fefc45f76d055c08b58976ab95e035cd73a49a Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Mon, 1 May 2017 17:02:58 -0400 Subject: [PATCH 06/20] Adding post_parent__in --- tests/query/query.php | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/tests/query/query.php b/tests/query/query.php index 6df89d5..81fe0eb 100644 --- a/tests/query/query.php +++ b/tests/query/query.php @@ -141,16 +141,49 @@ function test_post_name__in() { } } - public function test_orderby_post_parent__in() { + public function test_post_parent__in() { $parent_a = $this->factory->post->create(); $parent_b = $this->factory->post->create(); $parent_c = $this->factory->post->create(); $children = []; foreach( [ $parent_a, $parent_b, $parent_c ] as $parent ) { - for ( $i = 0; $i < 2; $i += 1 ) { - var_dump($i); - } + $children[ $parent ] = $this->factory->post->create( [ 'post_parent' => $parent ] ); + } + + es_wp_query_index_test_data(); + + $post_parent__in = [ + $parent_b, + $parent_a, + $parent_c, + ]; + + $q = new ES_WP_Query( [ + 'post_parent__in' => $post_parent__in, + 'orderby' => 'post_parent__in', + 'order' => 'ASC', + 'posts_per_page' => 9, // 3 parents * 2 children each. + ] ); + + $this->assertNotEmpty( $q->posts ); + + // Verify that the post is in the proper children array. + foreach ( $q->posts as $post ) { + $this->assertEquals( + $post->ID, + $children[ $post->post_parent ], + 'Unexpected post returned from `post_parent__in`.' + ); + } + + // Verify the order of `post_parent__in`. + foreach ( $post_parent__in as $i => $post_parent_id ) { + $this->assertEquals( + $post_parent_id, + $q->posts[ $i ]->post_parent, + 'Post not in expected order from `post_parent__in`.' + ); } } } From c3955bb460a7546fdbc46bbd242a6aee1467f302 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Mon, 1 May 2017 17:04:43 -0400 Subject: [PATCH 07/20] Revert one --- class-es-wp-query-wrapper.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/class-es-wp-query-wrapper.php b/class-es-wp-query-wrapper.php index e81bcc2..1327457 100644 --- a/class-es-wp-query-wrapper.php +++ b/class-es-wp-query-wrapper.php @@ -49,7 +49,7 @@ protected function set_posts( $q, $es_response ) { } $this->posts = $this->post_query_sort_handler( $this->posts, $q ); - break; + return; case 'id=>parent' : foreach ( $es_response['hits']['hits'] as $hit ) { @@ -57,7 +57,7 @@ protected function set_posts( $q, $es_response ) { $post_parent = (array) $hit['fields'][ $this->es_map( 'post_parent' ) ]; $this->posts[ reset( $post_id ) ] = reset( $post_parent ); } - break; + return; default : if ( apply_filters( 'es_query_use_source', false ) ) { @@ -77,7 +77,7 @@ protected function set_posts( $q, $es_response ) { $this->posts = $this->post_query_sort_handler( $this->posts, $q ); } - break; + return; } } else { $this->posts = array(); From 373c9cab42a13ac2c992a6a39db53741f5080039 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Mon, 1 May 2017 17:08:26 -0400 Subject: [PATCH 08/20] Add test coverage for 'id' field query --- tests/query/query.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/query/query.php b/tests/query/query.php index 81fe0eb..e2548a8 100644 --- a/tests/query/query.php +++ b/tests/query/query.php @@ -104,6 +104,31 @@ function test_orderby_post__in() { 'Post not in expected order from `post__in`.' ); } + + // Query only the ID field. + $q2 = new ES_WP_Query( [ + 'post__in' => $post__in, + 'orderby' => 'post__in', + 'order' => 'ASC', + 'posts_per_page' => 4, + 'fields' => 'ids', + ] ); + + $this->assertNotEmpty( $q2->posts ); + + // Verify that the post is in the proper array. + foreach ( $q2->posts as $post ) { + $this->assertTrue( in_array( $post, $post__in, true ) ); + } + + // Assert that the order matches + foreach ( $post__in as $i => $post_ID ) { + $this->assertEquals( + $post_ID, + $q2->posts[ $i ], + 'Post not in expected order from `post__in`.' + ); + } } function test_post_name__in() { From ee97c65eb895337fd0b2e811cdc365cc717fd169 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Mon, 1 May 2017 17:09:33 -0400 Subject: [PATCH 09/20] Remove 5.3 support --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index b84ca7c..7c5fc83 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,10 +2,6 @@ language: php matrix: include: - - php: 5.3 - env: WP_VERSION=4.3.3 ES_VERSION=2.2.0 - - php: 5.3 - env: WP_VERSION=latest ES_VERSION=2.2.0 - php: 5.6 env: WP_VERSION=latest ES_VERSION=2.2.0 - php: 7.0 From dd077b9534e9341dc9f22f4d1ec4b00ad7ff8d3d Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Mon, 1 May 2017 17:11:22 -0400 Subject: [PATCH 10/20] Fixing travis --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index 7c5fc83..fefe759 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,13 @@ before_install: - sudo service elasticsearch start before_script: + - export PATH="$HOME/.composer/vendor/bin:$PATH" + - | + if [[ ${TRAVIS_PHP_VERSION:0:2} == "7." ]]; then + composer global require "phpunit/phpunit=5.7.*" + else + composer global require "phpunit/phpunit=4.8.*" + fi - bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION - sleep 5 # ensure ES is running From 934970bd1ae0a2e8b24261def8d654c38d5e3c27 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Mon, 1 May 2017 17:19:00 -0400 Subject: [PATCH 11/20] Drop the ppp --- tests/query/query.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/query/query.php b/tests/query/query.php index e2548a8..de0a58e 100644 --- a/tests/query/query.php +++ b/tests/query/query.php @@ -188,7 +188,6 @@ public function test_post_parent__in() { 'post_parent__in' => $post_parent__in, 'orderby' => 'post_parent__in', 'order' => 'ASC', - 'posts_per_page' => 9, // 3 parents * 2 children each. ] ); $this->assertNotEmpty( $q->posts ); From 14f415f1c5a77fd984dfc1786337add9ac025171 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Tue, 2 May 2017 13:02:31 -0400 Subject: [PATCH 12/20] Adding sorting to the wpcom wrapper --- adapters/wpcom-vip.php | 6 ++++-- tests/query/query.php | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/adapters/wpcom-vip.php b/adapters/wpcom-vip.php index f012bb3..1254007 100644 --- a/adapters/wpcom-vip.php +++ b/adapters/wpcom-vip.php @@ -20,6 +20,8 @@ protected function set_posts( $q, $es_response ) { $post_id = (array) $hit['fields'][ $this->es_map( 'post_id' ) ]; $this->posts[] = reset( $post_id ); } + + $this->posts = $this->post_query_sort_handler( $this->posts, $q ); return; case 'id=>parent' : @@ -33,7 +35,6 @@ protected function set_posts( $q, $es_response ) { default : if ( apply_filters( 'es_query_use_source', false ) ) { $this->posts = wp_list_pluck( $es_response['results']['hits'], '_source' ); - return; } else { $post_ids = array(); foreach ( $es_response['results']['hits'] as $hit ) { @@ -46,8 +47,9 @@ protected function set_posts( $q, $es_response ) { $post__in = implode( ',', $post_ids ); $this->posts = $wpdb->get_results( "SELECT $wpdb->posts.* FROM $wpdb->posts WHERE ID IN ($post__in) ORDER BY FIELD( {$wpdb->posts}.ID, $post__in )" ); } - return; } + + $this->posts = $this->post_query_sort_handler( $this->posts, $q ); } } else { $this->posts = array(); diff --git a/tests/query/query.php b/tests/query/query.php index de0a58e..0164808 100644 --- a/tests/query/query.php +++ b/tests/query/query.php @@ -156,7 +156,7 @@ function test_post_name__in() { $this->assertTrue( in_array( $post->post_name, $post_name__in, true ) ); } - // Assert that the order matches + // Assert that the order matches. foreach ( $post_name__in as $i => $post_name ) { $this->assertEquals( $post_name, From dae3f15a7e76e9d41d7384c5bdbfb8294826ac91 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Tue, 2 May 2017 13:18:52 -0400 Subject: [PATCH 13/20] Add support for the 'es_query_use_source' filter --- class-es-wp-query-wrapper.php | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/class-es-wp-query-wrapper.php b/class-es-wp-query-wrapper.php index 1327457..42e03b2 100644 --- a/class-es-wp-query-wrapper.php +++ b/class-es-wp-query-wrapper.php @@ -74,10 +74,9 @@ protected function set_posts( $q, $es_response ) { $post__in = implode( ',', $post_ids ); $this->posts = $wpdb->get_results( "SELECT $wpdb->posts.* FROM $wpdb->posts WHERE ID IN ($post__in) ORDER BY FIELD( {$wpdb->posts}.ID, $post__in )" ); } - - $this->posts = $this->post_query_sort_handler( $this->posts, $q ); } - return; + + $this->posts = $this->post_query_sort_handler( $this->posts, $q ); } } else { $this->posts = array(); @@ -117,15 +116,26 @@ protected function post_query_sort_handler( $posts, $query ) { // Flip the order to allow retrieval by index. $order = array_flip( $query[ $query['orderby'] ] ); + $use_source = apply_filters( 'es_query_use_source', false ); - usort( $posts, function( $a, $b ) use ( $order, $key ) { - // Add support for a query of only post ID fields. - if ( ! ( $a instanceof WP_Post ) ) { - $a = get_post( $a ); - } + usort( $posts, function( $a, $b ) use ( $order, $key, $use_source ) { + // Add support for using the Elasticsearch _source field. + if ( $use_source && 'ID' === $key ) { + // Elasticsearch stores the `ID` field as `post_id`. + $key = 'post_id'; - if ( ! ( $b instanceof WP_Post ) ) { - $b = get_post( $b ); + // Cast the array to object to mock the `WP_Post` object. + $a = (object) $a; + $b = (object) $b; + } else { + // Add support for a query of only post ID fields. + if ( ! ( $a instanceof WP_Post ) ) { + $a = get_post( $a ); + } + + if ( ! ( $b instanceof WP_Post ) ) { + $b = get_post( $b ); + } } if ( ! isset( $order[ $a->$key ] ) || ! isset( $order[ $b->$key ] ) ) { From a1e9fb204d9a6be364152083178e317f057896e4 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Tue, 2 May 2017 13:19:55 -0400 Subject: [PATCH 14/20] Add support for the 'es_query_use_source' filter --- tests/query/query.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/query/query.php b/tests/query/query.php index 0164808..9bd490f 100644 --- a/tests/query/query.php +++ b/tests/query/query.php @@ -104,9 +104,11 @@ function test_orderby_post__in() { 'Post not in expected order from `post__in`.' ); } + } + function test_orderby_post__in_ids() { // Query only the ID field. - $q2 = new ES_WP_Query( [ + $q = new ES_WP_Query( [ 'post__in' => $post__in, 'orderby' => 'post__in', 'order' => 'ASC', @@ -114,10 +116,10 @@ function test_orderby_post__in() { 'fields' => 'ids', ] ); - $this->assertNotEmpty( $q2->posts ); + $this->assertNotEmpty( $q->posts ); // Verify that the post is in the proper array. - foreach ( $q2->posts as $post ) { + foreach ( $q->posts as $post ) { $this->assertTrue( in_array( $post, $post__in, true ) ); } @@ -125,7 +127,7 @@ function test_orderby_post__in() { foreach ( $post__in as $i => $post_ID ) { $this->assertEquals( $post_ID, - $q2->posts[ $i ], + $q->posts[ $i ], 'Post not in expected order from `post__in`.' ); } From 266e759bdbfc81e0981939f87c2a0f0ad802004d Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Tue, 2 May 2017 13:32:22 -0400 Subject: [PATCH 15/20] Support DESC order --- class-es-wp-query-wrapper.php | 8 ++++++-- tests/query/query.php | 28 ++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/class-es-wp-query-wrapper.php b/class-es-wp-query-wrapper.php index 42e03b2..47ace86 100644 --- a/class-es-wp-query-wrapper.php +++ b/class-es-wp-query-wrapper.php @@ -116,9 +116,10 @@ protected function post_query_sort_handler( $posts, $query ) { // Flip the order to allow retrieval by index. $order = array_flip( $query[ $query['orderby'] ] ); + $orderby = ( ! empty( $query['order'] ) ) ? strtoupper( $query['order'] ) : 'DESC'; $use_source = apply_filters( 'es_query_use_source', false ); - usort( $posts, function( $a, $b ) use ( $order, $key, $use_source ) { + usort( $posts, function( $a, $b ) use ( $order, $orderby, $key, $use_source ) { // Add support for using the Elasticsearch _source field. if ( $use_source && 'ID' === $key ) { // Elasticsearch stores the `ID` field as `post_id`. @@ -144,8 +145,11 @@ protected function post_query_sort_handler( $posts, $query ) { if ( $order[ $a->$key ] === $order[ $b->$key ] ) { return 0; - } else { + } elseif ( 'ASC' === $orderby ) { return $order[ $a->$key ] < $order[ $b->$key ] ? -1 : 1; + } else { + // Descending order. + return $order[ $a->$key ] > $order[ $b->$key ] ? -1 : 1; } } ); diff --git a/tests/query/query.php b/tests/query/query.php index 9bd490f..cbc4f87 100644 --- a/tests/query/query.php +++ b/tests/query/query.php @@ -104,11 +104,9 @@ function test_orderby_post__in() { 'Post not in expected order from `post__in`.' ); } - } - function test_orderby_post__in_ids() { // Query only the ID field. - $q = new ES_WP_Query( [ + $q2 = new ES_WP_Query( [ 'post__in' => $post__in, 'orderby' => 'post__in', 'order' => 'ASC', @@ -116,10 +114,10 @@ function test_orderby_post__in_ids() { 'fields' => 'ids', ] ); - $this->assertNotEmpty( $q->posts ); + $this->assertNotEmpty( $q2->posts ); // Verify that the post is in the proper array. - foreach ( $q->posts as $post ) { + foreach ( $q2->posts as $post ) { $this->assertTrue( in_array( $post, $post__in, true ) ); } @@ -127,10 +125,28 @@ function test_orderby_post__in_ids() { foreach ( $post__in as $i => $post_ID ) { $this->assertEquals( $post_ID, - $q->posts[ $i ], + $q2->posts[ $i ], 'Post not in expected order from `post__in`.' ); } + + // Test sorting in the inverse direction. + $q3 = new ES_WP_Query( [ + 'post__in' => $post__in, + 'orderby' => 'post__in', + 'order' => 'DESC', + 'posts_per_page' => 4, + ] ); + + // Assert the order matches the inverse direction. + $post__in_reverse = array_reverse( $post__in, false ); + foreach ( $post__in_reverse as $i => $post_ID ) { + $this->assertEquals( + $post_ID, + $q3->posts[ $i ]->ID, + 'Post not in expected order from `post__in` when ordered by DESC.' + ); + } } function test_post_name__in() { From ba30c643c3a33ff77858db15e622db70aa0b21a1 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Tue, 2 May 2017 13:34:03 -0400 Subject: [PATCH 16/20] Remove DESC order since these ordering types don't matter what 'order' is passed --- class-es-wp-query-wrapper.php | 8 ++------ tests/query/query.php | 18 ------------------ 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/class-es-wp-query-wrapper.php b/class-es-wp-query-wrapper.php index 47ace86..42e03b2 100644 --- a/class-es-wp-query-wrapper.php +++ b/class-es-wp-query-wrapper.php @@ -116,10 +116,9 @@ protected function post_query_sort_handler( $posts, $query ) { // Flip the order to allow retrieval by index. $order = array_flip( $query[ $query['orderby'] ] ); - $orderby = ( ! empty( $query['order'] ) ) ? strtoupper( $query['order'] ) : 'DESC'; $use_source = apply_filters( 'es_query_use_source', false ); - usort( $posts, function( $a, $b ) use ( $order, $orderby, $key, $use_source ) { + usort( $posts, function( $a, $b ) use ( $order, $key, $use_source ) { // Add support for using the Elasticsearch _source field. if ( $use_source && 'ID' === $key ) { // Elasticsearch stores the `ID` field as `post_id`. @@ -145,11 +144,8 @@ protected function post_query_sort_handler( $posts, $query ) { if ( $order[ $a->$key ] === $order[ $b->$key ] ) { return 0; - } elseif ( 'ASC' === $orderby ) { - return $order[ $a->$key ] < $order[ $b->$key ] ? -1 : 1; } else { - // Descending order. - return $order[ $a->$key ] > $order[ $b->$key ] ? -1 : 1; + return $order[ $a->$key ] < $order[ $b->$key ] ? -1 : 1; } } ); diff --git a/tests/query/query.php b/tests/query/query.php index cbc4f87..0164808 100644 --- a/tests/query/query.php +++ b/tests/query/query.php @@ -129,24 +129,6 @@ function test_orderby_post__in() { 'Post not in expected order from `post__in`.' ); } - - // Test sorting in the inverse direction. - $q3 = new ES_WP_Query( [ - 'post__in' => $post__in, - 'orderby' => 'post__in', - 'order' => 'DESC', - 'posts_per_page' => 4, - ] ); - - // Assert the order matches the inverse direction. - $post__in_reverse = array_reverse( $post__in, false ); - foreach ( $post__in_reverse as $i => $post_ID ) { - $this->assertEquals( - $post_ID, - $q3->posts[ $i ]->ID, - 'Post not in expected order from `post__in` when ordered by DESC.' - ); - } } function test_post_name__in() { From 4d4cc8561aa267c7693db72f6119955b281d107e Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Tue, 2 May 2017 13:37:06 -0400 Subject: [PATCH 17/20] Clearing up doc --- class-es-wp-query-wrapper.php | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/class-es-wp-query-wrapper.php b/class-es-wp-query-wrapper.php index 42e03b2..651bdee 100644 --- a/class-es-wp-query-wrapper.php +++ b/class-es-wp-query-wrapper.php @@ -756,14 +756,8 @@ public function get_posts() { } } elseif ( 'none' == $q['orderby'] ) { // nothing to see here - } elseif ( $q['orderby'] == 'post__in' && ! empty( $post__in ) ) { - // @todo: Figure this out... Elasticsearch doesn't have an equivalent of this - // $orderby = "FIELD( {$wpdb->posts}.ID, $post__in )"; - } elseif ( $q['orderby'] == 'post_parent__in' && ! empty( $post_parent__in ) ) { - // (see above) - // $orderby = "FIELD( {$wpdb->posts}.post_parent, $post_parent__in )"; - } elseif ( $q['orderby'] === 'post_name__in' && ! empty( $post_name__in ) ) { - // (see above) + } elseif ( in_array( $q['orderby'], array( 'post__in', 'post_parent__in', 'post_name__in' ) ) ) { + // Handled post-query by `ES_WP_Query_Wrapper::post_query_sort_handler()`. } else { if ( is_array( $q['orderby'] ) ) { foreach ( $q['orderby'] as $_orderby => $order ) { From 7b9872dabcea3843e35a03f35d0a2c8c87d6e6f4 Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Tue, 2 May 2017 16:37:07 -0400 Subject: [PATCH 18/20] Always support _source even if not using sort by ID --- class-es-wp-query-wrapper.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/class-es-wp-query-wrapper.php b/class-es-wp-query-wrapper.php index 651bdee..f6373d7 100644 --- a/class-es-wp-query-wrapper.php +++ b/class-es-wp-query-wrapper.php @@ -120,9 +120,11 @@ protected function post_query_sort_handler( $posts, $query ) { usort( $posts, function( $a, $b ) use ( $order, $key, $use_source ) { // Add support for using the Elasticsearch _source field. - if ( $use_source && 'ID' === $key ) { + if ( $use_source ) { // Elasticsearch stores the `ID` field as `post_id`. - $key = 'post_id'; + if ( 'ID' === $key ) { + $key = 'post_id'; + } // Cast the array to object to mock the `WP_Post` object. $a = (object) $a; From 6a350f10e0d4eb84d358b6a4a2830c3d98d6c14f Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Wed, 3 May 2017 16:59:55 -0400 Subject: [PATCH 19/20] Enabling some more fields that VIP is indexing --- adapters/wpcom-vip.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/adapters/wpcom-vip.php b/adapters/wpcom-vip.php index 1254007..d73808b 100644 --- a/adapters/wpcom-vip.php +++ b/adapters/wpcom-vip.php @@ -102,8 +102,8 @@ function vip_es_field_map( $es_map ) { 'post_title' => 'title', 'post_title.analyzed' => 'title', 'post_excerpt' => 'excerpt', - 'post_password' => 'post_password', // this isn't indexed on vip - 'post_name' => 'post_name', // this isn't indexed on vip + 'post_password' => 'post_password', // this isn't indexed on vip + 'post_name' => 'slug', 'post_modified' => 'modified', 'post_modified.year' => 'modified_token.year', 'post_modified.month' => 'modified_token.month', @@ -125,9 +125,9 @@ function vip_es_field_map( $es_map ) { 'post_modified_gmt.minute' => 'modified_gmt_token.minute', 'post_modified_gmt.second' => 'modified_gmt_token.second', 'post_parent' => 'parent_post_id', - 'menu_order' => 'menu_order', // this isn't indexed on vip + 'menu_order' => 'menu_order', 'post_mime_type' => 'post_mime_type', // this isn't indexed on vip - 'comment_count' => 'comment_count', // this isn't indexed on vip + 'comment_count' => 'discussion.comment_count', 'post_meta' => 'meta.%s.value.raw_lc', 'post_meta.analyzed' => 'meta.%s.value', 'post_meta.long' => 'meta.%s.long', From c51c74ce13de3523a73ea1b441b8b4cf87d8b3bb Mon Sep 17 00:00:00 2001 From: Sean Fisher Date: Wed, 3 May 2017 17:15:07 -0400 Subject: [PATCH 20/20] Support translating the documents --- adapters/searchpress.php | 3 ++- adapters/travis.php | 1 + adapters/wpcom-vip.php | 2 ++ class-es-wp-query-wrapper.php | 14 ++++++++------ 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/adapters/searchpress.php b/adapters/searchpress.php index 0f2b5fb..3633d89 100644 --- a/adapters/searchpress.php +++ b/adapters/searchpress.php @@ -11,6 +11,7 @@ protected function query_es( $es_args ) { function sp_es_field_map( $es_map ) { return wp_parse_args( array( + 'ID' => 'post_id', 'post_name' => 'post_name.raw', 'post_title' => 'post_title.raw', 'post_title.analyzed' => 'post_title', @@ -74,4 +75,4 @@ function es_wp_query_index_test_data() { SP_API()->post( '_refresh' ); } -} \ No newline at end of file +} diff --git a/adapters/travis.php b/adapters/travis.php index 7c66213..07dc6d9 100644 --- a/adapters/travis.php +++ b/adapters/travis.php @@ -13,6 +13,7 @@ protected function query_es( $es_args ) { function travis_es_field_map( $es_map ) { return wp_parse_args( array( + 'ID' => 'post_id', 'post_meta' => 'post_meta.%s.value', 'post_author' => 'post_author.user_id', 'post_date' => 'post_date.date', diff --git a/adapters/wpcom-vip.php b/adapters/wpcom-vip.php index d73808b..e88ff28 100644 --- a/adapters/wpcom-vip.php +++ b/adapters/wpcom-vip.php @@ -50,6 +50,7 @@ protected function set_posts( $q, $es_response ) { } $this->posts = $this->post_query_sort_handler( $this->posts, $q ); + return; } } else { $this->posts = array(); @@ -75,6 +76,7 @@ public function set_found_posts( $q, $es_response ) { function vip_es_field_map( $es_map ) { return wp_parse_args( array( + 'ID' => 'post_id', 'post_author' => 'author_id', 'post_author.user_nicename' => 'author_login', 'post_date' => 'date', diff --git a/class-es-wp-query-wrapper.php b/class-es-wp-query-wrapper.php index f6373d7..a35a417 100644 --- a/class-es-wp-query-wrapper.php +++ b/class-es-wp-query-wrapper.php @@ -116,16 +116,16 @@ protected function post_query_sort_handler( $posts, $query ) { // Flip the order to allow retrieval by index. $order = array_flip( $query[ $query['orderby'] ] ); + + // Support raw Elasticsearch documents. $use_source = apply_filters( 'es_query_use_source', false ); + if ( $use_source ) { + $key = $this->es_map( $key ); + } usort( $posts, function( $a, $b ) use ( $order, $key, $use_source ) { // Add support for using the Elasticsearch _source field. if ( $use_source ) { - // Elasticsearch stores the `ID` field as `post_id`. - if ( 'ID' === $key ) { - $key = 'post_id'; - } - // Cast the array to object to mock the `WP_Post` object. $a = (object) $a; $b = (object) $b; @@ -140,7 +140,9 @@ protected function post_query_sort_handler( $posts, $query ) { } } - if ( ! isset( $order[ $a->$key ] ) || ! isset( $order[ $b->$key ] ) ) { + if ( + ! isset( $a->$key ) || ! isset( $b->$key ) + || ! isset( $order[ $a->$key ] ) || ! isset( $order[ $b->$key ] ) ) { return 0; }