Found this code on another thread but can't make it work.
PDF uploaded to wp-content/child-theme/.
Goal is to attach the pdf to the completed order emails that woocommerce will send out.
Not sure if customer_completed_order is correct?
add_filter( 'woocommerce_email_attachments', 'attach_terms_conditions_pdf_to_email', 10, 3 );
function attach_terms_conditions_pdf_to_email ( $attachments , $email_id, $email_object ) {
// Avoiding errors and problems
if ( ! is_a( $order, 'WC_Order' ) || ! isset( $email_id ) ) {
return $attachments;
}
if( $email_id === 'customer_completed_order' ){
$your_pdf_path = get_stylesheet_directory() . '/Q-0319B.pdf';
$attachments[] = $your_pdf_path;
}
return $attachments;
}
There are some errors in your code: The $email_object function argument is the wrong variable name and should be instead $order to match with your first if statement.
Now for the attachement path linked to the theme, you will use:
get_stylesheet_directory() for a child theme
get_template_directory() for a parent theme (Website without a child theme)
The email Id customer_completed_order is correct to target Customer "completed" email notification.
As you are not using the $order variable argument in your code, ! is_a( $order, 'WC_Order' ) is not needed, so the working code will be:
add_filter( 'woocommerce_email_attachments', 'attach_pdf_file_to_customer_completed_email', 10, 3);
function attach_pdf_file_to_customer_completed_email( $attachments, $email_id, $order ) {
if( isset( $email_id ) && $email_id === 'customer_completed_order' ){
$attachments[] = get_stylesheet_directory() . '/Q-0319B.pdf'; // Child theme
}
return $attachments;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and work.
For a parent theme replace:
$attachments[] = get_stylesheet_directory() . '/Q-0319B.pdf'; // Child theme
by the following line:
$attachments[] = get_template_directory() . '/Q-0319B.pdf'; // Parent theme
Related
In the functions.php file I have this shortcode which shows the download button of the last order placed by a woocommerce customer. Everything works fine for customers who have bought something, however if a customer has no downloads or no order, the layout breaks. I suppose this happens because there is nothing to be displayed.
So I would like to display a message for those who have no download or have not placed an order, I tried with else but it didn't work.
Sorry but I'm relatively new to php, can anyone help me figure out how to introduce a warning message?
add_shortcode( 'order_download' , 'last_order_info_08' );
function last_order_info_08( $downloads ){
$customer = new WC_Customer( get_current_user_id() );
$last_order = $customer->get_last_order();
$downloads = $last_order->get_downloadable_items();
if ($downloads) {
wc_get_template(
'button-downloads.php',
array(
'downloads' => $downloads,
'show_title' => true,
)
);
}
}
I modified the code a bit and should suit your need. You should be able to just replace the current code with this. Tested and confirmed locally on any page the shortcode is added it displayed. If you have some odd CSS setup it may or may not display correct on your site.
add_shortcode( 'order_download' , 'last_order_info_08' );
function last_order_info_08( $downloads ){
$customer = new WC_Customer( get_current_user_id() );
$last_order = $customer->get_last_order();
$shop_url = get_permalink( wc_get_page_id( 'shop' ) );
// Check to see if they have an order
if ($last_order) {
// Get download items from last order.
$downloads = $last_order->get_downloadable_items();
// Check to see if it contains downloadable items
if ($downloads) {
wc_get_template(
'button-downloads.php',
array(
'downloads' => $downloads,
'show_title' => true,
)
);
} else {
wc_add_notice( '<a class="woocommerce-Button button" href="'. $shop_url .'"> Browse products</a> No downloads available yet.', 'notice' );
}
} else {
wc_add_notice( '<a class="woocommerce-Button button" href="'. $shop_url .'"> Browse products</a> No downloads available yet.', 'notice' );
}
// HERE we print the notices
wc_print_notices();
}
In WooCommerce, on top of my thank you / order-received page, I've added a custom text, with the following code:
add_action( 'woocommerce_thankyou', 'my_order_received_text', 1, 0);
function my_order_received_text(){
echo '<div class="my_thankyou2"><p>' . __('Your download link was sent to: ') . '</p></div>' ;
}
How can I get the email address of the customer added to the end of the custom text?
To get the customer billing email, you can use one of those:
The Woocommerce WC_Order method get_billing_email()
The WordPress function get_post_meta() with the meta key _billing_email from order ID.
Now you can set the text in 2 different locations:
1) On top of Order received page:
add_filter( 'woocommerce_thankyou_order_received_text', 'my_order_received_text', 10, 2 );
function my_order_received_text( $text, $order ){
if( ! is_a($order, 'WC_Order') ) {
return $text;
}
// Get Customer billing email
$email = $order->get_billing_email();
return $text . '<br>
<div class="my_thankyou2"><p>' . __('Your download link was sent to: ') . $email . '</p></div>' ;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
2) On bottom of Order received page:
Using the WC_Order method get_billing_email() this way:
add_action( 'woocommerce_thankyou', 'my_order_received_text', 10, 1 );
function my_order_received_text( $order_id ){
if( ! $order_id ){
return;
}
$order = wc_get_order( $order_id ); // Get an instance of the WC_Order Object
$email = $order->get_billing_email(); // Get Customer billing email
echo '<div class="my_thankyou2"><p>' . __('Your download link was sent to: ') . $email . '</p></div>' ;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Alternatively, using WordPress get_post_meta() function, replacing in the function:
$order = wc_get_order( $order_id ); // Get an instance of the WC_Order Object
$email = $order->get_billing_email(); // Get Customer billing email
By the following line:
$email = get_post_meta( $order_id, '_billing_email', true ); // Get Customer billing email
So, i've built myself an enqueue'd stylesheet concatenator, while it works, what I've found is that the "dependencies" seem to be out of order... in this instance, I deregister and dequeue my "custom" stylesheet, register and enqueue my concatenated stylesheet, and then "re" register and "re" enqueue my custom style sheet using the concatenated handle as the dependency for it... and it always loads before the concatenated stylesheet.
Any ideas why this may be happenning? In my child-theme, I am enqueing "custom" at the default priority, in the parent theme, is where I am performing the concatenation, and my action has the highest possibly priority.
The Code:
protected function concatenate_css( $_cache_time ) {
add_action( 'wp_enqueue_scripts', function( ) use ( $_cache_time ) {
// need our global
global $wp_styles;
// our css string holder
$_css_string = '';
// path to the theme
$_theme_path = get_stylesheet_directory( );
// uri to the theme
$_theme_uri = get_stylesheet_directory_uri( );
// new file path
$_new_css = $_theme_path . '/style.concat.css';
// force the order based on the dependencies
$wp_styles -> all_deps( $wp_styles -> queue );
// setup our exclusions
$_exclude = array( 'custom', 'concatcss', );
// loop through everything in our global
foreach( $wp_styles -> queue as $_hndl ) {
// get the source from the hanlde
$_path = $wp_styles -> registered[$_hndl]->src;
// if we have a "custom" handle, we do not want to process it, so ... skip it
// we also do want to process any source that is not set
if( ! in_array( $_hndl, $_exclude ) && $_path ) {
// we also only want to do this for local stylehseets
if ( strpos( $_path, site_url( ) ) !== false ) {
$_path = ABSPATH . str_replace( site_url( ), '', $_path );
// now that we have everything we need, let's hold the contents of the file in a string variable, while concatenating
$_css_string .= file_get_contents( $_path ) . PHP_EOL;
// now remove the css from queue
wp_dequeue_style( $_hndl );
// and deregister it
wp_deregister_style( $_hndl );
}
}
}
// dequeue and deregsiter any "custom" style
wp_dequeue_style( 'custom' );
wp_deregister_style( 'custom' );
// now write out the new stylesheet to the theme, and enqueue it
// check the timestamp on it, versus the number of seconds we are specifying to see if we need to write a new file
if( file_exists( $_new_css ) ) {
$_ftime = filemtime( $_new_css ) + ( $_cache_time );
$_ctime = time( );
if( ( $_ftime <= $_ctime ) ) {
file_put_contents( $_new_css, $_css_string );
}
} else {
file_put_contents( $_new_css, $_css_string );
}
wp_register_style( 'concatcss', $_theme_uri . '/style.concat.css', array( ), null );
wp_enqueue_style( 'concatcss' );
// requeue and reregister our custom stylesheet, using this concatenated stylesheet as it's dependency
wp_register_style( 'custom', $_theme_uri . '/css/custom.css?_=' . time( ), array( 'concatcss' ), null );
wp_enqueue_style( 'custom' );
}, PHP_INT_MAX );
}
Screenshot of the page source
Just register your concatenated script, but don't enqueue it.
wp_register_style( 'concatcss', $_theme_uri . '/style.concat.css', array( ), null );
// requeue and reregister our custom stylesheet, using this concatenated stylesheet as it's dependency
wp_enqueue_style( 'custom', $_theme_uri . '/css/custom.css?_=' . time( ), array( 'concatcss' ), null );
In woocommerce I am using following code for adding PDF files as email attachment:
add_filter( 'woocommerce_email_attachments', 'attach_terms_conditions_pdf_to_email', 10, 3);
function attach_terms_conditions_pdf_to_email ( $attachments , $id, $object ) {
$your_pdf_path1 = get_stylesheet_directory() . '/pdf/ano1.pdf';
$your_pdf_path2 = get_stylesheet_directory() . '/pdf/ano2.pdf';
$attachments[] = $your_pdf_path1;
$attachments[] = $your_pdf_path2;
return $attachments;
}
My problem is that attachment is sending always for all email to customers. I would like to send email attachment only in case that Order status is "on-hold".
How is possible to know status of my order and send email attachment only for this case?
Updated
You need to use the $id argument with 'customer_on_hold_order' as email ID in your function as a condition…
add_filter( 'woocommerce_email_attachments', 'attach_terms_conditions_pdf_to_email', 10, 3);
function attach_terms_conditions_pdf_to_email ( $attachments , $id, $object ) {
// Continue if it's customer_on_hold email notiication
if ( $id != 'customer_on_hold_order' ) return $attachments;
$your_pdf_path1 = get_stylesheet_directory() . '/pdf/ano1.pdf';
$your_pdf_path2 = get_stylesheet_directory() . '/pdf/ano2.pdf';
$attachments[] = $your_pdf_path1;
$attachments[] = $your_pdf_path2;
return $attachments;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works
On my WordPress website, I have an archive page e.g.: http://www.example.com/2017. My archive.php file has a query to show posts as well as two custom post types: case-studies and media:
global $wp_query;
$args = array_merge( $wp_query->query, array( 'post_type' => array('post','case-studies','media'), 'posts_per_page' => 3 ) );
query_posts( $args );
while ( have_posts() ) : the_post();
The archive page will only show provided there are posts under post (the standard post type that is included within WordPress) otherwise it will 404, even though there are posts under case-studies and media.
Is there a workaround this?
Here is a link to my archive.php for those who are interested: archive.php
I've had this problem before. You can include a function in your functions.php file which can redirect the page to archive.php instead of the usual 404. See if this works:
function wpd_date_404_template( $template = '' ){
global $wp_query;
if( isset($wp_query->query['year'])
|| isset($wp_query->query['monthnum'])
|| isset($wp_query->query['day']) ){
$template = locate_template( 'archive.php', false );
}
return $template;
}
add_filter( '404_template', 'wpd_date_404_template' );
Credit to Milo at the WordPress StackExchange. See his answer here: Preventing 404 error on empty date archive
function wpd_date_404_template( $template = '' ){
global $wp_query;
if(
isset($wp_query->query['year']) ||
isset($wp_query->query['monthnum']) ||
isset($wp_query->query['day'])
) {
$template = locate_template( 'archive.php', false );
if ( isset( $wp_query->query['post_type'] ) ) {
$located = locate_template( 'archive-' . $wp_query->query['post_type'] . '.php', false );
$template = $located !== '' ? $located : locate_template( 'archive.php', false );
}
}
return $template;
}
add_filter( '404_template', 'wpd_date_404_template' );
Just used #Dev1997 his answer to solve the issue. With a small improvement to use the specific template for the current (custom) post_type. Maybe it will help someone who is using custom post types.