Appending a class attribute to woocommerce single product image - wordpress

- $image_title = esc_attr( get_the_title( get_post_thumbnail_id() ) );
$image_link = wp_get_attachment_url( get_post_thumbnail_id() );
$image = get_the_post_thumbnail( $post->ID, apply_filters( 'single_product_large_thumbnail_size', 'shop_single' ), array(
'title' => $image_title
) );
$attachment_count = count( $product->get_gallery_attachment_ids() );
if ( $attachment_count > 0 ) {
$gallery = '[product-gallery]';
} else {
$gallery = '';
}
echo apply_filters( 'woocommerce_single_product_image_html', sprintf( '%s', $image_link, $image_title, $image ), $post->ID );
Above is the code from product-image.php file of woocommerce. I want to add a class to the image of single product. I am unable to find out the way for it. Please help.
Thanks

$image = get_the_post_thumbnail( $post->ID, apply_filters( 'single_product_large_thumbnail_size', 'shop_single' ), array(
'title' => $image_title,
'class' => 'your class here'
));
I added the class key in get_the_post_thumbnail

Related

CMB2 How do I get my custom fields to show in my template?

<table class="lg-directory-table">
<?php foreach( $grouped_results as $key => $grouped_result ): ?>
<?php if( !empty( $group_posts ) ): ?>
<tr>
<th colspan="<?php echo count( $args['fields'] ); ?>" scope="rowgroup">
<?php $term = get_term($key, LG_PREFIX . 'directory_group'); ?>
<?php echo $term->name; ?>
</th>
</tr>
<?php endif; ?>
<?php if(
!isset( $args['template_options']['show_headers'] )
|| $args['template_options']['show_headers']
): ?>
<tr>
<?php foreach( $args['template_options']['fields'] as $field_name ): ?>
<th><small><?php echo apply_filters('lg_directory_member_field_header', $field_name ); ?></small></th>
<?php endforeach; ?>
</tr>
<?php endif; ?>
<?php global $post; ?>
<?php foreach( $grouped_result as $post ): setup_postdata($post); ?>
<?php
$member = array();
$member_metabox = cmb2_get_metabox( LG_PREFIX . 'directory_member' , LG_PREFIX . 'directory_member' );
foreach( $member_metabox->prop( 'fields' ) as $field_id => $field ) {
$field_value = get_post_meta( $post->ID, $field_id, true );
if( $field_value ) {
$array_field_id = str_replace( LG_PREFIX . 'directory_member_', '', $field_id );
$member[ $array_field_id ] = $field_value;
}
}
?>
<tr>
<?php foreach( $args['template_options']['fields'] as $field_name ): ?>
<td>
<span class="<?php echo 'lg-directory-' . $field_name; ?>">
<?php
$field_value = '';
if( isset( $member[$field_name] ) ) {
$field_value = $member[$field_name];
}
echo apply_filters('lg_directory_member_field_value', $field_value, $field_name, $member, $args );
?>
</span>
</td>
<?php endforeach; ?>
</tr>
<?php endforeach; wp_reset_postdata(); ?>
<?php endforeach; ?>
</table>
<?php endif; ?>
My fields show and save data in the backend, but in my template, they just refuse to show the data at all. Is there a special way I need to do it? I can't figure this thing out. If someone could just point me in the right direction. (And not to the CMB2 GitHub no one comments their code so I have no idea what they're doing and what goes where!)
Please help!
I will answer with example.
This is my CMB2 Meta box back end part:
/* Tour Metabox */
add_action( 'cmb2_admin_init', 'lmbox_register_tour_metabox' );
function lmbox_register_tour_metabox() {
$prefix = 'tour_';
//Itinerary Metabox
$lmd_metabox = new_cmb2_box( array(
'id' => 'tour_metabox2',
'title' => esc_html__( 'Tour Itinerary', 'lombokmedia' ),
'object_types' => array( 'tour' ), // Post type
'context' => 'normal',
'priority' => 'high',
) );
$group_field_id = $lmd_metabox->add_field( array(
'id' => $prefix . 'demo',
'type' => 'group',
'description' => esc_html__( 'Rincian jadwal tour', 'cmb2' ),
'options' => array(
'group_title' => esc_html__( 'Hari {#}', 'cmb2' ),
'add_button' => esc_html__( 'Tambah', 'cmb2' ),
'remove_button' => esc_html__( 'Hapus', 'cmb2' ),
'sortable' => true,
// 'closed' => true,
),
) );
$lmd_metabox->add_group_field( $group_field_id, array(
'name' => esc_html__( 'Judul', 'cmb2' ),
'id' => 'titlex1',
'type' => 'text',
'default' => 'Hari ',
) );
$lmd_metabox->add_group_field( $group_field_id, array(
'name' => esc_html__( 'Rincian', 'cmb2' ),
'description' => esc_html__( 'Rincian itinerary hari itu', 'cmb2' ),
'id' => 'itinerary_desc',
'type' => 'wysiwyg',
'options' => array(
'wpautop' => true, // use wpautop?
'media_buttons' => false,
'textarea_rows' => get_option('default_post_edit_rows', 5),
),
) );
} //END
And this is how I displayed it in single-tour.php (just the itinerary part)
<h2 class="post-title"><?php _e('Jadwal Kegiatan', 'lombokmedia') ?> <?php the_title(); ?>:</h2>
<?php
$entries = get_post_meta( get_the_ID(), 'tour_demo', true );
foreach ( (array) $entries as $key => $entry ) {
$title = $desc = '';
if ( isset( $entry['titlex1'] ) ) {
$title = esc_html( $entry['titlex1'] );
}
if ( isset( $entry['itinerary_desc'] ) ) {
$desc = wpautop( $entry['itinerary_desc'] );
}
echo '<div class="tour-item">';
echo '<h3>'.$title.'</h3>';
echo '<div>'.$desc.'</div>';
echo '</div>';
}
?>
I hope this help you understand and figured it out.

