Merge pull request #22112 from Prospress/fix/22101

Introduce wc_attribute_taxonomy_slug()
This commit is contained in:
Mike Jolley 2019-01-23 21:57:07 +00:00 committed by GitHub
commit 00a93ae8f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 94 additions and 48 deletions

View File

@ -337,7 +337,7 @@ abstract class WC_Widget extends WP_Widget {
// All current filters.
if ( $_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes() ) { // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.Found, WordPress.CodeAnalysis.AssignmentInCondition.Found
foreach ( $_chosen_attributes as $name => $data ) {
$filter_name = sanitize_title( str_replace( 'pa_', '', $name ) );
$filter_name = wc_attribute_taxonomy_slug( $name );
if ( ! empty( $data['terms'] ) ) {
$link = add_query_arg( 'filter_' . $filter_name, implode( ',', $data['terms'] ), $link );
}

View File

@ -82,7 +82,7 @@ class WC_Admin_Importers {
*/
public function admin_scripts() {
$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
wp_register_script( 'wc-product-import', WC()->plugin_url() . '/assets/js/admin/wc-product-import' . $suffix . '.js', array( 'jquery' ), WC_VERSION );
wp_register_script( 'wc-product-import', WC()->plugin_url() . '/assets/js/admin/wc-product-import' . $suffix . '.js', array( 'jquery' ), WC_VERSION, true );
}
/**
@ -159,7 +159,7 @@ class WC_Admin_Importers {
foreach ( $post['terms'] as $term ) {
if ( strstr( $term['domain'], 'pa_' ) ) {
if ( ! taxonomy_exists( $term['domain'] ) ) {
$attribute_name = wc_sanitize_taxonomy_name( str_replace( 'pa_', '', $term['domain'] ) );
$attribute_name = wc_attribute_taxonomy_slug( $term['domain'] );
// Create the taxonomy.
if ( ! in_array( $attribute_name, wc_get_attribute_taxonomies(), true ) ) {
@ -179,7 +179,8 @@ class WC_Admin_Importers {
$term['domain'],
apply_filters( 'woocommerce_taxonomy_objects_' . $term['domain'], array( 'product' ) ),
apply_filters(
'woocommerce_taxonomy_args_' . $term['domain'], array(
'woocommerce_taxonomy_args_' . $term['domain'],
array(
'hierarchical' => true,
'show_ui' => false,
'query_var' => true,
@ -248,16 +249,20 @@ class WC_Admin_Importers {
// @codingStandardsIgnoreEnd.
// Clean up orphaned data.
$wpdb->query( "
$wpdb->query(
"
DELETE {$wpdb->posts}.* FROM {$wpdb->posts}
LEFT JOIN {$wpdb->posts} wp ON wp.ID = {$wpdb->posts}.post_parent
WHERE wp.ID IS NULL AND {$wpdb->posts}.post_type = 'product_variation'
" );
$wpdb->query( "
"
);
$wpdb->query(
"
DELETE {$wpdb->postmeta}.* FROM {$wpdb->postmeta}
LEFT JOIN {$wpdb->posts} wp ON wp.ID = {$wpdb->postmeta}.post_id
WHERE wp.ID IS NULL
" );
"
);
// @codingStandardsIgnoreStart.
$wpdb->query( "
DELETE tr.* FROM {$wpdb->term_relationships} tr

View File

@ -500,7 +500,7 @@ class WC_API_Products extends WC_API_Resource {
// taxonomy-based attributes are prefixed with `pa_`, otherwise simply `attribute_`
$attributes[] = array(
'name' => ucwords( str_replace( 'attribute_', '', str_replace( 'pa_', '', $attribute_name ) ) ),
'name' => ucwords( str_replace( 'attribute_', '', wc_attribute_taxonomy_slug( $attribute_name ) ) ),
'option' => $attribute,
);
}
@ -508,7 +508,7 @@ class WC_API_Products extends WC_API_Resource {
foreach ( $product->get_attributes() as $attribute ) {
$attributes[] = array(
'name' => ucwords( str_replace( 'pa_', '', $attribute['name'] ) ),
'name' => ucwords( wc_attribute_taxonomy_slug( $attribute['name'] ) ),
'position' => $attribute['position'],
'visible' => (bool) $attribute['is_visible'],
'variation' => (bool) $attribute['is_variation'],

View File

@ -973,7 +973,7 @@ class WC_API_Orders extends WC_API_Resource {
if ( isset( $variations ) && is_array( $variations ) ) {
// start by normalizing the passed variations
foreach ( $variations as $key => $value ) {
$key = str_replace( 'attribute_', '', str_replace( 'pa_', '', $key ) ); // from get_attributes in class-wc-api-products.php
$key = str_replace( 'attribute_', '', wc_attribute_taxonomy_slug( $key ) ); // from get_attributes in class-wc-api-products.php
$variations_normalized[ $key ] = strtolower( $value );
}
// now search through each product child and see if our passed variations match anything
@ -981,7 +981,7 @@ class WC_API_Orders extends WC_API_Resource {
$meta = array();
foreach ( get_post_meta( $variation ) as $key => $value ) {
$value = $value[0];
$key = str_replace( 'attribute_', '', str_replace( 'pa_', '', $key ) );
$key = str_replace( 'attribute_', '', wc_attribute_taxonomy_slug( $key ) );
$meta[ $key ] = strtolower( $value );
}
// if the variation array is a part of the $meta array, we found our match

View File

@ -1778,7 +1778,7 @@ class WC_API_Products extends WC_API_Resource {
// taxonomy-based attributes are prefixed with `pa_`, otherwise simply `attribute_`
$attributes[] = array(
'name' => wc_attribute_label( str_replace( 'attribute_', '', $attribute_name ) ),
'slug' => str_replace( 'attribute_', '', str_replace( 'pa_', '', $attribute_name ) ),
'slug' => str_replace( 'attribute_', '', wc_attribute_taxonomy_slug( $attribute_name ) ),
'option' => $attribute,
);
}
@ -1787,7 +1787,7 @@ class WC_API_Products extends WC_API_Resource {
foreach ( $product->get_attributes() as $attribute ) {
$attributes[] = array(
'name' => wc_attribute_label( $attribute['name'] ),
'slug' => str_replace( 'pa_', '', $attribute['name'] ),
'slug' => wc_attribute_taxonomy_slug( $attribute['name'] ),
'position' => (int) $attribute['position'],
'visible' => (bool) $attribute['is_visible'],
'variation' => (bool) $attribute['is_variation'],

View File

@ -1018,7 +1018,7 @@ class WC_API_Orders extends WC_API_Resource {
if ( isset( $variations ) && is_array( $variations ) ) {
// start by normalizing the passed variations
foreach ( $variations as $key => $value ) {
$key = str_replace( 'attribute_', '', str_replace( 'pa_', '', $key ) ); // from get_attributes in class-wc-api-products.php
$key = str_replace( 'attribute_', '', wc_attribute_taxonomy_slug( $key ) ); // from get_attributes in class-wc-api-products.php
$variations_normalized[ $key ] = strtolower( $value );
}
// now search through each product child and see if our passed variations match anything
@ -1026,7 +1026,7 @@ class WC_API_Orders extends WC_API_Resource {
$meta = array();
foreach ( get_post_meta( $variation ) as $key => $value ) {
$value = $value[0];
$key = str_replace( 'attribute_', '', str_replace( 'pa_', '', $key ) );
$key = str_replace( 'attribute_', '', wc_attribute_taxonomy_slug( $key ) );
$meta[ $key ] = strtolower( $value );
}
// if the variation array is a part of the $meta array, we found our match

View File

@ -2336,7 +2336,7 @@ class WC_API_Products extends WC_API_Resource {
// taxonomy-based attributes are prefixed with `pa_`, otherwise simply `attribute_`
$attributes[] = array(
'name' => wc_attribute_label( str_replace( 'attribute_', '', $attribute_name ), $product ),
'slug' => str_replace( 'attribute_', '', str_replace( 'pa_', '', $attribute_name ) ),
'slug' => str_replace( 'attribute_', '', wc_attribute_taxonomy_slug( $attribute_name ) ),
'option' => $attribute,
);
}
@ -2345,7 +2345,7 @@ class WC_API_Products extends WC_API_Resource {
foreach ( $product->get_attributes() as $attribute ) {
$attributes[] = array(
'name' => wc_attribute_label( $attribute['name'], $product ),
'slug' => str_replace( 'pa_', '', $attribute['name'] ),
'slug' => wc_attribute_taxonomy_slug( $attribute['name'] ),
'position' => (int) $attribute['position'],
'visible' => (bool) $attribute['is_visible'],
'variation' => (bool) $attribute['is_variation'],

View File

@ -352,7 +352,7 @@ class WC_REST_Products_V1_Controller extends WC_REST_Posts_Controller {
} else {
$default[] = array(
'id' => 0,
'name' => str_replace( 'pa_', '', $key ),
'name' => wc_attribute_taxonomy_slug( $key ),
'option' => $value,
);
}

View File

@ -58,7 +58,8 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
*/
public function register_routes() {
register_rest_route(
$this->namespace, '/' . $this->rest_base, // @codingStandardsIgnoreLine.
$this->namespace,
'/' . $this->rest_base,
array(
array(
'methods' => WP_REST_Server::READABLE,
@ -77,7 +78,8 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
);
register_rest_route(
$this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', // @codingStandardsIgnoreLine.
$this->namespace,
'/' . $this->rest_base . '/(?P<id>[\d]+)',
array(
'args' => array(
'id' => array(
@ -120,7 +122,8 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
);
register_rest_route(
$this->namespace, '/' . $this->rest_base . '/batch', // @codingStandardsIgnoreLine.
$this->namespace,
'/' . $this->rest_base . '/batch',
array(
array(
'methods' => WP_REST_Server::EDITABLE,
@ -265,7 +268,8 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
}
$args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok.
$args, array(
$args,
array(
'key' => '_sku',
'value' => $skus,
'compare' => 'IN',
@ -276,7 +280,8 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
// Filter by tax class.
if ( ! empty( $request['tax_class'] ) ) {
$args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok.
$args, array(
$args,
array(
'key' => '_tax_class',
'value' => 'standard' !== $request['tax_class'] ? $request['tax_class'] : '',
)
@ -291,7 +296,8 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
// Filter product in stock or out of stock.
if ( is_bool( $request['in_stock'] ) ) {
$args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok.
$args, array(
$args,
array(
'key' => '_stock_status',
'value' => true === $request['in_stock'] ? 'instock' : 'outofstock',
)
@ -454,7 +460,7 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
$attributes = $product->get_attributes();
if ( ! isset( $attributes[ $slug ] ) ) {
return str_replace( 'pa_', '', $slug );
return wc_attribute_taxonomy_slug( $slug );
}
$attribute = $attributes[ $slug ];
@ -511,7 +517,9 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
protected function get_attribute_options( $product_id, $attribute ) {
if ( isset( $attribute['is_taxonomy'] ) && $attribute['is_taxonomy'] ) {
return wc_get_product_terms(
$product_id, $attribute['name'], array(
$product_id,
$attribute['name'],
array(
'fields' => 'names',
)
);
@ -713,7 +721,9 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
if ( 'variation' === $product->get_type() ) {
return new WP_Error(
"woocommerce_rest_invalid_{$this->post_type}_id", __( 'To manipulate product variations you should use the /products/&lt;product_id&gt;/variations/&lt;id&gt; endpoint.', 'woocommerce' ), array(
"woocommerce_rest_invalid_{$this->post_type}_id",
__( 'To manipulate product variations you should use the /products/&lt;product_id&gt;/variations/&lt;id&gt; endpoint.', 'woocommerce' ),
array(
'status' => 404,
)
);
@ -1199,7 +1209,7 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
*
* @param WC_Product $product Product instance.
* @param array $downloads Downloads data.
* @param int $deprecated Deprecated since 3.0
* @param int $deprecated Deprecated since 3.0.
*
* @return WC_Product
*/
@ -1332,7 +1342,9 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
if ( ! $object || 0 === $object->get_id() ) {
return new WP_Error(
"woocommerce_rest_{$this->post_type}_invalid_id", __( 'Invalid ID.', 'woocommerce' ), array(
"woocommerce_rest_{$this->post_type}_invalid_id",
__( 'Invalid ID.', 'woocommerce' ),
array(
'status' => 404,
)
);
@ -1340,7 +1352,9 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
if ( 'variation' === $object->get_type() ) {
return new WP_Error(
"woocommerce_rest_invalid_{$this->post_type}_id", __( 'To manipulate product variations you should use the /products/&lt;product_id&gt;/variations/&lt;id&gt; endpoint.', 'woocommerce' ), array(
"woocommerce_rest_invalid_{$this->post_type}_id",
__( 'To manipulate product variations you should use the /products/&lt;product_id&gt;/variations/&lt;id&gt; endpoint.', 'woocommerce' ),
array(
'status' => 404,
)
);
@ -1360,8 +1374,10 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
if ( ! wc_rest_check_post_permissions( $this->post_type, 'delete', $object->get_id() ) ) {
return new WP_Error(
"woocommerce_rest_user_cannot_delete_{$this->post_type}",
/* translators: %s: post type */
"woocommerce_rest_user_cannot_delete_{$this->post_type}", sprintf( __( 'Sorry, you are not allowed to delete %s.', 'woocommerce' ), $this->post_type ), array(
sprintf( __( 'Sorry, you are not allowed to delete %s.', 'woocommerce' ), $this->post_type ),
array(
'status' => rest_authorization_required_code(),
)
);
@ -1396,8 +1412,10 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
// If we don't support trashing for this type, error out.
if ( ! $supports_trash ) {
return new WP_Error(
'woocommerce_rest_trash_not_supported',
/* translators: %s: post type */
'woocommerce_rest_trash_not_supported', sprintf( __( 'The %s does not support trashing.', 'woocommerce' ), $this->post_type ), array(
sprintf( __( 'The %s does not support trashing.', 'woocommerce' ), $this->post_type ),
array(
'status' => 501,
)
);
@ -1407,8 +1425,10 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
if ( is_callable( array( $object, 'get_status' ) ) ) {
if ( 'trash' === $object->get_status() ) {
return new WP_Error(
'woocommerce_rest_already_trashed',
/* translators: %s: post type */
'woocommerce_rest_already_trashed', sprintf( __( 'The %s has already been deleted.', 'woocommerce' ), $this->post_type ), array(
sprintf( __( 'The %s has already been deleted.', 'woocommerce' ), $this->post_type ),
array(
'status' => 410,
)
);
@ -1421,8 +1441,10 @@ class WC_REST_Products_V2_Controller extends WC_REST_Legacy_Products_Controller
if ( ! $result ) {
return new WP_Error(
'woocommerce_rest_cannot_delete',
/* translators: %s: post type */
'woocommerce_rest_cannot_delete', sprintf( __( 'The %s cannot be deleted.', 'woocommerce' ), $this->post_type ), array(
sprintf( __( 'The %s cannot be deleted.', 'woocommerce' ), $this->post_type ),
array(
'status' => 500,
)
);

View File

@ -97,7 +97,8 @@ function wc_attribute_taxonomy_name_by_id( $attribute_id ) {
SELECT attribute_name
FROM {$wpdb->prefix}woocommerce_attribute_taxonomies
WHERE attribute_id = %d
", $attribute_id
",
$attribute_id
)
);
@ -116,7 +117,7 @@ function wc_attribute_taxonomy_name_by_id( $attribute_id ) {
* @return int
*/
function wc_attribute_taxonomy_id_by_name( $name ) {
$name = str_replace( 'pa_', '', wc_sanitize_taxonomy_name( $name ) );
$name = wc_attribute_taxonomy_slug( $name );
$taxonomies = wp_list_pluck( wc_get_attribute_taxonomies(), 'attribute_id', 'attribute_name' );
return isset( $taxonomies[ $name ] ) ? (int) $taxonomies[ $name ] : 0;
@ -131,7 +132,7 @@ function wc_attribute_taxonomy_id_by_name( $name ) {
*/
function wc_attribute_label( $name, $product = '' ) {
if ( taxonomy_is_product_attribute( $name ) ) {
$name = wc_sanitize_taxonomy_name( str_replace( 'pa_', '', $name ) );
$name = wc_attribute_taxonomy_slug( $name );
$all_labels = wp_list_pluck( wc_get_attribute_taxonomies(), 'attribute_label', 'attribute_name' );
$label = isset( $all_labels[ $name ] ) ? $all_labels[ $name ] : $name;
} elseif ( $product ) {
@ -166,7 +167,7 @@ function wc_attribute_label( $name, $product = '' ) {
function wc_attribute_orderby( $name ) {
global $wc_product_attributes, $wpdb;
$name = str_replace( 'pa_', '', sanitize_title( $name ) );
$name = wc_attribute_taxonomy_slug( $name );
if ( isset( $wc_product_attributes[ 'pa_' . $name ] ) ) {
$orderby = $wc_product_attributes[ 'pa_' . $name ]->attribute_orderby;
@ -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' ),
)
);
@ -385,7 +387,8 @@ function wc_get_attribute( $id ) {
SELECT *
FROM {$wpdb->prefix}woocommerce_attribute_taxonomies
WHERE attribute_id = %d
", $id
",
$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'] );
@ -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']
)
);
@ -623,7 +628,8 @@ function wc_delete_attribute( $id ) {
SELECT attribute_name
FROM {$wpdb->prefix}woocommerce_attribute_taxonomies
WHERE attribute_id = %d
", $id
",
$id
)
);
@ -662,3 +668,16 @@ function wc_delete_attribute( $id ) {
return false;
}
/**
* Get an unprefixed product attribute name.
*
* @since 3.6.0
*
* @param string $attribute_name Attribute name.
* @return string
*/
function wc_attribute_taxonomy_slug( $attribute_name ) {
$attribute_name = wc_sanitize_taxonomy_name( $attribute_name );
return 0 === strpos( $attribute_name, 'pa_' ) ? substr( $attribute_name, 3 ) : $attribute_name;
}

View File

@ -65,7 +65,7 @@ class WC_Widget_Layered_Nav_Filters extends WC_Widget {
continue;
}
$filter_name = 'filter_' . sanitize_title( str_replace( 'pa_', '', $taxonomy ) );
$filter_name = 'filter_' . wc_attribute_taxonomy_slug( $taxonomy );
$current_filter = isset( $_GET[ $filter_name ] ) ? explode( ',', wc_clean( wp_unslash( $_GET[ $filter_name ] ) ) ) : array(); // WPCS: input var ok, CSRF ok.
$current_filter = array_map( 'sanitize_title', $current_filter );
$new_filter = array_diff( $current_filter, array( $term_slug ) );

View File

@ -223,7 +223,7 @@ class WC_Widget_Layered_Nav extends WC_Widget {
if ( $taxonomy !== $this->get_current_taxonomy() ) {
$term_counts = $this->get_filtered_term_product_counts( wp_list_pluck( $terms, 'term_id' ), $taxonomy, $query_type );
$_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes();
$taxonomy_filter_name = str_replace( 'pa_', '', $taxonomy );
$taxonomy_filter_name = wc_attribute_taxonomy_slug( $taxonomy );
$taxonomy_label = wc_attribute_label( $taxonomy );
/* translators: %s: taxonomy name */
@ -423,7 +423,7 @@ class WC_Widget_Layered_Nav extends WC_Widget {
continue;
}
$filter_name = 'filter_' . str_replace( 'pa_', '', $taxonomy );
$filter_name = 'filter_' . wc_attribute_taxonomy_slug( $taxonomy );
$current_filter = isset( $_GET[ $filter_name ] ) ? explode( ',', wc_clean( wp_unslash( $_GET[ $filter_name ] ) ) ) : array(); // WPCS: input var ok, CSRF ok.
$current_filter = array_map( 'sanitize_title', $current_filter );
@ -452,7 +452,7 @@ class WC_Widget_Layered_Nav extends WC_Widget {
// Add Query type Arg to URL.
if ( 'or' === $query_type && ! ( 1 === count( $current_filter ) && $option_is_set ) ) {
$link = add_query_arg( 'query_type_' . sanitize_title( str_replace( 'pa_', '', $taxonomy ) ), 'or', $link );
$link = add_query_arg( 'query_type_' . wc_attribute_taxonomy_slug( $taxonomy ), 'or', $link );
}
$link = str_replace( '%2C', ',', $link );
}