registerAsyncMails(); add_action('fluent_cart/order_placed_offline', function ($data) { $this->mailEmailsOfEvent( 'order_placed_offline', $data ); }, 999, 1); // To Customer add_action('fluent_cart/order_paid', function ($data) { $this->mailEmailsOfEvent( 'order_paid', $data ); }, 999, 1); // To Admin add_action('fluent_cart/order_paid_done', function ($data) { $this->mailEmailsOfEvent( 'order_paid_done', $data ); }, 10, 1); // to customer and admin add_action('fluent_cart/subscription_renewed', function ($data) { $this->mailEmailsOfEvent( 'subscription_renewed', $data ); }, 999, 1); // to customer and admin add_action('fluent_cart/subscription_canceled', function ($data) { $this->mailEmailsOfEvent( 'subscription_canceled', $data ); }, 999, 1); add_action('fluent_cart/order_refunded', function ($data) { $this->mailEmailsOfEvent('order_refunded', $data); }, 999, 1); add_action('fluent_cart/shipping_status_changed_to_shipped', function ($data) { $this->mailEmailsOfEvent('shipping_status_changed_to_shipped', $data); }, 999, 1); add_action('fluent_cart/shipping_status_changed_to_delivered', function ($data) { $this->mailEmailsOfEvent('shipping_status_changed_to_delivered', $data); }, 999, 1); add_action('fluent_cart/renewal_created', function ($data) { $this->mailEmailsOfEvent('renewal_created', $data); }, 999, 1); add_action('fluent_cart/renewal_payment_reminder', function ($data) { $this->mailEmailsOfEvent('renewal_payment_reminder', $data); }, 999, 1); // Fired by RenewalService when a system renewal order is created ahead of // its automatic charge — the customer's advance notice of amount and date. add_action('fluent_cart/subscriptions/system_renewal_scheduled', function ($data) { $shouldSend = apply_filters('fluent_cart/subscriptions/upcoming_charge_notification', true, $data); if ($shouldSend) { $this->mailEmailsOfEvent('system_upcoming_charge', $data); } }, 999, 1); // Fired by SystemChargeService when an automatic (system) renewal charge // fails and the customer should be notified (first failure by default). add_action('fluent_cart/subscriptions/system_charge_failed_notification', function ($data) { $this->mailEmailsOfEvent('system_charge_failed', $data); }, 999, 1); add_action('fluent_cart/subscription_period_skipped', function ($data) { $this->mailEmailsOfEvent('subscription_period_skipped', $data); }, 999, 1); add_action('fluent_cart/subscription_past_due', function ($data) { $this->mailEmailsOfEvent('subscription_past_due', $data); }, 999, 1); add_action('fluent_cart/renewal_reminder_due', function ($data) { $this->mailEmailsOfEvent('renewal_reminder_due', $data); }, 999, 1); add_action('fluent_cart/renewal_reminder_overdue', function ($data) { $this->mailEmailsOfEvent('renewal_reminder_overdue', $data); }, 999, 1); add_action('fluent_cart/subscription_renewal_reminder', function ($data) { $this->mailEmailsOfEvent('subscription_renewal_reminder', $data); }, 999, 1); add_action('fluent_cart/subscription_trial_end_reminder', function ($data) { $this->mailEmailsOfEvent('subscription_trial_end_reminder', $data); }, 999, 1); } public function registerAsyncMails() { //For Async Actions add_action('fluent_cart/async_mail/order_created', function ($orderId, $mailName = '') { (new static())->sendAsyncOrderMail($mailName, $orderId); }, 10, 2); add_action('fluent_cart/async_mail/order_placed_offline', function ($orderId, $mailName = '') { (new static())->sendAsyncOrderMail($mailName, $orderId); }, 10, 2); add_action('fluent_cart/async_mail/order_paid', function ($orderId, $mailName = '') { (new static())->sendAsyncOrderMail($mailName, $orderId); }, 10, 2); add_action('fluent_cart/async_mail/order_updated', function ($orderId, $mailName = '') { (new static())->sendAsyncOrderMail($mailName, $orderId); }, 10, 2); add_action('fluent_cart/async_mail/order_refunded', function ($orderId, $mailName = '') { (new static())->sendAsyncOrderMail($mailName, $orderId); }, 10, 2); add_action('fluent_cart/async_mail/subscription_activated', function ($subscriptionId, $mailName = '') { (new static())->sendAsyncSubscriptionMail($mailName, $subscriptionId); }, 10, 2); add_action('fluent_cart/async_mail/subscription_reactivated', function ($subscriptionId, $mailName = '') { (new static())->sendAsyncSubscriptionMail($mailName, $subscriptionId); }, 10, 2); add_action('fluent_cart/async_mail/subscription_renewed', function ($subscriptionId, $mailName = '') { (new static())->sendAsyncSubscriptionMail($mailName, $subscriptionId); }, 10, 2); add_action('fluent_cart/async_mail/subscription_eot', function ($subscriptionId, $mailName = '') { (new static())->sendAsyncSubscriptionMail($mailName, $subscriptionId); }, 10, 2); add_action('fluent_cart/async_mail/subscription_canceled', function ($subscriptionId, $mailName = '') { (new static())->sendAsyncSubscriptionMail($mailName, $subscriptionId); }, 10, 2); add_action('fluent_cart/async_mail/subscription_expired', function ($subscriptionId, $mailName = '') { (new static())->sendAsyncSubscriptionMail($mailName, $subscriptionId); }, 10, 2); } public function formatParsable($parsable) { foreach ($parsable as &$item) { if ($item instanceof Model) { $item = $item->toArray(); } } if (!Arr::has($parsable, 'order.customer')) { $parsable['order']['customer'] = Arr::get( $parsable, 'customer', [] ); } return $parsable; } public function mailEmailsOfEvent($event, $data, $asyncHook = '', $asyncData = []) { $parsedData = $this->formatParsable($data); $order = Arr::get($data, 'order'); // Pass original Model data for template rendering (templates use $order->method()) $notifications = EmailNotifications::getNotificationsOfEvent($event, $data); foreach ($notifications as $mailName => $notification) { if ($order instanceof Order && !apply_filters('fluent_cart/should_send_email_notification', true, [ 'event' => $event, 'mail_name' => $mailName, 'order' => $order, ])) { continue; } $isAsync = Arr::get($notification, 'is_async', false); if ($isAsync && !empty($asyncHook)) { $asyncData['mailName'] = $mailName; as_enqueue_async_action($asyncHook, $asyncData); } else { list($body, $subject, $to) = $this->parseEmailContent($notification, $data); $mailer = Mailer::make()->to($to)->subject($subject)->body($body); $pdfPath = null; $templateId = Arr::get($notification, 'settings.attach_pdf_template', ''); // Backward compat: old attach_pdf='yes' maps to order_receipt if (empty($templateId) && Arr::get($notification, 'settings.attach_pdf', 'no') === 'yes') { $templateId = 'order_receipt'; } if (!empty($templateId) && defined('FLUENT_PDF')) { $pdfPath = $this->generateOrderPdf($data, $templateId); if ($pdfPath) { $mailer->addAttachment($pdfPath); } } $mailer->send(true); // Clean up temp PDF file after sending if ($pdfPath && file_exists($pdfPath)) { @unlink($pdfPath); } } } } public function mailByEmailName($emailName, $data) { // $data keeps its Models: parseEmailContent renders emails.parts.order_header, // which reads $order->invoice_no / $order->orderTaxRates — an array here // warns and then fatals inside the view (regression of 201a14885 via 44a39aa1d) $orderModel = Arr::get($data, 'order'); $notification = EmailNotifications::getNotification($emailName); $notification = EmailNotifications::formatNotification($notification, $data); list($body, $subject, $to) = $this->parseEmailContent($notification, $data); $mailer = Mailer::make()->to($to)->subject($subject)->body($body); $pdfPath = null; $templateId = Arr::get($notification, 'settings.attach_pdf_template', ''); if (empty($templateId) && Arr::get($notification, 'settings.attach_pdf', 'no') === 'yes') { $templateId = 'order_receipt'; } if (!empty($templateId) && defined('FLUENT_PDF')) { $pdfPath = $this->generateOrderPdf(['order' => $orderModel], $templateId); if ($pdfPath) { $mailer->addAttachment($pdfPath); } } $mailer->send(true); if ($pdfPath && file_exists($pdfPath)) { @unlink($pdfPath); } } public function getEmailFooter(): string { $footer = ""; $settings = EmailNotifications::getSettings(); $emailFooter = Arr::get($settings, 'email_footer', ''); if (!empty($emailFooter)) { $footer .= ShortcodeTemplateBuilder::make($emailFooter, []); } $isEmailFooter = EmailNotifications::getSettings('show_email_footer'); if (!App::isProActive() || $isEmailFooter === 'yes') { $cartFooter = "