Merge pull request #16020 from woocommerce/feature/12273

New attribute helper functions
This commit is contained in:
Claudiu Lodromanean 2017-07-10 13:20:59 -07:00 committed by GitHub
commit 1699a9769f
2 changed files with 290 additions and 0 deletions

View File

@ -347,3 +347,177 @@ function wc_is_attribute_in_product_name( $attribute, $name ) {
function wc_array_filter_default_attributes( $attribute ) {
return ( ! empty( $attribute ) || '0' === $attribute );
}
/**
* Get attribute data by ID.
*
* @since 3.2.0
* @param int $id Attribute ID.
* @return stdClass|null
*/
function wc_get_attribute( $id ) {
global $wpdb;
$data = $wpdb->get_row( $wpdb->prepare( "
SELECT *
FROM {$wpdb->prefix}woocommerce_attribute_taxonomies
WHERE attribute_id = %d
", $id ) );
if ( is_wp_error( $data ) || is_null( $data ) ) {
return null;
}
$attribute = new stdClass();
$attribute->id = (int) $data->attribute_id;
$attribute->name = $data->attribute_label;
$attribute->slug = wc_attribute_taxonomy_name( $data->attribute_name );
$attribute->type = $data->attribute_type;
$attribute->order_by = $data->attribute_orderby;
$attribute->has_archives = (bool) $data->attribute_public;
return $attribute;
}
/**
* Create attribute.
*
* Options:
*
* id - Unique identifier, used to update an attribute.
* name - Attribute name.
* slug - Attribute alphanumeric identifier.
* type - Type of attribute, core options: 'select' and 'text', default to 'select'.
* order_by - Sort order, options: 'menu_order', 'name', 'name_num' and 'id'.
* has_archives - Enable or disable attribute archives.
*
* @since 3.2.0
* @param array $args Attribute arguments.
* @return int|WP_Error
*/
function wc_create_attribute( $args ) {
global $wpdb;
$args = wp_unslash( $args );
$id = ! empty( $args['id'] ) ? intval( $args['id'] ) : 0;
$format = array( '%s', '%s', '%s', '%s', '%d' );
// Name is required.
if ( empty( $args['name'] ) ) {
return new WP_Error( 'missing_attribute_name', __( 'Missing attribute name', 'woocommerce' ), array( 'status' => 400 ) );
}
// Set the attribute slug.
if ( empty( $args['slug'] ) ) {
$slug = wc_sanitize_taxonomy_name( $args['name'] );
} else {
$slug = preg_replace( '/^pa\_/', '', wc_sanitize_taxonomy_name( $args['slug'] ) );
}
// Validate slug.
if ( strlen( $slug ) >= 28 ) {
return new WP_Error( 'invalid_product_attribute_slug_too_long', sprintf( __( 'Slug "%s" is too long (28 characters max). Shorten it, please.', 'woocommerce' ), $slug ), array( 'status' => 400 ) );
} elseif ( wc_check_if_attribute_name_is_reserved( $slug ) ) {
return new WP_Error( 'invalid_product_attribute_slug_reserved_name', sprintf( __( 'Slug "%s" is not allowed because it is a reserved term. Change it, please.', 'woocommerce' ), $slug ), array( 'status' => 400 ) );
} elseif ( 0 === $id && taxonomy_exists( wc_attribute_taxonomy_name( $slug ) ) ) {
return new WP_Error( 'invalid_product_attribute_slug_already_exists', sprintf( __( 'Slug "%s" is already in use. Change it, please.', 'woocommerce' ), $slug ), array( 'status' => 400 ) );
}
// Validate type.
if ( empty( $args['type'] ) || ! array_key_exists( $args['type'], wc_get_attribute_types() ) ) {
$args['type'] = 'select';
}
// Validate order by.
if ( empty( $args['order_by'] ) || ! in_array( $args['order_by'], array( 'menu_order', 'name', 'name_num', 'id' ), true ) ) {
$args['order_by'] = 'menu_order';
}
$data = array(
'attribute_label' => $args['name'],
'attribute_name' => $slug,
'attribute_type' => $args['type'],
'attribute_orderby' => $args['order_by'],
'attribute_public' => isset( $args['has_archives'] ) ? (bool) $args['has_archives'] : false,
);
// Create or update.
if ( 0 === $id ) {
$results = $wpdb->insert(
$wpdb->prefix . 'woocommerce_attribute_taxonomies',
$data,
$format
);
if ( is_wp_error( $results ) ) {
return new WP_Error( 'cannot_create_attribute', $results->get_error_message(), array( 'status' => 400 ) );
}
$id = $wpdb->insert_id;
} else {
$results = $wpdb->update(
$wpdb->prefix . 'woocommerce_attribute_taxonomies',
$data,
array( 'attribute_id' => $id ),
$format,
array( '%d' )
);
if ( false === $results ) {
return new WP_Error( 'cannot_update_attribute', __( 'Could not update the attribute.', 'woocommerce' ), array( 'status' => 400 ) );
}
}
// Clear transients.
delete_transient( 'wc_attribute_taxonomies' );
return $id;
}
/**
* Update an attribute.
*
* For available args see wc_create_attribute().
*
* @since 3.2.0
* @param int $id Attribute ID.
* @param array $args Attribute arguments.
* @return int|WP_Error]
*/
function wc_update_attribute( $id, $args ) {
$attribute = wc_get_attribute( $id );
$args['id'] = $attribute ? $attribute->id : 0;
if ( $args['id'] && empty( $args['name'] ) ) {
$args['name'] = $attribute->name;
}
return wc_create_attribute( $args );
}
/**
* Delete attribute by ID.
*
* @since 3.2.0
* @param int $id Attribute ID.
* @return bool
*/
function wc_delete_attribute( $id ) {
global $wpdb;
$deleted = $wpdb->delete(
$wpdb->prefix . 'woocommerce_attribute_taxonomies',
array( 'attribute_id' => $id ),
array( '%d' )
);
if ( in_array( $deleted, array( 0, false ), true ) ) {
return false;
}
// Clear transients.
delete_transient( 'wc_attribute_taxonomies' );
return true;
}

View File

@ -0,0 +1,116 @@
<<?php
/**
* Class Functions.
* @package WooCommerce\Tests\Attributes
* @since 3.2.0
*/
class WC_Tests_Attributes_Functions extends WC_Unit_Test_Case {
/**
* Tests wc_get_attribute().
*
* @since 3.2.0
*/
public function test_wc_get_attribute() {
$args = array(
'name' => 'Brand',
'type' => 'select',
'order_by' => 'name',
'has_archives' => true,
);
$id = wc_create_attribute( $args );
$attribute = (array) wc_get_attribute( $id );
$expected = array(
'id' => $id,
'name' => 'Brand',
'slug' => 'pa_brand',
'type' => 'select',
'order_by' => 'name',
'has_archives' => true,
);
wc_delete_attribute( $id );
$this->assertEquals( $expected, $attribute );
}
/**
* Tests wc_create_attribute().
*
* @since 3.2.0
*/
public function test_wc_create_attribute() {
// Test success.
$id = wc_create_attribute( array( 'name' => 'Brand' ) );
$this->assertInternalType( 'int', $id );
// Test failures.
$err = wc_create_attribute( array() );
$this->assertEquals( 'missing_attribute_name', $err->get_error_code() );
$err = wc_create_attribute( array( 'name' => 'This is a big name for a product attribute!' ) );
$this->assertEquals( 'invalid_product_attribute_slug_too_long', $err->get_error_code() );
$err = wc_create_attribute( array( 'name' => 'Cat' ) );
$this->assertEquals( 'invalid_product_attribute_slug_reserved_name', $err->get_error_code() );
register_taxonomy( 'pa_brand', array( 'product' ), array( 'labels' => array( 'name' => 'Brand' ) ) );
$err = wc_create_attribute( array( 'name' => 'Brand' ) );
$this->assertEquals( 'invalid_product_attribute_slug_already_exists', $err->get_error_code() );
unregister_taxonomy( 'pa_brand' );
wc_delete_attribute( $id );
}
/**
* Tests wc_update_attribute().
*
* @since 3.2.0
*/
public function test_wc_update_attribute() {
$args = array(
'name' => 'Brand',
'type' => 'select',
'order_by' => 'name',
'has_archives' => true,
);
$id = wc_create_attribute( $args );
$updated = array(
'id' => $id,
'name' => 'Brand',
'slug' => 'pa_brand',
'type' => 'text',
'order_by' => 'menu_order',
'has_archives' => true,
);
wc_update_attribute( $id, $updated );
$attribute = (array) wc_get_attribute( $id );
wc_delete_attribute( $id );
$this->assertEquals( $updated, $attribute );
}
/**
* Tests wc_delete_attribute().
*
* @since 3.2.0
*/
public function test_wc_delete_attribute() {
// Success.
$id = wc_create_attribute( array( 'name' => 'Brand' ) );
$result = wc_delete_attribute( $id );
$this->assertTrue( $result );
// Failure.
$result = wc_delete_attribute( 9999999 );
$this->assertFalse( $result );
}
}