diff --git a/mailpoet/lib/API/JSON/v1/Settings.php b/mailpoet/lib/API/JSON/v1/Settings.php index c2cd83a613..50776102f0 100644 --- a/mailpoet/lib/API/JSON/v1/Settings.php +++ b/mailpoet/lib/API/JSON/v1/Settings.php @@ -4,7 +4,9 @@ namespace MailPoet\API\JSON\v1; use MailPoet\API\JSON\Endpoint as APIEndpoint; use MailPoet\API\JSON\Error as APIError; +use MailPoet\API\JSON\ErrorResponse; use MailPoet\API\JSON\Response; +use MailPoet\API\JSON\SuccessResponse; use MailPoet\Config\AccessControl; use MailPoet\Config\ServicesChecker; use MailPoet\Cron\Workers\SubscribersEngagementScore; @@ -493,4 +495,24 @@ class Settings extends APIEndpoint { 'action' => 'reactivate', ]; } + + /** + * Prepares the settings to set up MSS with the given key and calls the set method. + * + * @param string $apiKey + * @return ErrorResponse|SuccessResponse + */ + public function setupMSS(string $apiKey) { + $new_settings = [ + 'mta_group' => 'mailpoet', + 'mta' => [ + 'method' => 'MailPoet', + 'mailpoet_api_key' => $apiKey, + ], + 'signup_confirmation' => [ + 'enabled' => '1', + ], + ]; + return $this->set($new_settings); + } } diff --git a/mailpoet/lib/Config/Hooks.php b/mailpoet/lib/Config/Hooks.php index bb79d48872..f7003a062c 100644 --- a/mailpoet/lib/Config/Hooks.php +++ b/mailpoet/lib/Config/Hooks.php @@ -13,6 +13,7 @@ use MailPoet\Subscription\Form; use MailPoet\Subscription\Manage; use MailPoet\Subscription\Registration; use MailPoet\WP\Functions as WPFunctions; +use MailPoet\WPCOM\DotcomLicenseProvisioner; class Hooks { /** @var Form */ @@ -54,6 +55,9 @@ class Hooks { /** @var SubscriberChangesNotifier */ private $subscriberChangesNotifier; + /** @var DotcomLicenseProvisioner */ + private $dotcomLicenseProvisioner; + public function __construct( Form $subscriptionForm, Comment $subscriptionComment, @@ -67,7 +71,8 @@ class Hooks { HooksWooCommerce $hooksWooCommerce, SubscriberHandler $subscriberHandler, SubscriberChangesNotifier $subscriberChangesNotifier, - WP $wpSegment + WP $wpSegment, + DotcomLicenseProvisioner $dotcomLicenseProvisioner ) { $this->subscriptionForm = $subscriptionForm; $this->subscriptionComment = $subscriptionComment; @@ -82,6 +87,7 @@ class Hooks { $this->subscriberHandler = $subscriberHandler; $this->hooksWooCommerce = $hooksWooCommerce; $this->subscriberChangesNotifier = $subscriberChangesNotifier; + $this->dotcomLicenseProvisioner = $dotcomLicenseProvisioner; } public function init() { @@ -99,6 +105,7 @@ class Hooks { $this->setupFooter(); $this->setupSettingsLinkInPluginPage(); $this->setupChangeNotifications(); + $this->setupLicenseProvisioning(); } public function initEarlyHooks() { @@ -475,4 +482,13 @@ class Hooks { [$this->subscriberChangesNotifier, 'notify'] ); } + + public function setupLicenseProvisioning(): void { + $this->wp->addFilter( + 'wpcom_marketplace_webhook_response_mailpoet-business', + [$this->dotcomLicenseProvisioner, 'provisionLicense'], + 10, + 3 + ); + } } diff --git a/mailpoet/lib/DI/ContainerConfigurator.php b/mailpoet/lib/DI/ContainerConfigurator.php index 101db072f8..fe2407bfbc 100644 --- a/mailpoet/lib/DI/ContainerConfigurator.php +++ b/mailpoet/lib/DI/ContainerConfigurator.php @@ -537,6 +537,8 @@ class ContainerConfigurator implements IContainerConfigurator { $container->autowire(\MailPoet\WP\Emoji::class)->setPublic(true); $container->autowire(\MailPoet\WP\Functions::class)->setPublic(true); $container->autowire(\MailPoet\WP\AutocompletePostListLoader::class)->setPublic(true); + // WordPress.com + $container->autowire(\MailPoet\WPCOM\DotcomLicenseProvisioner::class)->setPublic(true); // Third party classes $container->autowire(\MailPoetVendor\CSS::class)->setClass(\MailPoetVendor\CSS::class)->setPublic(true); $container->autowire(\MailPoetVendor\csstidy::class)->setClass(\MailPoetVendor\csstidy::class); diff --git a/mailpoet/lib/Logging/LoggerFactory.php b/mailpoet/lib/Logging/LoggerFactory.php index 49db366de1..45a6853368 100644 --- a/mailpoet/lib/Logging/LoggerFactory.php +++ b/mailpoet/lib/Logging/LoggerFactory.php @@ -35,6 +35,7 @@ class LoggerFactory { const TOPIC_API = 'api'; const TOPIC_TRACKING = 'tracking'; const TOPIC_COUPONS = 'coupons'; + const TOPIC_PROVISIONING = 'provisioning'; /** @var LoggerFactory */ private static $instance; diff --git a/mailpoet/lib/WPCOM/DotcomLicenseProvisioner.php b/mailpoet/lib/WPCOM/DotcomLicenseProvisioner.php new file mode 100644 index 0000000000..3e78cf2946 --- /dev/null +++ b/mailpoet/lib/WPCOM/DotcomLicenseProvisioner.php @@ -0,0 +1,126 @@ +loggerFactory = $loggerFactory; + $this->settings = $settings; + $this->services = $services; + } + + /** + * Returns true if in the context of WordPress.com Atomic platform. + * + * @return bool + */ + private function isAtomicPlatform(): bool { + return defined('IS_ATOMIC') && IS_ATOMIC && defined('ATOMIC_CLIENT_ID') && (ATOMIC_CLIENT_ID === '2'); + } + + /** + * Activates MSS and adds API key for subscriptions purchased from WP.com Marketplace. + * + * @param bool $result + * @param array $licensePayload + * @param string $eventType + * @return bool|WP_Error + */ + public function provisionLicense(bool $result, array $licensePayload, string $eventType) { + if (!$this->isAtomicPlatform() || $eventType !== self::EVENT_TYPE_PROVISION_LICENSE) { + return $result; + } + + $apiKey = $this->getKeyFromPayload($licensePayload); + if (is_wp_error($apiKey)) { + $this->loggerFactory->getLogger(LoggerFactory::TOPIC_PROVISIONING)->error( + 'key was not found in license payload'); + return $apiKey; + } + + return $this->activateMSS($apiKey); + } + + /** + * Returns API key from license payload. + * @param array $licensePayload + * @return string|WP_Error + */ + private function getKeyFromPayload(array $licensePayload) { + if (isset($licensePayload['apiKey']) && is_string($licensePayload['apiKey'])) { + return $licensePayload['apiKey']; + } + + return new WP_Error('invalid_license_payload', 'Invalid license payload: Missing API key.'); + } + + /** + * Saves the API key and activates MSS. + * @param string $apiKey + * @return true|WP_Error + */ + private function activateMSS(string $apiKey) { + $response = $this->settings->setupMSS($apiKey); + if ($response instanceof ErrorResponse) { + $this->loggerFactory->getLogger(LoggerFactory::TOPIC_PROVISIONING)->error( + 'Setting sending method and key failed', + ['$response' => $response] + ); + return new WP_Error('Provisioning failed setting the data', $this->concatMessages($response)); + } + + // This is necessary if the key changed but the sending method was already set to MailPoet + $response = $this->services->refreshMSSKeyStatus(); + if ($response instanceof ErrorResponse) { + $this->loggerFactory->getLogger(LoggerFactory::TOPIC_PROVISIONING)->error( + 'Refreshing the key failed', + ['$response' => $response] + ); + return new WP_Error('Provisioning failed activating the data', $this->concatMessages($response)); + } + + + $this->loggerFactory->getLogger(LoggerFactory::TOPIC_PROVISIONING)->info( + 'License was provisioned' + ); + return true; + } + + private function concatMessages(ErrorResponse $response): string { + $data = $response->getData(); + $result = ''; + + if (empty($data) || !isset($data['errors'])) { + return $result; + } + + foreach ($data['errors'] as $error) { + $result .= $error['message'] . " "; + } + return $result; + } +}