woocommerce display last purchase and cross sells current user - woocommerce

I use specific thank you pages depend of product
I want to display the last purchase (product's name) of the current user on this page and fetch cross sell of the specific product too.
Any help would be apreciate
OF course i made some research and found tutorial like this one
https://www.skyverge.com/blog/get-all-woocommerce-orders-for-a-customer/#comment-703884
But i am not enaugh good at php to modify it for my needs
Thank you

If you want to display 50 last purchased product for example, go to function.php in Appearance>Editor>function.php then past the code below:
// Recently Sold Products shortcode for WooCommerce
add_shortcode('sold_products', 'sold_products');
function sold_products($attributes) {
global $wpdb, $woocommerce;
$defaults = array('max_products' => 50, 'title' => "Last purchased");
$parameters = shortcode_atts( $defaults, $attributes);
$max = absint($parameters['max_products']); // number of products to show
$title = sanitize_text_field($parameters['title']);
$html = '<div class="sold_products">'.PHP_EOL;
if ($title) {
$html .= '<h3>Last purchased:</h3>'.PHP_EOL;
}
$table = $wpdb->prefix.'woocommerce_order_items';
$my_query = $wpdb->prepare("SELECT * FROM $table WHERE `order_item_type`='line_item' ORDER BY `order_id` DESC LIMIT %d", $max);
$nr_rows = $wpdb->query($my_query);
if (!$nr_rows) {
$html .= '<p>Aucun produit n\'est acheté encore!</p>';
} else {
$html .= '<ul>'.PHP_EOL;
for ($offset = 0; $offset < $nr_rows; $offset++) {
if ( is_user_logged_in() ) {
$user_info = wp_get_current_user();
}
$row = $wpdb->get_row($my_query, OBJECT, $offset);
$product_name = $row->order_item_name;
$product = get_page_by_title($product_name, OBJECT, 'product');
$url = get_permalink($product->ID);
$order_id = $row->order_id;
$order = new WC_Order($order_id);
$user = $order->get_user();
if ($user) {
$user_id = $user->ID;
} else {
$user_id = 'Guest';
}
if($user_info->ID == $user_id){
$unix_date = strtotime($order->order_date);
$date = date('d/m/y', $unix_date);
$html .= '<li>'.$product_name.' acheté le '.$date.'</li>'.PHP_EOL;
}
}
$html .= '</ul>'.PHP_EOL;
}
$html .= '</div>'.PHP_EOL;
return $html;
} // end function
you can dislay this result anywhere in your pages just past this shotcode where you want it to be displayed:
[sold_products max_products="50" title="Last purchased"]

Related

Pods Custom Post types use Tags with Check Boxes like Categories

I have been using pods to create various custom post types .. I was able to find some code to do what I want for the Standard wordpress post type .. How can I modify this code to work with my pods post types ?
I wan to Change from having to type the tags to pulling in the tags with check boxes
Like this here
Here is the code `/*
* Meta Box Removal
*/
function rudr_post_tags_meta_box_remove() {
$id = 'tagsdiv-post_tag'; // you can find it in a page source code (Ctrl+U)
$post_type = 'post'; // remove only from post edit screen
$position = 'side';
remove_meta_box( $id, $post_type, $position );
}
add_action( 'admin_menu', 'rudr_post_tags_meta_box_remove');
/*
* Add
*/
function rudr_add_new_tags_metabox(){
$id = 'rudrtagsdiv-post_tag'; // it should be unique
$heading = 'Tags'; // meta box heading
$callback = 'rudr_metabox_content'; // the name of the callback function
$post_type = 'post';
$position = 'side';
$pri = 'default'; // priority, 'default' is good for us
add_meta_box( $id, $heading, $callback, $post_type, $position, $pri );
}
add_action( 'admin_menu', 'rudr_add_new_tags_metabox');
/*
* Fill
*/
function rudr_metabox_content($post) {
// get all blog post tags as an array of objects
$all_tags = get_terms( array('taxonomy' => 'post_tag', 'hide_empty' => 0) );
// get all tags assigned to a post
$all_tags_of_post = get_the_terms( $post->ID, 'post_tag' );
// create an array of post tags ids
$ids = array();
if ( $all_tags_of_post ) {
foreach ($all_tags_of_post as $tag ) {
$ids[] = $tag->term_id;
}
}
// HTML
echo '<div id="taxonomy-post_tag" class="categorydiv">';
echo '<input type="hidden" name="tax_input[post_tag][]" value="0" />';
echo '<ul>';
foreach( $all_tags as $tag ){
// unchecked by default
$checked = "";
// if an ID of a tag in the loop is in the array of assigned post tags - then check the checkbox
if ( in_array( $tag->term_id, $ids ) ) {
$checked = " checked='checked'";
}
$id = 'post_tag-' . $tag->term_id;
echo "<li id='{$id}'>";
echo "<label><input type='checkbox' name='tax_input[post_tag][]' id='in-$id'". $checked ." value='$tag->slug' /> $tag->name</label><br />";
echo "</li>";
}
echo '</ul></div>'; // end HTML
}
`

Shortcode that displays product attributes set for a WooCommerce product by ID

I found the following code in an older thread (Shortcode that display all product attributes set for a WooCommerce product) which basicly SHOULD be the solution to what im looking for
function get_product_attributes_shortcode($atts ) {
// Extract shortcode attributes
extract( shortcode_atts( array(
'id' => get_the_ID(),
), $atts, 'display-attributes' ) );
global $product;
if ( ! is_a($product, 'WC_Product') ) {
$product = wc_get_product( $id );
}
if ( is_a($product, 'WC_Product') ) {
$html = []; // Initializing
foreach ( $product->get_attributes() as $attribute => $values ) {
$attribute_name = wc_attribute_label($values->get_name());
$attribute_data = $values->get_data();
$is_taxonomy = $attribute_data['is_taxonomy'];
$option_values = array(); // Initializing
// For taxonomy product attribute values
if( $is_taxonomy ) {
$terms = $values->get_terms(); // Get attribute WP_Terms
// Loop through attribute WP_Term(s)
foreach ( $terms as $term ) {
$term_link = get_term_link( $term, $attribute );
$option_values[] = ''.$term->name.'';
}
}
// For "custom" product attributes values
else {
// Loop through attribute option values
foreach ( $values->get_options() as $term_name ) {
$option_values[] = $term_name;
}
}
$html[] = '<strong>' . $attribute_name . '</strong>: ' . implode(', ', $option_values);
}
return '<div class="product-attributes">' . implode(' | ', $html) . '<div>';
}
}
add_shortcode( 'display-attributes', 'get_product_attributes_shortcode' );
I modified the output part to display the attributes in a table
// Loop through attribute WP_Term(s)
foreach ( $terms as $term ) {
$option_values[] = $term->name;
}
}
// For "custom" product attributes values
else {
// Loop through attribute option values
foreach ( $values->get_options() as $term_name ) {
$option_values[] = $term_name;
}
}
$html[] = '<tr><td class="column-1">' . $attribute_name . '</td><td class="column-2">' . implode(', ', $option_values) . '</td></tr>';
}
return '<h4>Technische Daten</h4><table class="tablepress table produktdatenblatt tablepress-responsive"><tbody class="row-hover">' . implode($html) . '</tbody></table>';
}
}
add_shortcode( 'display_attributes', 'get_product_attributes_shortcode' );
Usage should be like this: [display-attributes] or with a defined product Id [display-attributes id="254"]
But its not showing the attributes from the respective ID i put into the shortcode. Its just showing attributes from one product. I want to use the shortcode on Wordpress Pages and Posts to enrich product descriptions i do.
I tried to figure out if i can fix it myself, but im realy bad when it comes to coding :)
Can somebody help me with this?

