/** * Loads an array of attributes used for variations, as well as their possible values. * * @param WC_Product */ private function read_variation_attributes(&$product) { global $wpdb; $variation_attributes = array(); $attributes = $product->get_attributes(); $child_ids = $product->get_children(); if (!empty($child_ids) && !empty($attributes)) { foreach ($attributes as $attribute) { if (empty($attribute['is_variation'])) { continue; } // Get possible values for this attribute, for only visible variations. $values = array_unique($wpdb->get_col($wpdb->prepare("SELECT meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s AND post_id IN (" . implode(',', array_map('esc_sql', $child_ids)) . ")", wc_variation_attribute_name($attribute['name'])))); // Empty value indicates that all options for given attribute are available. if (in_array('', $values) || empty($values)) { $values = $attribute['is_taxonomy'] ? wc_get_object_terms($product->get_id(), $attribute['name'], 'slug') : wc_get_text_attributes($attribute['value']); // Get custom attributes (non taxonomy) as defined. } elseif (!$attribute['is_taxonomy']) { $text_attributes = wc_get_text_attributes($attribute['value']); $assigned_text_attributes = $values; $values = array(); // Pre 2.4 handling where 'slugs' were saved instead of the full text attribute if (version_compare(get_post_meta($product->get_id(), '_product_version', true), '2.4.0', '<')) { $assigned_text_attributes = array_map('sanitize_title', $assigned_text_attributes); foreach ($text_attributes as $text_attribute) { if (in_array(sanitize_title($text_attribute), $assigned_text_attributes)) { $values[] = $text_attribute; } } } else { foreach ($text_attributes as $text_attribute) { if (in_array($text_attribute, $assigned_text_attributes)) { $values[] = $text_attribute; } } } } $variation_attributes[$attribute['name']] = array_unique($values); } } $product->set_variation_attributes($variation_attributes); }
/** * Get attribute options. * * @param int $product_id * @param array $attribute * @return array */ protected function get_attribute_options($product_id, $attribute) { if (isset($attribute['is_taxonomy']) && $attribute['is_taxonomy']) { return wc_get_object_terms($product_id, $attribute['name'], 'name'); } elseif (isset($attribute['value'])) { return array_map('trim', explode('|', $attribute['value'])); } return array(); }
/** * Wrapper for wp_get_post_terms which supports ordering by parent. * * NOTE: At this point in time, ordering by menu_order for example isn't possible with this function. wp_get_post_terms has no. * filters which we can utilise to modify it's query. https://core.trac.wordpress.org/ticket/19094. * * @param int $product_id Product ID. * @param string $taxonomy Taxonomy slug. * @param array $args Query arguments. * @return array */ function wc_get_product_terms($product_id, $taxonomy, $args = array()) { if (!taxonomy_exists($taxonomy)) { return array(); } if (empty($args['orderby']) && taxonomy_is_product_attribute($taxonomy)) { $args['orderby'] = wc_attribute_orderby($taxonomy); } // Support ordering by parent. if (!empty($args['orderby']) && in_array($args['orderby'], array('name_num', 'parent'))) { $fields = isset($args['fields']) ? $args['fields'] : 'all'; $orderby = $args['orderby']; // Unset for wp_get_post_terms. unset($args['orderby']); unset($args['fields']); $terms = _wc_get_cached_product_terms($product_id, $taxonomy, $args); switch ($orderby) { case 'name_num': usort($terms, '_wc_get_product_terms_name_num_usort_callback'); break; case 'parent': usort($terms, '_wc_get_product_terms_parent_usort_callback'); break; } switch ($fields) { case 'names': $terms = wp_list_pluck($terms, 'name'); break; case 'ids': $terms = wp_list_pluck($terms, 'term_id'); break; case 'slugs': $terms = wp_list_pluck($terms, 'slug'); break; } } elseif (!empty($args['orderby']) && 'menu_order' === $args['orderby']) { // wp_get_post_terms doesn't let us use custom sort order. $args['include'] = wc_get_object_terms($product_id, $taxonomy, 'id'); if (empty($args['include'])) { $terms = array(); } else { // This isn't needed for get_terms. unset($args['orderby']); // Set args for get_terms. $args['menu_order'] = isset($args['order']) ? $args['order'] : 'ASC'; $args['hide_empty'] = isset($args['hide_empty']) ? $args['hide_empty'] : 0; $args['fields'] = isset($args['fields']) ? $args['fields'] : 'names'; // Ensure slugs is valid for get_terms - slugs isn't supported. $args['fields'] = 'slugs' === $args['fields'] ? 'id=>slug' : $args['fields']; $terms = get_terms($taxonomy, $args); } } else { $terms = _wc_get_cached_product_terms($product_id, $taxonomy, $args); } return apply_filters('woocommerce_get_product_terms', $terms, $product_id, $taxonomy, $args); }
/** * Count terms. These are done at this point so all product props are set in advance. * * @param WC_Product * @since 2.7.0 */ protected function update_term_counts(&$product) { if (!wp_defer_term_counting()) { global $wc_allow_term_recount; $wc_allow_term_recount = true; $post_type = $product->is_type('variation') ? 'product_variation' : 'product'; // Update counts for the post's terms. foreach ((array) get_object_taxonomies($post_type) as $taxonomy) { $tt_ids = wc_get_object_terms($product->get_id(), $taxonomy, 'term_taxonomy_id'); wp_update_term_count($tt_ids, $taxonomy); } } }
/** * Output a list of variation attributes for use in the cart forms. * * @param array $args * @since 2.4.0 */ function wc_dropdown_variation_attribute_options($args = array()) { $args = wp_parse_args(apply_filters('woocommerce_dropdown_variation_attribute_options_args', $args), array('options' => false, 'attribute' => false, 'product' => false, 'selected' => false, 'name' => '', 'id' => '', 'class' => '', 'show_option_none' => __('Choose an option', 'woocommerce'))); $options = $args['options']; $product = $args['product']; $attribute = $args['attribute']; $name = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title($attribute); $id = $args['id'] ? $args['id'] : sanitize_title($attribute); $class = $args['class']; $show_option_none = $args['show_option_none'] ? true : false; if (empty($options) && !empty($product) && !empty($attribute)) { $attributes = $product->get_variation_attributes(); $options = $attributes[$attribute]; } $html = '<select id="' . esc_attr($id) . '" class="' . esc_attr($class) . '" name="' . esc_attr($name) . '" data-attribute_name="attribute_' . esc_attr(sanitize_title($attribute)) . '" data-show_option_none="' . ($show_option_none ? 'yes' : 'no') . '">'; if ($show_option_none) { $html .= '<option value="">' . esc_html($args['show_option_none']) . '</option>'; } if (!empty($options)) { if ($product && taxonomy_exists($attribute)) { // Get terms if this is a taxonomy - ordered. We need the names too. $terms = wc_get_object_terms($product->get_id(), $attribute); foreach ($terms as $term) { if (in_array($term->slug, $options)) { $html .= '<option value="' . esc_attr($term->slug) . '" ' . selected(sanitize_title($args['selected']), $term->slug, false) . '>' . esc_html(apply_filters('woocommerce_variation_option_name', $term->name)) . '</option>'; } } } else { foreach ($options as $option) { // This handles < 2.4.0 bw compatibility where text attributes were not sanitized. $selected = sanitize_title($args['selected']) === $args['selected'] ? selected($args['selected'], sanitize_title($option), false) : selected($args['selected'], $option, false); $html .= '<option value="' . esc_attr($option) . '" ' . $selected . '>' . esc_html(apply_filters('woocommerce_variation_option_name', $option)) . '</option>'; } } } $html .= '</select>'; echo apply_filters('woocommerce_dropdown_variation_attribute_options_html', $html, $args); }
/** * Returns a single product attribute as a string. * @param string $attribute to get. * @return string */ public function get_attribute($attribute) { $attributes = $this->get_attributes(); $attribute = sanitize_title($attribute); if (isset($attributes[$attribute])) { $attribute_object = $attributes[$attribute]; } elseif (isset($attributes['pa_' . $attribute])) { $attribute_object = $attributes['pa_' . $attribute]; } else { return ''; } return $attribute_object->is_taxonomy() ? implode(', ', wc_get_object_terms($this->get_id(), $attribute_object->get_name(), 'name')) : wc_implode_text_attributes($attribute_object->get_options()); }
/** * Copy the taxonomies of a post to another post. * * @param mixed $id * @param mixed $new_id * @param mixed $post_type */ private function duplicate_post_taxonomies($id, $new_id, $post_type) { $exclude = array_filter(apply_filters('woocommerce_duplicate_product_exclude_taxonomies', array())); $taxonomies = array_diff(get_object_taxonomies($post_type), $exclude); foreach ($taxonomies as $taxonomy) { $post_terms = wc_get_object_terms($id, $taxonomy); $post_terms_count = sizeof($post_terms); for ($i = 0; $i < $post_terms_count; $i++) { wp_set_object_terms($new_id, $post_terms[$i]->slug, $taxonomy, true); } } }
_e('Dimensions', 'woocommerce'); ?> </th> <td class="product_dimensions"><?php echo esc_html(wc_format_dimensions($product->get_dimensions(false))); ?> </td> </tr> <?php } ?> <?php foreach ($attributes as $attribute) { ?> <tr> <th><?php echo wc_attribute_label($attribute->get_name()); ?> </th> <td><?php $values = $attribute->is_taxonomy() ? wc_get_object_terms($product->get_id(), $attribute->get_name(), 'name') : $attribute->get_options(); echo apply_filters('woocommerce_attribute', wpautop(wptexturize(implode(', ', $values))), $attribute, $values); ?> </td> </tr> <?php } ?> </table>