Commit 18f6034b authored by Vladimir Roudakov's avatar Vladimir Roudakov Committed by Vladimir Roudakov
Browse files

Issue #3255184 by VladimirAus: Subscribe to content type: send a campaign via node advanced group

parent 5ee6b7c9
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
<?php

/**
 * @file
 * Install, update and uninstall functions for the Mailchimp marketing content type subscription.
 */

/**
 * Implements hook_uninstall().
 */
function mailchimp_marketing_subscribe_ct_uninstall() {
  \Drupal::configFactory()->getEditable('mailchimp_marketing_subscribe_ct.settings')->delete();
  \Drupal::messenger()->addMessage(t("Mailchimp marketing content type subscription module has been uninstalled successfully."));
}
+288 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\mailchimp_marketing_subscribe_ct\Plugin\WebformHandler;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Http\RequestStack;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Serialization\Yaml;
use Drupal\mailchimp_marketing\MailchimpInterface;
use Drupal\webform\Plugin\WebformHandlerBase;
use Drupal\webform\Utility\WebformElementHelper;
use Drupal\webform\WebformSubmissionInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Webform submission for mailchimp newsletter subscription.
 *
 * @WebformHandler(
 *   id = "mailchimp_ct_subscription",
 *   label = @Translation("Mailchimp content type subscription handler"),
 *   category = @Translation("Integration"),
 *   description = @Translation("Mailchimp content type subscription handler."),
 *   cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_SINGLE,
 *   results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
 *   submission = \Drupal\webform\Plugin\WebformHandlerInterface::SUBMISSION_OPTIONAL,
 * )
 */
class MailchimpCtSubscriptionHandler extends WebformHandlerBase {

  /**
   * The term storage.
   *
   * @var \Drupal\taxonomy\TermStorageInterface
   */
  protected $termStorage;

  /**
   * The request stack.
   *
   * @var \Drupal\Core\Http\RequestStack
   */
  protected RequestStack $requestStack;

  /**
   * The Mailchimp controller.
   *
   * @var \Drupal\mailchimp_marketing\MailchimpInterface
   */
  protected $mailchimp;