validate before add to cart not working woocommerce

i have something i cant get working and i dont understand why.
I want to add some custom fields below a grouped product in woocommerce on the frontend.
So i have the following function (which works fine):
function add_data_opbouw_front(){
global $woocommerce; global $post;
$id = $post->ID;
if ($id === 1411){
$optiestijd = array();
$optiesdag = array();
$id = get_the_ID();
$html = '<table><tbody>';
$i=0;
if( !empty(get_post_meta($id,'tijdslot',true) ) ){
$html .= '<tr><td>Kies een tijd:</td><td><select name="tijdslot" required><option value="">Kies:</option>';
$optiestijden = get_post_meta(get_the_ID(),'tijdslot',true);
foreach ($optiestijden as $key=>$optie){
$optiestijd[$optie] = 'Kies een tijdslot:';
}
foreach ($optiestijd as $optie => $label){
if(!empty($optie)){
$i++;
$html .= '<option value="'.$optie.'"><span class="choiceoption">'. $optie.'</span></option>';
}
}
$html .= '</select></td></tr>';
}
if( !empty(get_post_meta($id,'dag',true) ) ){
$optiesdagen = get_post_meta(get_the_ID(),'dag',true);
$optiesdagen = explode('|',$optiesdagen);
$html.= '<tr><td>Kies een dag:</td><td><select name="dag" required><option value="">Kies:</option>';
foreach ($optiesdagen as $optie){
$i++;
$html .= '<option value="'.$optie.'"><span class="choiceoption">'. $optie.'</span></option>';
}
}
$html .= '</select></td></tr></tbody></table>';
$html .= '<input type="hidden" name="voorraad_afname" value="1">';
echo $html;
}
}
add_action('woocommerce_before_add_to_cart_button','add_data_opbouw_front', 35);
because i want to obligate user to pick a day and time, i want to validate before the add to cart and i do it like this:
function so_validate_add_cart_item( $passed, $product_id, $quantity, $variation_id = '', $variations= '' ) {
global $woocommerce; global $post;
$id = $post->ID;
if ($id === 1411){
// do your validation, if not met switch $passed to false
if ( empty($_POST['tijdslot']) || empty($_POST['dag']) ){
$passed = false;
wc_add_notice( __( 'De velden "Kies een dag" en "Kies een tijdslot" zijn beiden verplicht', 'textdomain' ), 'error' );
}
}
return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'so_validate_add_cart_item', 10, 5 );
But when I leave one of the select boxes empty, the product is being added to the cart anyway. So the validate doesnt throw in the error. I dont really understand why this is not working.
Any ideas?
After a long puzzle, i found out that approaching global $post is not working. Better is to approach the product_id. Because it is a grouped product, i checked wether one of the grouped products ID are in the add-to-cart like so:
$check = array('1398','1399','1400');
if (in_array($product_id,$check)){
And that does work.
So updated code is:
function so_validate_add_cart_item( $passed, $product_id, $quantity, $variation_id = '', $variations= '' ) {
$check = array('1398','1399','1400');
if (in_array($product_id,$check)){
// check if both selectboxes are used
if ( empty($_POST['tijdslot']) || empty($_POST['dag']) ){
$passed = false;
wc_add_notice( __( 'De velden "Kies een dag" en "Kies een tijdslot" zijn beiden verplicht', 'textdomain' ), 'error' );
}
}
return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'so_validate_add_cart_item', 10, 5 );

Show the custom attribute "variable product" in the list of related products

Based on "How to add variation stock status to Woocommerce product variation dropdown" answer, I have made some code that shows the custom attribute of a variable product and its presence in the store:
// Function that will check the stock status and display the corresponding additional text
function get_stock_status_text($product, $name, $term_slug) {
foreach($product - > get_available_variations() as $variation) {
if ($variation['attributes'][$name] == $term_slug)
$stock = $variation['is_in_stock'];
}
return $stock == 1 ? '' : ' - out of stock';
}
// The hooked function that will add the stock status to the dropdown options elements.
add_filter('woocommerce_dropdown_variation_attribute_options_html', 'show_stock_status_in_dropdown', 10, 2);
function show_stock_status_in_dropdown($html, $args) {
// Only if there is a unique variation attribute (one dropdown)
if (sizeof($args['product'] - > get_variation_attributes()) == 1):
$options = $args['options'];
$product = $args['product'];
$attribute = $args['attribute']; // The product attribute taxonomy
$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;
$show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __('Select size', 'woocommerce');
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').
'">';
$html. = '<option value="">'.esc_html($show_option_none_text).
'</option>';
if (!empty($options)) {
if ($product && taxonomy_exists($attribute)) {
$terms = wc_get_product_terms($product - > get_id(), $attribute, array('fields' => 'all'));
foreach($terms as $term) {
if (in_array($term - > slug, $options)) {
// HERE Added the function to get the text status
$stock_status = get_stock_status_text($product, $name, $term - > slug);
$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).$stock_status).
'</option>';
}
}
} else {
foreach($options as $option) {
$selected = sanitize_title($args['selected']) === $args['selected'] ? selected($args['selected'], sanitize_title($option), false) : selected($args['selected'], $option, false);
// HERE Added the function to get the text status
$stock_status = get_the_stock_status($product, $name, $option);
$html. = '<option value="'.esc_attr($option).
'" '.$selected.
'>'.esc_html(apply_filters('woocommerce_variation_option_name', $option).$stock_status).
'</option>';
}
}
}
$html. = '</select>';
endif;
return $html;
}
On a single product page, I show related products. How to show this attribute (its presence in the store) in the form of a label in related products?
For example:
The product's name
Price - $25
Sizes available: L, XL
Try this code, I hooked into the woocommerce_after_shop_loop_item and displayed the product attributes. Right now it only works for the size attribute. It is showing the Large, Medium, Small. If you want to show L, XL, M, etc. just edit the size attribute.
add_action( 'woocommerce_after_shop_loop_item', 'mamham_woocommerce_after_shop_loop_item', 10);
function mamham_woocommerce_after_shop_loop_item() {
global $product;
// Bail if not in the single product page.
if ( ! is_product() ) return;
// Prduct attributes which you want to show.
// Attributes to show in the slug.
// 'attribute slug' => 'Text shown';
$show_attributes = array(
'size' => 'Sizes available:',
);
// Get the slugs.
$show_slugs = array_keys( $show_attributes );
// Get product type.
$product_type = $product->get_type();
if( 'simple' === $product_type ) {
$product_attributes = $product->get_attributes();
foreach( $product_attributes as $key => $product_attribute ) {
$slug = substr( $key, 3 );
if ( in_array( $slug, $show_slugs, TRUE ) ) {
$terms = $product_attribute->get_terms();
$terms_output = wp_list_pluck( $terms, 'name');
$terms_output = implode(', ', $terms_output );
echo esc_html( "${show_attributes[$slug]} ${terms_output}" );
}
}
} elseif ( 'variable' === $product_type ) {
$product_variations = $product->get_available_variations();
foreach ( $product_variations as $product_variation ) {
if ( $product_variation['is_in_stock'] && isset( $product_variation['attributes']['attribute_pa_size'] )) {
$terms_output[] = ucwords( $product_variation['attributes']['attribute_pa_size'] );
}
}
if ( ! empty( $terms_output) ) {
$terms_output = implode(', ', $terms_output );
echo esc_html( "Sizes available: ${terms_output}" );
}
}
}
Here is the screenshot, I have storefront theme and WooCommerce installed.

