PluginProbe ʕ •ᴥ•ʔ
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin / 3.5.2
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin v3.5.2
0.9.6 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.2 1.7.0 1.7.1 1.8.0 1.8.1 1.9.0 2.0.0 2.0.1 2.1.1 2.2.1 2.3.1 2.4.0 2.5.0 2.5.1 2.6.0 2.7.0 2.8.0 2.9.0 3.0.1 3.0.2 3.0.3 3.1.0 3.10.0 3.11.0 3.11.1 3.2.0 3.2.1 3.3.0 3.4.0 3.5.0 3.5.1 3.5.2 3.6.1 3.7.0 3.8.0 3.8.2 3.9.0 4.0.1 4.1.0 4.1.1 4.2.0 4.3.0 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.8.0 trunk 0.10.0 0.10.1 0.11.1 0.11.2 0.3.1 0.3.2 0.4 0.4.1 0.4.2 0.5.0 0.5.1 0.5.2 0.6 0.7 0.8 0.8.2 0.8.3 0.8.4 0.8.5 0.8.6 0.8.7 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5
wp-mail-smtp / src / Options.php
wp-mail-smtp / src Last commit date
Admin 3 years ago Compatibility 3 years ago Helpers 3 years ago Providers 3 years ago Reports 3 years ago Tasks 3 years ago UsageTracking 3 years ago Conflicts.php 3 years ago Connect.php 3 years ago Core.php 3 years ago Debug.php 3 years ago Geo.php 3 years ago MailCatcher.php 3 years ago MailCatcherInterface.php 3 years ago MailCatcherV6.php 3 years ago Migration.php 3 years ago MigrationAbstract.php 3 years ago Options.php 3 years ago Processor.php 3 years ago SiteHealth.php 3 years ago Upgrade.php 3 years ago Uploads.php 3 years ago WP.php 3 years ago
Options.php
1481 lines
1 <?php
2
3 namespace WPMailSMTP;
4
5 use WPMailSMTP\Helpers\Crypto;
6 use WPMailSMTP\Reports\Emails\Summary as SummaryReportEmail;
7 use WPMailSMTP\UsageTracking\UsageTracking;
8
9 /**
10 * Class Options to handle all options management.
11 * WordPress does all the heavy work for caching get_option() data,
12 * so we don't have to do that. But we want to minimize cyclomatic complexity
13 * of calling a bunch of WP functions, thus we will cache them in a class as well.
14 *
15 * @since 1.0.0
16 */
17 class Options {
18
19 /**
20 * All the options keys.
21 *
22 * @since 1.3.0
23 * @since 1.4.0 Added Mailgun:region.
24 * @since 1.5.0 Added Outlook/AmazonSES.
25 * @since 1.8.0 Added Pepipost API.
26 * @since 2.0.0 Added SMTP.com API.
27 *
28 * @var array Map of all the default options of the plugin.
29 */
30 private static $map = [
31 'mail' => [
32 'from_name',
33 'from_email',
34 'mailer',
35 'return_path',
36 'from_name_force',
37 'from_email_force',
38 ],
39 'smtp' => [
40 'host',
41 'port',
42 'encryption',
43 'autotls',
44 'auth',
45 'user',
46 'pass',
47 ],
48 'gmail' => [
49 'client_id',
50 'client_secret',
51 ],
52 'outlook' => [
53 'client_id',
54 'client_secret',
55 ],
56 'zoho' => [
57 'domain',
58 'client_id',
59 'client_secret',
60 ],
61 'amazonses' => [
62 'client_id',
63 'client_secret',
64 'region',
65 ],
66 'mailgun' => [
67 'api_key',
68 'domain',
69 'region',
70 ],
71 'sendgrid' => [
72 'api_key',
73 'domain',
74 ],
75 'sparkpost' => [
76 'api_key',
77 'region',
78 ],
79 'postmark' => [
80 'server_api_token',
81 'message_stream',
82 ],
83 'smtpcom' => [
84 'api_key',
85 'channel',
86 ],
87 'sendinblue' => [
88 'api_key',
89 'domain',
90 ],
91 'sendlayer' => [
92 'api_key',
93 ],
94 'pepipostapi' => [
95 'api_key',
96 ],
97 'pepipost' => [
98 'host',
99 'port',
100 'encryption',
101 'auth',
102 'user',
103 'pass',
104 ],
105 'license' => [
106 'key',
107 ],
108 'alert_email' => [
109 'enabled',
110 'connections',
111 ],
112 'alert_slack_webhook' => [
113 'enabled',
114 'connections',
115 ],
116 'alert_twilio_sms' => [
117 'enabled',
118 'connections',
119 ],
120 'alert_custom_webhook' => [
121 'enabled',
122 'connections',
123 ],
124 ];
125
126 /**
127 * List of all mailers (except PHP default mailer 'mail').
128 *
129 * @since 3.3.0
130 *
131 * @var string[]
132 */
133 public static $mailers = [
134 'sendlayer',
135 'smtpcom',
136 'sendinblue',
137 'amazonses',
138 'gmail',
139 'mailgun',
140 'outlook',
141 'postmark',
142 'sendgrid',
143 'sparkpost',
144 'zoho',
145 'smtp',
146 'pepipost',
147 'pepipostapi',
148 ];
149
150 /**
151 * That's where plugin options are saved in wp_options table.
152 *
153 * @since 1.0.0
154 *
155 * @var string
156 */
157 const META_KEY = 'wp_mail_smtp';
158
159 /**
160 * All the plugin options.
161 *
162 * @since 1.0.0
163 *
164 * @var array
165 */
166 private $_options = [];
167
168 /**
169 * Init the Options class.
170 * TODO: add a flag to process without retrieving const values.
171 *
172 * @since 1.0.0
173 * @since 3.3.0 Deprecated instantiation via new keyword. `Options::init()` must be used.
174 */
175 public function __construct() {
176
177 $this->populate_options();
178 }
179
180 /**
181 * Initialize all the options.
182 *
183 * @since 1.0.0
184 *
185 * @return Options
186 */
187 public static function init() {
188
189 static $instance;
190
191 if ( ! $instance ) {
192 $instance = new self();
193 }
194
195 return $instance;
196 }
197
198 /**
199 * Default options that are saved on plugin activation.
200 *
201 * @since 1.3.0
202 * @since 2.1.0 Set the Force from email to "on" by default.
203 *
204 * @return array
205 */
206 public static function get_defaults() {
207
208 return [
209 'mail' => [
210 'from_email' => get_option( 'admin_email' ),
211 'from_name' => get_bloginfo( 'name' ),
212 'mailer' => 'mail',
213 'return_path' => false,
214 'from_email_force' => true,
215 'from_name_force' => false,
216 ],
217 'smtp' => [
218 'autotls' => true,
219 'auth' => true,
220 ],
221 'general' => [
222 SummaryReportEmail::SETTINGS_SLUG => ! is_multisite() ? false : true,
223 ],
224 ];
225 }
226
227 /**
228 * Retrieve all options of the plugin.
229 *
230 * @since 1.0.0
231 * @since 2.2.0 Added the filter.
232 */
233 protected function populate_options() {
234
235 $this->_options = apply_filters( 'wp_mail_smtp_populate_options', get_option( self::META_KEY, [] ) );
236 }
237
238 /**
239 * Get all the options.
240 *
241 * Options::init()->get_all();
242 *
243 * @since 1.0.0
244 *
245 * @return array
246 */
247 public function get_all() {
248
249 $options = $this->_options;
250
251 foreach ( $options as $group => $g_value ) {
252 foreach ( $g_value as $key => $value ) {
253 $options[ $group ][ $key ] = $this->get( $group, $key );
254 }
255 }
256
257 return apply_filters( 'wp_mail_smtp_options_get_all', $options );
258 }
259
260 /**
261 * Get all the options for a group.
262 *
263 * Options::init()->get_group('smtp') - will return the array of options for the group, including defaults and constants.
264 *
265 * @since 1.0.0
266 * @since 1.5.0 Process values through the get() method which is aware of constants.
267 *
268 * @param string $group
269 *
270 * @return array
271 */
272 public function get_group( $group ) {
273
274 // Just to feel safe.
275 $group = sanitize_key( $group );
276
277 /*
278 * Get the values saved in DB.
279 * If plugin is configured with constants right from the start - this will not have all the values.
280 */
281 $options = isset( $this->_options[ $group ] ) ? $this->_options[ $group ] : array();
282
283 // We need to process certain constants-aware options through actual constants.
284 if ( isset( self::$map[ $group ] ) ) {
285 foreach ( self::$map[ $group ] as $key ) {
286 $options[ $key ] = $this->get( $group, $key );
287 }
288 }
289
290 return apply_filters( 'wp_mail_smtp_options_get_group', $options, $group );
291 }
292
293 /**
294 * Get options by a group and a key.
295 *
296 * Options::init()->get( 'smtp', 'host' ) - will return only SMTP 'host' option.
297 *
298 * @since 1.0.0
299 * @since 2.5.0 Added $strip_slashes method parameter.
300 *
301 * @param string $group The option group.
302 * @param string $key The option key.
303 * @param bool $strip_slashes If the slashes should be stripped from string values.
304 *
305 * @return mixed|null Null if value doesn't exist anywhere: in constants, in DB, in a map. So it's completely custom or a typo.
306 */
307 public function get( $group, $key, $strip_slashes = true ) {
308
309 // Just to feel safe.
310 $group = sanitize_key( $group );
311 $key = sanitize_key( $key );
312 $value = null;
313
314 // Get the const value if we have one.
315 $value = $this->get_const_value( $group, $key, $value );
316
317 // We don't have a const value.
318 if ( $value === null ) {
319 // Ordinary database or default values.
320 if ( isset( $this->_options[ $group ] ) ) {
321 // Get the options key of a group.
322 if ( isset( $this->_options[ $group ][ $key ] ) ) {
323 $value = $this->get_existing_option_value( $group, $key );
324 } else {
325 $value = $this->postprocess_key_defaults( $group, $key );
326 }
327 } else {
328 /*
329 * Fallback to default if it doesn't exist in a map.
330 * Allow to retrieve only values from a map.
331 */
332 if (
333 isset( self::$map[ $group ] ) &&
334 in_array( $key, self::$map[ $group ], true )
335 ) {
336 $value = $this->postprocess_key_defaults( $group, $key );
337 }
338 }
339 }
340
341 // Conditionally strip slashes only from values saved in DB. Constants should be processed as is.
342 if ( $strip_slashes && is_string( $value ) && ! $this->is_const_defined( $group, $key ) ) {
343 $value = stripslashes( $value );
344 }
345
346 return apply_filters( 'wp_mail_smtp_options_get', $value, $group, $key );
347 }
348
349 /**
350 * Get the existing cached option value.
351 *
352 * @since 2.5.0
353 *
354 * @param string $group The options group.
355 * @param string $key The options key.
356 *
357 * @return mixed
358 */
359 private function get_existing_option_value( $group, $key ) {
360
361 if ( $group === 'smtp' && $key === 'pass' ) {
362 try {
363 return Crypto::decrypt( $this->_options[ $group ][ $key ] );
364 } catch ( \Exception $e ) {
365 return $this->_options[ $group ][ $key ];
366 }
367 }
368
369 return $this->_options[ $group ][ $key ];
370 }
371
372 /**
373 * Some options may be non-empty by default,
374 * so we need to postprocess them to convert.
375 *
376 * @since 1.0.0
377 * @since 1.4.0 Added Mailgun:region.
378 * @since 1.5.0 Added Outlook/AmazonSES, license key support.
379 *
380 * @param string $group
381 * @param string $key
382 *
383 * @return mixed
384 */
385 protected function postprocess_key_defaults( $group, $key ) {
386
387 $value = '';
388
389 switch ( $key ) {
390 case 'from_email_force':
391 case 'from_name_force':
392 case 'return_path':
393 $value = $group === 'mail' ? false : true;
394 break;
395
396 case 'mailer':
397 $value = 'mail';
398 break;
399
400 case 'encryption':
401 $value = in_array( $group, array( 'smtp', 'pepipost' ), true ) ? 'none' : $value;
402 break;
403
404 case 'region':
405 $value = $group === 'mailgun' || $group === 'sparkpost' ? 'US' : $value;
406 break;
407
408 case 'auth':
409 case 'autotls':
410 $value = in_array( $group, array( 'smtp', 'pepipost' ), true ) ? false : true;
411 break;
412
413 case 'pass':
414 $value = $this->get_const_value( $group, $key, $value );
415 break;
416
417 case 'type':
418 $value = $group === 'license' ? 'lite' : '';
419 break;
420 }
421
422 return apply_filters( 'wp_mail_smtp_options_postprocess_key_defaults', $value, $group, $key );
423 }
424
425 /**
426 * Process the options values through the constants check.
427 * If we have defined associated constant - use it instead of a DB value.
428 * Backward compatibility is hard.
429 * General section of options won't have constants, so we are omitting those checks and just return default value.
430 *
431 * @since 1.0.0
432 * @since 1.4.0 Added WPMS_MAILGUN_REGION.
433 * @since 1.5.0 Added Outlook/AmazonSES, license key support.
434 * @since 1.6.0 Added Sendinblue.
435 * @since 1.7.0 Added Do Not Send.
436 * @since 1.8.0 Added Pepipost API.
437 *
438 * @param string $group
439 * @param string $key
440 * @param mixed $value
441 *
442 * @return mixed
443 */
444 protected function get_const_value( $group, $key, $value ) {
445
446 if ( ! $this->is_const_enabled() ) {
447 return $value;
448 }
449
450 $return = null;
451
452 switch ( $group ) {
453 case 'mail':
454 switch ( $key ) {
455 case 'from_name':
456 /** @noinspection PhpUndefinedConstantInspection */
457 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAIL_FROM_NAME : $value;
458 break;
459 case 'from_email':
460 /** @noinspection PhpUndefinedConstantInspection */
461 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAIL_FROM : $value;
462 break;
463 case 'mailer':
464 /** @noinspection PhpUndefinedConstantInspection */
465 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAILER : $value;
466 break;
467 case 'return_path':
468 /** @noinspection PhpUndefinedConstantInspection */
469 $return = $this->is_const_defined( $group, $key ) ? WPMS_SET_RETURN_PATH : $value;
470 break;
471 case 'from_name_force':
472 /** @noinspection PhpUndefinedConstantInspection */
473 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAIL_FROM_NAME_FORCE : $value;
474 break;
475 case 'from_email_force':
476 /** @noinspection PhpUndefinedConstantInspection */
477 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAIL_FROM_FORCE : $value;
478 break;
479 }
480
481 break;
482
483 case 'smtp':
484 switch ( $key ) {
485 case 'host':
486 /** @noinspection PhpUndefinedConstantInspection */
487 $return = $this->is_const_defined( $group, $key ) ? WPMS_SMTP_HOST : $value;
488 break;
489 case 'port':
490 /** @noinspection PhpUndefinedConstantInspection */
491 $return = $this->is_const_defined( $group, $key ) ? WPMS_SMTP_PORT : $value;
492 break;
493 case 'encryption':
494 /** @noinspection PhpUndefinedConstantInspection */
495 $return = $this->is_const_defined( $group, $key ) ? ( WPMS_SSL === '' ? 'none' : WPMS_SSL ) : $value;
496 break;
497 case 'auth':
498 /** @noinspection PhpUndefinedConstantInspection */
499 $return = $this->is_const_defined( $group, $key ) ? (bool) WPMS_SMTP_AUTH : $value;
500 break;
501 case 'autotls':
502 /** @noinspection PhpUndefinedConstantInspection */
503 $return = $this->is_const_defined( $group, $key ) ? (bool) WPMS_SMTP_AUTOTLS : $value;
504 break;
505 case 'user':
506 /** @noinspection PhpUndefinedConstantInspection */
507 $return = $this->is_const_defined( $group, $key ) ? WPMS_SMTP_USER : $value;
508 break;
509 case 'pass':
510 /** @noinspection PhpUndefinedConstantInspection */
511 $return = $this->is_const_defined( $group, $key ) ? WPMS_SMTP_PASS : $value;
512 break;
513 }
514
515 break;
516
517 case 'sendlayer':
518 switch ( $key ) {
519 case 'api_key':
520 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
521 $return = $this->is_const_defined( $group, $key ) ? WPMS_SENDLAYER_API_KEY : $value;
522 break;
523 }
524
525 break;
526
527 case 'gmail':
528 switch ( $key ) {
529 case 'client_id':
530 /** @noinspection PhpUndefinedConstantInspection */
531 $return = $this->is_const_defined( $group, $key ) ? WPMS_GMAIL_CLIENT_ID : $value;
532 break;
533 case 'client_secret':
534 /** @noinspection PhpUndefinedConstantInspection */
535 $return = $this->is_const_defined( $group, $key ) ? WPMS_GMAIL_CLIENT_SECRET : $value;
536 break;
537 }
538
539 break;
540
541 case 'outlook':
542 switch ( $key ) {
543 case 'client_id':
544 /** @noinspection PhpUndefinedConstantInspection */
545 $return = $this->is_const_defined( $group, $key ) ? WPMS_OUTLOOK_CLIENT_ID : $value;
546 break;
547 case 'client_secret':
548 /** @noinspection PhpUndefinedConstantInspection */
549 $return = $this->is_const_defined( $group, $key ) ? WPMS_OUTLOOK_CLIENT_SECRET : $value;
550 break;
551 }
552
553 break;
554
555 case 'zoho':
556 switch ( $key ) {
557 case 'domain':
558 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
559 $return = $this->is_const_defined( $group, $key ) ? WPMS_ZOHO_DOMAIN : $value;
560 break;
561 case 'client_id':
562 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
563 $return = $this->is_const_defined( $group, $key ) ? WPMS_ZOHO_CLIENT_ID : $value;
564 break;
565 case 'client_secret':
566 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
567 $return = $this->is_const_defined( $group, $key ) ? WPMS_ZOHO_CLIENT_SECRET : $value;
568 break;
569 }
570
571 break;
572
573 case 'amazonses':
574 switch ( $key ) {
575 case 'client_id':
576 /** @noinspection PhpUndefinedConstantInspection */
577 $return = $this->is_const_defined( $group, $key ) ? WPMS_AMAZONSES_CLIENT_ID : $value;
578 break;
579 case 'client_secret':
580 /** @noinspection PhpUndefinedConstantInspection */
581 $return = $this->is_const_defined( $group, $key ) ? WPMS_AMAZONSES_CLIENT_SECRET : $value;
582 break;
583 case 'region':
584 /** @noinspection PhpUndefinedConstantInspection */
585 $return = $this->is_const_defined( $group, $key ) ? WPMS_AMAZONSES_REGION : $value;
586 break;
587 }
588
589 break;
590
591 case 'mailgun':
592 switch ( $key ) {
593 case 'api_key':
594 /** @noinspection PhpUndefinedConstantInspection */
595 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAILGUN_API_KEY : $value;
596 break;
597 case 'domain':
598 /** @noinspection PhpUndefinedConstantInspection */
599 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAILGUN_DOMAIN : $value;
600 break;
601 case 'region':
602 /** @noinspection PhpUndefinedConstantInspection */
603 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAILGUN_REGION : $value;
604 break;
605 }
606
607 break;
608
609 case 'sendgrid':
610 switch ( $key ) {
611 case 'api_key':
612 /** @noinspection PhpUndefinedConstantInspection */
613 $return = $this->is_const_defined( $group, $key ) ? WPMS_SENDGRID_API_KEY : $value;
614 break;
615 case 'domain':
616 /** @noinspection PhpUndefinedConstantInspection */
617 $return = $this->is_const_defined( $group, $key ) ? WPMS_SENDGRID_DOMAIN : $value;
618 break;
619 }
620
621 break;
622
623 case 'sparkpost':
624 switch ( $key ) {
625 case 'api_key':
626 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
627 $return = $this->is_const_defined( $group, $key ) ? WPMS_SPARKPOST_API_KEY : $value;
628 break;
629 case 'region':
630 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
631 $return = $this->is_const_defined( $group, $key ) ? WPMS_SPARKPOST_REGION : $value;
632 break;
633 }
634
635 break;
636
637 case 'postmark':
638 switch ( $key ) {
639 case 'server_api_token':
640 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
641 $return = $this->is_const_defined( $group, $key ) ? WPMS_POSTMARK_SERVER_API_TOKEN : $value;
642 break;
643 case 'message_stream':
644 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
645 $return = $this->is_const_defined( $group, $key ) ? WPMS_POSTMARK_MESSAGE_STREAM : $value;
646 break;
647 }
648
649 break;
650
651 case 'smtpcom':
652 switch ( $key ) {
653 case 'api_key':
654 /** @noinspection PhpUndefinedConstantInspection */
655 $return = $this->is_const_defined( $group, $key ) ? WPMS_SMTPCOM_API_KEY : $value;
656 break;
657 case 'channel':
658 /** @noinspection PhpUndefinedConstantInspection */
659 $return = $this->is_const_defined( $group, $key ) ? WPMS_SMTPCOM_CHANNEL : $value;
660 break;
661 }
662
663 break;
664
665 case 'sendinblue':
666 switch ( $key ) {
667 case 'api_key':
668 /** @noinspection PhpUndefinedConstantInspection */
669 $return = $this->is_const_defined( $group, $key ) ? WPMS_SENDINBLUE_API_KEY : $value;
670 break;
671 case 'domain':
672 /** @noinspection PhpUndefinedConstantInspection */
673 $return = $this->is_const_defined( $group, $key ) ? WPMS_SENDINBLUE_DOMAIN : $value;
674 break;
675 }
676
677 break;
678
679 case 'pepipostapi':
680 switch ( $key ) {
681 case 'api_key':
682 /** @noinspection PhpUndefinedConstantInspection */
683 $return = $this->is_const_defined( $group, $key ) ? WPMS_PEPIPOST_API_KEY : $value;
684 break;
685 }
686
687 case 'alert_email':
688 switch ( $key ) {
689 case 'connections':
690 $return = $this->is_const_defined( $group, $key ) ? [ [ 'send_to' => WPMS_ALERT_EMAIL_SEND_TO ] ] : $value;
691 break;
692 }
693
694 break;
695
696 case 'alert_slack_webhook':
697 switch ( $key ) {
698 case 'connections':
699 $return = $this->is_const_defined( $group, $key ) ? [ [ 'webhook_url' => WPMS_ALERT_SLACK_WEBHOOK_URL ] ] : $value;
700 break;
701 }
702
703 break;
704
705 case 'alert_twilio_sms':
706 switch ( $key ) {
707 case 'connections':
708 if ( $this->is_const_defined( $group, $key ) ) {
709 $return = [
710 [
711 'account_sid' => WPMS_ALERT_TWILIO_SMS_ACCOUNT_SID,
712 'auth_token' => WPMS_ALERT_TWILIO_SMS_AUTH_TOKEN,
713 'from_phone_number' => WPMS_ALERT_TWILIO_SMS_FROM_PHONE_NUMBER,
714 'to_phone_number' => WPMS_ALERT_TWILIO_SMS_TO_PHONE_NUMBER,
715 ],
716 ];
717 } else {
718 $return = $value;
719 }
720 break;
721 }
722
723 break;
724
725 case 'alert_custom_webhook':
726 switch ( $key ) {
727 case 'connections':
728 $return = $this->is_const_defined( $group, $key ) ? [ [ 'webhook_url' => WPMS_ALERT_CUSTOM_WEBHOOK_URL ] ] : $value;
729 break;
730 }
731
732 break;
733
734 case 'license':
735 switch ( $key ) {
736 case 'key':
737 /** @noinspection PhpUndefinedConstantInspection */
738 $return = $this->is_const_defined( $group, $key ) ? WPMS_LICENSE_KEY : $value;
739 break;
740 }
741
742 break;
743
744 case 'general':
745 switch ( $key ) {
746 case 'do_not_send':
747 /** @noinspection PhpUndefinedConstantInspection */
748 $return = $this->is_const_defined( $group, $key ) ? WPMS_DO_NOT_SEND : $value;
749 break;
750 case SummaryReportEmail::SETTINGS_SLUG:
751 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
752 $return = $this->is_const_defined( $group, $key ) ?
753 $this->parse_boolean( WPMS_SUMMARY_REPORT_EMAIL_DISABLED ) :
754 $value;
755 break;
756 }
757
758 break;
759
760 default:
761 // Always return the default value if nothing from above matches the request.
762 $return = $value;
763 }
764
765 return apply_filters( 'wp_mail_smtp_options_get_const_value', $return, $group, $key, $value );
766 }
767
768 /**
769 * Whether constants redefinition is enabled or not.
770 *
771 * @since 1.0.0
772 * @since 1.5.0 Added filter to redefine the value.
773 *
774 * @return bool
775 */
776 public function is_const_enabled() {
777
778 $return = defined( 'WPMS_ON' ) && WPMS_ON === true;
779
780 return apply_filters( 'wp_mail_smtp_options_is_const_enabled', $return );
781 }
782
783 /**
784 * We need this check to reuse later in admin area,
785 * to distinguish settings fields that were redefined,
786 * and display them differently.
787 *
788 * @since 1.0.0
789 * @since 1.5.0 Added a filter, Outlook/AmazonSES, license key support.
790 * @since 1.6.0 Added Sendinblue.
791 * @since 1.7.0 Added Do Not Send.
792 * @since 1.8.0 Added Pepipost API.
793 *
794 * @param string $group
795 * @param string $key
796 *
797 * @return bool
798 */
799 public function is_const_defined( $group, $key ) {
800
801 if ( ! $this->is_const_enabled() ) {
802 return false;
803 }
804
805 // Just to feel safe.
806 $group = sanitize_key( $group );
807 $key = sanitize_key( $key );
808 $return = false;
809
810 switch ( $group ) {
811 case 'mail':
812 switch ( $key ) {
813 case 'from_name':
814 $return = defined( 'WPMS_MAIL_FROM_NAME' ) && WPMS_MAIL_FROM_NAME;
815 break;
816 case 'from_email':
817 $return = defined( 'WPMS_MAIL_FROM' ) && WPMS_MAIL_FROM;
818 break;
819 case 'mailer':
820 $return = defined( 'WPMS_MAILER' ) && WPMS_MAILER;
821 break;
822 case 'return_path':
823 $return = defined( 'WPMS_SET_RETURN_PATH' ) && ( WPMS_SET_RETURN_PATH === 'true' || WPMS_SET_RETURN_PATH === true );
824 break;
825 case 'from_name_force':
826 $return = defined( 'WPMS_MAIL_FROM_NAME_FORCE' ) && ( WPMS_MAIL_FROM_NAME_FORCE === 'true' || WPMS_MAIL_FROM_NAME_FORCE === true );
827 break;
828 case 'from_email_force':
829 $return = defined( 'WPMS_MAIL_FROM_FORCE' ) && ( WPMS_MAIL_FROM_FORCE === 'true' || WPMS_MAIL_FROM_FORCE === true );
830 break;
831 }
832
833 break;
834
835 case 'smtp':
836 switch ( $key ) {
837 case 'host':
838 $return = defined( 'WPMS_SMTP_HOST' ) && WPMS_SMTP_HOST;
839 break;
840 case 'port':
841 $return = defined( 'WPMS_SMTP_PORT' ) && WPMS_SMTP_PORT;
842 break;
843 case 'encryption':
844 $return = defined( 'WPMS_SSL' );
845 break;
846 case 'auth':
847 $return = defined( 'WPMS_SMTP_AUTH' );
848 break;
849 case 'autotls':
850 $return = defined( 'WPMS_SMTP_AUTOTLS' );
851 break;
852 case 'user':
853 $return = defined( 'WPMS_SMTP_USER' ) && WPMS_SMTP_USER;
854 break;
855 case 'pass':
856 $return = defined( 'WPMS_SMTP_PASS' ) && WPMS_SMTP_PASS;
857 break;
858 }
859
860 break;
861
862 case 'sendlayer':
863 switch ( $key ) {
864 case 'api_key':
865 $return = defined( 'WPMS_SENDLAYER_API_KEY' ) && WPMS_SENDLAYER_API_KEY;
866 break;
867 }
868
869 break;
870
871 case 'gmail':
872 switch ( $key ) {
873 case 'client_id':
874 $return = defined( 'WPMS_GMAIL_CLIENT_ID' ) && WPMS_GMAIL_CLIENT_ID;
875 break;
876 case 'client_secret':
877 $return = defined( 'WPMS_GMAIL_CLIENT_SECRET' ) && WPMS_GMAIL_CLIENT_SECRET;
878 break;
879 }
880
881 break;
882
883 case 'outlook':
884 switch ( $key ) {
885 case 'client_id':
886 $return = defined( 'WPMS_OUTLOOK_CLIENT_ID' ) && WPMS_OUTLOOK_CLIENT_ID;
887 break;
888 case 'client_secret':
889 $return = defined( 'WPMS_OUTLOOK_CLIENT_SECRET' ) && WPMS_OUTLOOK_CLIENT_SECRET;
890 break;
891 }
892
893 break;
894
895 case 'zoho':
896 switch ( $key ) {
897 case 'domain':
898 $return = defined( 'WPMS_ZOHO_DOMAIN' ) && WPMS_ZOHO_DOMAIN;
899 break;
900 case 'client_id':
901 $return = defined( 'WPMS_ZOHO_CLIENT_ID' ) && WPMS_ZOHO_CLIENT_ID;
902 break;
903 case 'client_secret':
904 $return = defined( 'WPMS_ZOHO_CLIENT_SECRET' ) && WPMS_ZOHO_CLIENT_SECRET;
905 break;
906 }
907
908 break;
909
910 case 'amazonses':
911 switch ( $key ) {
912 case 'client_id':
913 $return = defined( 'WPMS_AMAZONSES_CLIENT_ID' ) && WPMS_AMAZONSES_CLIENT_ID;
914 break;
915 case 'client_secret':
916 $return = defined( 'WPMS_AMAZONSES_CLIENT_SECRET' ) && WPMS_AMAZONSES_CLIENT_SECRET;
917 break;
918 case 'region':
919 $return = defined( 'WPMS_AMAZONSES_REGION' ) && WPMS_AMAZONSES_REGION;
920 break;
921 }
922
923 break;
924
925 case 'mailgun':
926 switch ( $key ) {
927 case 'api_key':
928 $return = defined( 'WPMS_MAILGUN_API_KEY' ) && WPMS_MAILGUN_API_KEY;
929 break;
930 case 'domain':
931 $return = defined( 'WPMS_MAILGUN_DOMAIN' ) && WPMS_MAILGUN_DOMAIN;
932 break;
933 case 'region':
934 $return = defined( 'WPMS_MAILGUN_REGION' ) && WPMS_MAILGUN_REGION;
935 break;
936 }
937
938 break;
939
940 case 'sendgrid':
941 switch ( $key ) {
942 case 'api_key':
943 $return = defined( 'WPMS_SENDGRID_API_KEY' ) && WPMS_SENDGRID_API_KEY;
944 break;
945 case 'domain':
946 $return = defined( 'WPMS_SENDGRID_DOMAIN' ) && WPMS_SENDGRID_DOMAIN;
947 break;
948 }
949
950 break;
951
952 case 'sparkpost':
953 switch ( $key ) {
954 case 'api_key':
955 $return = defined( 'WPMS_SPARKPOST_API_KEY' ) && WPMS_SPARKPOST_API_KEY;
956 break;
957 case 'region':
958 $return = defined( 'WPMS_SPARKPOST_REGION' ) && WPMS_SPARKPOST_REGION;
959 break;
960 }
961
962 break;
963
964 case 'postmark':
965 switch ( $key ) {
966 case 'server_api_token':
967 $return = defined( 'WPMS_POSTMARK_SERVER_API_TOKEN' ) && WPMS_POSTMARK_SERVER_API_TOKEN;
968 break;
969 case 'message_stream':
970 $return = defined( 'WPMS_POSTMARK_MESSAGE_STREAM' ) && WPMS_POSTMARK_MESSAGE_STREAM;
971 break;
972 }
973
974 break;
975
976 case 'smtpcom':
977 switch ( $key ) {
978 case 'api_key':
979 $return = defined( 'WPMS_SMTPCOM_API_KEY' ) && WPMS_SMTPCOM_API_KEY;
980 break;
981 case 'channel':
982 $return = defined( 'WPMS_SMTPCOM_CHANNEL' ) && WPMS_SMTPCOM_CHANNEL;
983 break;
984 }
985
986 break;
987
988 case 'sendinblue':
989 switch ( $key ) {
990 case 'api_key':
991 $return = defined( 'WPMS_SENDINBLUE_API_KEY' ) && WPMS_SENDINBLUE_API_KEY;
992 break;
993 case 'domain':
994 $return = defined( 'WPMS_SENDINBLUE_DOMAIN' ) && WPMS_SENDINBLUE_DOMAIN;
995 break;
996 }
997
998 break;
999
1000 case 'pepipostapi':
1001 switch ( $key ) {
1002 case 'api_key':
1003 $return = defined( 'WPMS_PEPIPOST_API_KEY' ) && WPMS_PEPIPOST_API_KEY;
1004 break;
1005 }
1006
1007 break;
1008
1009 case 'alert_email':
1010 switch ( $key ) {
1011 case 'connections':
1012 $return = defined( 'WPMS_ALERT_EMAIL_SEND_TO' ) && WPMS_ALERT_EMAIL_SEND_TO;
1013 break;
1014 }
1015
1016 break;
1017
1018 case 'alert_slack_webhook':
1019 switch ( $key ) {
1020 case 'connections':
1021 $return = defined( 'WPMS_ALERT_SLACK_WEBHOOK_URL' ) && WPMS_ALERT_SLACK_WEBHOOK_URL;
1022 break;
1023 }
1024
1025 break;
1026
1027 case 'alert_twilio_sms':
1028 switch ( $key ) {
1029 case 'connections':
1030 $return = defined( 'WPMS_ALERT_TWILIO_SMS_ACCOUNT_SID' ) && WPMS_ALERT_TWILIO_SMS_ACCOUNT_SID &&
1031 defined( 'WPMS_ALERT_TWILIO_SMS_AUTH_TOKEN' ) && WPMS_ALERT_TWILIO_SMS_AUTH_TOKEN &&
1032 defined( 'WPMS_ALERT_TWILIO_SMS_FROM_PHONE_NUMBER' ) && WPMS_ALERT_TWILIO_SMS_FROM_PHONE_NUMBER &&
1033 defined( 'WPMS_ALERT_TWILIO_SMS_TO_PHONE_NUMBER' ) && WPMS_ALERT_TWILIO_SMS_TO_PHONE_NUMBER;
1034 break;
1035 }
1036
1037 break;
1038
1039 case 'alert_custom_webhook':
1040 switch ( $key ) {
1041 case 'connections':
1042 $return = defined( 'WPMS_ALERT_CUSTOM_WEBHOOK_URL' ) && WPMS_ALERT_CUSTOM_WEBHOOK_URL;
1043 break;
1044 }
1045
1046 break;
1047
1048 case 'license':
1049 switch ( $key ) {
1050 case 'key':
1051 $return = defined( 'WPMS_LICENSE_KEY' ) && WPMS_LICENSE_KEY;
1052 break;
1053 }
1054
1055 break;
1056
1057 case 'general':
1058 switch ( $key ) {
1059 case 'do_not_send':
1060 /** @noinspection PhpUndefinedConstantInspection */
1061 $return = defined( 'WPMS_DO_NOT_SEND' ) && WPMS_DO_NOT_SEND;
1062 break;
1063 case SummaryReportEmail::SETTINGS_SLUG:
1064 $return = defined( 'WPMS_SUMMARY_REPORT_EMAIL_DISABLED' );
1065 break;
1066 }
1067
1068 break;
1069 }
1070
1071 return apply_filters( 'wp_mail_smtp_options_is_const_defined', $return, $group, $key );
1072 }
1073
1074 /**
1075 * Set plugin options, all at once.
1076 *
1077 * @since 1.0.0
1078 * @since 1.3.0 Added $once argument to save options only if they don't exist already.
1079 * @since 1.4.0 Added Mailgun:region.
1080 * @since 1.5.0 Added Outlook/AmazonSES, Email Log. Stop saving const values into DB.
1081 * @since 2.5.0 Added $overwrite_existing method parameter.
1082 *
1083 * @param array $options Plugin options to save.
1084 * @param bool $once Whether to update existing options or to add these options only once.
1085 * @param bool $overwrite_existing Whether to overwrite existing settings or merge these passed options with existing ones.
1086 */
1087 public function set( $options, $once = false, $overwrite_existing = true ) {
1088
1089 // Merge existing settings with new values.
1090 if ( ! $overwrite_existing ) {
1091 $options = self::array_merge_recursive( $this->get_all_raw(), $options );
1092 }
1093
1094 $options = $this->process_generic_options( $options );
1095 $options = $this->process_mailer_specific_options( $options );
1096 $options = apply_filters( 'wp_mail_smtp_options_set', $options );
1097
1098 // Whether to update existing options or to add these options only once if they don't exist yet.
1099 if ( $once ) {
1100 add_option( self::META_KEY, $options, '', 'no' ); // Do not autoload these options.
1101 } else {
1102 if ( is_multisite() && WP::use_global_plugin_settings() ) {
1103 update_blog_option( get_main_site_id(), self::META_KEY, $options );
1104 } else {
1105 update_option( self::META_KEY, $options, 'no' );
1106 }
1107 }
1108
1109 // Now we need to re-cache values.
1110 $this->populate_options();
1111
1112 do_action( 'wp_mail_smtp_options_set_after', $options );
1113 }
1114
1115 /**
1116 * Process the generic plugin options.
1117 *
1118 * @since 2.5.0
1119 *
1120 * @param array $options The options array.
1121 *
1122 * @return array
1123 */
1124 private function process_generic_options( $options ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded, Generic.Metrics.NestingLevel.MaxExceeded
1125
1126 foreach ( (array) $options as $group => $keys ) {
1127 foreach ( $keys as $option_name => $option_value ) {
1128 switch ( $group ) {
1129 case 'mail':
1130 switch ( $option_name ) {
1131 case 'from_name':
1132 $options[ $group ][ $option_name ] = sanitize_text_field( $option_value );
1133 break;
1134 case 'mailer':
1135 $mailer = sanitize_text_field( $option_value );
1136
1137 $mailer = in_array( $mailer, self::$mailers, true ) ? $mailer : 'mail';
1138
1139 $options[ $group ][ $option_name ] = $mailer;
1140 break;
1141 case 'from_email':
1142 if ( filter_var( $option_value, FILTER_VALIDATE_EMAIL ) ) {
1143 $options[ $group ][ $option_name ] = sanitize_email( $option_value );
1144 } else {
1145 $options[ $group ][ $option_name ] = sanitize_email(
1146 wp_mail_smtp()->get_processor()->get_default_email()
1147 );
1148 }
1149 break;
1150 case 'return_path':
1151 case 'from_name_force':
1152 case 'from_email_force':
1153 $options[ $group ][ $option_name ] = (bool) $option_value;
1154 break;
1155 }
1156 break;
1157
1158 case 'general':
1159 switch ( $option_name ) {
1160 case 'do_not_send':
1161 case 'am_notifications_hidden':
1162 case 'email_delivery_errors_hidden':
1163 case 'dashboard_widget_hidden':
1164 case 'uninstall':
1165 case UsageTracking::SETTINGS_SLUG:
1166 case SummaryReportEmail::SETTINGS_SLUG:
1167 $options[ $group ][ $option_name ] = (bool) $option_value;
1168 break;
1169 }
1170
1171 case 'debug_events':
1172 switch ( $option_name ) {
1173 case 'email_debug':
1174 $options[ $group ][ $option_name ] = (bool) $option_value;
1175 break;
1176 }
1177 }
1178 }
1179 }
1180
1181 return $options;
1182 }
1183
1184 /**
1185 * Process mailers-specific plugin options.
1186 *
1187 * @since 2.5.0
1188 *
1189 * @param array $options The options array.
1190 *
1191 * @return array
1192 */
1193 private function process_mailer_specific_options( $options ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded, Generic.Metrics.NestingLevel.MaxExceeded
1194
1195 if (
1196 ! empty( $options['mail']['mailer'] ) &&
1197 isset( $options[ $options['mail']['mailer'] ] ) &&
1198 in_array( $options['mail']['mailer'], self::$mailers, true )
1199 ) {
1200
1201 $mailer = $options['mail']['mailer'];
1202
1203 foreach ( $options[ $mailer ] as $option_name => $option_value ) {
1204 switch ( $option_name ) {
1205 case 'host': // smtp.
1206 case 'user': // smtp.
1207 case 'encryption': // smtp.
1208 case 'region': // mailgun/amazonses/sparkpost.
1209 $options[ $mailer ][ $option_name ] = $this->is_const_defined( $mailer, $option_name ) ? '' : sanitize_text_field( $option_value );
1210 break; // smtp.
1211 case 'port':
1212 $options[ $mailer ][ $option_name ] = $this->is_const_defined( $mailer, $option_name ) ? 25 : (int) $option_value;
1213 break;
1214 case 'auth': // smtp.
1215 case 'autotls': // smtp.
1216 $option_value = (bool) $option_value;
1217
1218 $options[ $mailer ][ $option_name ] = $this->is_const_defined( $mailer, $option_name ) ? false : $option_value;
1219 break;
1220
1221 case 'pass': // smtp.
1222 // Do not process as they may contain certain special characters, but allow to be overwritten using constants.
1223 $option_value = trim( (string) $option_value );
1224 $options[ $mailer ][ $option_name ] = $this->is_const_defined( $mailer, $option_name ) ? '' : $option_value;
1225
1226 if ( $mailer === 'smtp' && ! $this->is_const_defined( 'smtp', 'pass' ) ) {
1227 try {
1228 $options[ $mailer ][ $option_name ] = Crypto::encrypt( $option_value );
1229 } catch ( \Exception $e ) {} // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch, Squiz.Commenting.EmptyCatchComment.Missing, Squiz.ControlStructures.ControlSignature.NewlineAfterOpenBrace
1230 }
1231 break;
1232
1233 case 'api_key': // mailgun/sendgrid/sendinblue/pepipostapi/smtpcom/sparkpost/sendlayer.
1234 case 'domain': // mailgun/zoho/sendgrid/sendinblue.
1235 case 'client_id': // gmail/outlook/amazonses/zoho.
1236 case 'client_secret': // gmail/outlook/amazonses/zoho.
1237 case 'auth_code': // gmail/outlook.
1238 case 'channel': // smtpcom.
1239 case 'server_api_token': // postmark.
1240 case 'message_stream': // postmark.
1241 $options[ $mailer ][ $option_name ] = $this->is_const_defined( $mailer, $option_name ) ? '' : sanitize_text_field( $option_value );
1242 break;
1243
1244 case 'access_token': // gmail/outlook/zoho, is an array.
1245 case 'user_details': // outlook/zoho, is an array.
1246 // These options don't support constants.
1247 $options[ $mailer ][ $option_name ] = $option_value;
1248 break;
1249 }
1250 }
1251 }
1252
1253 return $options;
1254 }
1255
1256 /**
1257 * Merge recursively, including a proper substitution of values in sub-arrays when keys are the same.
1258 * It's more like array_merge() and array_merge_recursive() combined.
1259 *
1260 * @since 1.0.0
1261 *
1262 * @return array
1263 */
1264 public static function array_merge_recursive() {
1265
1266 $arrays = func_get_args();
1267
1268 if ( count( $arrays ) < 2 ) {
1269 return isset( $arrays[0] ) ? $arrays[0] : array();
1270 }
1271
1272 $merged = array();
1273
1274 while ( $arrays ) {
1275 $array = array_shift( $arrays );
1276
1277 if ( ! is_array( $array ) ) {
1278 return array();
1279 }
1280
1281 if ( empty( $array ) ) {
1282 continue;
1283 }
1284
1285 foreach ( $array as $key => $value ) {
1286 if ( is_string( $key ) ) {
1287 if (
1288 is_array( $value ) &&
1289 array_key_exists( $key, $merged ) &&
1290 is_array( $merged[ $key ] )
1291 ) {
1292 $merged[ $key ] = call_user_func( __METHOD__, $merged[ $key ], $value );
1293 } else {
1294 $merged[ $key ] = $value;
1295 }
1296 } else {
1297 $merged[] = $value;
1298 }
1299 }
1300 }
1301
1302 return $merged;
1303 }
1304
1305 /**
1306 * Check whether the site is using Pepipost SMTP or not.
1307 *
1308 * @deprecated 2.4.0
1309 *
1310 * @since 1.0.0
1311 *
1312 * @return bool
1313 */
1314 public function is_pepipost_active() {
1315
1316 _deprecated_function(
1317 __METHOD__,
1318 '2.4.0',
1319 'WPMailSMTP\Options::is_mailer_active()'
1320 );
1321
1322 return apply_filters( 'wp_mail_smtp_options_is_pepipost_active', $this->is_mailer_active( 'pepipost' ) );
1323 }
1324
1325 /**
1326 * Check whether the site is using provided mailer or not.
1327 *
1328 * @since 2.3.0
1329 *
1330 * @param string $mailer The mailer slug.
1331 *
1332 * @return bool
1333 */
1334 public function is_mailer_active( $mailer ) {
1335
1336 $mailer = sanitize_key( $mailer );
1337
1338 return apply_filters(
1339 "wp_mail_smtp_options_is_mailer_active_{$mailer}",
1340 $this->get( 'mail', 'mailer' ) === $mailer
1341 );
1342 }
1343
1344 /**
1345 * Check whether the site is using Pepipost/SMTP as a mailer or not.
1346 *
1347 * @since 1.1.0
1348 *
1349 * @return bool
1350 */
1351 public function is_mailer_smtp() {
1352 return apply_filters( 'wp_mail_smtp_options_is_mailer_smtp', in_array( $this->get( 'mail', 'mailer' ), array( 'pepipost', 'smtp' ), true ) );
1353 }
1354
1355 /**
1356 * Get all the options, but without stripping the slashes.
1357 *
1358 * @since 2.5.0
1359 *
1360 * @return array
1361 */
1362 public function get_all_raw() {
1363
1364 $options = $this->_options;
1365
1366 foreach ( $options as $group => $g_value ) {
1367 foreach ( $g_value as $key => $value ) {
1368 $options[ $group ][ $key ] = $this->get( $group, $key, false );
1369 }
1370 }
1371
1372 return $options;
1373 }
1374
1375 /**
1376 * Parse boolean value from string.
1377 *
1378 * @since 2.8.0
1379 *
1380 * @param string|boolean $value String or boolean value.
1381 *
1382 * @return boolean
1383 */
1384 public function parse_boolean( $value ) {
1385
1386 // Return early if it's boolean.
1387 if ( is_bool( $value ) ) {
1388 return $value;
1389 }
1390
1391 $value = trim( $value );
1392
1393 return $value === 'true';
1394 }
1395
1396 /**
1397 * Get a message of a constant that was set inside wp-config.php file.
1398 *
1399 * @since 2.8.0
1400 *
1401 * @param string $constant Constant name.
1402 *
1403 * @return string
1404 */
1405 public function get_const_set_message( $constant ) {
1406
1407 return sprintf( /* translators: %1$s - constant that was used; %2$s - file where it was used. */
1408 esc_html__( 'The value of this field was set using a constant %1$s most likely inside %2$s of your WordPress installation.', 'wp-mail-smtp' ),
1409 '<code>' . esc_html( $constant ) . '</code>',
1410 '<code>wp-config.php</code>'
1411 );
1412 }
1413
1414 /**
1415 * Whether option was changed.
1416 * Can be used only before option save to DB.
1417 *
1418 * @since 3.0.0
1419 *
1420 * @param string $new_value Submitted value (e.g from $_POST).
1421 * @param string $group Group key.
1422 * @param string $key Option key.
1423 *
1424 * @return bool
1425 */
1426 public function is_option_changed( $new_value, $group, $key ) {
1427
1428 $old_value = $this->get( $group, $key );
1429
1430 return $old_value !== $new_value;
1431 }
1432
1433 /**
1434 * Whether constant was changed.
1435 * Can be used only for insecure options.
1436 *
1437 * @since 3.0.0
1438 *
1439 * @param string $group Group key.
1440 * @param string $key Option key.
1441 *
1442 * @return bool
1443 */
1444 public function is_const_changed( $group, $key ) {
1445
1446 if ( ! $this->is_const_defined( $group, $key ) ) {
1447 return false;
1448 }
1449
1450 // Prevent double options update on multiple function call for same option.
1451 static $cache = [];
1452
1453 $cache_key = $group . '_' . $key;
1454
1455 if ( isset( $cache[ $cache_key ] ) ) {
1456 return $cache[ $cache_key ];
1457 }
1458
1459 $value = $this->get( $group, $key );
1460
1461 // Get old value from DB.
1462 add_filter( 'wp_mail_smtp_options_is_const_enabled', '__return_false', PHP_INT_MAX );
1463 $old_value = $this->get( $group, $key );
1464 remove_filter( 'wp_mail_smtp_options_is_const_enabled', '__return_false', PHP_INT_MAX );
1465
1466 $changed = $value !== $old_value;
1467
1468 // Save new constant value to DB.
1469 if ( $changed ) {
1470 $old_opt = $this->get_all_raw();
1471
1472 $old_opt[ $group ][ $key ] = $value;
1473 $this->set( $old_opt );
1474 }
1475
1476 $cache[ $cache_key ] = $changed;
1477
1478 return $changed;
1479 }
1480 }
1481