From a7f66d981212692bd5bf6c00dac25b83dbe3f6a2 Mon Sep 17 00:00:00 2001 From: David Remer Date: Fri, 15 Sep 2023 08:51:19 +0300 Subject: [PATCH] Add BuysAProduct trigger backend [MAILPOET-5516] --- .../Triggers/BuysAProductTrigger.php | 154 ++++++++++++++++++ .../WooCommerce/WooCommerceIntegration.php | 7 + mailpoet/lib/DI/ContainerConfigurator.php | 1 + 3 files changed, 162 insertions(+) create mode 100644 mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/BuysAProductTrigger.php diff --git a/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/BuysAProductTrigger.php b/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/BuysAProductTrigger.php new file mode 100644 index 0000000000..de8879425c --- /dev/null +++ b/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/BuysAProductTrigger.php @@ -0,0 +1,154 @@ +wp = $wp; + $this->wc = $wc; + $this->automationRunStorage = $automationRunStorage; + $this->filterHandler = $filterHandler; + } + + public function getKey(): string { + return self::KEY; + } + + public function getName(): string { + return __('Customer buys a product', 'mailpoet'); + } + + public function getArgsSchema(): ObjectSchema { + return Builder::object([ + 'product_ids' => Builder::array( + Builder::integer() + )->minItems(1)->required(), + 'to' => Builder::string()->required()->default('wc-completed'), + ]); + } + + public function getSubjectKeys(): array { + return [ + OrderSubject::KEY, + OrderStatusChangeSubject::KEY, + CustomerSubject::KEY, + ]; + } + + public function validate(StepValidationArgs $args): void { + } + + public function registerHooks(): void { + $this->wp->addAction( + 'woocommerce_order_status_changed', + [ + $this, + 'handle', + ], + 10, + 3 + ); + } + + /** + * @param int $orderId + * @param string $from + * @param string $to + * @return void + */ + public function handle($orderId, $from, $to): void { + $order = $this->wc->wcGetOrder($orderId); + if (!$order) { + return; + } + $this->wp->doAction(Hooks::TRIGGER, $this, [ + new Subject(OrderSubject::KEY, ['order_id' => $orderId]), + new Subject(CustomerSubject::KEY, ['customer_id' => $order->get_customer_id()]), + new Subject(OrderStatusChangeSubject::KEY, ['from' => $from, 'to' => $to]), + ]); + } + + public function isTriggeredBy(StepRunArgs $args): bool { + + //Trigger the run only once. + $orderSubjectData = $args->getSingleSubjectEntryByClass(OrderSubject::class)->getSubjectData(); + if ($this->automationRunStorage->getCountByAutomationAndSubject($args->getAutomation(), $orderSubjectData) > 0) { + return false; + } + $group = new FilterGroup( + '', + FilterGroup::OPERATOR_AND, + $this->getFilters($args) + ); + return $this->filterHandler->matchesGroup($group, $args); + } + + protected function getFilters(StepRunArgs $args): array { + $triggerArgs = $args->getStep()->getArgs(); + $filters = [ + Filter::fromArray([ + 'id' => '', + 'field_type' => Field::TYPE_ENUM_ARRAY, + 'field_key' => 'woocommerce:order:products', + 'condition' => EnumArrayFilter::CONDITION_MATCHES_ANY_OF, + 'args' => [ + 'value' => $triggerArgs['product_ids'] ?? [], + ], + ]), + ]; + $status = str_replace('wc-', '', $triggerArgs['to'] ?? 'completed'); + if ($status === 'any') { + return $filters; + } + + $filters[] = Filter::fromArray([ + 'id' => '', + 'field_type' => Field::TYPE_ENUM, + 'field_key' => 'woocommerce:order:status', + 'condition' => EnumFilter::IS_ANY_OF, + 'args' => [ + 'value' => [$status], + ], + ]); + return $filters; + } +} diff --git a/mailpoet/lib/Automation/Integrations/WooCommerce/WooCommerceIntegration.php b/mailpoet/lib/Automation/Integrations/WooCommerce/WooCommerceIntegration.php index 5fb704cc94..17100f21ba 100644 --- a/mailpoet/lib/Automation/Integrations/WooCommerce/WooCommerceIntegration.php +++ b/mailpoet/lib/Automation/Integrations/WooCommerce/WooCommerceIntegration.php @@ -9,6 +9,7 @@ use MailPoet\Automation\Integrations\WooCommerce\Subjects\OrderStatusChangeSubje use MailPoet\Automation\Integrations\WooCommerce\Subjects\OrderSubject; use MailPoet\Automation\Integrations\WooCommerce\SubjectTransformers\WordPressUserSubjectToWooCommerceCustomerSubjectTransformer; use MailPoet\Automation\Integrations\WooCommerce\Triggers\AbandonedCart\AbandonedCartTrigger; +use MailPoet\Automation\Integrations\WooCommerce\Triggers\BuysAProductTrigger; use MailPoet\Automation\Integrations\WooCommerce\Triggers\OrderStatusChangedTrigger; class WooCommerceIntegration { @@ -19,6 +20,9 @@ class WooCommerceIntegration { /** @var AbandonedCartTrigger */ private $abandonedCartTrigger; + /** @var BuysAProductTrigger */ + private $buysAProductTrigger; + /** @var AbandonedCartSubject */ private $abandonedCartSubject; @@ -43,6 +47,7 @@ class WooCommerceIntegration { public function __construct( OrderStatusChangedTrigger $orderStatusChangedTrigger, AbandonedCartTrigger $abandonedCartTrigger, + BuysAProductTrigger $buysAProductTrigger, AbandonedCartSubject $abandonedCartSubject, OrderStatusChangeSubject $orderStatusChangeSubject, OrderSubject $orderSubject, @@ -53,6 +58,7 @@ class WooCommerceIntegration { ) { $this->orderStatusChangedTrigger = $orderStatusChangedTrigger; $this->abandonedCartTrigger = $abandonedCartTrigger; + $this->buysAProductTrigger = $buysAProductTrigger; $this->abandonedCartSubject = $abandonedCartSubject; $this->orderStatusChangeSubject = $orderStatusChangeSubject; $this->orderSubject = $orderSubject; @@ -77,6 +83,7 @@ class WooCommerceIntegration { $registry->addSubject($this->customerSubject); $registry->addTrigger($this->orderStatusChangedTrigger); $registry->addTrigger($this->abandonedCartTrigger); + $registry->addTrigger($this->buysAProductTrigger); $registry->addSubjectTransformer($this->wordPressUserToWooCommerceCustomerTransformer); } } diff --git a/mailpoet/lib/DI/ContainerConfigurator.php b/mailpoet/lib/DI/ContainerConfigurator.php index 35e43bf6e7..84de88bc4b 100644 --- a/mailpoet/lib/DI/ContainerConfigurator.php +++ b/mailpoet/lib/DI/ContainerConfigurator.php @@ -197,6 +197,7 @@ class ContainerConfigurator implements IContainerConfigurator { $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Fields\TermOptionsBuilder::class)->setPublic(true); $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Fields\TermParentsLoader::class)->setPublic(true); $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Triggers\OrderStatusChangedTrigger::class)->setPublic(true)->setShared(false); + $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Triggers\BuysAProductTrigger::class)->setPublic(true)->setShared(false); $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Subjects\OrderSubject::class)->setPublic(true)->setShared(false); $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Subjects\OrderStatusChangeSubject::class)->setPublic(true)->setShared(false); $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Subjects\CustomerSubject::class)->setPublic(true)->setShared(false);