Commit 937c2ee0 authored by Vladimir Roudakov's avatar Vladimir Roudakov
Browse files

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

parent 18f6034b
Loading
Loading
Loading
Loading
+369 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\mailchimp_marketing_subscribe_ct\Form;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Config\Config;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\mailchimp_marketing\MailchimpInterface;
use Drupal\node\NodeInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Configure Mailchimp campaign generation.
 */
class NodeTabForm extends FormBase {

  /**
   * The currently authenticated user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;


  /**
   * Mailchimp configuration.
   *
   * @var \Drupal\Core\Config\Config
   */
  protected Config $configMailchimpCt;

  /**
   * The Messenger service.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * The logger service.
   *
   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
   */
  protected $logger;

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

  /**
   * Constructs a new NodeTabForm.
   *
   * @param \Drupal\Core\Session\AccountInterface $current_user
   *   The currently authenticated user.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The factory for configuration objects.
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger.
   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger
   *   The logger service.
   * @param \Drupal\mailchimp_marketing\MailchimpInterface $mailchimp
   *   The mailchimp service.
   */
  public function __construct(AccountInterface $current_user, ConfigFactoryInterface $config_factory, MessengerInterface $messenger, LoggerChannelFactoryInterface $logger, MailchimpInterface $mailchimp) {
    $this->currentUser = $current_user;
    $this->configMailchimpCt = $config_factory->get('mailchimp_marketing_subscribe_ct.settings');
    $this->messenger = $messenger;
    $this->logger = $logger->get('mailchimp_marketing_subscribe_ct');
    $this->mailchimp = $mailchimp;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('current_user'),
      $container->get('config.factory'),
      $container->get('messenger'),
      $container->get('logger.factory'),
      $container->get('mailchimp_marketing.mailchimp')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'mailchimp_marketing_subscribe_ct_node_tab';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, NodeInterface $node = NULL) {
    //$config = $this->config('simplenews.settings');
    $form['#title'] = $this->t('<em>Mailchimp campaign</em> @title', ['@title' => $node->getTitle()]);

    // We will need the node.
    $form_state->set('node', $node);

    // Show newsletter sending options if newsletter has not been send yet.
    // If send a notification is shown.

    $form['test'] = [
      '#type' => 'details',
      '#open' => TRUE,
      '#title' => $this->t('Test'),
    ];

    /*$form['test']['test_address'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Test email addresses'),
      '#description' => $this->t('A comma-separated list of email addresses to be used as test addresses.'),
      '#default_value' => $this->currentUser->getEmail(),
      '#size' => 60,
      '#maxlength' => 128,
    ];*/

    $form['test']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Create test campaign'),
      '#name' => 'send_test',
      '#submit' => ['::submitTestCampaign'],
      //'#validate' => ['::validateTestAddress'],
    ];

    $form['send'] = [
      '#type' => 'details',
      '#open' => TRUE,
      '#title' => $this->t('Send'),
    ];

    if (!$node->isPublished()) {
      $send_text = $this->t('Mails will be sent when the issue is published.');
      $button_text = $this->t('Send on publish');
    }
    else {
      $send_text = $this->t('Campaigns will be sent immediately.');
    }

    $form['send']['method'] = [
      '#type' => 'item',
      '#markup' => $send_text,
    ];

    $form['send']['send'] = [
      '#type' => 'submit',
      '#button_type' => 'primary',
      '#value' => $button_text ?? $this->t('Send now'),
    ];

