Woocommerce recently viewed Products - wordpress

I have created a recently viewed script which generated a shortcode which I then inserted into my home page.
The script is designed so that people who may have visited my website and left, once they come back can see instantly what products they had been viewing on their last visit.
I have placed the shortcode [woocommerce_recently_viewed_products]
and have generated the shortcode using the following script:
function rc_woocommerce_recently_viewed_products( $atts, $content = null ) {
// Get shortcode parameters
extract(shortcode_atts(array(
"per_page" => '5'
), $atts));
// Get WooCommerce Global
global $woocommerce;
// Get recently viewed product cookies data
$viewed_products = ! empty( $_COOKIE['woocommerce_recently_viewed'] ) ? (array) explode( '|', $_COOKIE['woocommerce_recently_viewed'] ) : array();
$viewed_products = array_filter( array_map( 'absint', $viewed_products ) );
// If no data, quit
if ( empty( $viewed_products ) )
return __( 'You have not viewed any product yet!', 'rc_wc_rvp' );
// Create the object
ob_start();
wc_setcookie( 'woocommerce_recently_viewed', implode( '|', $viewed_products ) );
}
// Get products per page
if( !isset( $per_page ) ? $number = 4 : $number = $per_page )
// Create query arguments array
$query_args = array(
'posts_per_page' => $number,
'no_found_rows' => 1,
'post_status' => 'publish',
'post_type' => 'product',
'post__in' => $viewed_products,
'orderby' => 'rand'
);
// Add meta_query to query args
$query_args['meta_query'] = array();
// Check products stock status
$query_args['meta_query'][] = $woocommerce->query->stock_status_meta_query();
// Create a new query
$r = new WP_Query($query_args);
// If query return results
if ( $r->have_posts() ) {
$content = '<ul class="rc_wc_rvp_product_list_widget">';
// Start the loop
while ( $r->have_posts()) {
$r->the_post();
global $product;
$content .= '<li>
<a href="' . get_permalink() . '">
' . ( has_post_thumbnail() ? get_the_post_thumbnail( $r->post->ID, 'shop_thumbnail' ) : woocommerce_placeholder_img( 'shop_thumbnail' ) ) . ' ' . get_the_title() . '
</a> ' . $product->get_price_html() . '
</li>';
}
$content .= '</ul>';
}
// Get clean object
$content .= ob_get_clean();
// Return whole content
return $content;
}
// Register the shortcode
add_shortcode("woocommerce_recently_viewed_products",
"rc_woocommerce_recently_viewed_products");
Everything seems to have registered. However,when I test this myself. I view a few products, go back to the homepage where the shortcode is registered and I see the text
You have not viewed any product yet!
I can not figure out what might be missing in order to register and show the products which I or a potential customer may have viewed.

Woocommerce only save the recently viewed cookie IF woocommerce_recently_viewed_products WIDGET is ACTIVE! See code in wc-product-functions.php wc_track_product_view() function.
Code to save the cookie always in functions.php:
/**
* Track product views. Always.
*/
function wc_track_product_view_always() {
if ( ! is_singular( 'product' ) /* xnagyg: remove this condition to run: || ! is_active_widget( false, false, 'woocommerce_recently_viewed_products', true )*/ ) {
return;
}
global $post;
if ( empty( $_COOKIE['woocommerce_recently_viewed'] ) ) { // #codingStandardsIgnoreLine.
$viewed_products = array();
} else {
$viewed_products = wp_parse_id_list( (array) explode( '|', wp_unslash( $_COOKIE['woocommerce_recently_viewed'] ) ) ); // #codingStandardsIgnoreLine.
}
// Unset if already in viewed products list.
$keys = array_flip( $viewed_products );
if ( isset( $keys[ $post->ID ] ) ) {
unset( $viewed_products[ $keys[ $post->ID ] ] );
}
$viewed_products[] = $post->ID;
if ( count( $viewed_products ) > 15 ) {
array_shift( $viewed_products );
}
// Store for session only.
wc_setcookie( 'woocommerce_recently_viewed', implode( '|', $viewed_products ) );
}
remove_action('template_redirect', 'wc_track_product_view', 20);
add_action( 'template_redirect', 'wc_track_product_view_always', 20 );