Get a product custom field value in Woocommerce single product pages

Could anyone assist in helping me get the below code to function correctly. I have taken bits of code from various other posts to create it.
I need to create a custom field (Datasheet) and be able to post a link to a PDF file. It should then appear just before the meta data on each product page.
Current code is as follows:
add_action( 'woocommerce_product_options_general_product_data',
'woo_add_custom_general_fields' );
function woo_add_custom_general_fields() {
global $woocommerce, $post;
echo '<div class="options_group">';
woocommerce_wp_text_input( array( // Text Field type
'id' => '_datasheet_url',
'label' => __( 'Datasheet', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => 'true',
'description' => __( 'Datasheet URL here.', 'woocommerce' )
) );
echo '</div>';
}
add_action( 'woocommerce_process_product_meta',
'woo_save_custom_general_fields' );
function woo_save_custom_general_fields( $post_id ){
$datasheet_field= $_POST['_datasheet_url'];
if( !empty( $datasheet_field ) )
update_post_meta( $post_id, '_datasheet_url', esc_attr( $datasheet_field
) );
}
add_action('woocommerce_product_meta_start',
'woo_display_custom_general_fields_values', 5);
function woo_display_custom_general_fields_values() {
global $product;
$url = get_post_meta( $post->ID, 'Datasheet', true );
echo '<img src="http://www.freemansolutions.co.uk/wp-content/uploads/pdf-
icon.png"> Datasheet';
}
The main error is $url = get_post_meta( $post->ID, 'Datasheet', true ); as $post is not defined, then $post->ID throw an error and you can get the URL custom field value.
Try the following instead:
add_action( 'woocommerce_product_options_general_product_data', 'add_datasheet_url_custom_field' );
function add_datasheet_url_custom_field() {
echo '<div class="options_group">';
woocommerce_wp_text_input( array(
'id' => '_datasheet_url',
'label' => __('Datasheet URL', 'woocommerce'),
'placeholder' => 'http://',
'desc_tip' => 'true',
'description' => __('Set the "Datasheet" URL here.', 'woocommerce'),
) );
echo '</div>';
}
add_action( 'woocommerce_process_product_meta', 'save_datasheet_url_custom_field', 12, 1 );
function save_datasheet_url_custom_field( $post_id ){
if( isset( $_POST['_datasheet_url'] ) )
update_post_meta( $post_id, '_datasheet_url', sanitize_text_field( $_POST['_datasheet_url'] ) );
}
add_action('woocommerce_product_meta_start', 'use_datasheet_url_custom_field', 5 );
function use_datasheet_url_custom_field() {
$pdf_url = get_post_meta( get_the_id(), '_datasheet_url', true );
if( ! empty( $pdf_url ) ){
$icon_pdf = home_url( '/wp-content/uploads/pdf-icon.png' );
echo '<img src="'.$icon_pdf.'" /> ' . __('Datasheet', 'woocommerce') . '';
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Display custom post categories as plan text

I am using this code to display custom post categories hierarchicaly, everything is working till now great but what I want to achieve also is to display these categories as plain text (without <a href="..."). Can anyone help?
$taxonomy = 'produkte_kategorie'; // change this to your taxonomy
$terms = wp_get_post_terms( $post->ID, $taxonomy, array( "fields" => "ids" ) );
if( $terms ) {
echo '<ul class="p-kategorie">';
$terms = trim( implode( ',', (array) $terms ), ' ,' );
wp_list_categories( 'title_li=&taxonomy=' . $taxonomy . '&include=' . $terms );
echo '</ul>';
}
You can do that via the following function,
$terms = trim( implode( ',', (array) $terms ), ' ,' );
$categories = get_categories(array('include'=>$terms,'taxonomy'=>'produkte_kategorie'));
foreach ($categories as $category) {
echo $category->cat_name;
}
Actually this didn't worked for me but I made a solution with this code from wordpress codex: https://developer.wordpress.org/reference/functions/wp_list_categories/
$taxonomy = 'category';
// Get the term IDs assigned to post.
$post_terms = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );
// Separator between links.
$separator = ', ';
if ( ! empty( $post_terms ) && ! is_wp_error( $post_terms ) ) {
$term_ids = implode( ',' , $post_terms );
$terms = wp_list_categories( array(
'title_li' => '',
'style' => 'none',
'echo' => false,
'taxonomy' => $taxonomy,
'include' => $term_ids
) );
$terms = rtrim( trim( str_replace( '<br />', $separator, $terms ) ), $separator );
// Display post categories.
echo $terms;
Thanks a lot for your Feedback

woocommerce Recent X commented products

I'am looking for code in Woocommerce that allow me to display x items wth recent comments (reviews) added
simlar to [recent_products per_page="16" columns="4" orderby="rand"] shortcode but allowing to get post only with comments
I don't believe there is a shortcode for this. You'd have to write some PHP. The way that you can do this is:
$number = 5; // Change as desired
$comments = get_comments( array( 'number' => $number, 'status' => 'approve', 'post_status' => 'publish', 'post_type' => 'product' ) );
if ( $comments ) {
echo '<ul class="product_list_widget">';
foreach ( (array) $comments as $comment ) {
$_product = wc_get_product( $comment->comment_post_ID );
$rating = intval( get_comment_meta( $comment->comment_ID, 'rating', true ) );
$rating_html = $_product->get_rating_html( $rating );
echo '<li><a href="' . esc_url( get_comment_link( $comment->comment_ID ) ) . '">';
echo $_product->get_image();
echo $_product->get_title() . '</a>';
echo $rating_html;
printf( '<span class="reviewer">' . _x( 'by %1$s', 'by comment author', 'woocommerce' ) . '</span>', get_comment_author() );
echo '</li>';
}
echo '</ul>';
}
(Note: this code is lifted with modification from the WooCommerce plugin, "recent reviews" widget: woocommerce/includes/widgets/class-wc-widget-recent-reviews.php)
This is untested, but something like this should work:
$args = array(
'post_type' => 'product',
'orderby' => 'comment_count',
'order' => 'DESC'
);
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) {
while ( $loop->have_posts() ) : $loop->the_post();
if ( $post->comment_count < 1 ) continue;
wc_get_template_part( 'content', 'product' );
endwhile;
} else {
echo __( 'No products found' );
}
wp_reset_postdata();

Woocommerce, sort dropdown on shortcode based product lists

In our shop, we have a number of standard WP pages. On these pages we show ~40 products using the standard Woocommerce shortcodes.
For example:
[product_category category="boots" per_page="20" columns="4" orderby="price" order="desc"]
The products appears, but there are two things missing:
No sorting dropdown appears above the product lists, so the products cannot be sorted by our visitors.
We don't see any pagination buttons, so it's impossible to see more than the first 20 products on each page.
Any ideas how we can fix those two things?
Regarding your first issue, I have not found any good solutions beside hacking the shortcode within WC. Not entirely advisable as it will be overwritten each upgrade/patch of WC. If it's absolutely necessary, you could maintain the code by rewriting the hack each time you upgrade.
Alright, first download a copy of includes\class-wc-shortcodes.php in your woocommerce folder. Make a backup of the original before editing it, I usually rename the file with a -o or change the file type to .bak.
Assuming you'd want the original sort by dropdown that comes with WC on the Shop Page.
Step 1
Remove orderby and order arguments on the shortcode:
[product_category category="boots" per_page="20" columns="4"]
Step 2
Edit the Product Category shortcode on class-wc-shortcodes.php as such:
/**
* List products in a category shortcode
*
* #access public
* #param array $atts
* #return string
*/
public static function product_category( $atts ) {
global $woocommerce_loop, $wpdb;
if ( empty( $atts ) ) return '';
extract( shortcode_atts( array(
'per_page' => '12',
'columns' => '4',
'orderby' => 'title',
'order' => 'asc',
'category' => '',
'operator' => 'IN' // Possible values are 'IN', 'NOT IN', 'AND'.
), $atts ) );
if ( ! $category ) return '';
// Default ordering args
// $ordering_args = WC()->query->get_catalog_ordering_args( $orderby, $order ); // COMMENT THIS OUT
$orderby = 'title';
$order = 'asc';
if ( isset( $_GET['orderby'] ) ) {
$getorderby = $_GET['orderby'];
}
if ($getorderby == 'popularity') {
$orderby = 'meta_value_num';
$order = 'desc';
$meta_key = 'total_sales';
} elseif ($getorderby == 'rating') {
$fields .= ", AVG( $wpdb->commentmeta.meta_value ) as average_rating ";
$where .= " AND ( $wpdb->commentmeta.meta_key = 'rating' OR $wpdb->commentmeta.meta_key IS null ) ";
$join .= "
LEFT OUTER JOIN $wpdb->comments ON($wpdb->posts.ID = $wpdb->comments.comment_post_ID)
LEFT JOIN $wpdb->commentmeta ON($wpdb->comments.comment_ID = $wpdb->commentmeta.comment_id)
";
$orderby = "average_rating DESC, $wpdb->posts.post_date DESC";
$groupby = "$wpdb->posts.ID";
} elseif ($getorderby == 'date') {
$orderby = 'date';
$order = 'desc';
} elseif ($getorderby == 'price') {
$orderby = 'meta_value_num';
$order = 'asc';
$meta_key = '_price';
} elseif ($getorderby == 'price-desc') {
$orderby = 'meta_value_num';
$order = 'desc';
$meta_key = '_price';
}
$args = array(
'post_type' => 'product',
'post_status' => 'publish',
'ignore_sticky_posts' => 1,
'orderby' => $orderby, // $ordering_args['orderby'],
'order' => $order, // $ordering_args['order'],
'meta_key' => $meta_key,
'fields' => $fields,
'where' => $where,
'join' => $join,
'groupby' => $groupby,
'posts_per_page' => $per_page,
'meta_query' => array(
array(
'key' => '_visibility',
'value' => array('catalog', 'visible'),
'compare' => 'IN'
)
),
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'terms' => array( esc_attr( $category ) ),
'field' => 'slug',
'operator' => $operator
)
)
);
if ( isset( $ordering_args['meta_key'] ) ) {
$args['meta_key'] = $ordering_args['meta_key'];
}
ob_start();
$products = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $args, $atts ) );
$woocommerce_loop['columns'] = $columns;
if ( $products->have_posts() ) : ?>
<div style="width:100%;">
<div style="float:right">
<form class="woocommerce-ordering" method="get">
<select name="orderby" class="orderby">
<?php
$catalog_orderby = apply_filters( 'woocommerce_catalog_orderby', array(
'menu_order' => __( 'Default sorting', 'woocommerce' ),
'popularity' => __( 'Sort by popularity', 'woocommerce' ),
'rating' => __( 'Sort by average rating', 'woocommerce' ),
'date' => __( 'Sort by newness', 'woocommerce' ),
'price' => __( 'Sort by price: low to high', 'woocommerce' ),
'price-desc' => __( 'Sort by price: high to low', 'woocommerce' )
) );
if ( get_option( 'woocommerce_enable_review_rating' ) === 'no' )
unset( $catalog_orderby['rating'] );
foreach ( $catalog_orderby as $id => $name )
echo '<option value="' . esc_attr( $id ) . '" ' . selected( $getorderby, $id, false ) . '>' . esc_attr( $name ) . '</option>';
?>
</select>
<?php
// Keep query string vars intact
foreach ( $_GET as $key => $val ) {
if ( 'orderby' === $key || 'submit' === $key )
continue;
if ( is_array( $val ) ) {
foreach( $val as $innerVal ) {
echo '<input type="hidden" name="' . esc_attr( $key ) . '[]" value="' . esc_attr( $innerVal ) . '" />';
}
} else {
echo '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $val ) . '" />';
}
}
?>
</form>
</div>
</div>
<div style="clear:both;"></div>
<?php woocommerce_product_loop_start(); ?>
<?php while ( $products->have_posts() ) : $products->the_post(); ?>
<?php wc_get_template_part( 'content', 'product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php woocommerce_product_loop_end(); ?>
<?php endif;
woocommerce_reset_loop();
wp_reset_postdata();
return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
}
Upload the file back into the includes folder and you're done! Your shortcode product pages will now have a working sort by dropdown same as the one that appears on the WC Shop Page.
Edit the sort options to your liking! Hope it helps!
Well for your second problem: Your shortcode is limiting to see only 20 products. Change the it to per_page="40" and you should see 40 products or simply remove the line and the number of products is not limited.
For your first problem I don't have an answer. I'm looking it for my self as well :).
If you add the paginate="true" attribute to your [products] shortcode, then the shortcode, then the Sort by dropdown menu will appear on the page.
Change this
[product_category category="boots" per_page="20" columns="4"]
to this
[product_category category="boots" paginate="true" limit="20" columns="4"]

Resources