Merge pull request #19096 from woocommerce/update/19061

Add stopword support to product searches
This commit is contained in:
Mike Jolley 2018-03-16 14:08:17 +00:00 committed by GitHub
commit 73ed35bc07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 301 additions and 127 deletions

View File

@ -454,10 +454,9 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
// Search using CRUD.
if ( ! empty( $query_vars['s'] ) ) {
$data_store = WC_Data_Store::load( 'product' );
$ids = $data_store->search_products( wc_clean( $query_vars['s'] ), '', true, true );
$query_vars['post__in'] = array_merge( $ids, array( 0 ) );
// So we know we are searching products.
$data_store = WC_Data_Store::load( 'product' );
$ids = $data_store->search_products( wc_clean( wp_unslash( $query_vars['s'] ) ), '', true, true );
$query_vars['post__in'] = array_merge( $ids, array( 0 ) );
$query_vars['product_search'] = true;
unset( $query_vars['s'] );
}

View File

@ -1,21 +1,18 @@
<?php
/**
* Class WC_Data_Store_WP file.
*
* @package WooCommerce\DataStores
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Shared logic for WP based data.
* Contains functions like meta handling for all default data stores.
* Your own data store doesn't need to use WC_Data_Store_WP -- you can write
* your own meta handling functions.
*
* @version 3.0.0
* @version 3.0.0
* @package WooCommerce/Classes
*/
defined( 'ABSPATH' ) || exit;
/**
* WC_Data_Store_WP class.
*/
class WC_Data_Store_WP {
@ -171,7 +168,6 @@ class WC_Data_Store_WP {
* @since 2.6.0
*
* @param string $key Prefix to be added to meta keys.
*
* @return string
*/
protected function prefix_key( $key ) {
@ -383,7 +379,6 @@ class WC_Data_Store_WP {
'compare' => $operator,
);
break;
case '<':
case '>=':
$wp_query_args['meta_query'][] = array(
@ -392,7 +387,6 @@ class WC_Data_Store_WP {
'compare' => $operator,
);
break;
default:
$wp_query_args['meta_query'][] = array(
'key' => $key,
@ -438,4 +432,61 @@ class WC_Data_Store_WP {
public function get_internal_meta_keys() {
return $this->internal_meta_keys;
}
/**
* Check if the terms are suitable for searching.
*
* Uses an array of stopwords (terms) that are excluded from the separate
* term matching when searching for posts. The list of English stopwords is
* the approximate search engines list, and is translatable.
*
* @since 3.4.0
* @param array $terms Terms to check.
* @return array Terms that are not stopwords.
*/
protected function get_valid_search_terms( $terms ) {
$valid_terms = array();
$stopwords = $this->get_search_stopwords();
foreach ( $terms as $term ) {
// keep before/after spaces when term is for exact match, otherwise trim quotes and spaces.
if ( preg_match( '/^".+"$/', $term ) ) {
$term = trim( $term, "\"'" );
} else {
$term = trim( $term, "\"' " );
}
// Avoid single A-Z and single dashes.
if ( empty( $term ) || ( 1 === strlen( $term ) && preg_match( '/^[a-z\-]$/i', $term ) ) ) {
continue;
}
if ( in_array( wc_strtolower( $term ), $stopwords, true ) ) {
continue;
}
$valid_terms[] = $term;
}
return $valid_terms;
}
/**
* Retrieve stopwords used when parsing search terms.
*
* @since 3.4.0
* @return array Stopwords.
*/
protected function get_search_stopwords() {
// Translators: This is a comma-separated list of very common words that should be excluded from a search, like a, an, and the. These are usually called "stopwords". You should not simply translate these individual words into your language. Instead, look for and provide commonly accepted stopwords in your language.
$stopwords = array_map( 'wc_strtolower', array_map( 'trim', explode(
',', _x(
'about,an,are,as,at,be,by,com,for,from,how,in,is,it,of,on,or,that,the,this,to,was,what,when,where,who,will,with,www',
'Comma-separated list of search stopwords in your language',
'woocommerce'
)
) ) );
return apply_filters( 'wp_search_stopwords', $stopwords );
}
}

View File

@ -1327,12 +1327,54 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
public function search_products( $term, $type = '', $include_variations = false, $all_statuses = false ) {
global $wpdb;
$like_term = '%' . $wpdb->esc_like( $term ) . '%';
$post_types = $include_variations ? array( 'product', 'product_variation' ) : array( 'product' );
$post_statuses = current_user_can( 'edit_private_products' ) ? array( 'private', 'publish' ) : array( 'publish' );
$type_join = '';
$type_where = '';
$status_where = '';
$term = wc_strtolower( $term );
// See if search term contains OR keywords.
if ( strstr( $term, ' or ' ) ) {
$term_groups = explode( ' or ', $term );
} else {
$term_groups = array( $term );
}
$search_where = '';
$search_queries = array();
foreach ( $term_groups as $term_group ) {
// Parse search terms.
if ( preg_match_all( '/".*?("|$)|((?<=[\t ",+])|^)[^\t ",+]+/', $term_group, $matches ) ) {
$search_terms = $this->get_valid_search_terms( $matches[0] );
$count = count( $search_terms );
// if the search string has only short terms or stopwords, or is 10+ terms long, match it as sentence.
if ( 9 < $count || 0 === $count ) {
$search_terms = array( $term_group );
}
} else {
$search_terms = array( $term_group );
}
$term_group_query = '';
$searchand = '';
foreach ( $search_terms as $search_term ) {
$like = '%' . $wpdb->esc_like( $search_term ) . '%';
$term_group_query .= $wpdb->prepare( " {$searchand} ( ( posts.post_title LIKE %s) OR ( posts.post_excerpt LIKE %s) OR ( posts.post_content LIKE %s ) OR ( postmeta.meta_key = '_sku' AND postmeta.meta_value LIKE %s ) )", $like, $like, $like ); // @codingStandardsIgnoreLine.
$searchand = ' AND ';
}
if ( $term_group_query ) {
$search_queries[] = $term_group_query;
}
}
if ( $search_queries ) {
$search_where = 'AND (' . implode( ') OR (', $search_queries ) . ')';
}
if ( $type ) {
if ( in_array( $type, array( 'virtual', 'downloadable' ), true ) ) {
@ -1348,27 +1390,14 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
// phpcs:ignore WordPress.VIP.DirectDatabaseQuery.DirectQuery
$search_results = $wpdb->get_results(
// phpcs:disable
$wpdb->prepare(
"SELECT DISTINCT posts.ID as product_id, posts.post_parent as parent_id FROM {$wpdb->posts} posts
LEFT JOIN {$wpdb->postmeta} postmeta ON posts.ID = postmeta.post_id
$type_join
WHERE (
posts.post_title LIKE %s
OR posts.post_excerpt LIKE %s
OR posts.post_content LIKE %s
OR (
postmeta.meta_key = '_sku' AND postmeta.meta_value LIKE %s
)
)
AND posts.post_type IN ('" . implode( "','", $post_types ) . "')
$status_where
$type_where
ORDER BY posts.post_parent ASC, posts.post_title ASC",
$like_term,
$like_term,
$like_term,
$like_term
)
"SELECT DISTINCT posts.ID as product_id, posts.post_parent as parent_id FROM {$wpdb->posts} posts
LEFT JOIN {$wpdb->postmeta} postmeta ON posts.ID = postmeta.post_id
$type_join
WHERE posts.post_type IN ('" . implode( "','", $post_types ) . "')
$search_where
$status_where
$type_where
ORDER BY posts.post_parent ASC, posts.post_title ASC"
// phpcs:enable
);

View File

@ -1,6 +1,7 @@
<?php
/**
* Data Store Tests: Tests WC_Products's WC_Data_Store.
*
* @package WooCommerce\Tests\Product
* @since 3.0.0
*/
@ -11,7 +12,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
*
* @since 3.0.0
*/
function test_product_store_loads() {
public function test_product_store_loads() {
$product_store = new WC_Data_Store( 'product' );
$this->assertTrue( is_callable( array( $product_store, 'read' ) ) );
$this->assertEquals( 'WC_Product_Data_Store_CPT', $product_store->get_current_class_name() );
@ -22,24 +23,24 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
*
* @since 3.0.0
*/
function test_product_create() {
$product = new WC_Product;
$product->set_regular_price( 42 );
$product->set_name( 'My Product' );
$product->save();
public function test_product_create() {
$product = new WC_Product();
$product->set_regular_price( 42 );
$product->set_name( 'My Product' );
$product->save();
$read_product = new WC_Product( $product->get_id() );
$read_product = new WC_Product( $product->get_id() );
$this->assertEquals( '42', $read_product->get_regular_price() );
$this->assertEquals( 'My Product', $read_product->get_name() );
}
$this->assertEquals( '42', $read_product->get_regular_price() );
$this->assertEquals( 'My Product', $read_product->get_name() );
}
/**
* Test reading a product.
*
* @since 3.0.0
*/
function test_product_read() {
public function test_product_read() {
$product = WC_Helper_Product::create_simple_product();
$product = new WC_Product( $product->get_id() );
@ -51,7 +52,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
*
* @since 3.0.0
*/
function test_product_update() {
public function test_product_update() {
$product = WC_Helper_Product::create_simple_product();
$this->assertEquals( '10', $product->get_regular_price() );
@ -70,7 +71,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
*
* @since 3.0.0
*/
function test_product_trash() {
public function test_product_trash() {
$product = WC_Helper_Product::create_simple_product();
$product->delete();
$this->assertEquals( 'trash', $product->get_status() );
@ -81,7 +82,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
*
* @since 3.0.0
*/
function test_product_delete() {
public function test_product_delete() {
$product = WC_Helper_Product::create_simple_product();
$product->delete( true );
$this->assertEquals( 0, $product->get_id() );
@ -92,35 +93,36 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
*
* @since 3.0.0
*/
function test_grouped_product_create() {
public function test_grouped_product_create() {
$simple_product = WC_Helper_Product::create_simple_product();
$product = new WC_Product_Grouped;
$product = new WC_Product_Grouped();
$product->set_children( array( $simple_product->get_id() ) );
$product->set_name( 'My Grouped Product' );
$product->save();
$read_product = new WC_Product_Grouped( $product->get_id() );
$this->assertEquals( 'My Grouped Product', $read_product->get_name() );
$this->assertEquals( array( $simple_product->get_id() ), $read_product->get_children() );
}
}
/**
* Test getting / reading an grouped product.
*
* @since 3.0.0
*/
function test_grouped_product_read() {
$product = WC_Helper_Product::create_grouped_product();
public function test_grouped_product_read() {
$product = WC_Helper_Product::create_grouped_product();
$read_product = new WC_Product_Grouped( $product->get_id() );
$this->assertEquals( 'Dummy Grouped Product', $read_product->get_name() );
$this->assertEquals( 2, count( $read_product->get_children() ) );
}
/**
* Test updating an grouped product.
*
* @since 3.0.0
*/
function test_grouped_product_update() {
$product = WC_Helper_Product::create_grouped_product();
public function test_grouped_product_update() {
$product = WC_Helper_Product::create_grouped_product();
$simple_product = WC_Helper_Product::create_simple_product();
$this->assertEquals( 'Dummy Grouped Product', $product->get_name() );
$this->assertEquals( 2, count( $product->get_children() ) );
@ -140,21 +142,21 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
*
* @since 3.0.0
*/
function test_external_product_create() {
$product = new WC_Product_External;
$product->set_regular_price( 42 );
$product->set_button_text( 'Test CRUD' );
$product->set_product_url( 'http://automattic.com' );
$product->set_name( 'My External Product' );
$product->save();
public function test_external_product_create() {
$product = new WC_Product_External();
$product->set_regular_price( 42 );
$product->set_button_text( 'Test CRUD' );
$product->set_product_url( 'http://automattic.com' );
$product->set_name( 'My External Product' );
$product->save();
$read_product = new WC_Product_External( $product->get_id() );
$read_product = new WC_Product_External( $product->get_id() );
$this->assertEquals( '42', $read_product->get_regular_price() );
$this->assertEquals( 'Test CRUD', $read_product->get_button_text() );
$this->assertEquals( 'http://automattic.com', $read_product->get_product_url() );
$this->assertEquals( 'My External Product', $read_product->get_name() );
}
$this->assertEquals( '42', $read_product->get_regular_price() );
$this->assertEquals( 'Test CRUD', $read_product->get_button_text() );
$this->assertEquals( 'http://automattic.com', $read_product->get_product_url() );
$this->assertEquals( 'My External Product', $read_product->get_name() );
}
/**
* Test getting / reading an external product. Make sure both our external
@ -162,7 +164,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
*
* @since 3.0.0
*/
function test_external_product_read() {
public function test_external_product_read() {
$product = WC_Helper_Product::create_external_product();
$product = new WC_Product_External( $product->get_id() );
@ -176,7 +178,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
*
* @since 3.0.0
*/
function test_external_product_update() {
public function test_external_product_update() {
$product = WC_Helper_Product::create_external_product();
$this->assertEquals( 'Buy external product', $product->get_button_text() );
@ -199,7 +201,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
* @since 3.0.0
*/
public function test_variable_read() {
$product = WC_Helper_Product::create_variation_product();
$product = WC_Helper_Product::create_variation_product();
$children = $product->get_children();
// Test sale prices too
@ -213,8 +215,10 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
$expected_prices['price'][ $children[0] ] = 8.00;
$expected_prices['price'][ $children[1] ] = 15.00;
$expected_prices['regular_price'][ $children[0] ] = 10.00;
$expected_prices['regular_price'][ $children[1] ] = 15.00;
$expected_prices['sale_price'][ $children[0] ] = 8.00;
$expected_prices['sale_price'][ $children[1] ] = 15.00;
@ -230,8 +234,8 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
*
* @since 3.0.0
*/
function test_variables_and_variations() {
$product = new WC_Product_Variable;
public function test_variables_and_variations() {
$product = new WC_Product_Variable();
$product->set_name( 'Variable Product' );
$attribute = new WC_Product_Attribute();
@ -246,7 +250,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
$this->assertEquals( 'Variable Product', $product->get_name() );
$variation = new WC_Product_Variation;
$variation = new WC_Product_Variation();
$variation->set_parent_id( $product->get_id() );
$variation->set_regular_price( 10 );
$variation->set_sku( 'CRUD DUMMY SKU VARIABLE GREEN' );
@ -260,14 +264,14 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
$this->assertEquals( 'CRUD DUMMY SKU VARIABLE GREEN', $variation->get_sku() );
$this->assertEquals( 10, $variation->get_price() );
$product = new WC_Product_Variable( $product->get_id() );
$product = new WC_Product_Variable( $product->get_id() );
$children = $product->get_children();
$this->assertEquals( $variation->get_id(), $children[0] );
$expected_attributes = array( 'pa_color' => array( 'green' ) );
$this->assertEquals( $expected_attributes, $product->get_variation_attributes() );
$variation_2 = new WC_Product_Variation;
$variation_2 = new WC_Product_Variation();
$variation_2->set_parent_id( $product->get_id() );
$variation_2->set_regular_price( 10 );
$variation_2->set_sku( 'CRUD DUMMY SKU VARIABLE RED' );
@ -281,7 +285,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
$this->assertEquals( 'CRUD DUMMY SKU VARIABLE RED', $variation_2->get_sku() );
$this->assertEquals( 10, $variation_2->get_price() );
$product = new WC_Product_Variable( $product->get_id() );
$product = new WC_Product_Variable( $product->get_id() );
$children = $product->get_children();
$this->assertEquals( $variation_2->get_id(), $children[1] );
$this->assertEquals( 2, count( $children ) );
@ -295,10 +299,13 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
$variation_2->save();
$product = new WC_Product_Variable( $product->get_id() );
$expected_prices['price'][ $children[0] ] = 10.00;
$expected_prices['price'][ $children[1] ] = 9.99;
$expected_prices['regular_price'][ $children[0] ] = 10.00;
$expected_prices['regular_price'][ $children[1] ] = 15.00;
$expected_prices['sale_price'][ $children[0] ] = 10.00;
$expected_prices['sale_price'][ $children[1] ] = 9.99;
@ -310,9 +317,9 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
$product->delete();
}
function test_variation_save_attributes() {
public function test_variation_save_attributes() {
// Create a variable product with a color attribute.
$product = new WC_Product_Variable;
$product = new WC_Product_Variable();
$attribute = new WC_Product_Attribute();
$attribute->set_id( 0 );
@ -325,7 +332,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
$product->save();
// Create a new variation with the color 'green'.
$variation = new WC_Product_Variation;
$variation = new WC_Product_Variation();
$variation->set_parent_id( $product->get_id() );
$variation->set_attributes( array( 'color' => 'green' ) );
$variation->set_status( 'private' );
@ -347,46 +354,46 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
public function test_save_default_attributes() {
// Create a variable product with sold individually.
$product = new WC_Product_Variable;
$product = new WC_Product_Variable();
$product->save();
$product_id = $product->get_id();
// Save with a set of FALSE equivalents and some values we expect to come through as true. We should see
// string types with a value of '0' making it through filtration.
$test_object = new stdClass();
$test_object = new stdClass();
$test_object->property = '12345';
$product->set_default_attributes( array(
'sample-attribute-false-0' => 0,
'sample-attribute-false-1' => false,
'sample-attribute-false-2' => '',
'sample-attribute-false-3' => null,
'sample-attribute-true-0' => '0',
'sample-attribute-true-1' => 1,
'sample-attribute-true-2' => 'true',
'sample-attribute-true-3' => 'false',
'sample-attribute-true-4' => array( 'exists' => 'false' ),
'sample-attribute-true-0' => '0',
'sample-attribute-true-1' => 1,
'sample-attribute-true-2' => 'true',
'sample-attribute-true-3' => 'false',
'sample-attribute-true-4' => array( 'exists' => 'false' ),
'sample-attribute-false-4' => $test_object,
));
$product->save();
// Revive the product from the database and analyze results
$product = wc_get_product( $product_id );
$product = wc_get_product( $product_id );
$default_attributes = $product->get_default_attributes();
$this->assertEquals( $default_attributes, array(
'sample-attribute-true-0' => '0',
'sample-attribute-true-1' => 1,
'sample-attribute-true-2' => 'true',
'sample-attribute-true-3' => 'false',
'sample-attribute-true-4' => array( 'exists' => 'false' ),
'sample-attribute-true-0' => '0',
'sample-attribute-true-1' => 1,
'sample-attribute-true-2' => 'true',
'sample-attribute-true-3' => 'false',
'sample-attribute-true-4' => array( 'exists' => 'false' ),
'sample-attribute-false-4' => $test_object,
));
}
function test_variable_child_has_dimensions() {
$product = new WC_Product_Variable;
public function test_variable_child_has_dimensions() {
$product = new WC_Product_Variable();
$product->save();
$variation = new WC_Product_variation;
$variation = new WC_Product_Variation();
$variation->set_parent_id( $product->get_id() );
$variation->set_width( 10 );
$variation->save();
@ -398,11 +405,11 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
$this->assertTrue( $store->child_has_dimensions( $product ) );
}
function test_variable_child_has_dimensions_no_dimensions() {
$product = new WC_Product_Variable;
public function test_variable_child_has_dimensions_no_dimensions() {
$product = new WC_Product_Variable();
$product->save();
$variation = new WC_Product_variation;
$variation = new WC_Product_Variation();
$variation->set_parent_id( $product->get_id() );
$variation->save();
@ -413,7 +420,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
$this->assertFalse( $store->child_has_dimensions( $product ) );
}
function test_get_on_sale_products() {
public function test_get_on_sale_products() {
$product_store = new WC_Product_Data_Store_CPT();
$sale_product = WC_Helper_Product::create_simple_product();
@ -434,7 +441,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
$future_sale_product->set_price( $future_sale_product->get_regular_price() );
$future_sale_product->save();
$sale_products = $product_store->get_on_sale_products();
$sale_products = $product_store->get_on_sale_products();
$sale_product_ids = wp_list_pluck( $sale_products, 'id' );
$this->assertContains( $sale_product->get_id(), $sale_product_ids );
@ -442,64 +449,71 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
$this->assertNotContains( $future_sale_product->get_id(), $sale_product_ids );
}
function test_generate_product_title() {
$product = new WC_Product;
public function test_generate_product_title() {
$product = new WC_Product();
$product->set_name( 'Test Product' );
$product->save();
$one_attribute_variation = new WC_Product_Variation;
$one_attribute_variation = new WC_Product_Variation();
$one_attribute_variation->set_parent_id( $product->get_id() );
$one_attribute_variation->set_attributes( array( 'color' => 'Green' ) );
$one_attribute_variation->save();
$two_attribute_variation = new WC_Product_Variation;
$two_attribute_variation = new WC_Product_Variation();
$two_attribute_variation->set_parent_id( $product->get_id() );
$two_attribute_variation->set_attributes( array( 'color' => 'Green', 'size' => 'Large' ) );
$two_attribute_variation->set_attributes( array(
'color' => 'Green',
'size' => 'Large',
) );
$two_attribute_variation->save();
$multiword_attribute_variation = new WC_Product_Variation;
$multiword_attribute_variation = new WC_Product_Variation();
$multiword_attribute_variation->set_parent_id( $product->get_id() );
$multiword_attribute_variation->set_attributes( array( 'color' => 'Green', 'mounting-plate' => 'galaxy-s6', 'support' => 'one-year' ) );
$multiword_attribute_variation->set_attributes( array(
'color' => 'Green',
'mounting-plate' => 'galaxy-s6',
'support' => 'one-year',
) );
$multiword_attribute_variation->save();
// Check the one attribute variation title.
$this->assertEquals( "Test Product - Green", $one_attribute_variation->get_name() );
$this->assertEquals( 'Test Product - Green', $one_attribute_variation->get_name() );
// Check the two attribute variation title.
$this->assertEquals( "Test Product - Green, Large", $two_attribute_variation->get_name() );
$this->assertEquals( 'Test Product - Green, Large', $two_attribute_variation->get_name() );
// Check the variation with a multiword attribute name.
$this->assertEquals( "Test Product", $multiword_attribute_variation->get_name() );
$this->assertEquals( 'Test Product', $multiword_attribute_variation->get_name() );
}
function test_generate_product_title_disable() {
public function test_generate_product_title_disable() {
add_filter( 'woocommerce_product_variation_title_include_attributes', '__return_false' );
$product = new WC_Product;
$product = new WC_Product();
$product->set_name( 'Test Product' );
$product->save();
$variation = new WC_Product_Variation;
$variation = new WC_Product_Variation();
$variation->set_parent_id( $product->get_id() );
$variation->set_attributes( array( 'color' => 'green' ) );
$variation->save();
$loaded_variation = wc_get_product( $variation->get_id() );
$this->assertEquals( "Test Product", $loaded_variation->get_name() );
$this->assertEquals( 'Test Product', $loaded_variation->get_name() );
}
function test_generate_product_title_no_attributes() {
$product = new WC_Product;
public function test_generate_product_title_no_attributes() {
$product = new WC_Product();
$product->set_name( 'Test Product' );
$product->save();
$variation = new WC_Product_Variation;
$variation = new WC_Product_Variation();
$variation->set_parent_id( $product->get_id() );
$variation->set_attributes( array() );
$variation->save();
$loaded_variation = wc_get_product( $variation->get_id() );
$this->assertEquals( "Test Product", $loaded_variation->get_name() );
$this->assertEquals( 'Test Product', $loaded_variation->get_name() );
}
/**
@ -507,8 +521,8 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
* https://github.com/woocommerce/woocommerce/issues/13960
* @since 3.0.1
*/
function test_product_meta_save_post() {
$product = new WC_Product;
public function test_product_meta_save_post() {
$product = new WC_Product();
$product->set_name( 'Test Product' );
$product->save();
update_post_meta( $product->get_id(), '_test2', 'default' ); // this is the value we don't want to get back.
@ -530,4 +544,85 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
remove_action( 'save_post', array( 'WC_Helper_Product', 'save_post_test_update_meta_data_direct' ) );
}
/**
* Test Product search functionality.
*
* @return void
*/
public function test_search_products() {
// Create some products to search for.
$product = new WC_Product();
$product->set_regular_price( 42 );
$product->set_name( 'Blue widget' );
$product->set_sku( 'blue-widget-1' );
$product->set_description( "You bet I'm agitated! I may be surrounded by insanity, but I am not insane. I suggest you drop it, Mr. Data. Not if I weaken first. Earl Grey tea, watercress sandwiches... and Bularian canapés? Are you up for promotion? and attack the Romulans. Yesterday I did not know how to eat gagh." );
$product->save();
$product2 = new WC_Product();
$product2->set_regular_price( 42 );
$product2->set_name( 'Red widget' );
$product2->set_sku( 'red-widget-1' );
$product2->set_description( "and attack the Romulans. Fear is the true enemy, the only enemy. The game's not big enough unless it scares you a little. What? We're not at all alike! Now, how the hell do we defeat an enemy that knows us better than we know ourselves? Mr. Worf, you do remember how to fire phasers?" );
$product2->save();
$product3 = new WC_Product();
$product3->set_regular_price( 42 );
$product3->set_name( 'Green widget' );
$product3->set_sku( 'green-widget-1' );
$product3->set_description( 'For an android with no feelings, he sure managed to evoke them in others. Then maybe you should consider this: if anything happens to them, Starfleet is going to want a full investigation. We have a saboteur aboard.' );
$product3->save();
$product4 = new WC_Product();
$product4->set_regular_price( 42 );
$product4->set_name( 'Another green widget' );
$product4->set_sku( 'green-widget-2' );
$product4->set_description( 'For an android with no feelings, he sure managed to evoke them in others. Then maybe you should consider this: if anything happens to them, Starfleet is going to want a full investigation. We have a saboteur aboard.' );
$product4->save();
$data_store = WC_Data_Store::load( 'product' );
// Search some things :)
$results = $data_store->search_products( 'green', '', true, true );
$this->assertNotContains( $product->get_id(), $results );
$this->assertNotContains( $product2->get_id(), $results );
$this->assertContains( $product3->get_id(), $results );
$this->assertContains( $product4->get_id(), $results );
$results = $data_store->search_products( 'blue-widget-1', '', true, true );
$this->assertContains( $product->get_id(), $results );
$this->assertNotContains( $product2->get_id(), $results );
$this->assertNotContains( $product3->get_id(), $results );
$this->assertNotContains( $product4->get_id(), $results );
$results = $data_store->search_products( 'blue-widget-1 OR green-widget', '', true, true );
$this->assertContains( $product->get_id(), $results );
$this->assertNotContains( $product2->get_id(), $results );
$this->assertContains( $product3->get_id(), $results );
$this->assertContains( $product4->get_id(), $results );
$results = $data_store->search_products( '"green widget"', '', true, true );
$this->assertNotContains( $product->get_id(), $results );
$this->assertNotContains( $product2->get_id(), $results );
$this->assertContains( $product3->get_id(), $results );
$this->assertContains( $product4->get_id(), $results );
$results = $data_store->search_products( 'Another widget', '', true, true );
$this->assertNotContains( $product->get_id(), $results );
$this->assertNotContains( $product2->get_id(), $results );
$this->assertNotContains( $product3->get_id(), $results );
$this->assertContains( $product4->get_id(), $results );
$results = $data_store->search_products( '"Fear is the true enemy"', '', true, true );
$this->assertNotContains( $product->get_id(), $results );
$this->assertContains( $product2->get_id(), $results );
$this->assertNotContains( $product3->get_id(), $results );
$this->assertNotContains( $product4->get_id(), $results );
// Clean up.
$product->delete();
$product2->delete();
$product3->delete();
$product4->delete();
}
}