You need to set the cookie when you are viewing a single product page so use something like this where I set the cookie to equal the product ID I just viewed. In your case you'll need to get the cookie value if it exists then append the new product to the list of products.
function set_user_visited_product_cookie() {
global $post;
if ( is_product() ){
// manipulate your cookie string here, explode, implode functions
wc_setcookie( 'woocommerce_recently_viewed', $post->ID );
}
}
add_action( 'wp', 'set_user_visited_product_cookie' );

Below code to set cookie 'woocommerce_recently_viewed' worked for me. Hope it helps other
$Existing_product_id = $_COOKIE['woocommerce_recently_viewed'];
if ( is_product() )
{
$updated_product_id = $Existing_product_id.'|'.$post->ID;
wc_setcookie( 'woocommerce_recently_viewed', $updated_product_id );
}

Related

WooCommerce function to display total product sales on site homepage

I am trying to find a function and shortcode to display the total amount of products sold as simply as possible on our website.
Don't want to show product names or any info just a count.
I found this function / shortcode that displays total orders. Just wondering fo anyone can help adapt it to display total products sold?
Thanks so much..
function display_woocommerce_order_count( $atts, $content = null ) {
$args = shortcode_atts( array(
'status' => 'completed',
), $atts );
$statuses = array_map( 'trim', explode( ',', $args['status'] ) );
$order_count = 0;
foreach ( $statuses as $status ) {
// if we didn't get a wc- prefix, add one
if ( 0 !== strpos( $status, 'wc-' ) ) {
$status = 'wc-' . $status;
}
$order_count += wp_count_posts( 'shop_order' )->$status;
}
ob_start();
echo number_format( $order_count );
return ob_get_clean();
}
add_shortcode( 'wc_order_count', 'display_woocommerce_order_count' );

WooCommerce: Display SKU number in admin side Order listing page custom column

