I have a single product custom variation table template in functions.php and I'm trying to get product custom attribute. I have two them (date and location).
I'm found a lot of solutions, but none didn't work for me.
Woocommerce version 3.2.6.
With this code below I get
Notice: Only variables should be passed by reference.
And I get type 'Null' of $date.
<td class="date">
<?php
$product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->id;
$date = array_shift( wc_get_product_terms( $product_id, 'pa_date', array( 'fields' => 'names' ) ) );
?>
</td>
This is my full product variation table code in function.php
function woocommerce_variable_add_to_cart(){
global $product, $post, $woocommerce;
$attributes = $product->get_attributes();
$variations = find_valid_variations();
// Check if the special 'price_grid' meta is set, if it is, load the default template:
if ( get_post_meta($post->ID, 'price_grid', true) ) {
wp_enqueue_script( 'wc-add-to-cart-variation' );
wc_get_template( 'single-product/add-to-cart/variable.php', array(
'available_variations' => $product->get_available_variations(),
'attributes' => $product->get_variation_attributes(),
'selected_attributes' => $product->get_variation_default_attributes()
) );
return;
}
?>
<table class="variations variations-grid" cellspacing="0">
<thead>
<tr>
<td> Date | Location </td>
<td> Price </td>
<td> Quantity </td>
<td> Availability </td>
<td> </td>
</tr>
</thead>
<tbody>
<?php
foreach ($variations as $key => $value) {
if( !$value['variation_is_visible'] ) continue;
?>
<tr>
<td class="date">
<?php
$product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->id; // Added WC 3+ support
$date = array_shift( wc_get_product_terms( $product_id, 'pa_date', array( 'fields' => 'names' ) ) );
?>
</td>
<td class="price">
<?php echo '<span>£</span>' . $product->get_price(); ?>
</td>
<td class="quantity">
<?php woocommerce_quantity_input(); ?>
</td>
<td class="stock">
<?php if (!$value['is_in_stock'] ) { ?>
<p class="stock out-of-stock"><?php _e( 'Places Not Available', 'woocommerce' ); ?></p>
<?php } else { ?>
<p class="stock in-stock"><?php _e( 'Places Available', 'woocommerce' ); ?></p>
</td>
<td class="add-to-cart">
<form class="cart" action="<?php echo esc_url( $product->add_to_cart_url() ); ?>" method="post" enctype='multipart/form-data'>
<?php
if(!empty($value['attributes'])){
foreach ($value['attributes'] as $attr_key => $attr_value) {
?>
<input type="hidden" name="<?php echo $attr_key?>" value="<?php echo $attr_value?>">
<?php
}
}
?>
<button type="submit" class="single_add_to_cart_button button alt"><span class="glyphicon glyphicon-tag"></span> Add to cart</button>
<input type="hidden" name="variation_id" value="<?php echo $value['variation_id']?>" />
<input type="hidden" name="product_id" value="<?php echo esc_attr( $post->ID ); ?>" />
<input type="hidden" name="add-to-cart" value="<?php echo esc_attr( $post->ID ); ?>" />
</form>
<?php } ?>
</td>
</tr>
<?php } ?>
</tbody>
</table>
<?php
}
function find_valid_variations() {
global $product;
$variations = $product->get_available_variations();
$attributes = $product->get_attributes();
$new_variants = array();
foreach( $variations as $variation ) {
// Peruse the attributes.
// 1. If both are explicitly set, this is a valid variation
// 2. If one is not set, that means any, and we must 'create' the rest.
$valid = true; // so far
foreach( $attributes as $slug => $args ) {
if( array_key_exists("attribute_$slug", $variation['attributes']) && !empty($variation['attributes']["attribute_$slug"]) ) {
// Exists
} else {
// Not exists, create
$valid = false; // it contains 'anys'
foreach( explode( '|', $attributes[$slug]['value']) as $attribute ) {
$attribute = trim( $attribute );
$new_variant = $variation;
$new_variant['attributes']["attribute_$slug"] = $attribute;
$new_variants[] = $new_variant;
}
}
}
// This contains ALL set attributes, and is itself a 'valid' variation.
if( $valid )
$new_variants[] = $variation;
}
return $new_variants;
}
UPDATE
I got this code working, but I get both attribute values (date location) in one tag.
How to seperate attributes?
<td>
<?php
foreach($value['attributes'] as $key => $val ) {
$val = str_replace(array('-','_'), ' ', $val);
printf( '<span class="attr attr-%s">%s</span>', $key, ucwords($val) );
}
?>
</td>
UPDATE
Finally I get date and location but with extra warnings, notices, and single characters.
Code
<?php
foreach($value as $date ) {
printf($date['attribute_date']);
}
?>
** SOLVED **
Maybe not the best method, but it's working.
<td class="date">
<?php
$i = 0;
foreach($value['attributes'] as $key => $val ) {
if($i == 0 ) {
echo $val;
}
$i++;
}
?>
</td>
<td class="location">
<?php
$i = 0;
foreach($value['attributes'] as $key => $val ) {
if($i !== 0) {
echo $val;
}
$i++;
}
?>
</td>
Use the method get_attributes() and function wc_get_product_terms() described here
<?php
// Get the attributes
$attributes = $product->get_attributes();
// Start the loop
foreach ( $attributes as $attribute ) : ?>
<?php
// Check and output, adopted from /templates/single-product/product-attributes.php
if ( $attribute['is_taxonomy'] ) {
$values = wc_get_product_terms( $product->id, $attribute['name'], array( 'fields' => 'names' ) );
echo apply_filters( 'woocommerce_attribute', wpautop( wptexturize( implode( ', ', $values ) ) ), $attribute, $values );
} else {
// Convert pipes to commas and display values
$values = array_map( 'trim', explode( WC_DELIMITER, $attribute['value'] ) );
echo apply_filters( 'woocommerce_attribute', wpautop( wptexturize( implode( ', ', $values ) ) ), $attribute, $values );
}
?>
<?php endforeach; ?>
If you look at the template \templates\single-product\product-attributes.php you can see how to get the individual attribute names.
if ( $attribute->is_taxonomy() ) {
$attribute_taxonomy = $attribute->get_taxonomy_object();
$attribute_values = wc_get_product_terms( $product->get_id(), $attribute->get_name(), array( 'fields' => 'all' ) );
foreach ( $attribute_values as $attribute_value ) {
$value_name = esc_html( $attribute_value->name );
if ( $attribute_taxonomy->attribute_public ) {
$values[] = '' . $value_name . '';
} else {
$values[] = $value_name;
}
}
}
Here's how to get specific Custom Attribute:
// Get the custom attribute
$svd_attribute = array_shift( wc_get_product_terms( $product->id, 'your_custom_attribute', array( 'fields' => 'names' ) ) );
// Display if String
if ( is_string( $svd_attribute ) ) {
echo wp_kses_post( "$svd_attribute" );
}
Just replace "your_custom_attribute"
Working on WooCommerce: 3.8.0
Related
I'm creating a plugin to set a different image for each out of stock product everything is displayed in the dashboard only if you set an image it doesn't work can someone help me solve the problem in the code, I would be very grateful
<?php
/**
* Plugin Name: Out of Stock Image Changer for WooCommerce
* Plugin URI:
* Description: Automatically changes the product image when it goes out of stock in WooCommerce
* Version: 1.0.0
* Author:
* Author URI:
* License:
*/
add_action( 'admin_menu', 'register_product_image_changer_page' );
function register_product_image_changer_page() {
add_submenu_page( 'edit.php?post_type=product', 'Out of stock images', 'Out of stock images', 'manage_options', 'out-of-stock-images', 'render_product_image_changer_page' );
}
function render_product_image_changer_page() {
global $wpdb;
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( __( 'You do not have sufficient permissions to access this page.', 'woocommerce' ) );
}
if ( ! empty( $_POST ) && check_admin_referer( 'update_out_of_stock_images' ) ) {
$product_ids = isset( $_POST['product_id'] ) ? $_POST['product_id'] : array();
$out_of_stock_images = isset( $_POST['out_of_stock_image'] ) ? $_POST['out_of_stock_image'] : array();
foreach ( $product_ids as $index => $product_id ) {
update_post_meta( $product_id, 'out_of_stock_image', $out_of_stock_images[ $index ] );
}
}
$results = $wpdb->get_results( "SELECT ID, post_title FROM $wpdb->posts WHERE post_type = 'product' AND post_status = 'publish'" );
?>
<div class="wrap">
<h1><?php _e( 'Out of stock images', 'woocommerce' ); ?></h1>
<form method="post">
<?php wp_nonce_field( 'update_out_of_stock_images' ); ?>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th><?php _e( 'Product', 'woocommerce' ); ?></th>
<th><?php _e( 'Out of stock image URL', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ( $results as $result ) : ?>
<tr>
<td><?php echo $result->post_title; ?></td>
<td>
<input type="hidden" name="product_id[]" value="<?php echo $result->ID; ?>">
<input type="text" name="out_of_stock_image[]" value="<?php echo get_post_meta( $result->ID, 'out_of_stock_image', true ); ?>" class="widefat">
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p class="submit">
<input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e( 'Save Changes', 'woocommerce' ); ?>">
</p>
</form>
</div>
<?php
}
add_action( 'woocommerce_before_single_product_summary', 'maybe_change_product_image', 9 );
function maybe_change_product_image() {
global $product;
if ( ! $product->is_in_stock() ) {
$out_of_stock_image = get_post_meta( get_the_ID(), 'out_of_stock_image', true );
if ( ! empty( $out_of_stock_image ) ) {
remove_action( 'woocommerce_before_single_product_summary', 'woocommerce_show_product_images', 20 );
add_action( 'woocommerce_before_single_product_summary', 'show_out_of_stock_image', 20 );
}
}
}
function show_out_of_stock_image() {
global $product;
$out_of_stock_image = get_post_meta( get_the_ID(), 'out_of_stock_image', true );
if ( ! empty( $out_of_stock_image ) ) {
echo '<img src="' . esc_url( $out_of_stock_image ) . '" class="attachment-shop_single size-shop_single wp-post-image" alt="">';
}
}
everything works in the dashboard, but if an image is set it is not displayed
this code worked for me.
/**
* Plugin Name: Out of Stock Image Changer for WooCommerce
* Plugin URI:
* Description: Automatically changes the product image when it goes out of stock in WooCommerce
* Version: 1.0.0
* Author:
* Author URI:
* License:
*/
add_action( 'admin_menu', 'register_product_image_changer_page' );
function register_product_image_changer_page() {
add_submenu_page( 'edit.php?post_type=product', 'Out of stock images', 'Out of stock images', 'manage_options', 'out-of-stock-images', 'render_product_image_changer_page' );
}
function render_product_image_changer_page() {
global $wpdb;
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( __( 'You do not have sufficient permissions to access this page.', 'woocommerce' ) );
}
if ( ! empty( $_POST ) && check_admin_referer( 'update_out_of_stock_images' ) ) {
$product_ids = isset( $_POST['product_id'] ) ? $_POST['product_id'] : array();
$out_of_stock_images = isset( $_POST['out_of_stock_image'] ) ? $_POST['out_of_stock_image'] : array();
foreach ( $product_ids as $index => $product_id ) {
update_post_meta( $product_id, 'out_of_stock_image', $out_of_stock_images[ $index ] );
}
}
$results = $wpdb->get_results( "SELECT ID, post_title FROM $wpdb->posts WHERE post_type = 'product' AND post_status = 'publish'" );
?>
<div class="wrap">
<h1><?php _e( 'Out of stock images', 'woocommerce' ); ?></h1>
<form method="post">
<?php wp_nonce_field( 'update_out_of_stock_images' ); ?>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th><?php _e( 'Product', 'woocommerce' ); ?></th>
<th><?php _e( 'Out of stock image URL', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ( $results as $result ) : ?>
<tr>
<td><?php echo $result->post_title; ?></td>
<td>
<input type="hidden" name="product_id[]" value="<?php echo $result->ID; ?>">
<input type="text" name="out_of_stock_image[]" value="<?php echo get_post_meta( $result->ID, 'out_of_stock_image', true ); ?>" class="widefat">
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p class="submit">
<input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e( 'Save Changes', 'woocommerce' ); ?>">
</p>
</form>
</div>
<?php
}
add_action( 'woocommerce_before_single_product', 'maybe_change_product_image', 9 );
function maybe_change_product_image() {
global $product;
if ( ! $product->is_in_stock() ) {
$out_of_stock_image = get_post_meta( $product->get_id(), 'out_of_stock_image', true );
if ( ! empty( $out_of_stock_image ) ) {
remove_action( 'woocommerce_before_single_product_summary', 'woocommerce_show_product_images', 20 );
add_action( 'woocommerce_before_single_product_summary', 'show_out_of_stock_image', 20 );
}
}
}
function show_out_of_stock_image() {
global $product;
$out_of_stock_image = get_post_meta( $product->get_id(), 'out_of_stock_image', true );
if ( ! empty( $out_of_stock_image ) ) {
echo '<img src="' . esc_url( $out_of_stock_image ) . '" class="attachment-shop_single size-shop_single wp-post-image" alt="">';
}
}
This question already has answers here:
Remove attribute values from product variation title and show them on separate rows
(1 answer)
Display variations attributes values as separate rows in Woocommerce cart / checkout
(1 answer)
Closed 2 years ago.
I noticed when I add to Cart products that have variations, Woocommerce uses 2 templates in Cart or Checkout pages.
if the product has only one or two variations, it uses this template as an example of my product:
<tr class="cart_item">
<td class="product-name">
3-in-1 Rechargeable Trimmer Grinder - CHINA, 3 IN 1 Grooming N5
<strong class="product-quantity">× 2</strong>
</td>
</tr>
If the product has more than two variations, it uses the following:
<tr class="cart_item">
<td class="product-name">
Mini Shaver Hair Trimmer Rechargeable
<strong class="product-quantity">× 1</strong>
<dl class="variation">
<dt class="variation-Size">Size:</dt>
<dd class="variation-Size"><p>Standard</p> </dd>
<dt class="variation-ShipsFrom">Ships From:</dt>
<dd class="variation-ShipsFrom"><p>CHINA</p> </dd>
<dt class="variation-Color">Color:</dt>
<dd class="variation-Color"><p>White</p> </dd>
</dl>
</td>
</tr>
As you notice when there are more than two it uses the class variations.
my question how to modify Woocommerce so that it uses only the 2nd template (more than two variations), in order to simplify code when i want customizing css or javascript.
more details :
review-order.php:
<tbody>
<?php
do_action( 'woocommerce_review_order_before_cart_contents' );
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_checkout_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
?>
<tr class="<?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ); ?>">
<td class="product-name">
<?php echo apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key ) . ' '; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php echo apply_filters( 'woocommerce_checkout_cart_item_quantity', ' <strong class="product-quantity">' . sprintf( '× %s', $cart_item['quantity'] ) . '</strong>', $cart_item, $cart_item_key ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php echo wc_get_formatted_cart_item_data( $cart_item ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</td>
<td class="product-total">
<?php echo apply_filters( 'woocommerce_cart_item_subtotal', WC()->cart->get_product_subtotal( $_product, $cart_item['quantity'] ), $cart_item, $cart_item_key ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</td>
</tr>
<?php
}
}
do_action( 'woocommerce_review_order_after_cart_contents' );
?>
</tbody>
cart-item-data.php:
<?php
/**
* Cart item data (when outputting non-flat)
*
* This template can be overridden by copying it to yourtheme/woocommerce/cart/cart-item-data.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* #see https://docs.woocommerce.com/document/template-structure/
* #package WooCommerce/Templates
* #version 2.4.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<dl class="variation">
<?php foreach ( $item_data as $data ) : ?>
<dt class="<?php echo sanitize_html_class( 'variation-' . $data['key'] ); ?>"><?php echo wp_kses_post( $data['key'] ); ?>:</dt>
<dd class="<?php echo sanitize_html_class( 'variation-' . $data['key'] ); ?>"><?php echo wp_kses_post( wpautop( $data['display'] ) ); ?></dd>
<?php endforeach; ?>
</dl>
cart.php :
<tbody>
<?php do_action( 'woocommerce_before_cart_contents' ); ?>
<?php
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
$product_permalink = apply_filters( 'woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink( $cart_item ) : '', $cart_item, $cart_item_key );
?>
<tr class="woocommerce-cart-form__cart-item <?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ); ?>">
<td class="product-remove">
<?php
echo apply_filters( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
'woocommerce_cart_item_remove_link',
sprintf(
'×',
esc_url( wc_get_cart_remove_url( $cart_item_key ) ),
esc_html__( 'Remove this item', 'woocommerce' ),
esc_attr( $product_id ),
esc_attr( $_product->get_sku() )
),
$cart_item_key
);
?>
</td>
<td class="product-thumbnail">
<?php
$thumbnail = apply_filters( 'woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key );
if ( ! $product_permalink ) {
echo $thumbnail; // PHPCS: XSS ok.
} else {
printf( '%s', esc_url( $product_permalink ), $thumbnail ); // PHPCS: XSS ok.
}
?>
</td>
<td class="product-name" data-title="<?php esc_attr_e( 'Product', 'woocommerce' ); ?>">
<?php
if ( ! $product_permalink ) {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key ) . ' ' );
} else {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', sprintf( '%s', esc_url( $product_permalink ), $_product->get_name() ), $cart_item, $cart_item_key ) );
}
do_action( 'woocommerce_after_cart_item_name', $cart_item, $cart_item_key );
// Meta data.
echo wc_get_formatted_cart_item_data( $cart_item ); // PHPCS: XSS ok.
// Backorder notification.
if ( $_product->backorders_require_notification() && $_product->is_on_backorder( $cart_item['quantity'] ) ) {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_backorder_notification', '<p class="backorder_notification">' . esc_html__( 'Available on backorder', 'woocommerce' ) . '</p>', $product_id ) );
}
?>
</td>
<td class="product-price" data-title="<?php esc_attr_e( 'Price', 'woocommerce' ); ?>">
<?php
echo apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key ); // PHPCS: XSS ok.
?>
</td>
<td class="product-quantity" data-title="<?php esc_attr_e( 'Quantity', 'woocommerce' ); ?>">
<?php
if ( $_product->is_sold_individually() ) {
$product_quantity = sprintf( '1 <input type="hidden" name="cart[%s][qty]" value="1" />', $cart_item_key );
} else {
$product_quantity = woocommerce_quantity_input(
array(
'input_name' => "cart[{$cart_item_key}][qty]",
'input_value' => $cart_item['quantity'],
'max_value' => $_product->get_max_purchase_quantity(),
'min_value' => '0',
'product_name' => $_product->get_name(),
),
$_product,
false
);
}
echo apply_filters( 'woocommerce_cart_item_quantity', $product_quantity, $cart_item_key, $cart_item ); // PHPCS: XSS ok.
?>
</td>
<td class="product-subtotal" data-title="<?php esc_attr_e( 'Subtotal', 'woocommerce' ); ?>">
<?php
echo apply_filters( 'woocommerce_cart_item_subtotal', WC()->cart->get_product_subtotal( $_product, $cart_item['quantity'] ), $cart_item, $cart_item_key ); // PHPCS: XSS ok.
?>
</td>
</tr>
<?php
}
}
?>
<?php do_action( 'woocommerce_cart_contents' ); ?>
<tr>
<td colspan="6" class="actions">
<?php if ( wc_coupons_enabled() ) { ?>
<div class="coupon">
<label for="coupon_code"><?php esc_html_e( 'Coupon:', 'woocommerce' ); ?></label> <input type="text" name="coupon_code" class="input-text" id="coupon_code" value="" placeholder="<?php esc_attr_e( 'Coupon code', 'woocommerce' ); ?>" /> <button type="submit" class="button" name="apply_coupon" value="<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>"><?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?></button>
<?php do_action( 'woocommerce_cart_coupon' ); ?>
</div>
<?php } ?>
<button type="submit" class="button" name="update_cart" value="<?php esc_attr_e( 'Update cart', 'woocommerce' ); ?>"><?php esc_html_e( 'Update cart', 'woocommerce' ); ?></button>
<?php do_action( 'woocommerce_cart_actions' ); ?>
<?php wp_nonce_field( 'woocommerce-cart', 'woocommerce-cart-nonce' ); ?>
</td>
</tr>
<?php do_action( 'woocommerce_after_cart_contents' ); ?>
</tbody>
wc-product-functions.php :
/**
* Variation Formatting.
*
* Gets a formatted version of variation data or item meta.
*
* #param array|WC_Product_Variation $variation Variation object.
* #param bool $flat Should this be a flat list or HTML list? (default: false).
* #param bool $include_names include attribute names/labels in the list.
* #param bool $skip_attributes_in_name Do not list attributes already part of the variation name.
* #return string
*/
function wc_get_formatted_variation( $variation, $flat = false, $include_names = true, $skip_attributes_in_name = false ) {
$return = '';
if ( is_a( $variation, 'WC_Product_Variation' ) ) {
$variation_attributes = $variation->get_attributes();
$product = $variation;
$variation_name = $variation->get_name();
} else {
$product = false;
$variation_name = '';
// Remove attribute_ prefix from names.
$variation_attributes = array();
if ( is_array( $variation ) ) {
foreach ( $variation as $key => $value ) {
$variation_attributes[ str_replace( 'attribute_', '', $key ) ] = $value;
}
}
}
$list_type = $include_names ? 'dl' : 'ul';
if ( is_array( $variation_attributes ) ) {
if ( ! $flat ) {
$return = '<' . $list_type . ' class="variation">';
}
$variation_list = array();
foreach ( $variation_attributes as $name => $value ) {
// If this is a term slug, get the term's nice name.
if ( taxonomy_exists( $name ) ) {
$term = get_term_by( 'slug', $value, $name );
if ( ! is_wp_error( $term ) && ! empty( $term->name ) ) {
$value = $term->name;
}
}
// Do not list attributes already part of the variation name.
if ( '' === $value || ( $skip_attributes_in_name && wc_is_attribute_in_product_name( $value, $variation_name ) ) ) {
continue;
}
if ( $include_names ) {
if ( $flat ) {
$variation_list[] = wc_attribute_label( $name, $product ) . ': ' . rawurldecode( $value );
} else {
$variation_list[] = '<dt>' . wc_attribute_label( $name, $product ) . ':</dt><dd>' . rawurldecode( $value ) . '</dd>';
}
} else {
if ( $flat ) {
$variation_list[] = rawurldecode( $value );
} else {
$variation_list[] = '<li>' . rawurldecode( $value ) . '</li>';
}
}
}
if ( $flat ) {
$return .= implode( ', ', $variation_list );
} else {
$return .= implode( '', $variation_list );
}
if ( ! $flat ) {
$return .= '</' . $list_type . '>';
}
}
return $return;
}
class-wc-order-item-meta.php :
/**
* Display meta in a formatted list.
*
* #param bool $flat Flat (default: false).
* #param bool $return Return (default: false).
* #param string $hideprefix Hide prefix (default: _).
* #param string $delimiter Delimiter used to separate items when $flat is true.
* #return string|void
*/
public function display( $flat = false, $return = false, $hideprefix = '_', $delimiter = ", \n" ) {
$output = '';
$formatted_meta = $this->get_formatted( $hideprefix );
if ( ! empty( $formatted_meta ) ) {
$meta_list = array();
foreach ( $formatted_meta as $meta ) {
if ( $flat ) {
$meta_list[] = wp_kses_post( $meta['label'] . ': ' . $meta['value'] );
} else {
$meta_list[] = '
<dt class="variation-' . sanitize_html_class( sanitize_text_field( $meta['key'] ) ) . '">' . wp_kses_post( $meta['label'] ) . ':</dt>
<dd class="variation-' . sanitize_html_class( sanitize_text_field( $meta['key'] ) ) . '">' . wp_kses_post( wpautop( make_clickable( $meta['value'] ) ) ) . '</dd>
';
}
}
if ( ! empty( $meta_list ) ) {
if ( $flat ) {
$output .= implode( $delimiter, $meta_list );
} else {
$output .= '<dl class="variation">' . implode( '', $meta_list ) . '</dl>';
}
}
}
$output = apply_filters( 'woocommerce_order_items_meta_display', $output, $this, $flat );
if ( $return ) {
return $output;
} else {
echo $output; // WPCS: XSS ok.
}
}
I'm newbie in wordpress and wondering how can I set custom <h1> for categories in wordpress. At the moment: <h1>Category:Category name</h1>. I've spent half day to find out how to do that. Advices from articles don't work.
Plugins: Yoast SEO, All-in-one SEO pack, WP SEO Meta
Editing functions.php in theme folder
add_action("category_edit_form_fields", 'mayak_category_meta');
function mayak_category_meta( $term ) {
?>
<tr class="form-field">
<th scope="row" valign="top"><label>Заголовок (title)</label></th>
<td>
<input type="text" name="mayak[title]" value="<?php echo esc_attr( get_term_meta( $term->term_id, 'title', 1 ) ) ?>"><br />
<p class="description">Не более 60 знаков, включая пробелы</p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top"><label>Заголовок h1</label></th>
<td>
<input type="text" name="mayak[h1]" value="<?php echo esc_attr( get_term_meta( $term->term_id, 'h1', 1 ) ) ?>"><br />
<p class="description">Заголовок страницы</p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top"><label>Ключевые слова</label></th>
<td>
<input type="text" name="mayak[keywords]" value="<?php echo esc_attr( get_term_meta( $term->term_id, 'keywords', 1 ) ) ?>"><br />
<p class="description">Ключевые слова (keywords)</p>
</td>
</tr>
<?php
}
function mayak_save_meta( $term_id ) {
if ( ! isset($_POST['mayak']) )
return;
$mayak = array_map('trim', $_POST['mayak']);
foreach( $mayak as $key => $value ){
if( empty($value) ){
delete_term_meta( $term_id, $key );
continue;
}
update_term_meta( $term_id, $key, $value );
}
return $term_id;
}
add_action("create_category", 'mayak_save_meta');
add_action("edited_category", 'mayak_save_meta');
function mayak_filter_single_cat_title($term_name) {
$terms = get_category( get_query_var('cat'));
$cat_id = $terms->cat_ID;
$term_name = get_term_meta ($cat_id, 'title', true);
return $term_name;
}
add_filter('single_cat_title', 'mayak_filter_single_cat_title', 10, 1 );
function mayak_single_cat_title ($term_name){
if(empty($term_name)){
$terms = get_category( get_query_var( 'cat' ));
$cat_id = $terms->cat_ID;
$term_name = get_cat_name($cat_id);
}
return $term_name;
}
add_filter( 'single_cat_title', 'mayak_single_cat_title', 10, 1 );
function mayak_cat_caption($caption) {
$terms = get_category( get_query_var( 'cat' ));
$cat_id = $terms->cat_ID;
$caption = get_cat_name($cat_id);
echo $caption;
}
function mayak_cat_h1($name_cat) {
$terms = get_category( get_query_var( 'cat' ));
$cat_id = $terms->cat_ID;
$name_cat = get_term_meta ( $cat_id, 'h1', true );
echo $name_cat;
if(empty($name_cat)){
echo mayak_cat_caption($caption);
}
}
The Solution was to edit archive.php file in theme folder and adding this code:
<?php
$term = get_queried_object();
$term_h1 = get_field('h1', $term);
if ( empty( $term_h1 ) )
the_archive_title( '<h1 class="page-title">', '</h1>' );
else
echo '<h1 class="page-title">' . $term_h1 . '</h1>';
the_archive_description( '<div class="taxonomy-description">', '</div>' );
?>
Shortcode Display WooCommerce Product Variations Dropdown
How to display the Product Variations in WooC Commerce with Shortcode???
This is my code:
add_shortcode( 'test_shortcode', 'woo_display_variation_dropdown' );
function woo_display_variation_dropdown() {
global $product;
if( $product->is_type( 'variable' )) {
$attribute_keys = array_keys( $product->get_attributes() );
?>
<form class="variations_form cart" method="post" enctype='multipart/form-data' data-product_id="<?php echo absint( $product->id ); ?>" data-product_variations="<?php echo htmlspecialchars( json_encode( $product->get_available_variations() ) ) ?>">
<?php do_action( 'woocommerce_before_variations_form' ); ?>
<?php if ( empty( $product->get_available_variations() ) && false !== $product->get_available_variations() ) : ?>
<p class="stock out-of-stock"><?php _e( 'This product is currently out of stock and unavailable.', 'woocommerce' ); ?></p>
<?php else : ?>
<table class="variations" cellspacing="0">
<tbody>
<?php foreach ( $product->get_attributes() as $attribute_name => $options ) : ?>
<tr>
<td class="label"><label for="<?php echo sanitize_title( $attribute_name ); ?>"><?php echo wc_attribute_label( $attribute_name ); ?></label></td>
<td class="value">
<?php
$selected = isset( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ? wc_clean( urldecode( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ) : $product->get_variation_default_attribute( $attribute_name );
wc_dropdown_variation_attribute_options( array( 'options' => $options, 'attribute' => $attribute_name, 'product' => $product, 'selected' => $selected ) );
echo end( $attribute_keys ) === $attribute_name ? apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . __( 'Clear', 'woocommerce' ) . '</a>' ) : '';
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<?php endif; ?>
</form>
<?php }
}
It does not work as I would like. What I am doing wrong?
Any help is appreciated.
I am using woocommerce in my website. I need radio buttons instead of dropdown for variations on product page. For this, I have replaced the variable.php file with the following code :--
<?php
/**
* Variable product add to cart
*
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.5.0
*
* Modified to use radio buttons instead of dropdowns
* #author 8manos
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! function_exists( 'print_attribute_radio' ) ) {
function print_attribute_radio( $checked_value, $value, $label, $name ) {
global $product;
// This handles < 2.4.0 bw compatibility where text attributes were not sanitized.
$checked = sanitize_title( $checked_value ) === $checked_value ? checked( $checked_value, sanitize_title( $value ), false ) : checked( $checked_value, $value, false );
$input_name = 'attribute_' . esc_attr( $name ) ;
$esc_value = esc_attr( $value );
$id = esc_attr( $name . '_v_' . $value . $product->get_id() ); //added product ID at the end of the name to target single products
$filtered_label = apply_filters( 'woocommerce_variation_option_name', $label );
printf( '<div><input type="radio" name="%1$s" value="%2$s" id="%3$s" %4$s><label for="%3$s">%5$s</label></div>', $input_name, $esc_value, $id, $checked, $filtered_label );
}
}
global $product;
$attribute_keys = array_keys( $attributes );
do_action( 'woocommerce_before_add_to_cart_form' ); ?>
<form class="variations_form cart" method="post" enctype='multipart/form-data' data-product_id="<?php echo absint( $product->get_id() ); ?>" data-product_variations="<?php echo htmlspecialchars( wp_json_encode( $available_variations ) ) ?>">
<?php do_action( 'woocommerce_before_variations_form' ); ?>
<?php if ( empty( $available_variations ) && false !== $available_variations ) : ?>
<p class="stock out-of-stock"><?php _e( 'This product is currently out of stock and unavailable.', 'woocommerce' ); ?></p>
<?php else : ?>
<table class="variations" cellspacing="0">
<tbody>
<?php foreach ( $attributes as $name => $options ) : ?>
<tr>
<td class="label"><label for="<?php echo sanitize_title( $name ); ?>"><?php echo wc_attribute_label( $name ); ?></label></td>
<?php
$sanitized_name = sanitize_title( $name );
if ( isset( $_REQUEST[ 'attribute_' . $sanitized_name ] ) ) {
$checked_value = $_REQUEST[ 'attribute_' . $sanitized_name ];
} elseif ( isset( $selected_attributes[ $sanitized_name ] ) ) {
$checked_value = $selected_attributes[ $sanitized_name ];
} else {
$checked_value = '';
}
?>
<td class="value">
<?php
if ( ! empty( $options ) ) {
if ( taxonomy_exists( $name ) ) {
// Get terms if this is a taxonomy - ordered. We need the names too.
$terms = wc_get_product_terms( $product->get_id(), $name, array( 'fields' => 'all' ) );
foreach ( $terms as $term ) {
if ( ! in_array( $term->slug, $options ) ) {
continue;
}
print_attribute_radio( $checked_value, $term->slug, $term->name, $sanitized_name );
}
} else {
foreach ( $options as $option ) {
print_attribute_radio( $checked_value, $option, $option, $sanitized_name );
}
}
}
echo end( $attribute_keys ) === $name ? apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations cstm-reset" href="#">' . __( 'Clear', 'woocommerce' ) . '</a>' ) : '';
?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php do_action( 'woocommerce_before_add_to_cart_button' ); ?>
<div class="single_variation_wrap">
<?php
do_action( 'woocommerce_before_single_variation' );
do_action( 'woocommerce_single_variation' );
do_action( 'woocommerce_after_single_variation' );
?>
</div>
<?php do_action( 'woocommerce_after_add_to_cart_button' ); ?>
<?php endif; ?>
<?php do_action( 'woocommerce_after_variations_form' ); ?>
</form>
<?php do_action( 'woocommerce_after_add_to_cart_form' ); ?>
It shows the radio buttons as I needed but the problem is that, the price is not displaying on variation products.You can check my website http://www.itsjal.com/store/product/led-lamp-par38/
Price should be displayed at the end when I select variations options. Can anybody help me to solve this problem ?
Thanks
You can try this plugin. https://wordpress.org/plugins/woocommerce-radio-buttons/
This plugin also has its own template files if you want to customize it.