Implement handling of changesets in the LookupDataStore class.
This commit is contained in:
parent
bbddcbcc15
commit
7c9137698b
|
@ -233,7 +233,7 @@ CREATE TABLE ' . $this->lookup_table_name . '(
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ( $product_ids as $id ) {
|
foreach ( $product_ids as $id ) {
|
||||||
$this->data_store->insert_data_for_product( $id );
|
$this->data_store->create_data_for_product( $id );
|
||||||
}
|
}
|
||||||
|
|
||||||
update_option( 'woocommerce_attribute_lookup__last_products_page_processed', $current_products_page );
|
update_option( 'woocommerce_attribute_lookup__last_products_page_processed', $current_products_page );
|
||||||
|
|
|
@ -14,6 +14,15 @@ defined( 'ABSPATH' ) || exit;
|
||||||
*/
|
*/
|
||||||
class LookupDataStore {
|
class LookupDataStore {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types of updates to perform depending on the current changest
|
||||||
|
*/
|
||||||
|
|
||||||
|
const ACTION_NONE = 0;
|
||||||
|
const ACTION_INSERT = 1;
|
||||||
|
const ACTION_UPDATE_STOCK = 2;
|
||||||
|
const ACTION_DELETE = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The lookup table name.
|
* The lookup table name.
|
||||||
*
|
*
|
||||||
|
@ -95,13 +104,13 @@ AND table_name = %s;',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name of the lookup table.
|
* Get the name of the lookup table.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function get_lookup_table_name() {
|
public function get_lookup_table_name() {
|
||||||
return $this->lookup_table_name;
|
return $this->lookup_table_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert/update the appropriate lookup table entries for a new or modified product or variation.
|
* Insert/update the appropriate lookup table entries for a new or modified product or variation.
|
||||||
|
@ -120,20 +129,82 @@ AND table_name = %s;',
|
||||||
$product = WC()->call_function( 'wc_get_product', $product );
|
$product = WC()->call_function( 'wc_get_product', $product );
|
||||||
}
|
}
|
||||||
|
|
||||||
// No changeset available: the product/variation is new, so just insert its data.
|
$update_type = $this->get_update_type( $changeset );
|
||||||
|
|
||||||
|
switch ( $update_type ) {
|
||||||
|
case self::ACTION_INSERT:
|
||||||
|
$this->delete_data_for( $product->get_id() );
|
||||||
|
$this->create_data_for( $product );
|
||||||
|
break;
|
||||||
|
case self::ACTION_UPDATE_STOCK:
|
||||||
|
$this->update_stock_status_for( $product );
|
||||||
|
break;
|
||||||
|
case self::ACTION_DELETE:
|
||||||
|
$this->delete_data_for( $product->get_id() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the type of action to perform depending on the received changeset.
|
||||||
|
*
|
||||||
|
* @param array|null $changeset The changeset received by on_product_changed.
|
||||||
|
* @return int One of the ACTION_ constants.
|
||||||
|
*/
|
||||||
|
private function get_update_type( $changeset ) {
|
||||||
if ( is_null( $changeset ) ) {
|
if ( is_null( $changeset ) ) {
|
||||||
$this->delete_lookup_table_entries_for( $product->get_id() );
|
// No changeset at all means that the product is new.
|
||||||
if ( $this->is_variation( $product ) ) {
|
return self::ACTION_INSERT;
|
||||||
$this->insert_data_for_variation( $product );
|
}
|
||||||
|
|
||||||
|
$keys = array_keys( $changeset );
|
||||||
|
|
||||||
|
// Order matters:
|
||||||
|
// - The change with the most precedence is a change in catalog visibility
|
||||||
|
// (which will result in all data being regenerated or deleted).
|
||||||
|
// - Then a change in attributes (all data will be regenerated).
|
||||||
|
// - And finally a change in stock status (existing data will be updated).
|
||||||
|
// Thus these conditions must be checked in that same order.
|
||||||
|
|
||||||
|
if ( in_array( 'catalog_visibility', $keys, true ) ) {
|
||||||
|
$new_visibility = $changeset['catalog_visibility'];
|
||||||
|
if ( 'visible' === $new_visibility || 'catalog' === $new_visibility ) {
|
||||||
|
return self::ACTION_INSERT;
|
||||||
} else {
|
} else {
|
||||||
$this->insert_data_for_product( $product );
|
return self::ACTION_DELETE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changeset available: process it.
|
if ( in_array( 'attributes', $keys, true ) ) {
|
||||||
|
return self::ACTION_INSERT;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Implement changeset processing.
|
if ( array_intersect( $keys, array( 'stock_quantity', 'stock_status', 'manage_stock' ) ) ) {
|
||||||
|
return self::ACTION_UPDATE_STOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::ACTION_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the stock status of the lookup table entries for a given product.
|
||||||
|
*
|
||||||
|
* @param \WC_Product $product The product to update the entries for.
|
||||||
|
*/
|
||||||
|
private function update_stock_status_for( \WC_Product $product ) {
|
||||||
|
global $wpdb;
|
||||||
|
|
||||||
|
$in_stock = $product->is_in_stock();
|
||||||
|
|
||||||
|
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
|
||||||
|
$wpdb->query(
|
||||||
|
$wpdb->prepare(
|
||||||
|
'UPDATE ' . $this->lookup_table_name . ' SET in_stock = %d WHERE product_id = %d',
|
||||||
|
$in_stock ? 1 : 0,
|
||||||
|
$product->get_id()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -154,31 +225,42 @@ AND table_name = %s;',
|
||||||
$product_id = $product;
|
$product_id = $product;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->delete_lookup_table_entries_for( $product_id );
|
$this->delete_data_for( $product_id );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert the lookup data for a given product or variation.
|
* Create the lookup data for a given product, if a variable product is passed
|
||||||
* If a variable product is passed the information is created for all of its variations.
|
* the information is created for all of its variations.
|
||||||
|
* This method is intended to be called from the data regenerator.
|
||||||
*
|
*
|
||||||
* @param int|WC_Product $product Product object or id.
|
* @param int|WC_Product $product Product object or id.
|
||||||
* @throws \Exception A variation object is passed.
|
* @throws \Exception A variation object is passed.
|
||||||
*/
|
*/
|
||||||
public function insert_data_for_product( $product ) {
|
public function create_data_for_product( $product ) {
|
||||||
if ( ! is_a( $product, \WC_Product::class ) ) {
|
if ( ! is_a( $product, \WC_Product::class ) ) {
|
||||||
$product = WC()->call_function( 'wc_get_product', $product );
|
$product = WC()->call_function( 'wc_get_product', $product );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $this->is_variation( $product ) ) {
|
if ( $this->is_variation( $product ) ) {
|
||||||
throw new \Exception( "LookupDataStore::insert_data_for_product can't be called for variations." );
|
throw new \Exception( "LookupDataStore::create_data_for_product can't be called for variations." );
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->delete_lookup_table_entries_for( $product->get_id() );
|
$this->delete_data_for( $product->get_id() );
|
||||||
|
$this->create_data_for( $product );
|
||||||
|
}
|
||||||
|
|
||||||
if ( $this->is_variable_product( $product ) ) {
|
/**
|
||||||
$this->create_lookup_table_entries_for_variable_product( $product );
|
* Create lookup table data for a given product.
|
||||||
|
*
|
||||||
|
* @param \WC_Product $product The product to create the data for.
|
||||||
|
*/
|
||||||
|
private function create_data_for( \WC_Product $product ) {
|
||||||
|
if ( $this->is_variation( $product ) ) {
|
||||||
|
$this->create_data_for_variation( $product );
|
||||||
|
} elseif ( $this->is_variable_product( $product ) ) {
|
||||||
|
$this->create_data_for_variable_product( $product );
|
||||||
} else {
|
} else {
|
||||||
$this->create_lookup_table_entries_for_simple_product( $product );
|
$this->create_data_for_simple_product( $product );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +270,7 @@ AND table_name = %s;',
|
||||||
*
|
*
|
||||||
* @param int $product_id Simple product id, or main/parent product id for variable products.
|
* @param int $product_id Simple product id, or main/parent product id for variable products.
|
||||||
*/
|
*/
|
||||||
private function delete_lookup_table_entries_for( int $product_id ) {
|
private function delete_data_for( int $product_id ) {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
|
|
||||||
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
|
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
|
||||||
|
@ -208,7 +290,7 @@ AND table_name = %s;',
|
||||||
*
|
*
|
||||||
* @param \WC_Product $product The product to create the entries for.
|
* @param \WC_Product $product The product to create the entries for.
|
||||||
*/
|
*/
|
||||||
private function create_lookup_table_entries_for_simple_product( \WC_Product $product ) {
|
private function create_data_for_simple_product( \WC_Product $product ) {
|
||||||
$product_attributes_data = $this->get_attribute_taxonomies( $product );
|
$product_attributes_data = $this->get_attribute_taxonomies( $product );
|
||||||
$has_stock = $product->is_in_stock();
|
$has_stock = $product->is_in_stock();
|
||||||
$product_id = $product->get_id();
|
$product_id = $product->get_id();
|
||||||
|
@ -226,7 +308,7 @@ AND table_name = %s;',
|
||||||
*
|
*
|
||||||
* @param \WC_Product_Variable $product The product to create the entries for.
|
* @param \WC_Product_Variable $product The product to create the entries for.
|
||||||
*/
|
*/
|
||||||
private function create_lookup_table_entries_for_variable_product( \WC_Product_Variable $product ) {
|
private function create_data_for_variable_product( \WC_Product_Variable $product ) {
|
||||||
$product_attributes_data = $this->get_attribute_taxonomies( $product );
|
$product_attributes_data = $this->get_attribute_taxonomies( $product );
|
||||||
$variation_attributes_data = array_filter(
|
$variation_attributes_data = array_filter(
|
||||||
$product_attributes_data,
|
$product_attributes_data,
|
||||||
|
@ -266,7 +348,7 @@ AND table_name = %s;',
|
||||||
*
|
*
|
||||||
* @param \WC_Product_Variation $variation The variation to create entries for.
|
* @param \WC_Product_Variation $variation The variation to create entries for.
|
||||||
*/
|
*/
|
||||||
private function insert_data_for_variation( \WC_Product_Variation $variation ) {
|
private function create_data_for_variation( \WC_Product_Variation $variation ) {
|
||||||
$main_product = wc_get_product( $variation->get_parent_id() );
|
$main_product = wc_get_product( $variation->get_parent_id() );
|
||||||
|
|
||||||
$product_attributes_data = $this->get_attribute_taxonomies( $main_product );
|
$product_attributes_data = $this->get_attribute_taxonomies( $main_product );
|
||||||
|
|
|
@ -51,7 +51,7 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case {
|
||||||
$this->lookup_data_store = new class() extends LookupDataStore {
|
$this->lookup_data_store = new class() extends LookupDataStore {
|
||||||
public $passed_products = array();
|
public $passed_products = array();
|
||||||
|
|
||||||
public function insert_data_for_product( $product ) {
|
public function create_data_for_product( $product ) {
|
||||||
$this->passed_products[] = $product;
|
$this->passed_products[] = $product;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,19 +42,19 @@ class LookupDataStoreTest extends \WC_Unit_Test_Case {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @testdox `insert_data_for_product` throws an exception if a variation is passed.
|
* @testdox `create_data_for_product` throws an exception if a variation is passed.
|
||||||
*/
|
*/
|
||||||
public function test_insert_data_for_product_throws_if_variation_is_passed() {
|
public function test_create_data_for_product_throws_if_variation_is_passed() {
|
||||||
$product = new \WC_Product_Variation();
|
$product = new \WC_Product_Variation();
|
||||||
|
|
||||||
$this->expectException( \Exception::class );
|
$this->expectException( \Exception::class );
|
||||||
$this->expectExceptionMessage( "LookupDataStore::insert_data_for_product can't be called for variations." );
|
$this->expectExceptionMessage( "LookupDataStore::create_data_for_product can't be called for variations." );
|
||||||
|
|
||||||
$this->sut->insert_data_for_product( $product );
|
$this->sut->create_data_for_product( $product );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @testdox `insert_data_for_product` creates the appropriate entries for simple products, skipping custom product attributes.
|
* @testdox `create_data_for_product` creates the appropriate entries for simple products, skipping custom product attributes.
|
||||||
*
|
*
|
||||||
* @testWith [true]
|
* @testWith [true]
|
||||||
* [false]
|
* [false]
|
||||||
|
@ -90,7 +90,7 @@ class LookupDataStoreTest extends \WC_Unit_Test_Case {
|
||||||
$expected_in_stock = 0;
|
$expected_in_stock = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->sut->insert_data_for_product( $product );
|
$this->sut->create_data_for_product( $product );
|
||||||
|
|
||||||
$expected = array(
|
$expected = array(
|
||||||
array(
|
array(
|
||||||
|
@ -133,7 +133,7 @@ class LookupDataStoreTest extends \WC_Unit_Test_Case {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @testdox `insert_data_for_product` creates the appropriate entries for variable products.
|
* @testdox `create_data_for_product` creates the appropriate entries for variable products.
|
||||||
*/
|
*/
|
||||||
public function test_update_data_for_variable_product() {
|
public function test_update_data_for_variable_product() {
|
||||||
$products = array();
|
$products = array();
|
||||||
|
@ -239,7 +239,7 @@ class LookupDataStoreTest extends \WC_Unit_Test_Case {
|
||||||
$products[1001] = $variation_1;
|
$products[1001] = $variation_1;
|
||||||
$products[1002] = $variation_2;
|
$products[1002] = $variation_2;
|
||||||
|
|
||||||
$this->sut->insert_data_for_product( $product );
|
$this->sut->create_data_for_product( $product );
|
||||||
|
|
||||||
$expected = array(
|
$expected = array(
|
||||||
// Main product: one entry for each of the regular attribute values,
|
// Main product: one entry for each of the regular attribute values,
|
||||||
|
|
Loading…
Reference in New Issue