Version 1
[yaffs-website] / web / modules / contrib / devel / src / Plugin / Mail / DevelMailLog.php
1 <?php
2
3 namespace Drupal\devel\Plugin\Mail;
4
5 use Drupal\Component\Utility\Unicode;
6 use Drupal\Core\Config\ConfigFactoryInterface;
7 use Drupal\Core\Mail\MailFormatHelper;
8 use Drupal\Core\Mail\MailInterface;
9 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
10 use Drupal\Core\Site\Settings;
11 use Symfony\Component\DependencyInjection\ContainerInterface;
12
13 /**
14  * Defines a mail backend that saves emails as temporary files.
15  *
16  * To enable, save a variable in settings.php (or otherwise) whose value
17  * can be as simple as:
18  * @code
19  * $config['system.mail']['interface']['default'] = 'devel_mail_log';
20  * @endcode
21  *
22  * By default the mails are saved in 'temporary://devel-mails'. This setting
23  * can be changed using 'debug_mail_directory' config setting. For example,
24  * @code
25  * $config['devel.settings']['debug_mail_directory'] = 'temporary://my-directory';
26  * @endcode
27  *
28  * The default filename pattern used is '%to-%subject-%datetime.mail.txt'. This
29  * setting can be changed using 'debug_mail_directory' config setting. For example,
30  * @code
31  * $config['devel.settings']['debug_mail_file_format'] = 'devel-mail-%to-%subject-%datetime.mail.txt';
32  * @endcode
33  *
34  * The following placeholders can be used in the filename pattern:
35  *   - %to: the email recipient.
36  *   - %subject: the email subject.
37  *   - %datetime: the current datetime in 'y-m-d_his' format.
38  *
39  * @Mail(
40  *   id = "devel_mail_log",
41  *   label = @Translation("Devel Logging Mailer"),
42  *   description = @Translation("Outputs the message as a file in the temporary directory.")
43  * )
44  */
45 class DevelMailLog implements MailInterface, ContainerFactoryPluginInterface {
46
47   /**
48    * The devel.settings config object.
49    *
50    * @var \Drupal\Core\Config\Config;
51    */
52   protected $config;
53
54   /**
55    * Constructs a new DevelMailLog object.
56    *
57    * @param array $configuration
58    *   A configuration array containing information about the plugin instance.
59    * @param string $plugin_id
60    *   The plugin_id for the plugin instance.
61    * @param mixed $plugin_definition
62    *   The plugin implementation definition.
63    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
64    *   The config factory service.
65    */
66   public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config_factory) {
67     $this->config = $config_factory->get('devel.settings');
68   }
69
70   /**
71    * {@inheritdoc}
72    */
73   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
74     return new static(
75       $configuration,
76       $plugin_id,
77       $plugin_definition,
78       $container->get('config.factory')
79     );
80   }
81
82   /**
83    * {@inheritdoc}
84    */
85   public function mail(array $message) {
86     $directory = $this->config->get('debug_mail_directory');
87
88     if (!$this->prepareDirectory($directory)) {
89       return FALSE;
90     }
91
92     $pattern = $this->config->get('debug_mail_file_format');
93     $filename = $this->replacePlaceholders($pattern, $message);
94     $output = $this->composeMessage($message);
95
96     return (bool) file_put_contents($directory . '/' . $filename, $output);
97   }
98
99   /**
100    * {@inheritdoc}
101    */
102   public function format(array $message) {
103     // Join the body array into one string.
104     $message['body'] = implode("\n\n", $message['body']);
105
106     // Convert any HTML to plain-text.
107     $message['body'] = MailFormatHelper::htmlToText($message['body']);
108     // Wrap the mail body for sending.
109     $message['body'] = MailFormatHelper::wrapMail($message['body']);
110
111     return $message;
112   }
113
114   /**
115    * Compose the output message.
116    *
117    * @param array $message
118    *   A message array, as described in hook_mail_alter().
119    *
120    * @return string
121    *   The output message.
122    */
123   protected function composeMessage($message) {
124     $mimeheaders = [];
125     $message['headers']['To'] = $message['to'];
126     foreach ($message['headers'] as $name => $value) {
127       $mimeheaders[] = $name . ': ' . Unicode::mimeHeaderEncode($value);
128     }
129
130     $line_endings = Settings::get('mail_line_endings', PHP_EOL);
131     $output = join($line_endings, $mimeheaders) . $line_endings;
132     // 'Subject:' is a mail header and should not be translated.
133     $output .= 'Subject: ' . $message['subject'] . $line_endings;
134     // Blank line to separate headers from body.
135     $output .= $line_endings;
136     $output .= preg_replace('@\r?\n@', $line_endings, $message['body']);
137     return $output;
138   }
139
140   /**
141    * Replaces placeholders with sanitized values in a string.
142    *
143    * @param $filename
144    *   The string that contains the placeholders. The following placeholders
145    *   are considered in the replacement:
146    *   - %to: replaced by the email recipient value.
147    *   - %subject: replaced by the email subject value.
148    *   - %datetime: replaced by the current datetime in 'y-m-d_his' format.
149    * @param array $message
150    *   A message array, as described in hook_mail_alter().
151    *
152    * @return string
153    *   The formatted string.
154    */
155   protected function replacePlaceholders($filename, $message) {
156     $tokens = [
157       '%to' => $message['to'],
158       '%subject' => $message['subject'],
159       '%datetime' => date('y-m-d_his'),
160     ];
161     $filename = str_replace(array_keys($tokens), array_values($tokens), $filename);
162     return preg_replace('/[^a-zA-Z0-9_\-\.@]/', '_', $filename);
163   }
164
165   /**
166    * Checks that the directory exists and is writable.
167    * Public directories will be protected by adding an .htaccess which
168    * indicates that the directory is private.
169    *
170    * @param $directory
171    *   A string reference containing the name of a directory path or URI.
172    *
173    * @return bool
174    *   TRUE if the directory exists (or was created), is writable and is
175    *   protected (if it is public). FALSE otherwise.
176    */
177   protected function prepareDirectory($directory) {
178     if (!file_prepare_directory($directory, FILE_CREATE_DIRECTORY)) {
179       return FALSE;
180     }
181     if (0 === strpos($directory, 'public://')) {
182       return file_save_htaccess($directory);
183     }
184
185     return TRUE;
186   }
187
188 }