WC_GZD_Emails

Attaches legal relevant Pages to WooCommerce Emails if has been set by WooCommerce Germanized Options.

Defined (1)

The class is defined in the following location(s).

/includes/class-wc-gzd-emails.php  
  1. class WC_GZD_Emails { 
  2.  
  3. /** 
  4. * Contains options and page ids 
  5. * @var array 
  6. */ 
  7. private $footer_attachments = array(); 
  8.  
  9. /** 
  10. * Contains WC_Emails instance after init 
  11. * @var WC_Emails 
  12. */ 
  13. private $mailer = null; 
  14.  
  15. /** 
  16. * Adds legal page ids to different options and adds a hook to the email footer 
  17. */ 
  18. public function __construct() { 
  19.  
  20. $this->set_footer_attachments(); 
  21.  
  22. add_action( 'woocommerce_email', array( $this, 'email_hooks' ), 0, 1 ); 
  23.  
  24. if ( wc_gzd_send_instant_order_confirmation() ) { 
  25.  
  26. // Send order notice directly after new order is being added - use these filters because order status has to be updated already 
  27. add_filter( 'woocommerce_payment_successful_result', array( $this, 'send_order_confirmation_mails' ), 0, 2 ); 
  28. add_filter( 'woocommerce_checkout_no_payment_needed_redirect', array( $this, 'send_order_confirmation_mails' ), 0, 2 ); 
  29.  
  30. // Disable paid order email for certain gateways (e.g. COD or invoice) 
  31. add_action( 'woocommerce_order_status_processing', array( $this, 'maybe_disable_order_paid_email_notification_2_6' ), 0, 1 ); 
  32. add_filter( 'woocommerce_allow_send_queued_transactional_email', array( $this, 'maybe_disable_order_paid_email_notification'), 10, 3 ); 
  33.  
  34. // Change email template path if is germanized email template 
  35. add_filter( 'woocommerce_template_directory', array( $this, 'set_woocommerce_template_dir' ), 10, 2 ); 
  36. // Map partially refunded order mail template to correct email instance 
  37. add_filter( 'woocommerce_gzd_email_template_id_comparison', array( $this, 'check_for_partial_refund_mail' ), 10, 3 ); 
  38. // Hide username if an email contains a password or password reset link (TS advises to do so) 
  39. if ( 'yes' === get_option( 'woocommerce_gzd_hide_username_with_password' ) ) 
  40. add_filter( 'woocommerce_before_template_part', array( $this, 'maybe_set_gettext_username_filter' ), 10, 4 ); 
  41.  
  42. if ( is_admin() ) 
  43. $this->admin_hooks(); 
  44.  
  45. public function maybe_set_gettext_username_filter( $template_name, $template_path, $located, $args ) { 
  46.  
  47. $templates = array( 
  48. 'emails/customer-reset-password.php' => 'maybe_hide_username_password_reset',  
  49. 'emails/plain/customer-reset-password.php' => 'maybe_hide_username_password_reset',  
  50. ); 
  51.  
  52. // If the password is generated automatically and sent by email, hide the username 
  53. if ( 'yes' === get_option( 'woocommerce_registration_generate_password' ) ) { 
  54. $templates = array_merge( $templates, array( 
  55. 'emails/customer-new-account.php' => 'maybe_hide_username_new_account',  
  56. 'emails/plain/customer-new-account.php' => 'maybe_hide_username_new_account' 
  57. ) ); 
  58.  
  59. if ( isset( $templates[ $template_name ] ) ) { 
  60. add_filter( 'gettext', array( $this, $templates[ $template_name ] ), 10, 3 ); 
  61.  
  62. public function maybe_hide_username_password_reset( $translated, $original, $domain ) { 
  63. if ( 'woocommerce' === $domain ) { 
  64. if ( 'Someone requested that the password be reset for the following account:' === $original ) { 
  65. return __( 'Someone requested a password reset for your account.', 'woocommerce-germanized' ); 
  66. } elseif ( 'Username: %s' === $original ) { 
  67. remove_filter( 'gettext', array( $this, 'maybe_hide_username_password_reset' ), 10, 3 ); 
  68. return ''; 
  69.  
  70. return $translated; 
  71.  
  72. public function maybe_hide_username_new_account( $translated, $original, $domain ) { 
  73. if ( 'woocommerce' === $domain && 'Thanks for creating an account on %s. Your username is <strong>%s</strong>' === $original ) { 
  74. remove_filter( 'gettext', array( $this, 'maybe_hide_username_new_account' ), 10, 3 ); 
  75. return __( 'Thanks for creating an account on %s.', 'woocommerce-germanized' ); 
  76. return $translated; 
  77.  
  78. public function check_for_partial_refund_mail( $result, $mail_id, $tpl ) { 
  79.  
  80. if ( $mail_id === 'customer_partially_refunded_order' && $tpl === 'customer_refunded_order' ) 
  81. return true; 
  82.  
  83. return $result; 
  84.  
  85. private function set_mailer( $mailer = null ) { 
  86. if ( $mailer ) 
  87. $this->mailer = $mailer; 
  88. else 
  89. $this->mailer = WC()->mailer(); 
  90.  
  91. private function set_footer_attachments() { 
  92.  
  93. // Order attachments 
  94. $attachment_order = wc_gzd_get_email_attachment_order(); 
  95. $this->footer_attachments = array(); 
  96.  
  97. foreach ( $attachment_order as $key => $order ) 
  98. $this->footer_attachments[ 'woocommerce_gzd_mail_attach_' . $key ] = $key; 
  99.  
  100. public function admin_hooks() { 
  101. add_filter( 'woocommerce_resend_order_emails_available', array( $this, 'resend_order_emails' ), 0 ); 
  102.  
  103. public function email_hooks( $mailer ) { 
  104.  
  105. $this->set_mailer( $mailer ); 
  106.  
  107. if ( wc_gzd_send_instant_order_confirmation() ) { 
  108. $this->prevent_confirmation_email_sending(); 
  109.  
  110. // Hook before WooCommerce Footer is applied 
  111. remove_action( 'woocommerce_email_footer', array( $this->mailer, 'email_footer' ) ); 
  112.  
  113. add_action( 'woocommerce_email_footer', array( $this, 'add_template_footers' ), 0 ); 
  114. add_action( 'woocommerce_email_footer', array( $this->mailer, 'email_footer' ), 1 ); 
  115.  
  116. add_filter( 'woocommerce_email_footer_text', array( $this, 'email_footer_plain' ), 0 ); 
  117. add_filter( 'woocommerce_email_styles', array( $this, 'styles' ) ); 
  118.  
  119. $mails = $this->mailer->get_emails(); 
  120.  
  121. if ( ! empty( $mails ) ) { 
  122.  
  123. foreach ( $mails as $mail ) 
  124. add_action( 'woocommerce_germanized_email_footer_' . $mail->id, array( $this, 'hook_mail_footer' ), 10, 1 ); 
  125.  
  126. // Set email filters 
  127. add_action( 'woocommerce_email_before_order_table', array( $this, 'set_order_email_filters' ), 10, 4 ); 
  128.  
  129. // Remove them after total has been displayed 
  130. add_action( 'woocommerce_email_after_order_table', array( $this, 'remove_order_email_filters' ), 10, 4 ); 
  131.  
  132. // Pay now button 
  133. add_action( 'woocommerce_email_before_order_table', array( $this, 'email_pay_now_button' ), 0, 1 ); 
  134. add_action( 'woocommerce_email_after_order_table', array( $this, 'email_digital_revocation_notice' ), 0, 3 ); 
  135.  
  136. public function get_gateways_disabling_paid_for_order_mail() { 
  137. return apply_filters( 'woocommerce_gzd_disable_gateways_paid_order_email', array( 'cod', 'invoice' ) ); 
  138.  
  139. public function maybe_disable_order_paid_email_notification_2_6( $order_id ) { 
  140.  
  141. $order = wc_get_order( $order_id ); 
  142.  
  143. if ( ! $order ) { 
  144. return; 
  145.  
  146. $method = wc_gzd_get_crud_data( $order, 'payment_method' ); 
  147. $current_status = $order->get_status(); 
  148. $disable_for_gateways = $this->get_gateways_disabling_paid_for_order_mail(); 
  149.  
  150. if ( in_array( $method, $disable_for_gateways ) ) { 
  151. // Remove action 
  152. if ( WC_germanized()->emails->get_email_instance_by_id( 'customer_paid_for_order' ) ) { 
  153. remove_action( 'woocommerce_order_status_pending_to_processing_notification', array( WC_germanized()->emails->get_email_instance_by_id( 'customer_paid_for_order' ), 'trigger' ), 30 ); 
  154.  
  155. public function maybe_disable_order_paid_email_notification( $send, $filter, $args ) { 
  156. if ( isset( $args[0] ) && is_numeric( $args[0] ) ) { 
  157. $order = wc_get_order( absint( $args[0] ) ); 
  158.  
  159. if ( $order ) { 
  160.  
  161. $method = wc_gzd_get_crud_data( $order, 'payment_method' ); 
  162. $current_status = $order->get_status(); 
  163. $disable_for_gateways = $this->get_gateways_disabling_paid_for_order_mail(); 
  164.  
  165. if ( in_array( $method, $disable_for_gateways ) && $filter === 'woocommerce_order_status_pending_to_processing' ) { 
  166. return false; 
  167. return $send; 
  168.  
  169. public function resend_order_emails( $emails ) { 
  170. global $theorder; 
  171.  
  172. if ( is_null( $theorder ) ) 
  173. return $emails; 
  174.  
  175. array_push( $emails, 'customer_paid_for_order' ); 
  176.  
  177. return $emails; 
  178.  
  179. public function set_woocommerce_template_dir( $dir, $template ) { 
  180. if ( file_exists( WC_germanized()->plugin_path() . '/templates/' . $template ) ) 
  181. return 'woocommerce-germanized'; 
  182. return $dir; 
  183.  
  184. private function get_confirmation_email_transaction_statuses() { 
  185. return array( 
  186. 'woocommerce_order_status_pending_to_processing',  
  187. 'woocommerce_order_status_pending_to_completed',  
  188. 'woocommerce_order_status_pending_to_on-hold',  
  189. 'woocommerce_order_status_on-hold_to_processing',  
  190. ); 
  191.  
  192. public function prevent_confirmation_email_sending() { 
  193.  
  194. foreach( $this->get_confirmation_email_transaction_statuses() as $status ) { 
  195.  
  196. remove_action( $status . '_notification', array( $this->get_email_instance_by_id( 'customer_processing_order' ), 'trigger' ) ); 
  197. remove_action( $status . '_notification', array( $this->get_email_instance_by_id( 'new_order' ), 'trigger' ) ); 
  198.  
  199. if ( $this->get_email_instance_by_id( 'customer_on_hold_order' ) ) 
  200. remove_action( 'woocommerce_order_status_pending_to_on-hold_notification', array( $this->get_email_instance_by_id( 'customer_on_hold_order' ), 'trigger' ) ); 
  201.  
  202.  
  203. /** 
  204. * Send order confirmation mail directly after order is being sent 
  205. * @param mixed $return 
  206. * @param mixed $order 
  207. */ 
  208. public function send_order_confirmation_mails( $result, $order ) { 
  209.  
  210. if ( ! is_object( $order ) ) 
  211. $order = wc_get_order( $order ); 
  212.  
  213. if ( ! apply_filters( 'woocommerce_germanized_send_instant_order_confirmation', true, $order ) ) 
  214. return $result; 
  215.  
  216. do_action( 'woocommerce_germanized_before_order_confirmation', wc_gzd_get_crud_data( $order, 'id' ) ); 
  217.  
  218. // Send order processing mail 
  219. if ( apply_filters( 'woocommerce_germanized_order_email_customer_confirmation_sent', false, wc_gzd_get_crud_data( $order, 'id' ) ) === false && $processing = $this->get_email_instance_by_id( 'customer_processing_order' ) ) 
  220. $processing->trigger( wc_gzd_get_crud_data( $order, 'id' ) ); 
  221.  
  222. // Send admin mail 
  223. if ( apply_filters( 'woocommerce_germanized_order_email_admin_confirmation_sent', false, wc_gzd_get_crud_data( $order, 'id' ) ) === false && $new_order = $this->get_email_instance_by_id( 'new_order' ) ) 
  224. $new_order->trigger( wc_gzd_get_crud_data( $order, 'id' ) ); 
  225.  
  226. // Always clear cart after order success 
  227. if ( get_option( 'woocommerce_gzd_checkout_stop_order_cancellation' ) === 'yes' ) 
  228. WC()->cart->empty_cart(); 
  229.  
  230. do_action( 'woocommerce_germanized_order_confirmation_sent', wc_gzd_get_crud_data( $order, 'id' ) ); 
  231.  
  232. return $result; 
  233.  
  234. public function email_digital_revocation_notice( $order, $sent_to_admin, $plain_text ) { 
  235.  
  236. if ( get_option( 'woocommerce_gzd_checkout_legal_digital_checkbox' ) !== 'yes' ) 
  237. return; 
  238.  
  239. $type = $this->get_current_email_object(); 
  240.  
  241. if ( $type && $type->id == 'customer_processing_order' ) { 
  242.  
  243. // Check if order contains digital products 
  244. $items = $order->get_items(); 
  245. $is_downloadable = false; 
  246. $is_service = false; 
  247.  
  248. if ( ! empty( $items ) ) { 
  249.  
  250. foreach ( $items as $item ) { 
  251.  
  252. $_product = apply_filters( 'woocommerce_order_item_product', $order->get_product_from_item( $item ), $item ); 
  253.  
  254. if ( ! $_product ) 
  255. continue; 
  256.  
  257. if ( wc_gzd_is_revocation_exempt( $_product ) || apply_filters( 'woocommerce_gzd_product_is_revocation_exception', false, $_product, 'digital' ) ) 
  258. $is_downloadable = true; 
  259.  
  260. if ( wc_gzd_is_revocation_exempt( $_product, 'service' ) || apply_filters( 'woocommerce_gzd_product_is_revocation_exception', false, $_product, 'service' ) ) 
  261. $is_service = true; 
  262.  
  263. if ( $is_downloadable && $text = wc_gzd_get_legal_text_digital_email_notice() ) 
  264. echo wpautop( apply_filters( 'woocommerce_gzd_order_confirmation_digital_notice', '<div class="gzd-digital-notice-text">' . $text . '</div>', $order ) ); 
  265.  
  266. if ( $is_service && $text = wc_gzd_get_legal_text_service_email_notice() ) 
  267. echo wpautop( apply_filters( 'woocommerce_gzd_order_confirmation_service_notice', '<div class="gzd-service-notice-text">' . $text . '</div>', $order ) ); 
  268.  
  269.  
  270. public function email_pay_now_button( $order ) { 
  271.  
  272. $type = $this->get_current_email_object(); 
  273.  
  274. if ( $type && $type->id == 'customer_processing_order' ) 
  275. WC_GZD_Checkout::instance()->add_payment_link( wc_gzd_get_crud_data( $order, 'id' ) ); 
  276.  
  277. public function email_footer_plain( $text ) { 
  278.  
  279. $type = $this->get_current_email_object(); 
  280.  
  281. if ( $type && $type->get_email_type() == 'plain' ) 
  282. $this->add_template_footers(); 
  283.  
  284. return $text; 
  285.  
  286.  
  287. public function get_email_instance_by_id( $id ) { 
  288.  
  289. if ( ! $this->mailer ) { 
  290. $this->set_mailer(); 
  291.  
  292. $mails = $this->mailer->get_emails(); 
  293.  
  294. foreach ( $mails as $mail ) { 
  295. if ( $id === $mail->id ) 
  296. return $mail; 
  297.  
  298. return false; 
  299.  
  300. public function set_order_email_filters() { 
  301.  
  302. $current = $this->get_current_email_object(); 
  303.  
  304. if ( ! $current || empty( $current ) ) 
  305. return; 
  306.  
  307. // Add order item name actions 
  308. add_action( 'woocommerce_order_item_name', 'wc_gzd_cart_product_units', wc_gzd_get_hook_priority( 'email_product_units' ), 2 ); 
  309. add_action( 'woocommerce_order_item_name', 'wc_gzd_cart_product_delivery_time', wc_gzd_get_hook_priority( 'email_product_delivery_time' ), 2 ); 
  310. add_action( 'woocommerce_order_item_name', 'wc_gzd_cart_product_item_desc', wc_gzd_get_hook_priority( 'email_product_item_desc' ), 2 ); 
  311. add_filter( 'woocommerce_order_formatted_line_subtotal', 'wc_gzd_cart_product_unit_price', wc_gzd_get_hook_priority( 'email_product_unit_price' ), 2 ); 
  312.  
  313.  
  314. public function remove_order_email_filters() { 
  315.  
  316. // Add order item name actions 
  317. remove_action( 'woocommerce_order_item_name', 'wc_gzd_cart_product_units', wc_gzd_get_hook_priority( 'email_product_units' ) ); 
  318. remove_action( 'woocommerce_order_item_name', 'wc_gzd_cart_product_delivery_time', wc_gzd_get_hook_priority( 'email_product_delivery_time' ) ); 
  319. remove_action( 'woocommerce_order_item_name', 'wc_gzd_cart_product_item_desc', wc_gzd_get_hook_priority( 'email_product_item_desc' ) ); 
  320. remove_filter( 'woocommerce_order_formatted_line_subtotal', 'wc_gzd_cart_product_unit_price', wc_gzd_get_hook_priority( 'email_product_unit_price' ) ); 
  321.  
  322.  
  323. /** 
  324. * Add email styles 
  325. *  
  326. * @param string $css  
  327. * @return string  
  328. */ 
  329. public function styles( $css ) { 
  330. return $css .= ' 
  331. .unit-price-cart { 
  332. display: block; 
  333. font-size: 0.9em; 
  334. .gzd-digital-notice-text { 
  335. margin-top: 16px; 
  336. '; 
  337.  
  338. /** 
  339. * Hook into Email Footer and attach legal page content if necessary 
  340. *  
  341. * @param object $mail 
  342. */ 
  343. public function hook_mail_footer( $mail ) { 
  344. if ( ! empty( $this->footer_attachments ) ) { 
  345. foreach ( $this->footer_attachments as $option_key => $page_option ) { 
  346. $option = wc_get_page_id ( $page_option ); 
  347. if ( $option == -1 || ! get_option( $option_key ) ) 
  348. continue; 
  349. if ( in_array( $mail->id, get_option( $option_key ) ) && apply_filters( 'woocommerce_gzd_attach_email_footer', true, $mail, $page_option ) ) { 
  350. $this->attach_page_content( $option, $mail->get_email_type() ); 
  351.  
  352. /** 
  353. * Add global footer Hooks to Email templates 
  354. */ 
  355. public function add_template_footers() { 
  356. $type = $this->get_current_email_object(); 
  357. if ( $type ) 
  358. do_action( 'woocommerce_germanized_email_footer_' . $type->id, $type ); 
  359.  
  360. public function get_current_email_object() { 
  361.  
  362. if ( isset( $GLOBALS[ 'wc_gzd_template_name' ] ) && ! empty( $GLOBALS[ 'wc_gzd_template_name' ] ) ) { 
  363.  
  364. $object = $this->get_email_instance_by_tpl( $GLOBALS[ 'wc_gzd_template_name' ] ); 
  365. if ( is_object( $object ) ) 
  366. return $object; 
  367.  
  368. return false; 
  369.  
  370. /** 
  371. * Returns Email Object by examining the template file 
  372. *  
  373. * @param string $tpl  
  374. * @return mixed  
  375. */ 
  376. private function get_email_instance_by_tpl( $tpls = array() ) { 
  377.  
  378. if ( ! $this->mailer ) 
  379. $this->set_mailer(); 
  380.  
  381. $found_mails = array(); 
  382. $mails = $this->mailer->get_emails(); 
  383.  
  384. foreach ( $tpls as $tpl ) { 
  385.  
  386. $tpl = apply_filters( 'woocommerce_germanized_email_template_name', str_replace( array( 'admin-', '-' ), array( '', '_' ), basename( $tpl, '.php' ) ), $tpl ); 
  387.  
  388. if ( ! empty( $mails ) ) { 
  389.  
  390. foreach ( $mails as $mail ) { 
  391.  
  392. if ( is_object( $mail ) ) { 
  393.  
  394. if ( apply_filters( 'woocommerce_gzd_email_template_id_comparison', ( $mail->id === $tpl ), $mail->id, $tpl ) ) { 
  395. array_push( $found_mails, $mail ); 
  396.  
  397. if ( ! empty( $found_mails ) ) { 
  398. return $found_mails[ sizeof( $found_mails ) - 1 ]; 
  399.  
  400. return null; 
  401.  
  402. /** 
  403. * Attach page content by ID. Removes revocation_form shortcut to not show the form within the Email footer. 
  404. *  
  405. * @param integer $page_id  
  406. */ 
  407. public function attach_page_content( $page_id, $email_type = 'html' ) { 
  408.  
  409. remove_shortcode( 'revocation_form' ); 
  410. add_shortcode( 'revocation_form', array( $this, 'revocation_form_replacement' ) ); 
  411.  
  412. $template = 'emails/email-footer-attachment.php'; 
  413. if ( $email_type == 'plain' ) 
  414. $template = 'emails/plain/email-footer-attachment.php'; 
  415.  
  416. wc_get_template( $template, array( 
  417. 'post_attach' => get_post( $page_id ),  
  418. ) ); 
  419.  
  420. add_shortcode( 'revocation_form', 'WC_GZD_Shortcodes::revocation_form' ); 
  421.  
  422. /** 
  423. * Replaces revocation_form shortcut with a link to the revocation form 
  424. *  
  425. * @param array $atts  
  426. * @return string  
  427. */ 
  428. public function revocation_form_replacement( $atts ) { 
  429. return '<a href="' . esc_url( wc_gzd_get_page_permalink( 'revocation' ) ) . '">' . _x( 'Forward your Revocation online', 'revocation-form', 'woocommerce-germanized' ) . '</a>'; 
  430.