%PDF- %PDF-
Direktori : /var/www/cwg/wp-content/plugins/searchwp/tests/wpunit/SearchWP/ |
Current File : //var/www/cwg/wp-content/plugins/searchwp/tests/wpunit/SearchWP/ModTest.php |
<?php namespace SearchWP; class ModTest extends \Codeception\TestCase\WPTestCase { protected static $factory; protected static $post_type; protected static $post_ids; protected static $taxonomy = 'post_tag'; protected static $tax_terms; function _before() { self::$factory = static::factory(); self::$post_type = 'post' . SEARCHWP_SEPARATOR . 'post'; $post_ids[] = self::$factory->post->create( [ 'post_title' => 'modtest modtestlorem modtestipsum modtestdatemeta', 'meta_input' => [ 'custom_date_field' => current_time( 'Ymd' ) ], ] ); $tax_terms[] = self::$factory->tag->create_and_get( [ 'name' => 'modtesttag', ] ); self::$factory->tag->add_post_terms( $post_ids[0], [ $tax_terms[0]->term_id ], self::$taxonomy ); $post_ids[] = self::$factory->post->create( [ 'post_title' => 'modtest modtestlorem modtestdatemeta', 'post_date' => date( 'Y-m-d H:i:s', strtotime( '-1 day' ) ), 'meta_input' => [ 'custom_date_field' => date( 'Ymd', strtotime( '-5 months' ) ) ], ] ); $post_ids[] = self::$factory->post->create( [ 'post_title' => 'modtestdatemeta', 'post_date' => date( 'Y-m-d H:i:s', strtotime( '-1 week' ) ), ] ); self::$post_ids = $post_ids; self::$tax_terms = $tax_terms; // Create a Default Engine. $engine_model = json_decode( json_encode( new \SearchWP\Engine( 'default' ) ), true ); \SearchWP\Settings::update_engines_config( [ 'default' => \SearchWP\Utils::normalize_engine_config( $engine_model ), ] ); foreach ( self::$post_ids as $post_id ) { \SearchWP::$index->add( new \SearchWP\Entry( self::$post_type, $post_id ) ); } } function _after() { $index = \SearchWP::$index; $index->reset(); \SearchWP\Settings::update_engines_config( [] ); } public function test_taxonomy_bonus_weight() { global $wpdb; $mod = new \SearchWP\Mod(); $alias = $mod->get_foreign_alias(); $bonus = [ 'term_id' => self::$tax_terms[0]->term_id, 'weight' => 100, ]; $mod->relevance( "IF(( SELECT {$wpdb->prefix}posts.ID FROM {$wpdb->prefix}posts LEFT JOIN {$wpdb->prefix}term_relationships ON ( {$wpdb->prefix}posts.ID = {$wpdb->prefix}term_relationships.object_id ) WHERE {$wpdb->prefix}posts.ID = {$alias}.id AND {$wpdb->prefix}term_relationships.term_taxonomy_id = {$bonus['term_id']} LIMIT 1 ) > 0, {$bonus['weight']}, 0)" ); $query = new \SearchWP\Query( 'modtest', [ 'engine' => 'default', 'mods' => [ $mod ], ] ); $this->assertEquals( 2, count( $query->results ) ); // The post with the tax term should rank first. $this->assertEquals( self::$post_ids[0], $query->results[0]->id ); // The weight should be 800 because: // + 1 Title match = 300 // + 1 Slug match = 300 // + 1 Term match = 100 // ----- // 700 $this->assertEquals( 700, $query->results[0]->relevance ); // The post without the tax term should rank second and not have the bonus. $this->assertEquals( self::$post_ids[1], $query->results[1]->id ); $this->assertEquals( 600, $query->results[1]->relevance ); } public function test_source_post_id_limiter() { $source = \SearchWP\Utils::get_post_type_source_name( 'post' ); $mod = new \SearchWP\Mod( $source ); $mod->set_where( [ [ 'column' => 'id', 'value' => [ self::$post_ids[1] ], 'compare' => 'IN', 'type' => 'NUMERIC', ] ] ); $query = new \SearchWP\Query( 'modtest', [ 'engine' => 'default', 'mods' => [ $mod ], ] ); // Make sure only one post was returned despite two matches due to the limit. $this->assertEquals( 1, count( $query->results ) ); $this->assertEquals( self::$post_ids[1], $query->results[0]->id ); } public function test_adding_bonus_weight_to_source() { global $wpdb; $source = \SearchWP\Utils::get_post_type_source_name( 'post' ); $mod = new \SearchWP\Mod( $source ); $mod->relevance( $wpdb->prepare( "IF(s.source = %s, 99, 0)", $source ) ); $query = new \SearchWP\Query( 'modtest', [ 'engine' => 'default', 'mods' => [ $mod ], ] ); $this->assertEquals( 2, count( $query->results ) ); // Make sure our bonus weight (99) was added to the calculated weight (600). $this->assertEquals( 699, $query->results[0]->relevance ); } public function test_order_by_post_date() { $source = \SearchWP\Utils::get_post_type_source_name( 'post' ); $mod = new \SearchWP\Mod( $source ); $mod->order_by( function( $mod ) { return $mod->get_local_table_alias() . '.post_date'; }, 'ASC', 1 ); $query = new \SearchWP\Query( 'modtest', [ 'engine' => 'default', 'fields' => 'ids', 'mods' => [ $mod ], ] ); $this->assertEquals( 2, count( $query->results ) ); // The 2nd post we added has a date in the past, so it should be returned first. $this->assertEquals( $query->results[0], self::$post_ids[1] ); } public function test_title_not_like() { $source = \SearchWP\Utils::get_post_type_source_name( 'post' ); $mod = new \SearchWP\Mod( $source ); $mod->set_where( [ [ 'column' => 'post_title', 'value' => 'modtest', 'compare' => 'NOT LIKE', ] ] ); $query = new \SearchWP\Query( 'modtest', [ 'engine' => 'default', 'mods' => [ $mod ], ] ); // All titles have 'modtest' in them. $this->assertEquals( 0, count( $query->results ) ); } public function test_bonus_weight_stored_as_custom_field() { global $wpdb; // Custom Field name. Needs to store data as YYYYMMDD (ACF does this already). $my_meta_key = 'custom_date_field'; // NOTE: Metadata was set during init. $mod = new \SearchWP\Mod(); $mod->set_local_table( $wpdb->postmeta ); $mod->on( 'post_id', [ 'column' => 'id' ] ); $mod->on( 'meta_key', [ 'value' => $my_meta_key ] ); $mod->weight( function( $runtime ) use ( $wpdb, $my_meta_key ) { return $wpdb->prepare( " COALESCE( ROUND( ( ( UNIX_TIMESTAMP( {$runtime->get_local_table_alias()}.meta_value ) - ( SELECT UNIX_TIMESTAMP( meta_value ) FROM {$wpdb->postmeta} WHERE meta_key = %s ORDER BY meta_value ASC LIMIT 1 ) ) / 86400 ), 0 ), 0 )", $my_meta_key ); } ); $query = new \SearchWP\Query( 'modtestdatemeta', [ 'engine' => 'default', 'mods' => [ $mod ], ] ); // We should have two results. $this->assertEquals( 3, count( $query->results ) ); $this->assertContains( intval( $query->results[0]->id ), self::$post_ids ); $this->assertContains( intval( $query->results[1]->id ), self::$post_ids ); $this->assertContains( intval( $query->results[2]->id ), self::$post_ids ); // Determine that weights were in fact changed. $this->assertGreaterThan( 700, $query->results[0]->relevance ); // This should have no weight modification because it's the oldest date. $this->assertEquals( 600, $query->results[1]->relevance ); // This should have no weight modification because there was no meta value. $this->assertEquals( 600, $query->results[2]->relevance ); } public function test_bonus_weight_decays_over_time() { global $wpdb; $weight_adjust = 15; $mod = new \SearchWP\Mod(); $mod->set_local_table( $wpdb->posts ); $mod->on( 'ID', [ 'column' => 'id' ] ); $mod->weight( function( $runtime_mod ) use ( $weight_adjust ) { return "ROUND( ( 100 * EXP( ( 1 - ABS( ( UNIX_TIMESTAMP( {$runtime_mod->get_local_table_alias()}.post_date ) - UNIX_TIMESTAMP( NOW() ) ) / 86400 ) ) / 1 ) * {$weight_adjust} ), 0 )"; } ); $query = new \SearchWP\Query( 'modtest', [ 'engine' => 'default', 'mods' => [ $mod ], ] ); // We should have two results. $this->assertEquals( 2, count( $query->results ) ); $this->assertContains( intval( $query->results[0]->id ), self::$post_ids ); $this->assertContains( intval( $query->results[1]->id ), self::$post_ids ); // Determine that weights were in fact changed. // TODO: determine if these change over time since they're time based and the test suite may not run the same every time $this->assertGreaterThan( 4000, intval( $query->results[0]->relevance ) ); $this->assertGreaterThan( 2300, intval( $query->results[1]->relevance ) ); } public function test_bonus_weight_recently_published_posts() { global $wpdb; $mod = new \SearchWP\Mod(); $mod->set_local_table( $wpdb->posts ); $mod->on( 'ID', [ 'column' => 'id' ] ); $mod->relevance( function( $runtime ) use ( $wpdb ) { return " COALESCE( ROUND( ( ( UNIX_TIMESTAMP( {$runtime->get_local_table_alias()}.post_date ) - ( SELECT UNIX_TIMESTAMP( {$wpdb->posts}.post_date ) FROM {$wpdb->posts} WHERE {$wpdb->posts}.post_status = 'publish' ORDER BY {$wpdb->posts}.post_date ASC LIMIT 1 ) ) / 86400 ), 0 ), 0 )"; } ); $mods[] = $mod; $query = new \SearchWP\Query( 'modtest', [ 'engine' => 'default', 'mods' => [ $mod ], ] ); // We should have two results. $this->assertEquals( 2, count( $query->results ) ); $this->assertContains( intval( $query->results[0]->id ), self::$post_ids ); $this->assertContains( intval( $query->results[1]->id ), self::$post_ids ); // A bonus weight of 1 should be awarded to the more recently published post. $this->assertEquals( 607, $query->results[0]->relevance ); $this->assertEquals( 606, $query->results[1]->relevance ); } public function test_orderby() { // We're going to force a Source here because a Mod with an ORDER BY should be an Index Mod. $mod = new \SearchWP\Mod( \SearchWP\Utils::get_post_type_source_name( 'post' ) ); $mod->order_by( function( $mod ) { $source_order = [ \SearchWP\Utils::get_post_type_source_name( 'page' ), \SearchWP\Utils::get_post_type_source_name( 'post' ), ]; return "FIELD({$mod->get_foreign_alias()}.source, " . implode( ',', array_filter( array_map( function( $source_name ) { global $wpdb; return $wpdb->prepare( '%s', $source_name ); }, $source_order ) ) ) . ')'; }, '', 1 ); $mod->order_by( function( $mod ) { return $mod->get_local_table_alias() . '.post_date'; }, 'ASC', 2 ); $query = new \SearchWP\Query( 'modtest', [ 'engine' => 'default', 'fields' => 'ids', 'mods' => [ $mod ], ] ); // We should have two results. $this->assertEquals( 2, count( $query->results ) ); $this->assertContains( intval( $query->results[0] ), self::$post_ids ); $this->assertContains( intval( $query->results[1] ), self::$post_ids ); // The 2nd post we added has a date in the past, so it should be returned first. $this->assertEquals( $query->results[0], self::$post_ids[1] ); } public function test_post_type_taxonomy_limiter() { $mod = new \SearchWP\Mod( \SearchWP\Utils::get_post_type_source_name( 'post' ) ); $tax_args = [ 'taxonomy' => self::$taxonomy, 'field' => 'term_id', 'terms' => [ self::$tax_terms[0]->term_id ], ]; $alias = 'taxalias'; $tax_query = new \WP_Tax_Query( [ $tax_args ] ); $tq_sql = $tax_query->get_sql( $alias, 'ID' ); $mod->raw_join_sql( function( $runtime ) use ( $tq_sql, $alias ) { return str_replace( $alias, $runtime->get_local_table_alias(), $tq_sql['join'] ); } ); $mod->raw_where_sql( function( $runtime ) use ( $tq_sql, $alias ) { return '1=1 ' . str_replace( $alias, $runtime->get_local_table_alias(), $tq_sql['where'] ); } ); $query = new \SearchWP\Query( 'modtest', [ 'engine' => 'default', 'fields' => 'ids', 'mods' => [ $mod ], ] ); // Test that we have one result instead of two because only one has the taxonomy term we're limiting to. $this->assertEquals( 1, count( $query->results ) ); $this->assertContains( intval( $query->results[0] ), self::$post_ids ); } public function test_metrics_buoy() { global $wpdb; $meta_key = '_test_buoy_key'; delete_post_meta( self::$post_ids[0], $meta_key ); add_post_meta( self::$post_ids[0], $meta_key, 3, true ); $mod = new \SearchWP\Mod(); $mod->set_local_table( $wpdb->postmeta ); $mod->on( 'post_id', [ 'column' => 'id' ] ); $mod->on( 'meta_key', [ 'value' => $meta_key ] ); $mod->relevance( function( $mod, $args ) { return "( 10 * ( COALESCE({$mod->get_local_table_alias()}.meta_value, 0) ) )"; } ); $query = new \SearchWP\Query( 'modtest', [ 'engine' => 'default', 'mods' => [ $mod ], ] ); delete_post_meta( self::$post_ids[0], $meta_key ); $this->assertEquals( 2, count( $query->results ) ); $this->assertArrayHasKey( 0, $query->results ); $this->assertArrayHasKey( 1, $query->results ); $this->assertContains( intval( $query->results[0]->id ), self::$post_ids ); $this->assertContains( intval( $query->results[1]->id ), self::$post_ids ); // First result weight should be 660 // Title match 300 // Slug match 300 // Buoy weight 3 clicks * 10 weight $this->assertEquals( 630, $query->results[0]->relevance ); // Second result weight should be 660 // Title match 300 // Slug match 300 // Buoy weight 0 clicks * 10 weight * 2 attribute matches $this->assertEquals( 600, $query->results[1]->relevance ); } }