  /**
   * Constructs a MailchimpMarketingWebformHandler object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory service.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager service.
   * @param \Drupal\Core\Render\RendererInterface $renderer
   *   The renderer service.
   * @param \Drupal\Core\Http\RequestStack $request_stack
   *   The request stack.
   * @param \Drupal\mailchimp_marketing\MailchimpInterface $mailchimp_controller
   *   The Mailchimp controller.q
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition,
    ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager,
    RendererInterface $renderer, RequestStack $request_stack, MailchimpInterface $mailchimp_controller
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->renderer = $renderer;
    $this->configFactory = $config_factory;
    $this->termStorage = $entity_type_manager->getStorage('taxonomy_term');
    $this->requestStack = $request_stack;
    $this->mailchimp = $mailchimp_controller;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $instance = new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('config.factory'),
      $container->get('entity_type.manager'),
      $container->get('renderer'),
      $container->get('request_stack'),
      $container->get('mailchimp_marketing.mailchimp')
    );

    $instance->setConfiguration($configuration);
    $instance->termStorage = $container->get('entity_type.manager')->getStorage('taxonomy_term');

    return $instance;

  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'submission' => FALSE,
      'field_mailchimp_group' => '',
      'field_mailchimp_tags' => '',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getSummary() {
    return [
      '#markup' => Yaml::encode($this->configuration),
      '#prefix' => '<pre>',
      '#suffix' => '<pre>',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildConfigurationForm($form, $form_state);

    $form['field_mailchimp_group'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Groups field'),
      '#description' => $this->t('Webform field to provide content type to Mailchimp group item.'),
      '#default_value' => $this->configuration['field_mailchimp_group'],
    ];

    $form['field_mailchimp_tags'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Tags field'),
      '#description' => $this->t('Webform field to provide tags to Mailchimp.'),
      '#default_value' => $this->configuration['field_mailchimp_tags'],
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    parent::submitConfigurationForm($form, $form_state);
    $this->applyFormStateToConfiguration($form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function alterForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
    $unique_email_id = $this->requestStack->getCurrentRequest()->query->get('subscriber');
    $mailchimp_config = $this->configFactory->get('mailchimp_marketing_subscribe_ct.settings');
    dump($unique_email_id);
    if (empty($unique_email_id)) {
      return;
    }

    // Check connection to mailchimp.
    $is_ping_success = $this->mailchimp->pingSuccess();
    if (!$is_ping_success) {
      $form_state->setErrorByName('email', $this->t('Unable to connect to email service. Please, try again later.'));
      return;
    }

    // Get member by unique email id and pre-populate fields.
    $member = $this->mailchimp->getMemberByUniqueId($unique_email_id, $mailchimp_config->get('mailchimp_ct_audience_id'));
    dump($member);
    if ($member) {
      // Set user's email.
      $form['elements']['email']['#default_value'] = preg_replace("/(?!^).(?=[^@]+@)/", "*", $member->email_address);
      $form['elements']['email']['#attributes'] = ['readonly' => 'readonly'];
      $form['elements']['unique_email_id']['#default_value'] = $unique_email_id;

      // Set tags.
      $tag_field = $this->configuration['field_mailchimp_tags'];
      if (!empty($tag_field) && isset($form['elements'][$tag_field])) {
        $tags = $member->tags;
        foreach ($tags as $tag) {
          $tag_name = $tag->name;
          $form['elements'][$tag_field]['#default_value'][] = $tag_name;
        }
      }

      // @todo: Set group items.
    }
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
    // Check connection to mailchimp.
    $mailchimp_controller = $this->mailchimp;
    $mailchimp_config = $this->configFactory->get('mailchimp_marketing_subscribe_ct.settings');
    $is_ping_success = $mailchimp_controller->pingSuccess();
    if (!$is_ping_success) {
      $form_state->setErrorByName('email', $this->t('Unable to connect to email service. Please, try again later.'));
      return;
    }

    $configuration = $this->getConfiguration();
    $settings = $configuration['settings'];
    $data = ($settings['submission'])
      ? $webform_submission->toArray(TRUE)
      : $webform_submission->getData();
    WebformElementHelper::convertRenderMarkupToStrings($data);
    $email = $data['email'];
    $unique_email_id = $data['unique_email_id'];

    if (!empty($unique_email_id)) {
      $member = $mailchimp_controller->getMemberByUniqueId($unique_email_id);
      if ($member) {
        $email = $member->email_address;
      }
      else {
        $form_state->setErrorByName('email', $this->t('Unable to retrieve subscriber details. Please, try again later.'));
        return;
      }
    }

    // Check email is valid - according to mailchimp format.
    $is_valid_email = preg_match('/.+@.+\.+/', $email);
    if ($is_valid_email === 0 || $is_valid_email === FALSE) {
      $form_state->setErrorByName('email', $this->t('The domain portion of the email address is invalid.'));
      return;
    }

    $tag_field = $this->configuration['field_mailchimp_tags'];
    $group_field = $this->configuration['field_mailchimp_group'];
    $mailchimp_tags = [];
    $interests = [];

    if (!empty($tag_field) && ($tag_value = $form_state->getValue($tag_field))) {
      foreach ($tag_value as $value) {
        $mailchimp_tags[$value] = $value;
      }
    }
    if (!empty($group_field) && ($group_value = $form_state->getValue($group_field))) {
      foreach ($group_value as $value) {
        $interests[$value] = $value;
      }
    }

    // Convert interests to configuration.
    $options = [
      "tags" => $mailchimp_tags,
      "interests" => $interests,
    ];

    // @todo: check that default audience (list) is set.
    $member = $mailchimp_controller->addMember(
      $email,
      $mailchimp_config->get('mailchimp_ct_audience_id'),
      $options,
      'pending');

    // @todo: convert statuses to constants.
    if (!$member) {
      // Check if user could not subscribe because they have unsubscribed or their subscription is pending.
      $member = $mailchimp_controller->getMember($email, NULL);
      if ($member && ($member->status == 'unsubscribed' || $member->status == 'pending')) {
        $form_state->setValue('member_status', $member->status);
      }
      else {
        $form_state->setErrorByName('email', $this->t('Unable to complete the operation. Please, try again later.'));
      }
    }
    elseif ($member->status == 'subscribed') {
      // Check if user has already subscribed and they have updated their subscription.
      $form_state->setValue('member_status', $member->status);
      // Redirect edit form.
    }
  }

}