Merge pull request #22613 from woocommerce/performance/set-props

Performance: `set_props`
This commit is contained in:
Claudiu Lodromanean 2019-02-06 10:02:54 -08:00 committed by GitHub
commit 2d2d7a7053
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 109 additions and 94 deletions

View File

@ -220,7 +220,7 @@ abstract class WC_Data {
* @return string Data in JSON format. * @return string Data in JSON format.
*/ */
public function __toString() { public function __toString() {
return json_encode( $this->get_data() ); return wp_json_encode( $this->get_data() );
} }
/** /**
@ -283,7 +283,7 @@ abstract class WC_Data {
* @return bool true if it's an internal key, false otherwise * @return bool true if it's an internal key, false otherwise
*/ */
protected function is_internal_meta_key( $key ) { protected function is_internal_meta_key( $key ) {
$internal_meta_key = ! empty( $key ) && $this->data_store && in_array( $key, $this->data_store->get_internal_meta_keys() ); $internal_meta_key = ! empty( $key ) && $this->data_store && in_array( $key, $this->data_store->get_internal_meta_keys(), true );
if ( ! $internal_meta_key ) { if ( ! $internal_meta_key ) {
return false; return false;
@ -320,7 +320,7 @@ abstract class WC_Data {
$this->maybe_read_meta_data(); $this->maybe_read_meta_data();
$meta_data = $this->get_meta_data(); $meta_data = $this->get_meta_data();
$array_keys = array_keys( wp_list_pluck( $meta_data, 'key' ), $key ); $array_keys = array_keys( wp_list_pluck( $meta_data, 'key' ), $key, true );
$value = $single ? '' : array(); $value = $single ? '' : array();
if ( ! empty( $array_keys ) ) { if ( ! empty( $array_keys ) ) {
@ -349,7 +349,7 @@ abstract class WC_Data {
public function meta_exists( $key = '' ) { public function meta_exists( $key = '' ) {
$this->maybe_read_meta_data(); $this->maybe_read_meta_data();
$array_keys = wp_list_pluck( $this->get_meta_data(), 'key' ); $array_keys = wp_list_pluck( $this->get_meta_data(), 'key' );
return in_array( $key, $array_keys ); return in_array( $key, $array_keys, true );
} }
/** /**
@ -364,11 +364,13 @@ abstract class WC_Data {
foreach ( $data as $meta ) { foreach ( $data as $meta ) {
$meta = (array) $meta; $meta = (array) $meta;
if ( isset( $meta['key'], $meta['value'], $meta['id'] ) ) { if ( isset( $meta['key'], $meta['value'], $meta['id'] ) ) {
$this->meta_data[] = new WC_Meta_Data( array( $this->meta_data[] = new WC_Meta_Data(
'id' => $meta['id'], array(
'key' => $meta['key'], 'id' => $meta['id'],
'value' => $meta['value'], 'key' => $meta['key'],
) ); 'value' => $meta['value'],
)
);
} }
} }
} }
@ -379,9 +381,9 @@ abstract class WC_Data {
* *
* @since 2.6.0 * @since 2.6.0
* *
* @param string $key Meta key. * @param string $key Meta key.
* @param string|array $value Meta value. * @param string|array $value Meta value.
* @param bool $unique Should this be a unique key?. * @param bool $unique Should this be a unique key?.
*/ */
public function add_meta_data( $key, $value, $unique = false ) { public function add_meta_data( $key, $value, $unique = false ) {
if ( $this->is_internal_meta_key( $key ) ) { if ( $this->is_internal_meta_key( $key ) ) {
@ -396,10 +398,12 @@ abstract class WC_Data {
if ( $unique ) { if ( $unique ) {
$this->delete_meta_data( $key ); $this->delete_meta_data( $key );
} }
$this->meta_data[] = new WC_Meta_Data( array( $this->meta_data[] = new WC_Meta_Data(
'key' => $key, array(
'value' => $value, 'key' => $key,
) ); 'value' => $value,
)
);
} }
/** /**
@ -462,7 +466,7 @@ abstract class WC_Data {
*/ */
public function delete_meta_data( $key ) { public function delete_meta_data( $key ) {
$this->maybe_read_meta_data(); $this->maybe_read_meta_data();
$array_keys = array_keys( wp_list_pluck( $this->meta_data, 'key' ), $key ); $array_keys = array_keys( wp_list_pluck( $this->meta_data, 'key' ), $key, true );
if ( $array_keys ) { if ( $array_keys ) {
foreach ( $array_keys as $array_key ) { foreach ( $array_keys as $array_key ) {
@ -479,7 +483,7 @@ abstract class WC_Data {
*/ */
public function delete_meta_data_by_mid( $mid ) { public function delete_meta_data_by_mid( $mid ) {
$this->maybe_read_meta_data(); $this->maybe_read_meta_data();
$array_keys = array_keys( wp_list_pluck( $this->meta_data, 'id' ), $mid ); $array_keys = array_keys( wp_list_pluck( $this->meta_data, 'id' ), (int) $mid, true );
if ( $array_keys ) { if ( $array_keys ) {
foreach ( $array_keys as $array_key ) { foreach ( $array_keys as $array_key ) {
@ -507,8 +511,8 @@ abstract class WC_Data {
* @param bool $force_read True to force a new DB read (and update cache). * @param bool $force_read True to force a new DB read (and update cache).
*/ */
public function read_meta_data( $force_read = false ) { public function read_meta_data( $force_read = false ) {
$this->meta_data = array(); $this->meta_data = array();
$cache_loaded = false; $cache_loaded = false;
if ( ! $this->get_id() ) { if ( ! $this->get_id() ) {
return; return;
@ -533,11 +537,13 @@ abstract class WC_Data {
$raw_meta_data = $cache_loaded ? $cached_meta : $this->data_store->read_meta( $this ); $raw_meta_data = $cache_loaded ? $cached_meta : $this->data_store->read_meta( $this );
if ( $raw_meta_data ) { if ( $raw_meta_data ) {
foreach ( $raw_meta_data as $meta ) { foreach ( $raw_meta_data as $meta ) {
$this->meta_data[] = new WC_Meta_Data( array( $this->meta_data[] = new WC_Meta_Data(
'id' => (int) $meta->meta_id, array(
'key' => $meta->meta_key, 'id' => (int) $meta->meta_id,
'value' => maybe_unserialize( $meta->meta_value ), 'key' => $meta->meta_key,
) ); 'value' => maybe_unserialize( $meta->meta_value ),
)
);
} }
if ( ! $cache_loaded && ! empty( $this->cache_group ) ) { if ( ! $cache_loaded && ! empty( $this->cache_group ) ) {
@ -593,8 +599,8 @@ abstract class WC_Data {
* @since 3.0.0 * @since 3.0.0
*/ */
public function set_defaults() { public function set_defaults() {
$this->data = $this->default_data; $this->data = $this->default_data;
$this->changes = array(); $this->changes = array();
$this->set_object_read( false ); $this->set_object_read( false );
} }
@ -630,27 +636,30 @@ abstract class WC_Data {
* @return bool|WP_Error * @return bool|WP_Error
*/ */
public function set_props( $props, $context = 'set' ) { public function set_props( $props, $context = 'set' ) {
$errors = new WP_Error(); $errors = false;
foreach ( $props as $prop => $value ) { foreach ( $props as $prop => $value ) {
try { try {
if ( 'meta_data' === $prop ) { /**
* Checks if the prop being set is allowed, and the value is not null.
*/
if ( is_null( $value ) || in_array( $prop, array( 'prop', 'date_prop', 'meta_data' ), true ) ) {
continue; continue;
} }
$setter = "set_$prop"; $setter = "set_$prop";
if ( ! is_null( $value ) && is_callable( array( $this, $setter ) ) ) {
$reflection = new ReflectionMethod( $this, $setter );
if ( $reflection->isPublic() ) { if ( is_callable( array( $this, $setter ) ) ) {
$this->{$setter}( $value ); $this->{$setter}( $value );
}
} }
} catch ( WC_Data_Exception $e ) { } catch ( WC_Data_Exception $e ) {
if ( ! $errors ) {
$errors = new WP_Error();
}
$errors->add( $e->getErrorCode(), $e->getMessage() ); $errors->add( $e->getErrorCode(), $e->getMessage() );
} }
} }
return count( $errors->get_error_codes() ) ? $errors : true; return $errors && count( $errors->get_error_codes() ) ? $errors : true;
} }
/** /**
@ -757,7 +766,7 @@ abstract class WC_Data {
} else { } else {
$timestamp = wc_string_to_timestamp( get_gmt_from_date( gmdate( 'Y-m-d H:i:s', wc_string_to_timestamp( $value ) ) ) ); $timestamp = wc_string_to_timestamp( get_gmt_from_date( gmdate( 'Y-m-d H:i:s', wc_string_to_timestamp( $value ) ) ) );
} }
$datetime = new WC_DateTime( "@{$timestamp}", new DateTimeZone( 'UTC' ) ); $datetime = new WC_DateTime( "@{$timestamp}", new DateTimeZone( 'UTC' ) );
} }
// Set local timezone or offset. // Set local timezone or offset.

View File

@ -297,66 +297,72 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
* @since 3.0.0 * @since 3.0.0
*/ */
protected function read_product_data( &$product ) { protected function read_product_data( &$product ) {
$id = $product->get_id(); $id = $product->get_id();
$review_count = get_post_meta( $id, '_wc_review_count', true ); $post_meta_values = get_post_meta( $id );
$rating_counts = get_post_meta( $id, '_wc_rating_count', true ); $meta_key_to_props = array(
$average_rating = get_post_meta( $id, '_wc_average_rating', true ); '_sku' => 'sku',
'_regular_price' => 'regular_price',
if ( '' === $review_count ) { '_sale_price' => 'sale_price',
WC_Comments::get_review_count_for_product( $product ); '_price' => 'price',
} else { '_sale_price_dates_from' => 'date_on_sale_from',
$product->set_review_count( $review_count ); '_sale_price_dates_to' => 'date_on_sale_to',
} 'total_sales' => 'total_sales',
'_tax_status' => 'tax_status',
if ( '' === $rating_counts ) { '_tax_class' => 'tax_class',
WC_Comments::get_rating_counts_for_product( $product ); '_manage_stock' => 'manage_stock',
} else { '_backorders' => 'backorders',
$product->set_rating_counts( $rating_counts ); '_low_stock_amount' => 'low_stock_amount',
} '_sold_individually' => 'sold_individually',
'_weight' => 'weight',
if ( '' === $average_rating ) { '_length' => 'length',
WC_Comments::get_average_rating_for_product( $product ); '_width' => 'width',
} else { '_height' => 'height',
$product->set_average_rating( $average_rating ); '_upsell_ids' => 'upsell_ids',
} '_crosssell_ids' => 'cross_sell_ids',
'_purchase_note' => 'purchase_note',
$product->set_props( '_default_attributes' => 'default_attributes',
array( '_virtual' => 'virtual',
'sku' => get_post_meta( $id, '_sku', true ), '_downloadable' => 'downloadable',
'regular_price' => get_post_meta( $id, '_regular_price', true ), '_download_limit' => 'download_limit',
'sale_price' => get_post_meta( $id, '_sale_price', true ), '_download_expiry' => 'download_expiry',
'price' => get_post_meta( $id, '_price', true ), '_thumbnail_id' => 'image_id',
'date_on_sale_from' => get_post_meta( $id, '_sale_price_dates_from', true ), '_stock' => 'stock_quantity',
'date_on_sale_to' => get_post_meta( $id, '_sale_price_dates_to', true ), '_stock_status' => 'stock_status',
'total_sales' => get_post_meta( $id, 'total_sales', true ), '_wc_average_rating' => 'average_rating',
'tax_status' => get_post_meta( $id, '_tax_status', true ), '_wc_rating_count' => 'rating_counts',
'tax_class' => get_post_meta( $id, '_tax_class', true ), '_wc_review_count' => 'review_count',
'manage_stock' => get_post_meta( $id, '_manage_stock', true ), '_product_image_gallery' => 'gallery_image_ids',
'stock_quantity' => get_post_meta( $id, '_stock', true ),
'stock_status' => get_post_meta( $id, '_stock_status', true ),
'backorders' => get_post_meta( $id, '_backorders', true ),
'low_stock_amount' => get_post_meta( $id, '_low_stock_amount', true ),
'sold_individually' => get_post_meta( $id, '_sold_individually', true ),
'weight' => get_post_meta( $id, '_weight', true ),
'length' => get_post_meta( $id, '_length', true ),
'width' => get_post_meta( $id, '_width', true ),
'height' => get_post_meta( $id, '_height', true ),
'upsell_ids' => get_post_meta( $id, '_upsell_ids', true ),
'cross_sell_ids' => get_post_meta( $id, '_crosssell_ids', true ),
'purchase_note' => get_post_meta( $id, '_purchase_note', true ),
'default_attributes' => get_post_meta( $id, '_default_attributes', true ),
'category_ids' => $this->get_term_ids( $product, 'product_cat' ),
'tag_ids' => $this->get_term_ids( $product, 'product_tag' ),
'shipping_class_id' => current( $this->get_term_ids( $product, 'product_shipping_class' ) ),
'virtual' => get_post_meta( $id, '_virtual', true ),
'downloadable' => get_post_meta( $id, '_downloadable', true ),
'gallery_image_ids' => array_filter( explode( ',', get_post_meta( $id, '_product_image_gallery', true ) ) ),
'download_limit' => get_post_meta( $id, '_download_limit', true ),
'download_expiry' => get_post_meta( $id, '_download_expiry', true ),
'image_id' => get_post_thumbnail_id( $id ),
)
); );
$set_props = array();
foreach ( $meta_key_to_props as $meta_key => $prop ) {
$meta_value = isset( $post_meta_values[ $meta_key ][0] ) ? $post_meta_values[ $meta_key ][0] : '';
$set_props[ $prop ] = maybe_unserialize( $meta_value ); // get_post_meta only unserializes single values.
}
$set_props['category_ids'] = $this->get_term_ids( $product, 'product_cat' );
$set_props['tag_ids'] = $this->get_term_ids( $product, 'product_tag' );
$set_props['shipping_class_id'] = current( $this->get_term_ids( $product, 'product_shipping_class' ) );
$set_props['gallery_image_ids'] = array_filter( explode( ',', $set_props['gallery_image_ids'] ) );
if ( '' === $set_props['review_count'] ) {
unset( $set_props['review_count'] );
WC_Comments::get_review_count_for_product( $product );
}
if ( '' === $set_props['rating_counts'] ) {
unset( $set_props['rating_counts'] );
WC_Comments::get_rating_counts_for_product( $product );
}
if ( '' === $set_props['average_rating'] ) {
unset( $set_props['average_rating'] );
WC_Comments::get_average_rating_for_product( $product );
}
$product->set_props( $set_props );
// Handle sale dates on the fly in case of missed cron schedule. // Handle sale dates on the fly in case of missed cron schedule.
if ( $product->is_type( 'simple' ) && $product->is_on_sale( 'edit' ) && $product->get_sale_price( 'edit' ) !== $product->get_price( 'edit' ) ) { if ( $product->is_type( 'simple' ) && $product->is_on_sale( 'edit' ) && $product->get_sale_price( 'edit' ) !== $product->get_price( 'edit' ) ) {
update_post_meta( $product->get_id(), '_price', $product->get_sale_price( 'edit' ) ); update_post_meta( $product->get_id(), '_price', $product->get_sale_price( 'edit' ) );