inserting wp_nav_menu_items (or similar solution) without saving to database

So I coded some custom menu items as drop downs that are dynamically generated. It worked fine, but then I realised they were also saved to the database. i want to create drop downs that hook in to the main menu but do NOT save in the database as they are different for every user depending on user meta, any ideas?
Also this is a child theme so has to hook into the main menu, no option of generating a new menu etc as its part of a horrible theme builder.
function _custom_nav_menu_item( $title, $url, $order, $parent = 0 ){
$item = new stdClass();
$item->ID = 1000000 + $order + parent;
$item->db_id = $item->ID;
$item->title = $title;
$item->url = $url;
$item->menu_order = $order;
$item->menu_item_parent = $parent;
$item->type = '';
$item->object = '';
$item->object_id = '';
$item->classes = array();
$item->target = '';
$item->attr_title = '';
$item->description = '';
$item->xfn = '';
$item->status = '';
return $item;
}
// Custom nav menu. Adding dropdowns etc according to user permissions.
function custom_nav_menu_items( $items, $menu ){
$user_permissions = user_is_loggedin_with_permissions();
if( $menu->slug == 'main-menu-english' ){
// Announcements dropdown, users allowed regions.
$top = _custom_nav_menu_item( 'Announcements', site_url( '/announcements' ), 2 );
$items[] = $top;
$i = 1;
foreach( $user_permissions['Region'] as $region ){
$for_humans = ucfirst( str_replace( '_', ' ', $region ) );
$items[] = _custom_nav_menu_item( $for_humans, site_url( '?post_type=announcements&regions='.$region ), '10'.$i, $top->ID );
$i++;
}
}
return $items;
}
add_filter( 'wp_get_nav_menu_items', 'custom_nav_menu_items', 20, 2 );

Resources