问题
I have created a Woocommerce plugin and require it to do two things:
Send a notification message to a specific email address, based on which product variation is in the cart.
The email must contain only the relevant product, and not products that contain other attributes.
For example:
Product A has an Attribute named Chef, with chef-one and chef-two as variable Terms. The user may select Product A from chef-one or chef-two.
If the user selects Product A from chef-one, a notification email must be sent to chefone@email.com containing the name of the product ordered (as it would show up in a regular Woocommerce notification email).
If the user selects Product A from chef-one and Product B from chef-two, a notification email must be sent to chef-one containing only Product A, and a notification email must be sent to chef-two containing only Product B.
I have created the plugin using the tutorial found on https://www.skyverge.com/blog/how-to-add-a-custom-woocommerce-email/ and have adapted it to suit the above purpose.
I have also adapted code found the following solutions: Adding a custom woocommerce email based on the product attribute Woocommerce - Need to send email to specific address based on zip code
Here is the code from my plugin's class file:
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
/**
* A custom WAKIKI Order WooCommerce Email class
*
* @since 0.1
* @extends \WC_Email
*/
class WC_Wakiki_Order_Email extends WC_Email {
/**
* Set email defaults
*
* @since 0.1
*/
public function __construct() {
// set ID, this simply needs to be a unique name
$this->id = 'wc_wakiki_order';
// this is the title in WooCommerce Email settings
$this->title = 'WAKIKI Order';
// this is the description in WooCommerce email settings
$this->description = 'WAKIKI Order Notification emails are sent when a customer places an order on the website';
// these are the default heading and subject lines that can be overridden using the settings
$this->heading = 'WAKIKI Delivery Order';
$this->subject = 'WAKIKI Delivery Order';
// these define the locations of the templates that this email should use, we'll just use the new order template since this email is similar
$this->template_html = 'emails/admin-new-order.php';
$this->template_plain = 'emails/plain/admin-new-order.php';
// Trigger on new paid orders
add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_failed_to_processing_notification', array( $this, 'trigger' ) );
// Call parent constructor to load any other defaults not explicity defined here
parent::__construct();
// this sets the recipient to the settings defined below in init_form_fields()
$this->recipient = $this->get_option( 'recipient' );
// if none was entered, just use the WP admin email as a fallback
if ( ! $this->recipient )
$this->recipient = get_option( 'admin_email' );
}
/**
* Determine if the email should actually be sent and setup email merge variables
*
* @since 0.1
* @param int $order_id
*/
public function trigger( $order_id ) {
// Bail if no order ID is present
if ( ! $order_id )
return;
$order = new WC_Order( $order_id );
// Find the product_id
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item['product_id'];
}
// From the product_id get the product attribute
$product = new WC_Product( $product_id ); // create an object of WC_Product class
$patt = $product->get_attributes(); // call get_attributes method
// Condition valid to send the email (if the attributes is chef)
if ( array_key_exists('pa_chef', $patt) )
// Determine which email address to send to, based on Product Attribute Term)
add_filter( 'new_order' , 'add_recipient', 20, 2 );
function add_recipient( $email, $order ) {
$additional_email = "info@email.com";
$terms = get_terms("pa_chef");
if( $order->$term->name == "pa_chef-one" ){
$email = explode( ',', $email );
array_push( $email, $additional_email );
}
return $email;
}
{
// Send the email
// Setup order object
$this->object = new WC_Order( $order_id );
$this->recipient = $this->object->billing_email;
// Replace variables in the subject/headings
$this->find[] = '{order_date}';
$this->replace[] = date_i18n( woocommerce_date_format(), strtotime( $this->object->order_date ) );
$this->find[] = '{order_number}';
$this->replace[] = $this->object->get_order_number();
if ( ! $this->is_enabled() || ! $this->get_recipient() )
return;
// Send the email!
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
else
{
return; //do nothing if there is not chef attribute
}
}
/**
* get_content_plain function
*
* @since 0.1
* @return string
*/
public function get_content_plain() {
ob_start();
woocommerce_get_template( $this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading()
) );
return ob_get_clean();
}
/**
* Initialize Settings Form Fields
*
* @since 2.0
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => 'Enable/Disable',
'type' => 'checkbox',
'label' => 'Enable this email notification',
'default' => 'yes'
),
'recipient' => array(
'title' => 'Recipient(s)',
'type' => 'text',
'description' => sprintf( 'Enter recipients (comma separated) for this email. Defaults to <code>%s</code>.', esc_attr( get_option( 'admin_email' ) ) ),
'placeholder' => '',
'default' => ''
),
'subject' => array(
'title' => 'Subject',
'type' => 'text',
'description' => sprintf( 'This controls the email subject line. Leave blank to use the default subject: <code>%s</code>.', $this->subject ),
'placeholder' => '',
'default' => ''
),
'heading' => array(
'title' => 'Email Heading',
'type' => 'text',
'description' => sprintf( __( 'This controls the main heading contained within the email notification. Leave blank to use the default heading: <code>%s</code>.' ), $this->heading ),
'placeholder' => '',
'default' => ''
),
'email_type' => array(
'title' => 'Email type',
'type' => 'select',
'description' => 'Choose which format of email to send.',
'default' => 'html',
'class' => 'email_type',
'options' => array(
'plain' => __( 'Plain text', 'woocommerce' ),
'html' => __( 'HTML', 'woocommerce' ),
'multipart' => __( 'Multipart', 'woocommerce' ),
)
)
);
}
This is as close as I am able to get it, but it is not working. I suspect the problem lies somewhere around the line that says "Determine which email address to send to, based on Product Attribute Term". The plugin was loading until I added that section.
Is the function supposed to be in a separate plugin file?
I also need help in getting the email to contain only the information relevant to the vendor it is being sent to.
Any assistance in getting this plugin to work would be greatly appreciated.
回答1:
The filter
new_order
doesn't exist in WooCommerce (or in your code)
The correct filter hook (located in WC_Email class core code, line 269) is this one:
$recipient = apply_filters( 'woocommerce_email_recipient_' . $this->id, $this->recipient, $this->object );
In this hook, $this->id
is 'new_order
' for you.
There is big errors in your code:
- The term name should be something like
"one"
or"chef-one"
, but absolutely not"pa_chef-one"
, as"pa_chef"
is the taxonomy slug for your attribute "Chef". - The multiple email recipients are not in an array, but in a coma separated string.
So the correct code should be something like:
add_filter( 'woocommerce_email_recipient_new_order', 'add_recipient', 10, 2 );
function add_recipient( $recipient, $order )
{
if ( ! is_a( $order, 'WC_Order' ) ) return $recipient;
// Additional email recipient
$additional_email = "info@email.com";
// The term name "pa_chef-one" is very strange … It should be "one" or "chef-one" (may be)
$term_slug = "one";
$has_term = false;
// Iterating through each order item
foreach ($order->get_items() as $item_id => $item_obj) {
$variation_id = $item_obj->get_variation_id();
$variation_obj = wc_get_product($variation_id);
$variation_attributes = $variation_obj->get_attributes();
foreach( $variation_attributes as $taxonomy_key => $term_value ){
if( $taxonomy_key == "pa_chef" && $term_value == $term_slug ){
$recipient .= ','. $additional_email;
$has_term = true;
break; // stop the 2nd loop
}
}
if( $has_term ) break; // stop the 1st loop
}
return $recipient;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Made for WooCommerce version 3+
Similar answers:
Add the New order email notification attachment to the vendor email
Woocommerce email notification recipient conditionally based on custom field
WooCommerce email notifications: different email recipient for different cities
来源:https://stackoverflow.com/questions/45673781/adding-recipients-to-woocommerce-email-notifications-based-on-product-variation