    return $form;
  }

  /**
   * Validates the test address.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state.
   */
  public function validateTestAddress(array $form, FormStateInterface $form_state) {
    $test_address = $form_state->getValue('test_address');
    $test_address = trim($test_address);
    if (!empty($test_address)) {
      $mails = explode(',', $test_address);
      foreach ($mails as $mail) {
        $mail = trim($mail);
        if (!$this->emailValidator->isValid($mail)) {
          $form_state->setErrorByName('test_address', $this->t('Invalid email address "%mail".', ['%mail' => $mail]));
        }
      }
      $form_state->set('test_addresses', $mails);
    }
    else {
      $form_state->setErrorByName('test_address', $this->t('Missing test email address.'));
    }
  }

  /**
   * Submit handler for sending test mails.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state.
   */
  public function submitTestCampaign(array &$form, FormStateInterface $form_state) {
    $mailchimp = $this->mailchimp->getConnection();

    try {
      // Create campaign.
      $node = $form_state->get('node');
      $request = $this->buildCampaignRequest([], $node);
      $response = $mailchimp->campaigns->create($request);
      $campaignId = $response->id;


      $value = <<< BODY
<table cellpadding="0" cellspacing="0" border="0" width="100%">
    <tbody><tr>
      <td bgcolor="#FAFAFA" style="padding:10px;border:1px solid #CCCCCC;">
        <table cellpadding="0" cellspacing="0" border="0" width="100%" style="color:#333333;"><tbody><tr><td>
          <img alt="Australian Competition and Consumer Commission" src="https://www.accc.gov.au/sites/www.accc.gov.au/themes/accc_accc_responsive/images/top-logo.png" data-inlineimagemanipulating="true" style="width: 400px; max-width: 800px;">
        </td><td align="right">[current-date:custom:'j F Y']</td></tr></tbody></table>
      </td>
    </tr>
    <tr>
      <td style="padding:10px; border-left:1px solid #CCCCCC; border-right:1px solid #CCCCCC;">
        <h2>[node:title]</h2>
        <div>[node:body]</div>
<a href="[node:url]" target="_blank" rel="noreferrer noopener">Read more</a>
<!--      <p class="ydp790b47cyiv6349091600newsletter-footer"><a href="https://www.accc.gov.au/newsletter/confirm/remove/191886f9be65128t325" target="_blank" rel="noreferrer noopener">Unsubscribe from this newsletter</a></p>-->

      </td>
    </tr>
    <tr>
      <td bgcolor="#E1E1E1" style="padding:10px; border:1px solid #CCCCCC;">
<a href="https://www.accc.gov.au/" style="color:#464545;" target="_blank" rel="noreferrer noopener">www.accc.gov.au</a>&nbsp;|&nbsp;<a href="https://www.accc.gov.au/about-us/using-our-website/privacy-policy" style="color:#464545;" target="_blank" rel="noreferrer noopener">Privacy</a>
</td>
    </tr>
  </tbody>
</table>
BODY;

      $body = \Drupal::token()->replace($value, [$node->getEntityType()->id() => $node], ['clear' => TRUE]);

      $mailchimp->campaigns->setContent($campaignId, [
        //'html' => str_replace('[CONTENT]', $campaign['html'], $campaignTemplate),
        'html' => $body,
      ]);
      // Schedule campaign.
      /*if ($this->configAccc->get('campaign_schedule')) {
        $scheduleTime = $this->configAccc->get('campaign_schedule_time');
        $datetime = new \DateTime($scheduleTime);
        $datetime->setTimezone(new \DateTimeZone('UTC'));
        $hours = $datetime->format('H');
        $minutes = (int) $datetime->format('i');
        $minutes = $minutes - ($minutes % 15) + 15;
        $datetime->setTime($hours, $minutes, 0);
        $mailchimp->campaigns->schedule($campaignId, [
          'schedule_time' => $datetime->format('Y-m-d\TH:i:s\Z'),
        ]);
      }
      else {
        $mailchimp->campaigns->send($campaignId);
      }*/

      $message = $this->t('Create campaigns: Campaign id @id for segments @segments was created', [
        '@id' => $campaignId,
        //'@segments' => implode(', ', $campaign['segment_ids']),
      ]);

      $this->logger->notice($message);
    }
    catch (\Exception $error) {
      $campaignError = TRUE;
      $message = $this->t('Create campaign: Failed to create campaign.');
      $this->logger->error($this->t('Error message: @message<br />Details: @details<br /> Campaign details: <br /><pre>@campaign</pre><br /> Request details: <br /><pre>@request</pre>', [
        '@message' => $message,
        '@details' => $error->getMessage(),
        //'@campaign' => print_r($campaign, TRUE),
        '@request' => print_r($request, TRUE),
      ]));
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    //$this->spoolStorage->addIssue($form_state->get('node'));
  }

  /**
   * Creates campaign request structure.
   *
   * @param array $tagIds
   *   List of segments.
   * @param array $interests
   *   List of categories (titles)
   *
   * @return array
   *   Request structure.
   */
  private function buildCampaignRequest(array $tagIds, $node) {
    $segments = [];
    foreach ($tagIds as $tagId) {
      if (isset($tagId)) {
        $segments[] = [
          "condition_type" => "StaticSegment",
          "field" => "static_segment",
          "op" => "static_is",
          "value" => $tagId,
        ];
      }
    }

    /*$interestsSubject = '';
    if (count($interests) > 0) {
      $interestsSubject = '(' . implode(', ', $interests) . ')';
    }*/
    $value = "[node:content-type]: [node:title]";
    $subject = \Drupal::token()->replace($value, [$node->getEntityType()->id() => $node], ['clear' => TRUE]);

    $request = [
      "type" => "regular",
      "recipients" => [
        "list_id" => $this->configMailchimpCt->get('mailchimp_ct_audience_id'),
      ],
      "settings" => [
        "subject_line" => $subject,
        "preview_text" => 'Preview',
        "title" => $subject,
        "from_name" => 'ACCC Media',
        "reply_to" => 'media@accc.gov.au',
        "use_conversation" => FALSE,
        "to_name" => "",
        "folder_id" => "",
        "authenticate" => FALSE,
        "auto_footer" => FALSE,
        "inline_css" => FALSE,
        "auto_tweet" => FALSE,
        "auto_fb_post" => [],
        "fb_comments" => FALSE,
        "template_id" => 0,
      ],
      "content_type" => "template",
    ];

    if (count($segments) > 0) {
      $request['recipients']['segment_opts'] =
        [
          "match" => "any",
          "conditions" => $segments,
        ];
    }

    return $request;
  }

  /**
   * Checks access for the mailchimp node tab.
   *
   * @param \Drupal\node\NodeInterface $node
   *   The node where the tab should be added.
   *
   * @return \Drupal\Core\Access\AccessResult
   *   An access result object.
   */
  public function checkAccess(NodeInterface $node) {
    $mapping = $this->configMailchimpCt->get('mailchimp_ct_mapping');

    return AccessResult::allowedIf(is_array($mapping) &&
      in_array($node->getType(), array_keys($mapping)) &&
      ($this->currentUser()->hasPermission('send mailchimp campaign')));
  }

}