Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / action / src / Plugin / Action / EmailAction.php
1 <?php
2
3 namespace Drupal\action\Plugin\Action;
4
5 use Drupal\Component\Render\PlainTextOutput;
6 use Drupal\Core\Access\AccessResult;
7 use Drupal\Core\Action\ConfigurableActionBase;
8 use Drupal\Core\Entity\EntityManagerInterface;
9 use Drupal\Core\Form\FormStateInterface;
10 use Drupal\Core\Language\LanguageManagerInterface;
11 use Drupal\Core\Mail\MailManagerInterface;
12 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
13 use Drupal\Core\Session\AccountInterface;
14 use Drupal\Core\Utility\Token;
15 use Psr\Log\LoggerInterface;
16 use Egulias\EmailValidator\EmailValidator;
17 use Symfony\Component\DependencyInjection\ContainerInterface;
18
19 /**
20  * Sends an email message.
21  *
22  * @Action(
23  *   id = "action_send_email_action",
24  *   label = @Translation("Send email"),
25  *   type = "system"
26  * )
27  */
28 class EmailAction extends ConfigurableActionBase implements ContainerFactoryPluginInterface {
29
30   /**
31    * The token service.
32    *
33    * @var \Drupal\Core\Utility\Token
34    */
35   protected $token;
36
37   /**
38    * The user storage.
39    *
40    * @var \Drupal\Core\Entity\EntityStorageInterface
41    */
42   protected $storage;
43
44   /**
45    * A logger instance.
46    *
47    * @var \Psr\Log\LoggerInterface
48    */
49   protected $logger;
50
51   /**
52    * The mail manager
53    *
54    * @var \Drupal\Core\Mail\MailManagerInterface
55    */
56   protected $mailManager;
57
58   /**
59    * The language manager.
60    *
61    * @var \Drupal\Core\Language\LanguageManagerInterface
62    */
63   protected $languageManager;
64
65   /**
66    * The email validator.
67    *
68    * @var \Egulias\EmailValidator\EmailValidator
69    */
70   protected $emailValidator;
71
72   /**
73    * Constructs a EmailAction object.
74    *
75    * @param array $configuration
76    *   A configuration array containing information about the plugin instance.
77    * @param string $plugin_id
78    *   The plugin ID for the plugin instance.
79    * @param mixed $plugin_definition
80    *   The plugin implementation definition.
81    * @param \Drupal\Core\Utility\Token $token
82    *   The token service.
83    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
84    *   The entity manager.
85    * @param \Psr\Log\LoggerInterface $logger
86    *   A logger instance.
87    * @param \Drupal\Core\Mail\MailManagerInterface $mail_manager
88    *   The mail manager.
89    * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
90    *   The language manager.
91    * @param \Egulias\EmailValidator\EmailValidator $email_validator
92    *   The email validator.
93    */
94   public function __construct(array $configuration, $plugin_id, $plugin_definition, Token $token, EntityManagerInterface $entity_manager, LoggerInterface $logger, MailManagerInterface $mail_manager, LanguageManagerInterface $language_manager, EmailValidator $email_validator) {
95     parent::__construct($configuration, $plugin_id, $plugin_definition);
96
97     $this->token = $token;
98     $this->storage = $entity_manager->getStorage('user');
99     $this->logger = $logger;
100     $this->mailManager = $mail_manager;
101     $this->languageManager = $language_manager;
102     $this->emailValidator = $email_validator;
103   }
104
105   /**
106    * {@inheritdoc}
107    */
108   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
109     return new static($configuration, $plugin_id, $plugin_definition,
110       $container->get('token'),
111       $container->get('entity.manager'),
112       $container->get('logger.factory')->get('action'),
113       $container->get('plugin.manager.mail'),
114       $container->get('language_manager'),
115       $container->get('email.validator')
116     );
117   }
118
119   /**
120    * {@inheritdoc}
121    */
122   public function execute($entity = NULL) {
123     if (empty($this->configuration['node'])) {
124       $this->configuration['node'] = $entity;
125     }
126
127     $recipient = PlainTextOutput::renderFromHtml($this->token->replace($this->configuration['recipient'], $this->configuration));
128
129     // If the recipient is a registered user with a language preference, use
130     // the recipient's preferred language. Otherwise, use the system default
131     // language.
132     $recipient_accounts = $this->storage->loadByProperties(['mail' => $recipient]);
133     $recipient_account = reset($recipient_accounts);
134     if ($recipient_account) {
135       $langcode = $recipient_account->getPreferredLangcode();
136     }
137     else {
138       $langcode = $this->languageManager->getDefaultLanguage()->getId();
139     }
140     $params = ['context' => $this->configuration];
141
142     if ($this->mailManager->mail('system', 'action_send_email', $recipient, $langcode, $params)) {
143       $this->logger->notice('Sent email to %recipient', ['%recipient' => $recipient]);
144     }
145     else {
146       $this->logger->error('Unable to send email to %recipient', ['%recipient' => $recipient]);
147     }
148   }
149
150   /**
151    * {@inheritdoc}
152    */
153   public function defaultConfiguration() {
154     return [
155       'recipient' => '',
156       'subject' => '',
157       'message' => '',
158     ];
159   }
160
161   /**
162    * {@inheritdoc}
163    */
164   public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
165     $form['recipient'] = [
166       '#type' => 'textfield',
167       '#title' => t('Recipient email address'),
168       '#default_value' => $this->configuration['recipient'],
169       '#maxlength' => '254',
170       '#description' => t('You may also use tokens: [node:author:mail], [comment:author:mail], etc. Separate recipients with a comma.'),
171     ];
172     $form['subject'] = [
173       '#type' => 'textfield',
174       '#title' => t('Subject'),
175       '#default_value' => $this->configuration['subject'],
176       '#maxlength' => '254',
177       '#description' => t('The subject of the message.'),
178     ];
179     $form['message'] = [
180       '#type' => 'textarea',
181       '#title' => t('Message'),
182       '#default_value' => $this->configuration['message'],
183       '#cols' => '80',
184       '#rows' => '20',
185       '#description' => t('The message that should be sent. You may include placeholders like [node:title], [user:account-name], [user:display-name] and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
186     ];
187     return $form;
188   }
189
190   /**
191    * {@inheritdoc}
192    */
193   public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
194     if (!$this->emailValidator->isValid($form_state->getValue('recipient')) && strpos($form_state->getValue('recipient'), ':mail') === FALSE) {
195       // We want the literal %author placeholder to be emphasized in the error message.
196       $form_state->setErrorByName('recipient', t('Enter a valid email address or use a token email address such as %author.', ['%author' => '[node:author:mail]']));
197     }
198   }
199
200   /**
201    * {@inheritdoc}
202    */
203   public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
204     $this->configuration['recipient'] = $form_state->getValue('recipient');
205     $this->configuration['subject'] = $form_state->getValue('subject');
206     $this->configuration['message'] = $form_state->getValue('message');
207   }
208
209   /**
210    * {@inheritdoc}
211    */
212   public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
213     $result = AccessResult::allowed();
214     return $return_as_object ? $result : $result->isAllowed();
215   }
216
217 }