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));
}
}
