diff --git a/lib/Config/Hooks.php b/lib/Config/Hooks.php index 2d0c1b4cb3..7777152eb9 100644 --- a/lib/Config/Hooks.php +++ b/lib/Config/Hooks.php @@ -3,6 +3,7 @@ namespace MailPoet\Config; use MailPoet\Settings\SettingsController; +use MailPoet\Statistics\Track\WooCommerceOrders; use MailPoet\Subscription\Comment; use MailPoet\Subscription\Form; use MailPoet\Subscription\Registration; @@ -29,13 +30,17 @@ class Hooks { /** @var WooCommerceSegment */ private $woocommerce_segment; + /** @var WooCommerceOrders */ + private $woocommerce_orders; + function __construct( Form $subscription_form, Comment $subscription_comment, Registration $subscription_registration, SettingsController $settings, WPFunctions $wp, - WooCommerceSegment $woocommerce_segment + WooCommerceSegment $woocommerce_segment, + WooCommerceOrders $woocommerce_orders ) { $this->subscription_form = $subscription_form; $this->subscription_comment = $subscription_comment; @@ -43,11 +48,13 @@ class Hooks { $this->settings = $settings; $this->wp = $wp; $this->woocommerce_segment = $woocommerce_segment; + $this->woocommerce_orders = $woocommerce_orders; } function init() { $this->setupWPUsers(); $this->setupWooCommerceUsers(); + $this->setupWooCommerceOrders(); $this->setupImageSize(); $this->setupListing(); $this->setupSubscriptionEvents(); @@ -206,6 +213,14 @@ class Hooks { ); } + + function setupWooCommerceOrders() { + $this->wp->addAction( + 'woocommerce_payment_complete', + [$this->woocommerce_orders, 'trackPaidOrder'] + ); + } + function setupImageSize() { $this->wp->addFilter( 'image_size_names_choose', diff --git a/lib/DI/ContainerConfigurator.php b/lib/DI/ContainerConfigurator.php index 977a04521f..d2b5c09815 100644 --- a/lib/DI/ContainerConfigurator.php +++ b/lib/DI/ContainerConfigurator.php @@ -82,6 +82,7 @@ class ContainerConfigurator implements IContainerConfigurator { $container->autowire(\MailPoet\Router\Endpoints\Track::class)->setPublic(true); $container->autowire(\MailPoet\Statistics\Track\Clicks::class); $container->autowire(\MailPoet\Statistics\Track\Opens::class); + $container->autowire(\MailPoet\Statistics\Track\WooCommerceOrders::class)->setPublic(true); $container->autowire(\MailPoet\Router\Router::class) ->setArgument('$container', new Reference(ContainerWrapper::class)); // Mailer diff --git a/lib/Models/StatisticsClicks.php b/lib/Models/StatisticsClicks.php index 7b3c87016e..29d489dad6 100644 --- a/lib/Models/StatisticsClicks.php +++ b/lib/Models/StatisticsClicks.php @@ -1,6 +1,8 @@ where('clicks.subscriber_id', $subscriber->id()) ->orderByAsc('url'); } + + static function findLatestPerNewsletterBySubscriber(Subscriber $subscriber, DateTime $before, $since_days_ago) { + // subquery to find latest click IDs for each newsletter + $table = self::$_table; + $latest_click_ids_per_newsletter_query = " + SELECT ( + SELECT id + FROM $table + WHERE newsletter_id = c.newsletter_id + ORDER BY updated_at DESC + LIMIT 1 + ) + FROM $table c + WHERE c.subscriber_id = :subscriber_id + AND c.updated_at < :before + AND c.updated_at > DATE_SUB(NOW(), INTERVAL :since_days_ago DAY) + GROUP BY c.newsletter_id + "; + + return static::tableAlias('clicks') + ->whereRaw("clicks.id IN ($latest_click_ids_per_newsletter_query)", [ + 'subscriber_id' => $subscriber->id, + 'before' => $before->format('Y-m-d H:i:s'), + 'since_days_ago' => $since_days_ago, + ]) + ->findMany(); + } } diff --git a/lib/Models/StatisticsWooCommerceOrders.php b/lib/Models/StatisticsWooCommerceOrders.php new file mode 100644 index 0000000000..00204d8e3e --- /dev/null +++ b/lib/Models/StatisticsWooCommerceOrders.php @@ -0,0 +1,38 @@ +id) + ->where('order_id', $order->get_id()) + ->findOne(); + + if (!$statistics) { + $statistics = self::create(); + $statistics->newsletter_id = $click->newsletter_id; + $statistics->subscriber_id = $click->subscriber_id; + $statistics->queue_id = $click->queue_id; + $statistics->click_id = $click->id; + $statistics->order_id = $order->get_id(); + } + + $statistics->order_currency = $order->get_currency(); + $statistics->order_price_total = (float)$order->get_total(); + return $statistics->save(); + } +} diff --git a/lib/Statistics/Track/WooCommerceOrders.php b/lib/Statistics/Track/WooCommerceOrders.php new file mode 100644 index 0000000000..255994a723 --- /dev/null +++ b/lib/Statistics/Track/WooCommerceOrders.php @@ -0,0 +1,43 @@ +woocommerce_helper = $woocommerce_helper; + } + + function trackPaidOrder($id) { + $order = $this->woocommerce_helper->wcGetOrder($id); + if (!$order instanceof WC_Order || floatval($order->get_total()) <= 0) { + return; + } + + $subscriber = Subscriber::findOne($order->get_billing_email()); + if (!$subscriber instanceof Subscriber) { + return; + } + + $clicks = StatisticsClicks::findLatestPerNewsletterBySubscriber( + $subscriber, + $order->get_date_created(), + self::USE_CLICKS_SINCE_DAYS_AGO + ); + + foreach ($clicks as $click) { + StatisticsWooCommerceOrders::createOrUpdateByClickAndOrder($click, $order); + } + } +}