function test_varation_save_attributes() { // Create a variable product with a color attribute. $product = new WC_Product_Variable(); $attribute = new WC_Product_Attribute(); $attribute->set_id(0); $attribute->set_name('color'); $attribute->set_options(explode(WC_DELIMITER, 'green | red')); $attribute->set_visible(true); $attribute->set_variation(true); $product->set_attributes(array($attribute)); $product->save(); // Create a new variation with the color 'green'. $variation = new WC_Product_Variation(); $variation->set_parent_id($product->get_id()); $variation->set_attributes(array('color' => 'green')); $variation->set_status('private'); $variation->save(); // Now update some value unrelated to attributes. $variation = wc_get_product($variation->get_id()); $variation->set_status('publish'); $variation->save(); // Load up the updated variation and verify that the saved state is correct. $loaded_variation = wc_get_product($variation->get_id()); $this->assertEquals('publish', $loaded_variation->get_status('edit')); $_attribute = $loaded_variation->get_attributes('edit'); $this->assertEquals('green', $_attribute['color']); }
/** * Test product setters and getters * @since 2.7.0 */ public function test_product_getters_and_setters() { global $wpdb; $attributes = array(); $attribute = new WC_Product_Attribute(); $attribute->set_id(0); $attribute->set_name('Test Attribute'); $attribute->set_options(array('Fish', 'Fingers')); $attribute->set_position(0); $attribute->set_visible(true); $attribute->set_variation(false); $attributes['test-attribute'] = $attribute; $getters_and_setters = array('name' => 'Test', 'slug' => 'test', 'status' => 'publish', 'catalog_visibility' => 'search', 'featured' => false, 'description' => 'Hello world', 'short_description' => 'hello', 'sku' => 'TEST SKU', 'regular_price' => 15.0, 'sale_price' => 10.0, 'date_on_sale_from' => '1475798400', 'date_on_sale_to' => '1477267200', 'total_sales' => 20, 'tax_status' => 'none', 'tax_class' => '', 'manage_stock' => true, 'stock_quantity' => 10, 'stock_status' => 'instock', 'backorders' => 'notify', 'sold_individually' => false, 'weight' => 100, 'length' => 10, 'width' => 10, 'height' => 10, 'upsell_ids' => array(2, 3), 'cross_sell_ids' => array(4, 5), 'parent_id' => 0, 'reviews_allowed' => true, 'default_attributes' => array(), 'purchase_note' => 'A note', 'menu_order' => 2, 'gallery_image_ids' => array(), 'download_expiry' => -1, 'download_limit' => 5, 'attributes' => $attributes); $product = new WC_Product(); foreach ($getters_and_setters as $function => $value) { $product->{"set_{$function}"}($value); } $product->save(); $product = new WC_Product_Simple($product->get_id()); foreach ($getters_and_setters as $function => $value) { $this->assertEquals($value, $product->{"get_{$function}"}(), $function); } $image_url = media_sideload_image("https://cldup.com/Dr1Bczxq4q.png", $product->get_id(), '', 'src'); $image_id = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE guid='%s';", $image_url)); $product->set_image_id($image_id[0]); $product->save(); $this->assertEquals($image_id[0], $product->get_image_id()); }
/** * Read attributes from post meta. * * @param WC_Product * @since 2.7.0 */ protected function read_attributes(&$product) { $meta_values = maybe_unserialize(get_post_meta($product->get_id(), '_product_attributes', true)); if ($meta_values) { $attributes = array(); foreach ($meta_values as $meta_value) { if (!empty($meta_value['is_taxonomy'])) { if (!taxonomy_exists($meta_value['name'])) { continue; } $options = wc_get_object_terms($product->get_id(), $meta_value['name'], 'term_id'); } else { $options = wc_get_text_attributes($meta_value['value']); } $attribute = new WC_Product_Attribute(); $attribute->set_id(wc_attribute_taxonomy_id_by_name($meta_value['name'])); $attribute->set_name($meta_value['name']); $attribute->set_options($options); $attribute->set_position($meta_value['position']); $attribute->set_visible($meta_value['is_visible']); $attribute->set_variation($meta_value['is_variation']); $attributes[] = $attribute; } $product->set_attributes($attributes); } }
/** * Save product meta. * * @throws WC_REST_Exception REST API exceptions. * @param WC_Product $product Product instance. * @param WP_REST_Request $request Request data. * @return WC_Product */ protected function save_product_meta($product, $request) { global $wpdb; // Virtual. if (isset($request['virtual'])) { $product->set_virtual($request['virtual']); } // Tax status. if (isset($request['tax_status'])) { $product->set_tax_status($request['tax_status']); } // Tax Class. if (isset($request['tax_class'])) { $product->set_tax_class($request['tax_class']); } // Catalog Visibility. if (isset($request['catalog_visibility'])) { $product->set_catalog_visibility($request['catalog_visibility']); } // Purchase Note. if (isset($request['purchase_note'])) { $product->set_purchase_note(wc_clean($request['purchase_note'])); } // Featured Product. if (isset($request['featured'])) { $product->set_featured($request['featured']); } // Shipping data. $product = $this->save_product_shipping_data($product, $request); // SKU. if (isset($request['sku'])) { $product->set_sku(wc_clean($request['sku'])); } // Attributes. if (isset($request['attributes'])) { $attributes = array(); foreach ($request['attributes'] as $attribute) { $attribute_id = 0; $attribute_name = ''; // Check ID for global attributes or name for product attributes. if (!empty($attribute['id'])) { $attribute_id = absint($attribute['id']); $attribute_name = wc_attribute_taxonomy_name_by_id($attribute_id); } elseif (!empty($attribute['name'])) { $attribute_name = wc_clean($attribute['name']); } if (!$attribute_id && !$attribute_name) { continue; } if ($attribute_id) { if (isset($attribute['options'])) { $options = $attribute['options']; if (!is_array($attribute['options'])) { // Text based attributes - Posted values are term names. $options = explode(WC_DELIMITER, $options); } $values = array_map('wc_sanitize_term_text_based', $options); $values = array_filter($values, 'strlen'); } else { $values = array(); } if (!empty($values)) { // Add attribute to array, but don't set values. $attribute_object = new WC_Product_Attribute(); $attribute_object->set_id($attribute_id); $attribute_object->set_name($attribute_name); $attribute_object->set_options($values); $attribute_object->set_position(isset($attribute['position']) ? (string) absint($attribute['position']) : '0'); $attribute_object->set_visible(isset($attribute['visible']) && $attribute['visible'] ? 1 : 0); $attribute_object->set_variation(isset($attribute['variation']) && $attribute['variation'] ? 1 : 0); $attributes[] = $attribute_object; } } elseif (isset($attribute['options'])) { // Custom attribute - Add attribute to array and set the values. if (is_array($attribute['options'])) { $values = $attribute['options']; } else { $values = explode(WC_DELIMITER, $attribute['options']); } $attribute_object = new WC_Product_Attribute(); $attribute_object->set_name($attribute_name); $attribute_object->set_options($values); $attribute_object->set_position(isset($attribute['position']) ? (string) absint($attribute['position']) : '0'); $attribute_object->set_visible(isset($attribute['visible']) && $attribute['visible'] ? 1 : 0); $attribute_object->set_variation(isset($attribute['variation']) && $attribute['variation'] ? 1 : 0); $attributes[] = $attribute_object; } } $product->set_attributes($attributes); } // Sales and prices. if (in_array($product->get_type(), array('variable', 'grouped'), true)) { $product->set_regular_price(''); $product->set_sale_price(''); $product->set_date_on_sale_to(''); $product->set_date_on_sale_from(''); $product->set_price(''); } else { // Regular Price. if (isset($request['regular_price'])) { $product->set_regular_price($request['regular_price']); } // Sale Price. if (isset($request['sale_price'])) { $product->set_sale_price($request['sale_price']); } if (isset($request['date_on_sale_from'])) { $product->set_date_on_sale_from($request['date_on_sale_from']); } if (isset($request['date_on_sale_to'])) { $product->set_date_on_sale_to($request['date_on_sale_to']); } } // Product parent ID for groups. if (isset($request['parent_id'])) { $product->set_parent_id($request['parent_id']); } // Sold individually. if (isset($request['sold_individually'])) { $product->set_sold_individually($request['sold_individually']); } // Stock status. if (isset($request['in_stock'])) { $stock_status = true === $request['in_stock'] ? 'instock' : 'outofstock'; } else { $stock_status = $product->get_stock_status(); } // Stock data. if ('yes' === get_option('woocommerce_manage_stock')) { // Manage stock. if (isset($request['manage_stock'])) { $product->set_manage_stock($request['manage_stock']); } // Backorders. if (isset($request['backorders'])) { $product->set_backorders($request['backorders']); } if ($product->is_type('grouped')) { $product->set_manage_stock('no'); $product->set_backorders('no'); $product->set_stock_quantity(''); $product->set_stock_status($status); } elseif ($product->is_type('external')) { $product->set_manage_stock('no'); $product->set_backorders('no'); $product->set_stock_quantity(''); $product->set_stock_status('instock'); } elseif ($product->get_manage_stock()) { // Stock status is always determined by children so sync later. if (!$product->is_type('variable')) { $product->set_stock_status($stock_status); } // Stock quantity. if (isset($request['stock_quantity'])) { $product->set_stock_quantity(wc_stock_amount($request['stock_quantity'])); } elseif (isset($request['inventory_delta'])) { $stock_quantity = wc_stock_amount($product->get_stock_amount()); $stock_quantity += wc_stock_amount($request['inventory_delta']); $product->set_stock_quantity(wc_stock_amount($stock_quantity)); } } else { // Don't manage stock. $product->set_manage_stock('no'); $product->set_stock_quantity(''); $product->set_stock_status($stock_status); } } elseif (!$product->is_type('variable')) { $product->set_stock_status($stock_status); } // Upsells. if (isset($request['upsell_ids'])) { $upsells = array(); $ids = $request['upsell_ids']; if (!empty($ids)) { foreach ($ids as $id) { if ($id && $id > 0) { $upsells[] = $id; } } } $product->set_upsell_ids($upsells); } // Cross sells. if (isset($request['cross_sell_ids'])) { $crosssells = array(); $ids = $request['cross_sell_ids']; if (!empty($ids)) { foreach ($ids as $id) { if ($id && $id > 0) { $crosssells[] = $id; } } } $product->set_cross_sell_ids($crosssells); } // Product categories. if (isset($request['categories']) && is_array($request['categories'])) { $product = $this->save_taxonomy_terms($product, $request['categories']); } // Product tags. if (isset($request['tags']) && is_array($request['tags'])) { $product = $this->save_taxonomy_terms($product, $request['tags'], 'tag'); } // Downloadable. if (isset($request['downloadable'])) { $product->set_downloadable($request['downloadable']); } // Downloadable options. if ($product->get_downloadable()) { // Downloadable files. if (isset($request['downloads']) && is_array($request['downloads'])) { $product = $this->save_downloadable_files($product, $request['downloads']); } // Download limit. if (isset($request['download_limit'])) { $product->set_download_limit($request['download_limit']); } // Download expiry. if (isset($request['download_expiry'])) { $product->set_download_expiry($request['download_expiry']); } } // Product url and button text for external products. if ($product->is_type('external')) { if (isset($request['external_url'])) { $product->set_product_url($request['external_url']); } if (isset($request['button_text'])) { $product->set_button_text($request['button_text']); } } // Save default attributes for variable products. if ($product->is_type('variable')) { $product = $this->save_default_attributes($product, $request); } return $product; }
/** * Add an attribute row. */ public static function add_attribute() { ob_start(); check_ajax_referer('add-attribute', 'security'); if (!current_user_can('edit_products')) { die(-1); } $i = absint($_POST['i']); $metabox_class = array(); $attribute = new WC_Product_Attribute(); $attribute->set_id(wc_attribute_taxonomy_id_by_name(sanitize_text_field($_POST['taxonomy']))); $attribute->set_name(sanitize_text_field($_POST['taxonomy'])); $attribute->set_visible(apply_filters('woocommerce_attribute_default_visibility', 1)); $attribute->set_variation(apply_filters('woocommerce_attribute_default_is_variation', 0)); if ($attribute->is_taxonomy()) { $metabox_class[] = 'taxonomy'; $metabox_class[] = $attribute->get_name(); } include 'admin/meta-boxes/views/html-product-attribute.php'; die; }
/** * Save product meta * * @since 2.2 * @param WC_Product $product * @param array $data * @return WC_Product * @throws WC_API_Exception */ protected function save_product_meta($product, $data) { global $wpdb; // Virtual if (isset($data['virtual'])) { $product->set_virtual($data['virtual']); } // Tax status if (isset($data['tax_status'])) { $product->set_tax_status(wc_clean($data['tax_status'])); } // Tax Class if (isset($data['tax_class'])) { $product->set_tax_class(wc_clean($data['tax_class'])); } // Catalog Visibility if (isset($data['catalog_visibility'])) { $product->set_catalog_visibility(wc_clean($data['catalog_visibility'])); } // Purchase Note if (isset($data['purchase_note'])) { $product->set_purchase_note(wc_clean($data['purchase_note'])); } // Featured Product if (isset($data['featured'])) { $product->set_featured($data['featured']); } // Shipping data $product = $this->save_product_shipping_data($product, $data); // SKU if (isset($data['sku'])) { $sku = $product->get_sku(); $new_sku = wc_clean($data['sku']); if ('' == $new_sku) { $product->set_sku(''); } elseif ($new_sku !== $sku) { if (!empty($new_sku)) { $unique_sku = wc_product_has_unique_sku($product->get_id(), $new_sku); if (!$unique_sku) { throw new WC_API_Exception('woocommerce_api_product_sku_already_exists', __('The SKU already exists on another product.', 'woocommerce'), 400); } else { $product->set_sku($new_sku); } } else { $product->set_sku(''); } } } // Attributes if (isset($data['attributes'])) { $attributes = array(); foreach ($data['attributes'] as $attribute) { $is_taxonomy = 0; $taxonomy = 0; if (!isset($attribute['name'])) { continue; } $attribute_slug = sanitize_title($attribute['name']); if (isset($attribute['slug'])) { $taxonomy = $this->get_attribute_taxonomy_by_slug($attribute['slug']); $attribute_slug = sanitize_title($attribute['slug']); } if ($taxonomy) { $is_taxonomy = 1; } if ($is_taxonomy) { $attribute_id = wc_attribute_taxonomy_id_by_name($attribute['name']); if (isset($attribute['options'])) { $options = $attribute['options']; if (!is_array($attribute['options'])) { // Text based attributes - Posted values are term names $options = explode(WC_DELIMITER, $options); } $values = array_map('wc_sanitize_term_text_based', $options); $values = array_filter($values, 'strlen'); } else { $values = array(); } // Update post terms if (taxonomy_exists($taxonomy)) { wp_set_object_terms($product->get_id(), $values, $taxonomy); } if (!empty($values)) { // Add attribute to array, but don't set values. $attribute_object = new WC_Product_Attribute(); $attribute_object->set_id($attribute_id); $attribute_object->set_name($taxonomy); $attribute_object->set_options($values); $attribute_object->set_position(isset($attribute['position']) ? absint($attribute['position']) : 0); $attribute_object->set_visible(isset($attribute['visible']) && $attribute['visible'] ? 1 : 0); $attribute_object->set_variation(isset($attribute['variation']) && $attribute['variation'] ? 1 : 0); $attributes[] = $attribute_object; } } elseif (isset($attribute['options'])) { // Array based if (is_array($attribute['options'])) { $values = $attribute['options']; // Text based, separate by pipe } else { $values = array_map('wc_clean', explode(WC_DELIMITER, $attribute['options'])); } // Custom attribute - Add attribute to array and set the values. $attribute_object = new WC_Product_Attribute(); $attribute_object->set_name($attribute['name']); $attribute_object->set_options($values); $attribute_object->set_position(isset($attribute['position']) ? absint($attribute['position']) : 0); $attribute_object->set_visible(isset($attribute['visible']) && $attribute['visible'] ? 1 : 0); $attribute_object->set_variation(isset($attribute['variation']) && $attribute['variation'] ? 1 : 0); $attributes[] = $attribute_object; } } uasort($attributes, 'wc_product_attribute_uasort_comparison'); $product->set_attributes($attributes); } // Sales and prices if (in_array($product->get_type(), array('variable', 'grouped'))) { // Variable and grouped products have no prices. $product->set_regular_price(''); $product->set_sale_price(''); $product->set_date_on_sale_to(''); $product->set_date_on_sale_from(''); $product->set_price(''); } else { // Regular Price if (isset($data['regular_price'])) { $regular_price = '' === $data['regular_price'] ? '' : $data['regular_price']; } else { $regular_price = $product->get_regular_price(); } // Sale Price if (isset($data['sale_price'])) { $sale_price = '' === $data['sale_price'] ? '' : $data['sale_price']; } else { $sale_price = $product->get_sale_price(); } $product->set_regular_price($regular_price); $product->set_sale_price($sale_price); if (isset($data['sale_price_dates_from'])) { $date_from = $data['sale_price_dates_from']; } else { $date_from = $product->get_date_on_sale_from() ? date('Y-m-d', $date_from) : ''; } if (isset($data['sale_price_dates_to'])) { $date_to = $data['sale_price_dates_to']; } else { $date_to = $product->get_date_on_sale_to() ? date('Y-m-d', $date_to) : ''; } if ($date_to && !$date_from) { $date_from = strtotime('NOW', current_time('timestamp')); } $product->set_date_on_sale_to($date_to); $product->set_date_on_sale_from($date_from); if ($product->is_on_sale()) { $product->set_price($product->get_sale_price()); } else { $product->set_price($product->get_regular_price()); } } // Product parent ID for groups if (isset($data['parent_id'])) { $product->set_parent_id(absint($data['parent_id'])); } // Sold Individually if (isset($data['sold_individually'])) { $product->set_sold_individually(true === $data['sold_individually'] ? 'yes' : ''); } // Stock status if (isset($data['in_stock'])) { $stock_status = true === $data['in_stock'] ? 'instock' : 'outofstock'; } else { $stock_status = $product->get_stock_status(); if ('' === $stock_status) { $stock_status = 'instock'; } } // Stock Data if ('yes' == get_option('woocommerce_manage_stock')) { // Manage stock if (isset($data['managing_stock'])) { $managing_stock = true === $data['managing_stock'] ? 'yes' : 'no'; $product->set_manage_stock($managing_stock); } else { $managing_stock = $product->get_manage_stock() ? 'yes' : 'no'; } // Backorders if (isset($data['backorders'])) { if ('notify' == $data['backorders']) { $backorders = 'notify'; } else { $backorders = true === $data['backorders'] ? 'yes' : 'no'; } $product->set_backorders($backorders); } else { $backorders = $product->get_backorders(); } if ($product->is_type('grouped')) { $product->set_manage_stock('no'); $product->set_backorders('no'); $product->set_stock_quantity(''); $product->set_stock_status($stock_status); } elseif ($product->is_type('external')) { $product->set_manage_stock('no'); $product->set_backorders('no'); $product->set_stock_quantity(''); $product->set_stock_status('instock'); } elseif ('yes' == $managing_stock) { $product->set_backorders($backorders); // Stock status is always determined by children so sync later. if (!$product->is_type('variable')) { $product->set_stock_status($stock_status); } // Stock quantity if (isset($data['stock_quantity'])) { $product->set_stock_quantity(wc_stock_amount($data['stock_quantity'])); } } else { // Don't manage stock. $product->set_manage_stock('no'); $product->set_backorders($backorders); $product->set_stock_quantity(''); $product->set_stock_status($stock_status); } } elseif (!$product->is_type('variable')) { $product->set_stock_status($stock_status); } // Upsells if (isset($data['upsell_ids'])) { $upsells = array(); $ids = $data['upsell_ids']; if (!empty($ids)) { foreach ($ids as $id) { if ($id && $id > 0) { $upsells[] = $id; } } $product->set_upsell_ids($upsells); } else { $product->set_upsell_ids(array()); } } // Cross sells if (isset($data['cross_sell_ids'])) { $crosssells = array(); $ids = $data['cross_sell_ids']; if (!empty($ids)) { foreach ($ids as $id) { if ($id && $id > 0) { $crosssells[] = $id; } } $product->set_cross_sell_ids($crosssells); } else { $product->set_cross_sell_ids(array()); } } // Product categories if (isset($data['categories']) && is_array($data['categories'])) { $term_ids = array_unique(array_map('intval', $data['categories'])); $product->set_category_ids($term_ids); } // Product tags if (isset($data['tags']) && is_array($data['tags'])) { $term_ids = array_unique(array_map('intval', $data['tags'])); $product->set_tag_ids($term_ids); } // Downloadable if (isset($data['downloadable'])) { $is_downloadable = true === $data['downloadable'] ? 'yes' : 'no'; $product->set_downloadable($is_downloadable); } else { $is_downloadable = $product->get_downloadable() ? 'yes' : 'no'; } // Downloadable options if ('yes' == $is_downloadable) { // Downloadable files if (isset($data['downloads']) && is_array($data['downloads'])) { $product = $this->save_downloadable_files($product, $data['downloads']); } // Download limit if (isset($data['download_limit'])) { $product->set_download_limit($data['download_limit']); } // Download expiry if (isset($data['download_expiry'])) { $product->set_download_expiry($data['download_expiry']); } } // Product url if ($product->is_type('external')) { if (isset($data['product_url'])) { $product->set_product_url($data['product_url']); } if (isset($data['button_text'])) { $product->set_button_text($data['button_text']); } } // Reviews allowed if (isset($data['reviews_allowed'])) { $product->set_reviews_allowed($data['reviews_allowed']); } // Save default attributes for variable products. if ($product->is_type('variable')) { $product = $this->save_default_attributes($product, $data); } // Do action for product type do_action('woocommerce_api_process_product_meta_' . $product->get_type(), $product->get_id(), $data); return $product; }
/** * Prepare attributes for save. * @return array */ public static function prepare_attributes($data = false) { $attributes = array(); if (!$data) { $data = $_POST; } if (isset($data['attribute_names'], $data['attribute_values'])) { $attribute_names = $data['attribute_names']; $attribute_values = $data['attribute_values']; $attribute_visibility = isset($data['attribute_visibility']) ? $data['attribute_visibility'] : array(); $attribute_variation = isset($data['attribute_variation']) ? $data['attribute_variation'] : array(); $attribute_position = $data['attribute_position']; $attribute_names_max_key = max(array_keys($attribute_names)); for ($i = 0; $i <= $attribute_names_max_key; $i++) { if (empty($attribute_names[$i]) || !isset($attribute_values[$i])) { continue; } $attribute_name = wc_clean($attribute_names[$i]); $attribute_id = wc_attribute_taxonomy_id_by_name($attribute_name); $options = isset($attribute_values[$i]) ? $attribute_values[$i] : ''; if (is_array($options)) { // Term ids sent as array. $options = wp_parse_id_list($options); } else { // Terms or text sent in textarea. $options = 0 < $attribute_id ? wc_sanitize_textarea(wc_sanitize_term_text_based($options)) : wc_sanitize_textarea($options); $options = wc_get_text_attributes($options); } $attribute = new WC_Product_Attribute(); $attribute->set_id($attribute_id); $attribute->set_name($attribute_name); $attribute->set_options($options); $attribute->set_position($attribute_position[$i]); $attribute->set_visible(isset($attribute_visibility[$i])); $attribute->set_variation(isset($attribute_variation[$i])); $attributes[] = $attribute; } } return $attributes; }