cart_item_quantity_update',
[$this, 'handleCartChange'],
10
);
// item quantity set to zero (it removes the item but does not fire remove event)
$this->wp->addAction(
'woocommerce_before_cart_item_quantity_zero',
[$this, 'handleCartChange'],
10
);
// cart emptied (not called when all items removed)
$this->wp->addAction(
'woocommerce_cart_emptied',
[$this, 'handleCartChange'],
10
);
// undo removal of item from cart or cart emptying (does not fire any other cart change hook)
$this->wp->addAction(
'woocommerce_cart_item_restored',
[$this, 'handleCartChange'],
10
);
$this->subscriberActivityTracker->registerCallback(
'mailpoet_abandoned_cart',
[$this, 'handleSubscriberActivity']
);
}
public function handleCartChange() {
$cart = $this->wooCommerceHelper->WC()->cart;
$currentAction = current_action();
if ($currentAction !== 'woocommerce_cart_emptied' && $cart && !$cart->is_empty()) {
$this->scheduleAbandonedCartEmail($this->getCartProductIds($cart));
} else {
$this->cancelAbandonedCartEmail();
}
}
public function handleSubscriberActivity(SubscriberEntity $subscriber) {
// on subscriber activity on site reschedule all currently scheduled (not yet sent) emails for given subscriber
// (it tracks at most once per minute to avoid processing many calls at the same time, i.e. AJAX)
$this->rescheduleAbandonedCartEmail($subscriber);
}
private function getCartProductIds($cart) {
$cartItems = $cart->get_cart() ?: [];
return array_column($cartItems, 'product_id');
}
private function scheduleAbandonedCartEmail(array $cartProductIds = []) {
$subscriber = $this->getSubscriber();
if (!$subscriber || $subscriber->getStatus() !== SubscriberEntity::STATUS_SUBSCRIBED) {
return;
}
$this->wp->doAction(self::HOOK_SCHEDULE, $subscriber, $cartProductIds);
$meta = [self::TASK_META_NAME => $cartProductIds];
$this->scheduler->scheduleOrRescheduleAutomaticEmail(WooCommerceEmail::SLUG, self::SLUG, $subscriber, $meta);
}
private function rescheduleAbandonedCartEmail(SubscriberEntity $subscriber) {
$this->wp->doAction(self::HOOK_RE_SCHEDULE, $subscriber);
$this->scheduler->rescheduleAutomaticEmail(WooCommerceEmail::SLUG, self::SLUG, $subscriber);
}
private function cancelAbandonedCartEmail() {
$subscriber = $this->getSubscriber();
if (!$subscriber) {
return;
}
$this->wp->doAction(self::HOOK_CANCEL, $subscriber);
$this->scheduler->cancelAutomaticEmail(WooCommerceEmail::SLUG, self::SLUG, $subscriber);
}
private function getSubscriber(): ?SubscriberEntity {
$wpUser = $this->wp->wpGetCurrentUser();
if ($wpUser->exists()) {
return $this->subscribersRepository->findOneBy(['wpUserId' => $wpUser->ID]);
}
// if user not logged in, try to find subscriber by cookie
$subscriberId = $this->subscriberCookie->getSubscriberId();
if ($subscriberId) {
return $this->subscribersRepository->findOneById($subscriberId);
}
return null;
}
}