From a0aa663f29826be7638b9b10059308dd14fae9d1 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Tue, 8 Jan 2019 13:25:27 +0000 Subject: [PATCH 1/4] Attribute post data needs stripslashes --- includes/admin/meta-boxes/class-wc-meta-box-product-data.php | 2 +- includes/class-wc-ajax.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/admin/meta-boxes/class-wc-meta-box-product-data.php b/includes/admin/meta-boxes/class-wc-meta-box-product-data.php index 1219d40fcd66..f463f6af277b 100644 --- a/includes/admin/meta-boxes/class-wc-meta-box-product-data.php +++ b/includes/admin/meta-boxes/class-wc-meta-box-product-data.php @@ -228,7 +228,7 @@ public static function prepare_attributes( $data = false ) { $attributes = array(); if ( ! $data ) { - $data = $_POST; + $data = stripslashes_deep( $_POST ); } if ( isset( $data['attribute_names'], $data['attribute_values'] ) ) { diff --git a/includes/class-wc-ajax.php b/includes/class-wc-ajax.php index 92910a004d07..e3055f93e9d0 100644 --- a/includes/class-wc-ajax.php +++ b/includes/class-wc-ajax.php @@ -615,7 +615,7 @@ public static function save_attributes() { $response = array(); try { - parse_str( $_POST['data'], $data ); + parse_str( wp_unslash( $_POST['data'] ), $data ); $attributes = WC_Meta_Box_Product_Data::prepare_attributes( $data ); $product_id = absint( $_POST['post_id'] ); From e31b35597aad27a95a6c819b96ce2945bb268fc6 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Tue, 8 Jan 2019 13:28:26 +0000 Subject: [PATCH 2/4] Slash meta values to preserve slashes on save --- .../class-wc-product-data-store-cpt.php | 3 +- ...ss-wc-product-variation-data-store-cpt.php | 2 +- includes/wc-attribute-functions.php | 38 +++++++++++-------- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/includes/data-stores/class-wc-product-data-store-cpt.php b/includes/data-stores/class-wc-product-data-store-cpt.php index 34dad6f34550..f27cc529f1cd 100644 --- a/includes/data-stores/class-wc-product-data-store-cpt.php +++ b/includes/data-stores/class-wc-product-data-store-cpt.php @@ -764,7 +764,8 @@ protected function update_attributes( &$product, $force = false ) { ); } } - update_post_meta( $product->get_id(), '_product_attributes', $meta_values ); + // Note, we use wp_slash to add extra level of escaping. See https://codex.wordpress.org/Function_Reference/update_post_meta#Workaround. + update_post_meta( $product->get_id(), '_product_attributes', wp_slash( $meta_values ) ); } } diff --git a/includes/data-stores/class-wc-product-variation-data-store-cpt.php b/includes/data-stores/class-wc-product-variation-data-store-cpt.php index eb3a99a201bf..5d8cdbefe8f6 100644 --- a/includes/data-stores/class-wc-product-variation-data-store-cpt.php +++ b/includes/data-stores/class-wc-product-variation-data-store-cpt.php @@ -427,7 +427,7 @@ protected function update_attributes( &$product, $force = false ) { $attributes = $product->get_attributes(); $updated_attribute_keys = array(); foreach ( $attributes as $key => $value ) { - update_post_meta( $product->get_id(), 'attribute_' . $key, $value ); + update_post_meta( $product->get_id(), 'attribute_' . $key, wp_slash( $value ) ); $updated_attribute_keys[] = 'attribute_' . $key; } diff --git a/includes/wc-attribute-functions.php b/includes/wc-attribute-functions.php index b4a3616f0c2a..bae38e9651e4 100644 --- a/includes/wc-attribute-functions.php +++ b/includes/wc-attribute-functions.php @@ -94,10 +94,11 @@ function wc_attribute_taxonomy_name_by_id( $attribute_id ) { $attribute_name = $wpdb->get_var( $wpdb->prepare( " - SELECT attribute_name - FROM {$wpdb->prefix}woocommerce_attribute_taxonomies - WHERE attribute_id = %d - ", $attribute_id + SELECT attribute_name + FROM {$wpdb->prefix}woocommerce_attribute_taxonomies + WHERE attribute_id = %d + ", + $attribute_id ) ); @@ -201,7 +202,8 @@ function wc_get_attribute_taxonomy_names() { */ function wc_get_attribute_types() { return (array) apply_filters( - 'product_attributes_type_selector', array( + 'product_attributes_type_selector', + array( 'select' => __( 'Select', 'woocommerce' ), ) ); @@ -382,10 +384,11 @@ function wc_get_attribute( $id ) { $data = $wpdb->get_row( $wpdb->prepare( " - SELECT * - FROM {$wpdb->prefix}woocommerce_attribute_taxonomies - WHERE attribute_id = %d - ", $id + SELECT * + FROM {$wpdb->prefix}woocommerce_attribute_taxonomies + WHERE attribute_id = %d + ", + $id ) ); @@ -543,7 +546,8 @@ function wc_create_attribute( $args ) { "SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = '_product_attributes' AND meta_value LIKE %s", '%' . $wpdb->esc_like( $old_taxonomy_name ) . '%' ), - ARRAY_A ); + ARRAY_A + ); foreach ( $metadatas as $metadata ) { $product_id = $metadata['post_id']; $unserialized_data = maybe_unserialize( $metadata['meta_value'] ); @@ -554,7 +558,7 @@ function wc_create_attribute( $args ) { $unserialized_data[ $new_taxonomy_name ] = $unserialized_data[ $old_taxonomy_name ]; unset( $unserialized_data[ $old_taxonomy_name ] ); $unserialized_data[ $new_taxonomy_name ]['name'] = $new_taxonomy_name; - update_post_meta( $product_id, '_product_attributes', $unserialized_data ); + update_post_meta( $product_id, '_product_attributes', wp_slash( $unserialized_data ) ); } // Update variations which use this taxonomy. @@ -600,7 +604,8 @@ function wc_update_attribute( $id, $args ) { SELECT attribute_name FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_id = %d - ", $args['id'] + ", + $args['id'] ) ); @@ -620,10 +625,11 @@ function wc_delete_attribute( $id ) { $name = $wpdb->get_var( $wpdb->prepare( " - SELECT attribute_name - FROM {$wpdb->prefix}woocommerce_attribute_taxonomies - WHERE attribute_id = %d - ", $id + SELECT attribute_name + FROM {$wpdb->prefix}woocommerce_attribute_taxonomies + WHERE attribute_id = %d + ", + $id ) ); From a4925ff916eb72b8f7f4ee9b7133489c6b554280 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Tue, 8 Jan 2019 14:08:27 +0000 Subject: [PATCH 3/4] Loop to match text versions of attribute names and avoid problems with entities --- assets/js/frontend/add-to-cart-variation.js | 31 +++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/assets/js/frontend/add-to-cart-variation.js b/assets/js/frontend/add-to-cart-variation.js index 08b993123a98..919ca8d565ff 100644 --- a/assets/js/frontend/add-to-cart-variation.js +++ b/assets/js/frontend/add-to-cart-variation.js @@ -352,11 +352,19 @@ } if ( attr_val ) { - // Decode entities and add slashes. + // Decode entities. attr_val = $( '
' ).html( attr_val ).text(); - // Attach. - new_attr_select.find( 'option[value="' + form.addSlashes( attr_val ) + '"]' ).addClass( 'attached ' + variation_active ); + // Attach to matching options by value. This is done to compare + // TEXT values rather than any HTML entities. + new_attr_select.find( 'option' ).each( function( index, el ) { + var option_value = $( this ).val(); + + if ( attr_val === option_value ) { + $( this ).addClass( 'attached ' + variation_active ); + return false; // break. + } + }); } else { // Attach all apart from placeholder. new_attr_select.find( 'option:gt(0)' ).addClass( 'attached ' + variation_active ); @@ -371,8 +379,21 @@ attached_options_count = new_attr_select.find( 'option.attached' ).length; // Check if current selection is in attached options. - if ( selected_attr_val && ( attached_options_count === 0 || new_attr_select.find( 'option.attached.enabled[value="' + form.addSlashes( selected_attr_val ) + '"]' ).length === 0 ) ) { - selected_attr_val_valid = false; + if ( selected_attr_val ) { + if ( 0 === attached_options_count ) { + selected_attr_val_valid = false; + } else { + selected_attr_val_valid = false; + + new_attr_select.find( 'option.attached.enabled' ).each( function( index, el ) { + var option_value = $( this ).val(); + + if ( selected_attr_val === option_value ) { + selected_attr_val_valid = true; + return false; // break. + } + }); + } } // Detach the placeholder if: From 25a92b1d929cbe7457a4c2afe5fb90c166e50b9e Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Mon, 4 Feb 2019 12:51:20 +0000 Subject: [PATCH 4/4] Feedback --- assets/js/frontend/add-to-cart-variation.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/assets/js/frontend/add-to-cart-variation.js b/assets/js/frontend/add-to-cart-variation.js index 919ca8d565ff..5b1dcdec277f 100644 --- a/assets/js/frontend/add-to-cart-variation.js +++ b/assets/js/frontend/add-to-cart-variation.js @@ -380,11 +380,9 @@ // Check if current selection is in attached options. if ( selected_attr_val ) { - if ( 0 === attached_options_count ) { - selected_attr_val_valid = false; - } else { - selected_attr_val_valid = false; + selected_attr_val_valid = false; + if ( 0 !== attached_options_count ) { new_attr_select.find( 'option.attached.enabled' ).each( function( index, el ) { var option_value = $( this ).val();