get(WCHelper::class); } $this->helper = $helper; $this->scheduler = ContainerWrapper::getInstance()->get(AutomaticEmailScheduler::class); $this->loggerFactory = LoggerFactory::getInstance(); $this->automaticEmailsRepository = ContainerWrapper::getInstance()->get(AutomaticEmailsRepository::class); $this->subscribersRepository = ContainerWrapper::getInstance()->get(SubscribersRepository::class); } public function init() { WPFunctions::get()->addFilter('mailpoet_newsletter_shortcode', [ $this, 'handleOrderTotalShortcode', ], 10, 4); WPFunctions::get()->addFilter('mailpoet_newsletter_shortcode', [ $this, 'handleOrderDateShortcode', ], 10, 4); // We have to use a set of states because an order state after checkout differs for different payment methods $acceptedOrderStates = WPFunctions::get()->applyFilters('mailpoet_first_purchase_order_states', ['completed', 'processing']); foreach ($acceptedOrderStates as $state) { WPFunctions::get()->addAction('woocommerce_order_status_' . $state, [ $this, 'scheduleEmailWhenOrderIsPlaced', ], 10, 1); } } public function getEventDetails() { return [ 'slug' => self::SLUG, 'title' => __('First Purchase', 'mailpoet'), 'description' => __('Let MailPoet send an email to customers who make their first purchase.', 'mailpoet'), 'listingScheduleDisplayText' => __('Email sent when a customer makes their first purchase.', 'mailpoet'), 'afterDelayText' => __('after the first purchase', 'mailpoet'), 'badge' => [ 'text' => __('Must-have', 'mailpoet'), 'style' => 'red', ], 'timeDelayValues' => [ 'immediate' => [ 'text' => __('immediately', 'mailpoet'), 'displayAfterTimeNumberField' => false, ], 'minutes' => [ 'text' => __('minute(s)', 'mailpoet'), 'displayAfterTimeNumberField' => true, ], 'hours' => [ 'text' => __('hour(s)', 'mailpoet'), 'displayAfterTimeNumberField' => true, ], 'days' => [ 'text' => __('day(s)', 'mailpoet'), 'displayAfterTimeNumberField' => true, ], 'weeks' => [ 'text' => __('week(s)', 'mailpoet'), 'displayAfterTimeNumberField' => true, ], ], 'shortcodes' => [ [ 'text' => __('Order amount', 'mailpoet'), 'shortcode' => self::ORDER_TOTAL_SHORTCODE, ], [ 'text' => __('Order date', 'mailpoet'), 'shortcode' => self::ORDER_DATE_SHORTCODE, ], ], ]; } public function handleOrderDateShortcode($shortcode, $newsletter, $subscriber, $queue) { $result = $shortcode; if ($shortcode === self::ORDER_DATE_SHORTCODE) { $defaultValue = WPFunctions::get()->dateI18n(get_option('date_format')); if (!$queue) { $result = $defaultValue; } else { $meta = $queue->getMeta(); $result = (!empty($meta['order_date'])) ? WPFunctions::get()->dateI18n(get_option('date_format'), $meta['order_date']) : $defaultValue; } } $this->loggerFactory->getLogger(self::SLUG)->info( 'handleOrderDateShortcode called', [ 'newsletter_id' => ($newsletter instanceof NewsletterEntity) ? $newsletter->getId() : null, 'subscriber_id' => ($subscriber instanceof SubscriberEntity) ? $subscriber->getId() : null, 'task_id' => ($queue instanceof SendingQueueEntity) ? (($task = $queue->getTask()) ? $task->getId() : null) : null, 'shortcode' => $shortcode, 'result' => $result, ] ); return $result; } public function handleOrderTotalShortcode($shortcode, $newsletter, $subscriber, $queue) { $result = $shortcode; if ($shortcode === self::ORDER_TOTAL_SHORTCODE) { $defaultValue = $this->helper->wcPrice(0); if (!$queue) { $result = $defaultValue; } else { $meta = $queue->getMeta(); $result = (!empty($meta['order_amount'])) ? $this->helper->wcPrice($meta['order_amount']) : $defaultValue; } } $this->loggerFactory->getLogger(self::SLUG)->info( 'handleOrderTotalShortcode called', [ 'newsletter_id' => ($newsletter instanceof NewsletterEntity) ? $newsletter->getId() : null, 'subscriber_id' => ($subscriber instanceof SubscriberEntity) ? $subscriber->getId() : null, 'task_id' => ($queue instanceof SendingQueueEntity) ? (($task = $queue->getTask()) ? $task->getId() : null) : null, 'shortcode' => $shortcode, 'result' => $result, ] ); return $result; } public function scheduleEmailWhenOrderIsPlaced($orderId) { $orderDetails = $this->helper->wcGetOrder($orderId); if (!$orderDetails || !$orderDetails->get_billing_email()) { $this->loggerFactory->getLogger(self::SLUG)->info( 'Email not scheduled because the order customer was not found', ['order_id' => $orderId] ); return; } $customerEmail = $orderDetails->get_billing_email(); $customerOrderCount = $this->getCustomerOrderCount($customerEmail); if ($customerOrderCount > 1) { $this->loggerFactory->getLogger(self::SLUG)->info( 'Email not scheduled because this is not the first order of the customer', [ 'order_id' => $orderId, 'customer_email' => $customerEmail, 'order_count' => $customerOrderCount, ] ); return; } $meta = [ 'order_amount' => $orderDetails->get_total(), 'order_date' => $orderDetails->get_date_created()->getTimestamp(), 'order_id' => $orderDetails->get_id(), ]; $subscriber = $this->subscribersRepository->getWooCommerceSegmentSubscriber($customerEmail); if (!$subscriber instanceof SubscriberEntity) { $this->loggerFactory->getLogger(self::SLUG)->info( 'Email not scheduled because the customer was not found as WooCommerce list subscriber', ['order_id' => $orderId, 'customer_email' => $customerEmail] ); return; } $checkEmailWasNotScheduled = function (NewsletterEntity $newsletter) use ($subscriber) { return !$this->automaticEmailsRepository->wasScheduledForSubscriber((int)$newsletter->getId(), (int)$subscriber->getId()); }; $this->loggerFactory->getLogger(self::SLUG)->info( 'Email scheduled', [ 'order_id' => $orderId, 'customer_email' => $customerEmail, 'subscriber_id' => $subscriber->getId(), ] ); $this->scheduler->scheduleAutomaticEmail(WooCommerce::SLUG, self::SLUG, $checkEmailWasNotScheduled, $subscriber, $meta); } public function getCustomerOrderCount($customerEmail) { // registered user $user = WPFunctions::get()->getUserBy('email', $customerEmail); if ($user) { return $this->helper->wcGetCustomerOrderCount($user->ID); } // guest user return $this->getGuestCustomerOrderCountByEmail($customerEmail); } private function getGuestCustomerOrderCountByEmail(string $customerEmail): int { $ordersCount = $this->helper->wcGetOrders( [ 'status' => 'all', 'type' => 'shop_order', 'billing_email' => $customerEmail, 'limit' => 1, 'return' => 'ids', 'paginate' => true, ] )->total; return intval($ordersCount); } }