contacts_events-8.x-1.x-dev/src/ManualPaymentNotifications.php
src/ManualPaymentNotifications.php
<?php namespace Drupal\contacts_events; use Drupal\commerce_payment\Entity\PaymentGatewayInterface; use Drupal\commerce_payment\Entity\PaymentInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Language\LanguageDefault; use Drupal\Core\Mail\MailManagerInterface; use Drupal\Core\Render\ElementInfoManagerInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Utility\Token; /** * Service for sending manual payment notifications. */ class ManualPaymentNotifications { use StringTranslationTrait; /** * The mail key. */ const MAIL_KEY = 'pending_payment_notification'; /** * The third party settings key. */ const SETTINGS_KEY = 'pending_payment_notification'; /** * Mail manager service. * * @var \Drupal\Core\Mail\MailManagerInterface */ protected $mailManager; /** * The default language. * * @var \Drupal\Core\Language\LanguageDefault */ protected $defaultLanguage; /** * The element info manager. * * @var \Drupal\Core\Render\ElementInfoManagerInterface */ protected $elementInfo; /** * The token service, if available. * * @var \Drupal\Core\Utility\Token|null */ protected $token; /** * Constructs a ManualPaymentNotifications object. * * @param \Drupal\Core\Mail\MailManagerInterface $mail_manager * Mail manager service. * @param \Drupal\Core\Language\LanguageDefault $default_language * The default language. * @param \Drupal\Core\Render\ElementInfoManagerInterface $element_info * The element info manager. * @param \Drupal\Core\Utility\Token $token * The token service. */ public function __construct(MailManagerInterface $mail_manager, LanguageDefault $default_language, ElementInfoManagerInterface $element_info, Token $token = NULL) { $this->mailManager = $mail_manager; $this->defaultLanguage = $default_language; $this->elementInfo = $element_info; $this->token = $token; } /** * Send a notification of a manual payment, if required. * * @param \Drupal\commerce_payment\Entity\PaymentInterface $payment * The payment to notify. */ public function onInsert(PaymentInterface $payment): void { // We only support notifications for manual payments and we only want to // send on insert. if ($payment->getPaymentGateway()->getPluginId() != 'manual' || $payment->getState()->value != 'pending') { return; } // Skip sending if the remote state is not empty or it has a remote ID. if ($payment->getRemoteId() || $payment->getRemoteState()) { return; } // Check whether we have notifications enabled for this gateway. $gateway = $payment->getPaymentGateway(); $notification = $gateway->getThirdPartySetting('contacts_events', self::SETTINGS_KEY, []); if (empty($notification['enabled'])) { return; } // Build the params. $params['subject'] = $notification['subject']; $params['body'] = $notification['body']; $params['payment'] = $payment; // Send the email - errors are logged by the mail manager. $this->mailManager->mail( 'contacts_events', self::MAIL_KEY, $notification['to'], $this->defaultLanguage->get()->getId(), $params); } /** * Build the notification email. * * @param array $message * The message. * @param array $params * The params. * * @see \hook_mail() */ public function buildMail(array &$message, array $params) { $subject = $params['subject']; $body = $params['body']; // If we have the token service, perform the replacements. if ($this->token) { /** @var \Drupal\commerce_payment\Entity\PaymentInterface $payment */ $payment = $params['payment']; $order = $payment->getOrder(); $tokens = [ 'commerce_payment' => $payment, 'commerce_order' => $order, 'user' => $order->getCustomer(), ]; $subject = $this->token->replace($subject, $tokens); if (is_array($body)) { $body['value'] = $this->token->replace($body['value'], $tokens); } else { $body = $this->token->replace($body, $tokens); } } if (is_array($body)) { $renderable = [ '#type' => 'processed_text', '#format' => $body['format'], '#text' => $body['value'], ]; $body = \Drupal::service('renderer')->renderPlain($renderable); // Indicate the email is in HTML. $message['headers']['Content-Type'] = 'text/html; charset=UTF-8'; } $message['subject'] = $subject; $message['body'][] = $body; } /** * Form alter for the payment gateway form. * * @param array $form * The form array. * @param \Drupal\Core\Form\FormStateInterface $form_state * The form state. * * @see \contacts_events_form_commerce_payment_gateway_form_alter() */ public function gatewayFormAlter(array &$form, FormStateInterface $form_state) { /** @var \Drupal\Core\Entity\ContentEntityFormInterface $form_object */ $form_object = $form_state->getFormObject(); // Don't modify the delete operation. if ($form_object->getOperation() == 'delete') { return; } /** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface $gateway */ $gateway = $form_object->getEntity(); // Only modify manual gateways. $gateway_plugin = $form_state->getUserInput()['plugin'] ?? $gateway->getPluginId(); if ($gateway_plugin != 'manual') { return; } $settings = $gateway->getThirdPartySetting('contacts_events', self::SETTINGS_KEY, []); $form[self::SETTINGS_KEY] = [ '#type' => 'details', '#title' => $this->t('Notification of new payments'), '#open' => $gateway->isNew(), ]; $form[self::SETTINGS_KEY]['enabled'] = [ '#type' => 'checkbox', '#title' => $this->t('Enable notification of new payments using this gateway'), '#default_value' => $settings['enabled'] ?? FALSE, ]; $form[self::SETTINGS_KEY]['to'] = [ '#type' => 'textfield', '#title' => $this->t('Who should notifications be sent to?'), '#default_value' => $settings['to'] ?? '', '#description' => $this->t('A comma separated list of email addresses to notify.'), '#states' => [ 'required' => [ ':input[name="' . self::SETTINGS_KEY . '[enabled]"]' => ['checked' => TRUE], ], ], ]; $form[self::SETTINGS_KEY]['subject'] = [ '#type' => 'textfield', '#title' => $this->t('Email subject'), '#default_value' => $settings['subject'] ?? '', '#states' => [ 'required' => [ ':input[name="' . self::SETTINGS_KEY . '[enabled]"]' => ['checked' => TRUE], ], ], ]; $form[self::SETTINGS_KEY]['body'] = [ '#type' => 'textarea', '#title' => $this->t('Email text'), '#default_value' => isset($settings['body']) && is_array($settings['body']) ? $settings['body']['value'] : $settings['body'] ?? '', '#states' => [ 'required' => [ ':input[name="' . self::SETTINGS_KEY . '[enabled]"]' => ['checked' => TRUE], ], ], ]; if ($this->elementInfo->hasDefinition('text_format')) { $form[self::SETTINGS_KEY]['body']['#type'] = 'text_format'; $form[self::SETTINGS_KEY]['body']['#format'] = $settings['body']['format']; } if ($this->elementInfo->hasDefinition('token_tree_table')) { $form[self::SETTINGS_KEY]['tokens'] = [ '#theme' => 'token_tree_link', '#token_types' => [ 'commerce_payment', 'commerce_order', ], ]; } // Add our entity builder. $form['#validate'][] = [static::class, 'gatewayFormValidate']; $form['#entity_builders'][] = [static::class, 'gatewayFormBuildEntity']; } /** * Form validation callback for the gateway form. * * @param array $form * The form array. * @param \Drupal\Core\Form\FormStateInterface $form_state * The form state. * * @see \Drupal\contacts_events\ManualPaymentNotifications::gatewayFormAlter() */ public static function gatewayFormValidate(array $form, FormStateInterface $form_state) { $values = $form_state->getValue(self::SETTINGS_KEY); if (empty($values['enabled'])) { return; } if (empty($values['to'])) { $form_state->setError($form[self::SETTINGS_KEY]['to'], new TranslatableMarkup('A recipient is required to enable notifications.')); } if (empty($values['subject'])) { $form_state->setError($form[self::SETTINGS_KEY]['subject'], new TranslatableMarkup('Email subject is required to enable notifications.')); } $body = $form[self::SETTINGS_KEY]['body']['#type'] == 'text_format' ? $values['body']['value'] : $values['body']; if (empty($body)) { $form_state->setError($form[self::SETTINGS_KEY]['body'], new TranslatableMarkup('Email text is required to enable notifications.')); } } /** * Entity builder for the gateway form. * * @param string $entity_type_id * The entity type ID. * @param \Drupal\commerce_payment\Entity\PaymentGatewayInterface $entity * The gateway entity. * @param array $form * The form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The form state. */ public static function gatewayFormBuildEntity(string $entity_type_id, PaymentGatewayInterface $entity, array $form, FormStateInterface $form_state) { $entity->setThirdPartySetting('contacts_events', self::SETTINGS_KEY, $form_state->getValue(self::SETTINGS_KEY)); } }