I have added a custom column in Woocommerce admin side order listing page to display Ordered item Products name and total Quantity like this -> [http://prntscr.com/p11rdl] by using the following code:
add_filter('manage_edit-shop_order_columns', 'misha_order_items_column' );
function misha_order_items_column( $order_columns ) {
$order_columns['order_products'] = "Qty-Products Name-SKU";
return $order_columns;
}
add_action( 'manage_shop_order_posts_custom_column' , 'misha_order_items_column_cnt' );
function misha_order_items_column_cnt( $colname ) {
global $the_order; // the global order object
if( $colname == 'order_products' ) {
// get items from the order global object
$order_items = $the_order->get_items();
if ( !is_wp_error( $order_items ) ) {
foreach( $order_items as $order_item ) {
echo $order_item['quantity'] .' × '. $order_item['name'] .'<br />';
}
}
}
}
Now I also want to display ordered product SKU number after the product name. So anyone have solution for this then please provide help me.
Thank you,
Ketan
Just replace with follows code snippets to add SKU -
add_action( 'manage_shop_order_posts_custom_column' , 'misha_order_items_column_cnt' );
function misha_order_items_column_cnt( $colname ) {
global $the_order; // the global order object
if( $colname == 'order_products' ) {
// get items from the order global object
$order_items = $the_order->get_items();
if ( !is_wp_error( $order_items ) ) {
foreach( $order_items as $order_item ) {
$product = $order_item->get_product();
// product checking
$sku = ( $product && $product->get_sku() ) ? ' - ' . $product->get_sku() : '';
echo $order_item['quantity'] .' × '. $order_item['name'] . ''. $sku . '<br />';
}
}
}
}
Thank you so much I've found this thread extremely helpful, I couldn't thank the original poster enough as well the help from #itzmekhokan and various other contributors, this community is awesome.
What I'm needing now is to add product shelve location straight after SKU.
I have the below code for location fields but not sure how to amend to the code above to make it work. I'm new to coding in general, but have found snippets of code and made it work so far.
Your help and guidance would be greatly appreciated.
// Add Location field
add_action( 'woocommerce_product_options_stock_fields', 'product_shelf' );
function product_shelf() {
global $woocommerce, $post;
woocommerce_wp_text_input(
array(
'id' => 'product_shelf',
'placeholder' => 'Enter product shelf location here',
'label' => 'Shelf Location',
'description' => 'Shelf location of product',
'desc_tip' => 'true',
)
);
}
// Save location data
add_action( 'woocommerce_process_product_meta', 'product_shelf_data' );
function product_shelf_data( $post_id ) {
// grab the location from $_POST
$product_shelf = isset( $_POST[ 'product_shelf' ] ) ? sanitize_text_field( $_POST[ 'product_shelf' ] ) : '';
// grab the product
$product = wc_get_product( $post_id );
// save the location using WooCommerce built-in functions
$product->update_meta_data( 'product_shelf', $product_shelf_data );
$product->save();
}

Create custom notification in post insert in buddypress

I want to add custom notification in the time of post creation. I have followed this url https://webdevstudios.com/2015/10/06/buddypress-adding-custom-notifications/
What i have done, I am adding custom notification in creation of project or bid post type. But it not working. Please check my code and let me what i have done wrong.
// this is to add a fake component to BuddyPress. A registered component is needed to add notifications
function custom_filter_notifications_get_registered_components( $component_names = array() ) {
// Force $component_names to be an array
if ( ! is_array( $component_names ) ) {
$component_names = array();
}
// Add 'custom' component to registered components array
array_push( $component_names, 'projectadd' );
// Return component's with 'custom' appended
return $component_names;
}
add_filter( 'bp_notifications_get_registered_components', 'custom_filter_notifications_get_registered_components' );
// this hooks to post creation and saves the post id
function bp_custom_add_notification( $post_id, $post ) {
if ( $post->post_type == 'project' || $post->post_type == 'bid' ) {
$post = get_post( $post_id );
$author_id = $post->post_author;
bp_notifications_add_notification( array(
'user_id' => $author_id,
'item_id' => $post_id,
'component_name' => 'projectadd',
'component_action' => 'projectadd_action',
'date_notified' => bp_core_current_time(),
'is_new' => 1,
) );
}
}
add_action( 'wp_insert_post', 'bp_custom_add_notification', 99, 2 );
// this gets the saved item id, compiles some data and then displays the notification
function custom_format_buddypress_notifications( $content, $item_id, $secondary_item_id, $total_items, $format = 'string', $action, $component ) {
// New custom notifications
if ( 'projectadd_action' === $action ) {
$post = get_post( $item_id );
$custom_title = $post->post_author . ' add the project ' . get_the_title( $item_id );
$custom_link = get_permalink( $post );
$custom_text = $post->post_author . ' add the project ' . get_the_title( $item_id );
// WordPress Toolbar
if ( 'string' === $format ) {
$return = apply_filters( 'projectadd_filter', '' . esc_html( $custom_text ) . '', $custom_text, $custom_link );
// Deprecated BuddyBar
} else {
$return = apply_filters( 'projectadd_filter', array(
'text' => $custom_text,
'link' => $custom_link
), $custom_link, (int) $total_items, $custom_text, $custom_title );
}
return $return;
}
}
add_filter( 'bp_notifications_get_notifications_for_user', 'custom_format_buddypress_notifications', 10, 7 );
You've changed the number and order of arguments from the example you linked. The two arguments you added are never used. Restore the arguments in the function to match the example and the the number in your add_filter to 5.
function custom_format_buddypress_notifications( $content, $item_id, $secondary_item_id, $total_items, $format = 'string', $action, $component )
{
...
}
add_filter( 'bp_notifications_get_notifications_for_user', 'custom_format_buddypress_notifications', 10, 7 );
needs to be
function custom_format_buddypress_notifications( $action, $item_id, $secondary_item_id, $total_items, $format = 'string' )
{
...
}
add_filter( 'bp_notifications_get_notifications_for_user', 'custom_format_buddypress_notifications', 10, 5 );

Woocommerce Wordpress Adding Images to an Order in Cart

Here's the issue: I am trying to add multiple customer uploaded images to a woocommerce product order.
This is what my current function looks like to generate the fields before the add cart button (This displays properly and allows for a customer to select a file from their computer to upload):
function my_special_fields(){
if (get_the_title() == "My Special Product"){
echo '<table>
<tbody>
<tr>
<td>
<input type="file" name="my_image_upload" id="my_image_upload" multiple="false" />
</td>
</tr>
</tbody>
</table>';
}
}
Which I call with the hook:
add_filter('woocommerce_before_add_to_cart_button', 'my_special_fields');
I then use another hook for adding the item data to the cart:
add_action( 'woocommerce_add_cart_item_data', 'save_my_special_fields', 10, 2 );
And the function called with that hook looks like this:
function save_my_special_fields( $cart_item_data, $product_id ) {
// I save a lot of fields in here that are working fine so ignoring those for now
// This is where I try and find my file to upload
if( ! empty( $_FILES ) ) {
foreach( $_FILES as $file ) {
if( is_array( $file ) ) {
$attachment_id = upload_user_file( $file );
}
}
}
}
It calls this piece of code I found for uploading files into wordpress: https://hugh.blog/2014/03/20/wordpress-upload-user-submitted-files-frontend/
function upload_user_file( $file = array() ) {
require_once( ABSPATH . 'wp-admin/includes/admin.php' );
$file_return = wp_handle_upload( $file, array('test_form' => false ) );
if( isset( $file_return['error'] ) || isset( $file_return['upload_error_handler'] ) ) {
return false;
} else {
$filename = $file_return['file'];
$attachment = array(
'post_mime_type' => $file_return['type'],
'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ),
'post_content' => '',
'post_status' => 'inherit',
'guid' => $file_return['url']
);
$attachment_id = wp_insert_attachment( $attachment, $file_return['url'] );
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attachment_data = wp_generate_attachment_metadata( $attachment_id, $filename );
wp_update_attachment_metadata( $attachment_id, $attachment_data );
if( 0 < intval( $attachment_id ) ) {
return $attachment_id;
}
}
return false;
}
Right now I am not assigning to any post or doing anything with the image other than trying to get it to upload so that as an Admin I can view it in my media folder.
I think the issue is that the woocommerce form for the add to cart fields might not have this encoding:
enctype="multipart/form-data
Any help on implementing this without getting additional woocommerce plugins would be much appreciated.

How to make custom form-tag in contact form 7 required

So i make custom form-tag in contact form 7! It is a drop down with list of my courses and now I want to make it required because that is the main thing in whole form.
So can someone give me a tip how to do that?
When I do the [myCustomField* course-name class:custom-field]
It does not working with *
So if someone can help it will be great!
I have been working on this myself this afternoon and I do not think Mahmoud has added everything that is needed to get the validation working well and the messages showing up.
using what I have learnt from the posts on contact form 7 here:
https://contactform7.com/2015/01/10/adding-a-custom-form-tag
https://contactform7.com/2015/02/27/using-values-from-a-form-tag/
and looking at this file in the plugin: contact-form-7/modules/select.php which helped a lot.
I think this will work better and needs to be added to your functions.php file in your child-theme.
add_action( 'wpcf7_init', 'custom_add_form_tag_myCustomField' );
function custom_add_form_tag_myCustomField() {
wpcf7_add_form_tag( array( 'myCustomField', 'myCustomField*' ),
'custom_myCustomField_form_tag_handler', true );
}
function custom_myCustomField_form_tag_handler( $tag ) {
$tag = new WPCF7_FormTag( $tag );
if ( empty( $tag->name ) ) {
return '';
}
$validation_error = wpcf7_get_validation_error( $tag->name );
$class = wpcf7_form_controls_class( $tag->type );
if ( $validation_error ) {
$class .= ' wpcf7-not-valid';
}
$atts = array();
$atts['class'] = $tag->get_class_option( $class );
$atts['id'] = $tag->get_id_option();
if ( $tag->is_required() ) {
$atts['aria-required'] = 'true';
}
$atts['aria-invalid'] = $validation_error ? 'true' : 'false';
$atts['name'] = $tag->name;
$atts = wpcf7_format_atts( $atts );
$myCustomField = '';
$query = new WP_Query(array(
'post_type' => 'CUSTOM POST TYPE HERE',
'post_status' => 'publish',
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
));
while ($query->have_posts()) {
$query->the_post();
$post_title = get_the_title();
$myCustomField .= sprintf( '<option value="%1$s">%1$s</option>',
esc_html( $post_title ) );
}
wp_reset_query();
$myCustomField = sprintf(
'<span class="wpcf7-form-control-wrap %1$s"><select %2$s>%3$s</select>%4$s</span>',
sanitize_html_class( $tag->name ),
$atts,
$myCustomField,
$validation_error
);
return $myCustomField;
}
That is how we create the custom tag. The important differences here are the addition of the $validation_error variables as wells the aria-required and aria-invalid data. It is also important to include the $validation_error in the final output so that we can see the validation messages being created.
Then to finish it off we need to add some validation via filters.
There is no documentation on this yet, but I used the functions from the select.php and altered them to what I needed.
/* Validation filter */
add_filter( 'wpcf7_validate_myCustomField', 'wpcf7_myCustomField_validation_filter', 10, 2 );
add_filter( 'wpcf7_validate_myCustomField*', 'wpcf7_myCustomField_validation_filter', 10, 2 );
function wpcf7_myCustomField_validation_filter( $result, $tag ) {
$tag = new WPCF7_FormTag( $tag );
$name = $tag->name;
if ( isset( $_POST[$name] ) && is_array( $_POST[$name] ) ) {
foreach ( $_POST[$name] as $key => $value ) {
if ( '' === $value ) {
unset( $_POST[$name][$key] );
}
}
}
$empty = ! isset( $_POST[$name] ) || empty( $_POST[$name] ) && '0' !== $_POST[$name];
if ( $tag->is_required() && $empty ) {
$result->invalidate( $tag, wpcf7_get_message( 'invalid_required' ) );
}
return $result;
}
This code should also go in your functions.php file just under the code for the custom CF7 tag.
Here the filter's first string $tag should match with the class that is being generated in the custom CF7 tag so if your custom tag->type = 'myCustomField' then the $tag of the filter must include the name, like so wpcf7_validate_myCustomField as well as the required version of it, wpcf7_validate_myCustomField*.
I hope that helps anyone else looking for this.
If you want even more of the options available from the backend of Contact Form 7 check the select.php file as it lays it out quite nicely on how to get each option and include it.
You can use [select*] to output a required drop-down menu.
[select* course-name include_blank "English" "Math"]
Check https://contactform7.com/checkboxes-radio-buttons-and-menus/
EDIT:
So you have your own shortcode [myCustomField]. To make two versions of your shortcode as [myCustomField] and [myCustomField*] you have to pass both shortcodes to your function as the following:
add_action( 'wpcf7_init', 'wpcf7_add_form_tag_mycustomfield' );
function wpcf7_add_form_tag_mycustomfield() {
wpcf7_add_form_tag( array( 'myCustomField', 'myCustomField*'),
'wpcf7_mycustomfield_form_tag_handler', array( 'name-attr' => true ) );
}
function wpcf7_mycustomfield_form_tag_handler( $tag ) {
$tag = new WPCF7_FormTag( $tag );
if ( empty( $tag->name ) ) {
return '';
}
$atts = array();
$class = wpcf7_form_controls_class( $tag->type );
$atts['class'] = $tag->get_class_option( $class );
$atts['id'] = $tag->get_id_option();
$atts['name'] = $tag->name;
$atts = wpcf7_format_atts( $atts );
$html = sprintf( '<your-tag %s></your-tag>', $atts );
return $html;
}
Then, you can use it:
[myCustomField course-name class:custom-field]
or
[myCustomField* course-name class:custom-field]
References:
https://contactform7.com/2015/01/10/adding-a-custom-form-tag
https://contactform7.com/2015/02/27/using-values-from-a-form-tag/

Resources