WP Mail SMTP by WPForms - Version 1.3.0

Version Description

  • 2018-06-28 =
  • Added: New option: force From Email rewrite regardless of the current value.
  • Added: New option: force From Name rewrite regardless of the current value.
  • Added: New option: remove all plugin data on plugin uninstall (when user deletes it).
  • Added: Notify site admins in wp-admin area with a notice about last failed email delivery. Cleans up on successful delivery.
  • Added: Notify site admins in wp-admin area with a notice about possible compatibility issues with other SMTP and email delivery plugins.
  • Added: Improve User Debug Experience when doing Email Test - display helpful description and steps to fix the issue.
  • Added: New users: provide default SMTP Port value for new users based on Encryption selection.
  • Added: New users: notify about not configured plugin settings.
  • Added: New users: Recommend free WPForms Lite plugin for those who don't have it.
  • Added: SendGrid/Mailgun: provide support for multipart/alternative types of emails.
  • Added: Gmail: new button to remove connection and to connect a new Google account.
  • Fixed: Support plugin installation into /mu-plugins/ directory.
  • Fixed: SendGrid: required text/plain part of email being the first one - fixes plain text emails not having links.
  • Fixed: SendGrid and Mailgun: improperly sending plain text emails in html format.
  • Fixed: SMTP Debug output was empty in some cases.
  • Fixed: Compatibility with lots of other plugins that use Google Analytics library of different versions.
  • Fixed: "client_id is empty" is no more a problem, should be fixed.
  • Changed: For SendGrid and Mailgun allow using custom defined attachments names if present. Fallback to file name.
  • Changed: Gmail: switch to a wider scope to prevent possible issues in certain circumstances.
  • Changed: Remove whitespaces start/end of keys, secrets etc.
  • Changed: Improved helpful description tests of various options.
  • Changed: Improved plugin autoloading functionality.
Download this release

Release Info

Developer slaFFik
Plugin Icon 128x128 WP Mail SMTP by WPForms
Version 1.3.0
Comparing to
See all releases

Code changes from version 1.2.5 to 1.3.0

Files changed (62) hide show
  1. assets/css/smtp-admin.min.css +3 -3
  2. assets/js/smtp-admin.js +42 -6
  3. assets/js/smtp-admin.min.js +1 -1
  4. languages/wp-mail-smtp.pot +374 -221
  5. readme.txt +29 -5
  6. src/Admin/Area.php +74 -0
  7. src/Admin/Pages/Misc.php +18 -2
  8. src/Admin/Pages/Settings.php +158 -22
  9. src/Admin/Pages/Test.php +647 -13
  10. src/Core.php +299 -16
  11. src/Debug.php +2 -2
  12. src/MailCatcher.php +13 -1
  13. src/Migration.php +14 -4
  14. src/Options.php +57 -3
  15. src/Processor.php +54 -8
  16. src/Providers/Gmail/Auth.php +16 -8
  17. src/Providers/Gmail/Mailer.php +11 -2
  18. src/Providers/Gmail/Options.php +96 -18
  19. src/Providers/MailerAbstract.php +20 -7
  20. src/Providers/Mailgun/Mailer.php +5 -4
  21. src/Providers/OptionsAbstract.php +16 -16
  22. src/Providers/Sendgrid/Mailer.php +4 -4
  23. src/TGMPA.php +3857 -0
  24. uninstall.php +58 -0
  25. vendor/autoload.php +1 -1
  26. vendor/composer/ClassLoader.php +2 -2
  27. vendor/composer/autoload_classmap.php +0 -228
  28. vendor/composer/autoload_files.php +0 -14
  29. vendor/composer/autoload_psr4.php +1 -0
  30. vendor/composer/autoload_real.php +18 -9
  31. vendor/composer/autoload_static.php +13 -247
  32. vendor/google/apiclient-services/src/Google/Service/Gmail/Label.php +16 -0
  33. vendor/google/apiclient-services/src/Google/Service/Gmail/LabelColor.php +39 -0
  34. vendor/google/apiclient/src/Google/AccessToken/Verify.php +4 -3
  35. vendor/google/apiclient/src/Google/Client.php +16 -6
  36. vendor/google/apiclient/src/Google/Service/Resource.php +7 -1
  37. vendor/google/auth/src/ApplicationDefaultCredentials.php +2 -2
  38. vendor/google/auth/src/Cache/Item.php +1 -1
  39. vendor/google/auth/src/Cache/SysVCacheItemPool.php +231 -0
  40. vendor/google/auth/src/Credentials/GCECredentials.php +2 -2
  41. vendor/google/auth/src/HttpHandler/Guzzle5HttpHandler.php +64 -4
  42. vendor/google/auth/src/HttpHandler/Guzzle6HttpHandler.php +13 -0
  43. vendor/guzzlehttp/guzzle/LICENSE +1 -1
  44. vendor/guzzlehttp/guzzle/src/Client.php +18 -10
  45. vendor/guzzlehttp/guzzle/src/ClientInterface.php +1 -1
  46. vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php +3 -3
  47. vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php +1 -1
  48. vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php +6 -7
  49. vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php +9 -0
  50. vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php +9 -3
  51. vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php +3 -1
  52. vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php +3 -4
  53. vendor/guzzlehttp/guzzle/src/HandlerStack.php +1 -1
  54. vendor/guzzlehttp/guzzle/src/MessageFormatter.php +0 -2
  55. vendor/guzzlehttp/guzzle/src/Middleware.php +6 -5
  56. vendor/guzzlehttp/guzzle/src/UriTemplate.php +0 -4
  57. vendor/guzzlehttp/guzzle/src/functions.php +4 -2
  58. vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php +20 -16
  59. vendor/phpseclib/phpseclib/phpseclib/Crypt/Random.php +4 -0
  60. vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php +22 -18
  61. wp-mail-smtp.php +1 -52
  62. wp_mail_smtp.php +3 -3
assets/css/smtp-admin.min.css CHANGED
@@ -1,3 +1,3 @@
1
- #wpcontent{padding-left:0 !important;position:relative}@media (max-width: 320px){#wpcontent{padding-top:46px}}@media (max-width: 320px){#wpbody{padding-top:0}}#wp-mail-smtp-header{background-color:#f1f3f7;border-top:3px solid #FF982D;padding:20px}#wp-mail-smtp-header img{display:block;margin:0;max-width:242px}@media (max-width: 768px){#wp-mail-smtp-header img{max-width:200px}}#wp-mail-smtp{margin:0}#wp-mail-smtp .wp-mail-smtp-page-title{background-color:#fff;font-size:14px;margin:0 0 20px 0;padding:0 20px}#wp-mail-smtp .wp-mail-smtp-page-title a{border-bottom:2px solid #fff;box-shadow:none;color:#666;display:inline-block;margin-right:30px;padding:20px 0 18px 0;text-decoration:none}#wp-mail-smtp .wp-mail-smtp-page-title a.active{border-bottom:2px solid #FF982D}#wp-mail-smtp .wp-mail-smtp-page-title a:hover{border-color:#999}#wp-mail-smtp .wp-mail-smtp-page{padding:0 20px}#wp-mail-smtp .wp-mail-smtp-page *,#wp-mail-smtp .wp-mail-smtp-page *::before,#wp-mail-smtp .wp-mail-smtp-page *::after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-clear:before{content:" ";display:table}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-clear:after{clear:both;content:" ";display:table}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row{border-bottom:1px solid #e4e4e4;padding:30px 0;font-size:14px;line-height:1.3}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row:first-of-type{padding-top:10px !important}@media (max-width: 767px){#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row{padding:20px 0}}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.inactive{display:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.section-heading{padding:20px 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.section-heading.no-desc h2,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.section-heading.no-desc h4{margin:0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.section-heading .wp-mail-smtp-setting-field{margin:0;max-width:1000px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox input[type=checkbox]{float:left;margin:1px 0 0 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox input[type=checkbox]+label{margin:0 0 0 8px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox .desc{margin:0 0 0 30px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox input[type=checkbox]+label+.desc{margin:8px 0 0 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-text .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-password .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-number .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-email .wp-mail-smtp-setting-label{padding-top:8px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-select .wp-mail-smtp-setting-label{padding-top:8px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-radio .wp-mail-smtp-setting-field input[type=radio]{margin:-3px 10px 0 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-radio .wp-mail-smtp-setting-field label{margin-right:30px;display:inline-block}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field label{vertical-align:middle;display:inline-block}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field label:hover .wp-mail-smtp-setting-toggle-switch{background-color:#999}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]{display:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:checked+.wp-mail-smtp-setting-toggle-switch{background-color:#83c11f}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:checked+.wp-mail-smtp-setting-toggle-switch:before{-webkit-transform:translateX(19px);-ms-transform:translateX(19px);transform:translateX(19px)}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:checked+.wp-mail-smtp-setting-toggle-switch+.wp-mail-smtp-setting-toggle-checked-label{display:inline-block}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:checked+.wp-mail-smtp-setting-toggle-switch+.wp-mail-smtp-setting-toggle-checked-label+.wp-mail-smtp-setting-toggle-unchecked-label{display:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-unchecked-label,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-checked-label{text-transform:uppercase;font-weight:700;font-size:13px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-checked-label{display:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-switch{position:relative;cursor:pointer;background-color:#ccc;border-radius:15px;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;vertical-align:middle;position:relative;display:inline-block;margin:0 5px 0 0;width:40px;height:20px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-switch:before{position:absolute;content:"";height:14px;width:14px;left:3px;top:3px;background-color:#fff;border-radius:50%;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer{padding-bottom:20px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer{display:inline-block;width:140px;margin-right:10px;margin-bottom:10px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer:last-child{margin-right:0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer .wp-mail-smtp-mailer-image{background:#fff;text-align:center;border:2px solid #E5E5E5;border-radius:4px;height:76px;position:relative;margin-bottom:10px;cursor:pointer;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer .wp-mail-smtp-mailer-image img{display:block;position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);opacity:0.6;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer.active .wp-mail-smtp-mailer-image{border-color:#FF982D}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer.active .wp-mail-smtp-mailer-image img{opacity:1}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer:hover .wp-mail-smtp-mailer-image{border-color:#ccc}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer:hover .wp-mail-smtp-mailer-image img{opacity:1}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row h2,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row h4{color:#444;font-size:20px;font-weight:700;margin:0 0 6px 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row h3{color:#444;font-size:24px;font-weight:600;margin:0 0 20px 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row p{margin:12px 0 0;font-size:14px;line-height:1.3}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row p:first-of-type{margin:8px 0 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row p.desc{font-style:italic;color:#666}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password]{background-color:#fff;border:1px solid #ddd;border-radius:3px;box-shadow:none;color:#333;display:inline-block;vertical-align:middle;padding:7px 12px;margin:0 10px 0 0;width:400px;min-height:35px}@media (max-width: 1023px){#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password]{width:300px}}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text][readonly],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email][readonly],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number][readonly],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password][readonly]{background-color:#f9f9f9}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text].small-text,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email].small-text,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number].small-text,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password].small-text{width:75px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text]:focus,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email]:focus,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number]:focus,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password]:focus{border-color:#bbb}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text]:disabled,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email]:disabled,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number]:disabled,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password]:disabled{opacity:0.6}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-label{display:block;float:left;width:200px;padding:0}@media (max-width: 767px){#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-label{float:none;width:100%;padding-bottom:15px}}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-label label{display:block;font-weight:600}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-field{display:block;margin:0 0 0 200px;max-width:800px}@media (max-width: 767px){#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-field{margin:0}}#wp-mail-smtp .wp-mail-smtp-page p.wp-mail-smtp-submit{margin:0;padding:25px 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-mailer-options .wp-mail-smtp-mailer-option .wp-mail-smtp-setting-row.section-heading{padding:20px 0 !important}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-mailer-options .wp-mail-smtp-mailer-option blockquote{background:#E5E5E5;border-radius:4px;color:#666;font-size:14px;margin:20px 0;padding:15px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn{border:0;border-radius:3px;cursor:pointer;display:inline-block;margin:0;text-decoration:none;text-align:center;vertical-align:middle;white-space:nowrap;text-shadow:none;box-shadow:none;outline:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn .dashicons{font-size:16px;width:16px;height:16px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-block{display:block}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-md{font-size:13px;font-weight:600;padding:8px 12px;min-height:35px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-lg{font-size:16px;font-weight:600;padding:16px 28px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-orange{background-color:#FF982D;border-color:#FF982D;color:#fff}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-orange:hover,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-orange:active,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-orange:focus{background-color:#f97f00;border-color:#f97f00}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-grey{background-color:#eee;border-color:#ccc;color:#666}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-grey:hover,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-grey:active,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-grey:focus{background-color:#d7d7d7;border-color:#ccc;color:#444}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-light-grey{background-color:#f5f5f5;border:1px solid #ccc;color:#666}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-light-grey:hover,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-light-grey:active,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-light-grey:focus{background-color:#eee;color:#444}#wp-mail-smtp .wp-mail-smtp-page p{margin:0}#wp-mail-smtp .wp-mail-smtp-page .notice p{margin:0.5em 0}#wp-mail-smtp .wp-mail-smtp-page pre{white-space:pre-line}#wp-mail-smtp .wp-mail-smtp-page.active{display:block}
2
-
3
- /*# sourceMappingURL=smtp-admin.min.css.map */
1
+ #wpcontent{padding-left:0 !important;position:relative}@media (max-width: 600px){#wpcontent{padding-top:46px}}@media (max-width: 600px){#wpbody{padding-top:0}}#wp-mail-smtp-header{background-color:#f1f3f7;border-top:3px solid #FF982D;padding:20px}#wp-mail-smtp-header img{display:block;margin:0;max-width:242px}@media (max-width: 782px){#wp-mail-smtp-header img{max-width:200px}}#wp-mail-smtp{margin:0}#wp-mail-smtp .wp-mail-smtp-page-title{background-color:#fff;font-size:14px;margin:0 0 20px 0;padding:0 20px}#wp-mail-smtp .wp-mail-smtp-page-title a{border-bottom:2px solid #fff;box-shadow:none;color:#666;display:inline-block;margin-right:30px;padding:20px 0 18px 0;text-decoration:none}#wp-mail-smtp .wp-mail-smtp-page-title a.active{border-bottom:2px solid #FF982D}#wp-mail-smtp .wp-mail-smtp-page-title a:hover{border-color:#999}#wp-mail-smtp .wp-mail-smtp-page{padding:0 20px}#wp-mail-smtp .wp-mail-smtp-page *,#wp-mail-smtp .wp-mail-smtp-page *::before,#wp-mail-smtp .wp-mail-smtp-page *::after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-clear:before{content:" ";display:table}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-clear:after{clear:both;content:" ";display:table}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row{border-bottom:1px solid #e4e4e4;padding:30px 0;font-size:14px;line-height:1.3}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row:first-of-type{padding-top:10px !important}@media (max-width: 781px){#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row{padding:20px 0}}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.inactive{display:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row .wp-mail-smtp-setting-mid-row-sep{margin:15px 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.section-heading{padding:20px 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.section-heading.no-desc h2,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.section-heading.no-desc h4{margin:0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.section-heading .wp-mail-smtp-setting-field{margin:0;max-width:1000px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox input[type=checkbox]{float:left;margin:1px 0 0 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox input[type=checkbox]+label{margin:0 0 0 8px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox .desc{margin:0 0 0 30px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox input[type=checkbox]+label+.desc{margin:8px 0 0 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-text .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-password .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-number .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-email .wp-mail-smtp-setting-label{padding-top:8px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-select .wp-mail-smtp-setting-label{padding-top:8px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-radio .wp-mail-smtp-setting-field input[type=radio]{margin:-3px 10px 0 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-radio .wp-mail-smtp-setting-field label{margin-right:30px;display:inline-block}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field label{vertical-align:middle;display:inline-block}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field label:hover .wp-mail-smtp-setting-toggle-switch{background-color:#999}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]{display:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:checked+.wp-mail-smtp-setting-toggle-switch{background-color:#83c11f}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:checked+.wp-mail-smtp-setting-toggle-switch:before{-webkit-transform:translateX(19px);-ms-transform:translateX(19px);transform:translateX(19px)}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:checked+.wp-mail-smtp-setting-toggle-switch+.wp-mail-smtp-setting-toggle-checked-label{display:inline-block}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:checked+.wp-mail-smtp-setting-toggle-switch+.wp-mail-smtp-setting-toggle-checked-label+.wp-mail-smtp-setting-toggle-unchecked-label{display:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-unchecked-label,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-checked-label{text-transform:uppercase;font-weight:700;font-size:13px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-checked-label{display:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-switch{position:relative;cursor:pointer;background-color:#ccc;border-radius:15px;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;vertical-align:middle;position:relative;display:inline-block;margin:0 5px 0 0;width:40px;height:20px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-switch:before{position:absolute;content:"";height:14px;width:14px;left:3px;top:3px;background-color:#fff;border-radius:50%;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer{padding-bottom:20px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer{display:inline-block;width:140px;margin-right:10px;margin-bottom:10px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer:last-child{margin-right:0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer .wp-mail-smtp-mailer-image{background:#fff;text-align:center;border:2px solid #E5E5E5;border-radius:4px;height:76px;position:relative;margin-bottom:10px;cursor:pointer;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer .wp-mail-smtp-mailer-image img{display:block;position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);opacity:0.6;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer.active .wp-mail-smtp-mailer-image{border-color:#FF982D}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer.active .wp-mail-smtp-mailer-image img{opacity:1}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer:hover .wp-mail-smtp-mailer-image{border-color:#ccc}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer:hover .wp-mail-smtp-mailer-image img{opacity:1}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row h2,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row h4{color:#444;font-size:20px;font-weight:700;margin:0 0 6px 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row h3{color:#444;font-size:24px;font-weight:600;margin:0 0 20px 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row p{margin:12px 0 0;font-size:14px;line-height:1.3}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row p:first-of-type{margin:8px 0 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row p.desc{font-style:italic;color:#666}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password]{background-color:#fff;border:1px solid #ddd;border-radius:3px;box-shadow:none;color:#333;display:inline-block;vertical-align:middle;padding:7px 12px;margin:0 10px 0 0;width:400px;min-height:35px}@media (max-width: 959px){#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password]{width:300px}}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text][readonly],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email][readonly],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number][readonly],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password][readonly]{background-color:#f9f9f9}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text].small-text,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email].small-text,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number].small-text,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password].small-text{width:75px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text]:focus,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email]:focus,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number]:focus,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password]:focus{border-color:#bbb}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text]:disabled,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email]:disabled,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number]:disabled,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password]:disabled{opacity:0.6}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-label{display:block;float:left;width:200px;padding:0}@media (max-width: 781px){#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-label{float:none;width:100%;padding-bottom:15px}}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-label label{display:block;font-weight:600}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-field{display:block;margin:0 0 0 200px;max-width:800px}@media (max-width: 781px){#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-field{margin:0}}#wp-mail-smtp .wp-mail-smtp-page p.wp-mail-smtp-submit{margin:0;padding:25px 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-mailer-options .wp-mail-smtp-mailer-option .wp-mail-smtp-setting-row.section-heading{padding:20px 0 !important}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-mailer-options .wp-mail-smtp-mailer-option blockquote{background:#E5E5E5;border-radius:4px;color:#666;font-size:14px;margin:20px 0;padding:15px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn{border:0;border-radius:3px;cursor:pointer;display:inline-block;margin:0;text-decoration:none;text-align:center;vertical-align:middle;white-space:nowrap;text-shadow:none;box-shadow:none;outline:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn .dashicons{font-size:16px;width:16px;height:16px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-block{display:block}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-md{font-size:13px;font-weight:600;padding:8px 12px;min-height:35px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-lg{font-size:16px;font-weight:600;padding:16px 28px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-orange{background-color:#FF982D;border-color:#FF982D;color:#fff}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-orange:hover,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-orange:active,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-orange:focus{background-color:#f97f00;border-color:#f97f00}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-red{background-color:red;border-color:red;color:#fff}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-red:hover,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-red:active,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-red:focus{background-color:darkred;border-color:darkred}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-grey{background-color:#eee;border-color:#ccc;color:#666}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-grey:hover,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-grey:active,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-grey:focus{background-color:#d7d7d7;border-color:#ccc;color:#444}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-light-grey{background-color:#f5f5f5;border:1px solid #ccc;color:#666}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-light-grey:hover,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-light-grey:active,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-light-grey:focus{background-color:#eee;color:#444}#wp-mail-smtp .wp-mail-smtp-page p{margin:0}#wp-mail-smtp .wp-mail-smtp-page .notice-inline{background:#fff;border-left:4px solid #fff;box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);margin:5px 0 15px;padding:1px 12px}#wp-mail-smtp .wp-mail-smtp-page .notice-inline.notice-success{border-left-color:#46b450}#wp-mail-smtp .wp-mail-smtp-page .notice-inline.notice-warning{border-left-color:#ffb900}#wp-mail-smtp .wp-mail-smtp-page .notice-inline.notice-error{border-left-color:#dc3232}#wp-mail-smtp .wp-mail-smtp-page .notice-inline.notice-info{border-left-color:#00a0d2}#wp-mail-smtp .wp-mail-smtp-page .notice p,#wp-mail-smtp .wp-mail-smtp-page .notice-inline p{margin:0.5em 0;padding:2px}#wp-mail-smtp .wp-mail-smtp-page pre{white-space:pre-line}#wp-mail-smtp .wp-mail-smtp-page.active{display:block}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug{background-color:#fff;padding:25px 20px 1px 25px}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug h2{color:#444;margin:1.4em 0 0.8em;font-size:16px;font-weight:700}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug p{font-size:14px;color:#555;margin-bottom:1.1em}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug ul,#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug ol{font-size:14px;color:#555;margin:0 0 1.1em 1.8em}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug ul li,#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug ol li{margin:0 0 8px 0;line-height:1.5}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug ul li:last-of-type,#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug ol li:last-of-type{margin:0}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug ul li ul,#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug ol li ul{list-style-type:disc}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug a{color:#FF982D}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug a:hover{color:#f97f00}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug .dashicons-star-filled{color:#FF982D;width:16px;height:16px;font-size:16px;vertical-align:text-top}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug .error-log-toggle{text-decoration:none;color:#444}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug .error-log-toggle:hover{color:#FF982D}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug .error-log-toggle .dashicons{font-size:15px;height:15px;width:15px;padding-top:3px;border:0;outline:0}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug .error-log{border-left:3px solid #ffb900;padding:0 0 0 20px;margin:0 0 10px 0;font-size:12px;display:none}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug .error-log pre{margin:0}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-debug .error-log-note{display:none}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms{background-color:#fff;padding:25px 20px;border:1px solid #dadada;margin:10px 0 0 0;position:relative}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms .wp-mail-smtp-wpforms-dismiss{position:absolute;right:10px;top:10px}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms .wp-mail-smtp-wpforms-dismiss button{background:none;border:none;color:#a9a9a9;cursor:pointer;margin:0;padding:0}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms h2{color:#444;margin-top:0;font-size:16px;font-weight:700}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms p{font-size:14px;color:#555;margin-bottom:1.1em}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms p:last-of-type{margin:0}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms .benefits{margin:0 0 16px 0;overflow:auto;max-width:900px}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms ul{margin:0;padding:0;width:50%;float:left}@media (max-width: 600px){#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms ul{width:100%;float:none}}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms ul li{margin:0;padding:0 0 2px 16px;color:#555;font-size:14px;position:relative}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms ul li:before{content:'+';position:absolute;top:-1px;left:0}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms a{color:#FF982D}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms a:hover,#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms a:active,#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms a:focus{color:#f97f00}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms .stars{text-decoration:none}#wp-mail-smtp .wp-mail-smtp-page #wp-mail-smtp-wpforms .stars .dashicons{width:16px;height:16px;font-size:16px;vertical-align:text-top}
2
+
3
+ /*# sourceMappingURL=smtp-admin.min.css.map */
assets/js/smtp-admin.js CHANGED
@@ -22,22 +22,58 @@ jQuery( document ).ready( function ( $ ) {
22
  $( '.wp-mail-smtp-setting-copy' ).click( function ( e ) {
23
  e.preventDefault();
24
 
25
- var target = $( '#' + $( this ).data( 'source_id' ) ).get(0);
26
 
27
  target.select();
28
 
29
  document.execCommand( 'Copy' );
30
  } );
31
 
32
- $( '#wp-mail-smtp-setting-smtp-auth' ).change( function() {
33
  $( '#wp-mail-smtp-setting-row-smtp-user, #wp-mail-smtp-setting-row-smtp-pass' ).toggleClass( 'inactive' );
34
- });
 
 
 
 
 
35
 
36
- $( '#wp-mail-smtp-setting-row-smtp-encryption input').change( function() {
37
- if ( 'tls' === $(this).val() ) {
38
- $(' #wp-mail-smtp-setting-row-smtp-autotls' ).addClass( 'inactive' );
 
 
 
39
  } else {
 
40
  $( '#wp-mail-smtp-setting-row-smtp-autotls' ).removeClass( 'inactive' );
41
  }
42
  } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  } );
22
  $( '.wp-mail-smtp-setting-copy' ).click( function ( e ) {
23
  e.preventDefault();
24
 
25
+ var target = $( '#' + $( this ).data( 'source_id' ) ).get( 0 );
26
 
27
  target.select();
28
 
29
  document.execCommand( 'Copy' );
30
  } );
31
 
32
+ $( '#wp-mail-smtp-setting-smtp-auth' ).change( function () {
33
  $( '#wp-mail-smtp-setting-row-smtp-user, #wp-mail-smtp-setting-row-smtp-pass' ).toggleClass( 'inactive' );
34
+ } );
35
+
36
+ $( '#wp-mail-smtp-setting-row-smtp-encryption input' ).change( function () {
37
+
38
+ var $this = $( this ),
39
+ $smtpPort = $( '#' + 'wp-mail-smtp-setting-smtp-port' );
40
 
41
+ if ( 'tls' === $this.val() ) {
42
+ $smtpPort.val( '587' );
43
+ $( '#wp-mail-smtp-setting-row-smtp-autotls' ).addClass( 'inactive' );
44
+ } else if ( 'ssl' === $this.val() ) {
45
+ $smtpPort.val( '465' );
46
+ $( '#wp-mail-smtp-setting-row-smtp-autotls' ).removeClass( 'inactive' );
47
  } else {
48
+ $smtpPort.val( '25' );
49
  $( '#wp-mail-smtp-setting-row-smtp-autotls' ).removeClass( 'inactive' );
50
  }
51
  } );
52
+
53
+ $( '#wp-mail-smtp-wpforms-dismiss' ).on( 'click', function () {
54
+ $.ajax( {
55
+ url: ajaxurl,
56
+ dataType: 'json',
57
+ type: 'POST',
58
+ data: {
59
+ action: 'wp_mail_smtp_ajax',
60
+ task: 'wpforms_dismiss'
61
+ }
62
+ } )
63
+ .always( function () {
64
+ $( '#wp-mail-smtp-wpforms' ).fadeOut( 'fast' );
65
+ } );
66
+ } );
67
+
68
+ $( '#wp-mail-smtp-debug .error-log-toggle' ).on( 'click', function ( e ) {
69
+ e.preventDefault();
70
+
71
+ $( '#wp-mail-smtp-debug .error-log-toggle' ).find( '.dashicons' ).toggleClass( 'dashicons-arrow-right-alt2 dashicons-arrow-down-alt2' );
72
+ $( '#wp-mail-smtp-debug .error-log' ).slideToggle();
73
+ $( '#wp-mail-smtp-debug .error-log-note' ).toggle();
74
+ } );
75
+
76
+ $( '#wp-mail-smtp-gmail-remove' ).on( 'click', function () {
77
+ return confirm( window.wp_mail_smtp.text_gmail_remove );
78
+ } );
79
  } );
assets/js/smtp-admin.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(t){t(".wp-mail-smtp-mailer input").click(function(){if(t(this).prop("disabled"))return!1;t(".wp-mail-smtp-mailer").removeClass("active"),t(this).parents(".wp-mail-smtp-mailer").addClass("active"),t(".wp-mail-smtp-mailer-option").addClass("hidden").removeClass("active"),t(".wp-mail-smtp-mailer-option-"+t(this).val()).addClass("active").removeClass("hidden")}),t(".wp-mail-smtp-mailer-image").click(function(){t(this).parents(".wp-mail-smtp-mailer").find("input").trigger("click")}),t(".wp-mail-smtp-setting-copy").click(function(i){i.preventDefault(),t("#"+t(this).data("source_id")).get(0).select(),document.execCommand("Copy")}),t("#wp-mail-smtp-setting-smtp-auth").change(function(){t("#wp-mail-smtp-setting-row-smtp-user, #wp-mail-smtp-setting-row-smtp-pass").toggleClass("inactive")}),t("#wp-mail-smtp-setting-row-smtp-encryption input").change(function(){"tls"===t(this).val()?t(" #wp-mail-smtp-setting-row-smtp-autotls").addClass("inactive"):t("#wp-mail-smtp-setting-row-smtp-autotls").removeClass("inactive")})});
1
+ jQuery(document).ready(function(a){a(".wp-mail-smtp-mailer input").click(function(){if(a(this).prop("disabled"))return!1;a(".wp-mail-smtp-mailer").removeClass("active"),a(this).parents(".wp-mail-smtp-mailer").addClass("active"),a(".wp-mail-smtp-mailer-option").addClass("hidden").removeClass("active"),a(".wp-mail-smtp-mailer-option-"+a(this).val()).addClass("active").removeClass("hidden")}),a(".wp-mail-smtp-mailer-image").click(function(){a(this).parents(".wp-mail-smtp-mailer").find("input").trigger("click")}),a(".wp-mail-smtp-setting-copy").click(function(t){t.preventDefault(),a("#"+a(this).data("source_id")).get(0).select(),document.execCommand("Copy")}),a("#wp-mail-smtp-setting-smtp-auth").change(function(){a("#wp-mail-smtp-setting-row-smtp-user, #wp-mail-smtp-setting-row-smtp-pass").toggleClass("inactive")}),a("#wp-mail-smtp-setting-row-smtp-encryption input").change(function(){var t=a(this),i=a("#wp-mail-smtp-setting-smtp-port");"tls"===t.val()?(i.val("587"),a("#wp-mail-smtp-setting-row-smtp-autotls").addClass("inactive")):("ssl"===t.val()?i.val("465"):i.val("25"),a("#wp-mail-smtp-setting-row-smtp-autotls").removeClass("inactive"))}),a("#wp-mail-smtp-wpforms-dismiss").on("click",function(){a.ajax({url:ajaxurl,dataType:"json",type:"POST",data:{action:"wp_mail_smtp_ajax",task:"wpforms_dismiss"}}).always(function(){a("#wp-mail-smtp-wpforms").fadeOut("fast")})}),a("#wp-mail-smtp-debug .error-log-toggle").on("click",function(t){t.preventDefault(),a("#wp-mail-smtp-debug .error-log-toggle").find(".dashicons").toggleClass("dashicons-arrow-right-alt2 dashicons-arrow-down-alt2"),a("#wp-mail-smtp-debug .error-log").slideToggle(),a("#wp-mail-smtp-debug .error-log-note").toggle()}),a("#wp-mail-smtp-gmail-remove").on("click",function(){return confirm(window.wp_mail_smtp.text_gmail_remove)})});
languages/wp-mail-smtp.pot CHANGED
@@ -14,436 +14,455 @@ msgstr ""
14
  "X-Poedit-SourceCharset: UTF-8\n"
15
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
16
 
17
- #: wp_mail_smtp.php:251
18
- msgid "Test mail to %s"
 
19
  msgstr ""
20
 
21
- #: wp_mail_smtp.php:252
22
- msgid "This is a test email generated by the WP Mail SMTP WordPress plugin."
23
  msgstr ""
24
 
25
- #: wp_mail_smtp.php:268
26
- msgid "Test Message Sent"
27
  msgstr ""
28
 
29
- #: wp_mail_smtp.php:269
30
- msgid "The result was:"
31
  msgstr ""
32
 
33
- #: wp_mail_smtp.php:272
34
- msgid "The full debugging output is shown below:"
 
35
  msgstr ""
36
 
37
- #: wp_mail_smtp.php:275
38
- msgid "The SMTP debugging output is shown below:"
39
  msgstr ""
40
 
41
- #: wp_mail_smtp.php:242, wp_mail_smtp.php:616
42
- msgid "Send Test"
43
  msgstr ""
44
 
45
- #: wp_mail_smtp.php:287, wp_mail_smtp.php:652
46
- msgid "WP Mail SMTP Settings"
 
47
  msgstr ""
48
 
49
- #: wp_mail_smtp.php:296, src/Admin/Pages/Settings.php:58
50
- msgid "From Email"
51
  msgstr ""
52
 
53
- #: wp_mail_smtp.php:303
54
- msgid "You can specify the email address that emails should be sent from. If you leave this blank, the default email will be used."
55
  msgstr ""
56
 
57
- #: wp_mail_smtp.php:306
58
- msgid "<strong>Please Note:</strong> You appear to be using a version of WordPress prior to 2.3. Please ignore the From Name field and instead enter Name&lt;email@domain.com&gt; in this field."
59
  msgstr ""
60
 
61
- #: wp_mail_smtp.php:315, src/Admin/Pages/Settings.php:85
62
- msgid "From Name"
63
  msgstr ""
64
 
65
- #: wp_mail_smtp.php:321
66
- msgid "You can specify the name that emails should be sent from. If you leave this blank, the emails will be sent from WordPress."
67
  msgstr ""
68
 
69
- #: wp_mail_smtp.php:330, wp_mail_smtp.php:335, src/Admin/Pages/Settings.php:109
70
- msgid "Mailer"
71
  msgstr ""
72
 
73
- #: wp_mail_smtp.php:340
74
- msgid "Send all WordPress emails via SMTP."
75
  msgstr ""
76
 
77
- #: wp_mail_smtp.php:344
78
- msgid "Use the PHP mail() function to send emails."
79
  msgstr ""
80
 
81
- #: wp_mail_smtp.php:350
82
- msgid "Use Pepipost SMTP to send emails."
83
  msgstr ""
84
 
85
- #: wp_mail_smtp.php:356
86
- msgid "Looking for high inbox delivery? Try Pepipost with easy setup and free emails. Learn more %1$shere%2$s."
87
  msgstr ""
88
 
89
- #: wp_mail_smtp.php:371, wp_mail_smtp.php:376, src/Admin/Pages/Settings.php:142
90
- msgid "Return Path"
91
  msgstr ""
92
 
93
- #: wp_mail_smtp.php:381, src/Admin/Pages/Settings.php:151
94
- msgid "Set the return-path to match the From Email"
95
  msgstr ""
96
 
97
- #: wp_mail_smtp.php:385, src/Admin/Pages/Settings.php:154
98
- msgid "Return Path indicates where non-delivery receipts - or bounce messages - are to be sent."
99
  msgstr ""
100
 
101
- #: wp_mail_smtp.php:395, wp_mail_smtp.php:400, src/Admin/Pages/Misc.php:55
102
- msgid "Hide Announcements"
103
  msgstr ""
104
 
105
- #: wp_mail_smtp.php:405, src/Admin/Pages/Misc.php:62
106
- msgid "Check this if you would like to hide plugin announcements and update details."
107
  msgstr ""
108
 
109
- #: wp_mail_smtp.php:413, wp_mail_smtp.php:513, wp_mail_smtp.php:589
110
- msgid "Save Changes"
111
  msgstr ""
112
 
113
- #: wp_mail_smtp.php:418
114
- msgid "SMTP Options"
115
  msgstr ""
116
 
117
- #: wp_mail_smtp.php:420
118
- msgid "These options only apply if you have chosen to send mail by SMTP above."
119
  msgstr ""
120
 
121
- #: wp_mail_smtp.php:425, src/Providers/OptionsAbstract.php:126
122
- msgid "SMTP Host"
123
  msgstr ""
124
 
125
- #: wp_mail_smtp.php:433, wp_mail_smtp.php:551, src/Providers/OptionsAbstract.php:140
126
- msgid "SMTP Port"
127
  msgstr ""
128
 
129
- #: wp_mail_smtp.php:440, wp_mail_smtp.php:444, wp_mail_smtp.php:559, wp_mail_smtp.php:565, src/Providers/OptionsAbstract.php:154
130
- msgid "Encryption"
131
  msgstr ""
132
 
133
- #: wp_mail_smtp.php:449, wp_mail_smtp.php:571
134
- msgid "No encryption."
135
  msgstr ""
136
 
137
- #: wp_mail_smtp.php:454, wp_mail_smtp.php:576
138
- msgid "Use SSL encryption."
139
  msgstr ""
140
 
141
- #: wp_mail_smtp.php:459, wp_mail_smtp.php:581
142
- msgid "Use TLS encryption."
143
  msgstr ""
144
 
145
- #: wp_mail_smtp.php:462
146
- msgid "TLS is not the same as STARTTLS. For most servers SSL is the recommended option."
147
  msgstr ""
148
 
149
- #: wp_mail_smtp.php:467, wp_mail_smtp.php:471, src/Providers/OptionsAbstract.php:216
150
- msgid "Authentication"
151
  msgstr ""
152
 
153
- #: wp_mail_smtp.php:476
154
- msgid "No: Do not use SMTP authentication."
155
  msgstr ""
156
 
157
- #: wp_mail_smtp.php:481
158
- msgid "Yes: Use SMTP authentication."
159
  msgstr ""
160
 
161
- #: wp_mail_smtp.php:485
162
- msgid "If this is set to no, the values below are ignored."
 
163
  msgstr ""
164
 
165
- #: wp_mail_smtp.php:492, wp_mail_smtp.php:535
166
- msgid "Username"
 
167
  msgstr ""
168
 
169
- #: wp_mail_smtp.php:500, wp_mail_smtp.php:543
170
- msgid "Password"
171
  msgstr ""
172
 
173
- #: wp_mail_smtp.php:506
174
- msgid "This is in plain text because it must not be stored encrypted."
175
  msgstr ""
176
 
177
- #: wp_mail_smtp.php:520
178
- msgid "Pepipost SMTP Options"
179
  msgstr ""
180
 
181
- #: wp_mail_smtp.php:526
182
- msgid "You need to signup on %s to get the SMTP username/password."
183
  msgstr ""
184
 
185
- #: wp_mail_smtp.php:598, src/Admin/Pages/Test.php:49
186
- msgid "Send a Test Email"
187
  msgstr ""
188
 
189
- #: wp_mail_smtp.php:606
190
- msgid "To"
191
  msgstr ""
192
 
193
- #: wp_mail_smtp.php:610
194
- msgid "Type an email address here and then click Send Test to generate a test email."
195
  msgstr ""
196
 
197
- #: wp_mail_smtp.php:652, src/Admin/Area.php:127
198
- msgid "WP Mail SMTP"
199
  msgstr ""
200
 
201
- #: wp_mail_smtp.php:758, src/Admin/Area.php:370, src/Admin/Pages/Settings.php:26
202
- msgid "Settings"
203
  msgstr ""
204
 
205
- #: src/Admin/Area.php:88
206
- msgid "There was an error while processing the authentication request: %s. Please try again."
 
207
  msgstr ""
208
 
209
- #: src/Admin/Area.php:95
210
- msgid "There was an error while processing the authentication request. Please try again."
211
- msgstr ""
212
-
213
- #: src/Admin/Area.php:102
214
- msgid "There was an error while processing the authentication request. Please make sure that you have Client ID and Client Secret both valid and saved."
215
  msgstr ""
216
 
217
- #: src/Admin/Area.php:111
218
- msgid "You have successfully linked the current site with your Google API project. Now you can start sending emails through Google."
219
  msgstr ""
220
 
221
- #: src/Admin/Area.php:126
222
- msgid "WP Mail SMTP Options"
223
  msgstr ""
224
 
225
- #: src/Admin/Area.php:199
226
- msgid "Please rate <strong>WP Mail SMTP</strong> <a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">&#9733;&#9733;&#9733;&#9733;&#9733;</a> on <a href=\"%2$s\" target=\"_blank\">WordPress.org</a> to help us spread the word. Thank you from the WP Mail SMTP team!"
227
  msgstr ""
228
 
229
- #: src/Providers/OptionsAbstract.php:164
230
- msgid "None"
231
  msgstr ""
232
 
233
- #: src/Providers/OptionsAbstract.php:173
234
- msgid "SSL"
235
  msgstr ""
236
 
237
- #: src/Providers/OptionsAbstract.php:182
238
- msgid "TLS"
 
239
  msgstr ""
240
 
241
- #: src/Providers/OptionsAbstract.php:186
242
- msgid "For most servers TLS is the recommended option. If your SMTP provider offers both SSL and TLS options, we recommend using TLS."
 
243
  msgstr ""
244
 
245
- #: src/Providers/OptionsAbstract.php:194
246
- msgid "Auto TLS"
247
  msgstr ""
248
 
249
- #: src/Providers/OptionsAbstract.php:204, src/Providers/OptionsAbstract.php:226
250
- msgid "On"
251
  msgstr ""
252
 
253
- #: src/Providers/OptionsAbstract.php:205, src/Providers/OptionsAbstract.php:227
254
- msgid "Off"
255
  msgstr ""
256
 
257
- #: src/Providers/OptionsAbstract.php:208
258
- msgid "By default TLS encryption is automatically used if the server supports it, which is recommended. In some cases, due to server misconfigurations, this can cause issues and may need to be disabled."
259
- msgstr ""
 
 
 
 
260
 
261
- #: src/Providers/OptionsAbstract.php:235
262
- msgid "SMTP Username"
263
- msgstr ""
 
 
264
 
265
- #: src/Providers/OptionsAbstract.php:249
266
- msgid "SMTP Password"
267
- msgstr ""
 
 
268
 
269
- #: src/Providers/OptionsAbstract.php:263
270
- msgid "The password is stored in plain text. We highly recommend you setup your password in your WordPress configuration file for improved security; to do this add the lines below to your %s file."
271
  msgstr ""
272
 
273
- #: src/Providers/OptionsAbstract.php:300
274
- msgid "%1$s requires PHP %2$s to work and does not support your current PHP version %3$s. Please contact your host and request a PHP upgrade to the latest one."
275
  msgstr ""
276
 
277
- #: src/Providers/OptionsAbstract.php:307
278
- msgid "Meanwhile you can switch to the \"Other SMTP\" Mailer option."
 
279
  msgstr ""
280
 
281
- #: src/Admin/Pages/Misc.php:24
282
- msgid "Misc"
283
  msgstr ""
284
 
285
- #: src/Admin/Pages/Misc.php:48
286
- msgid "General"
 
287
  msgstr ""
288
 
289
- #: src/Admin/Pages/Misc.php:67, src/Admin/Pages/Settings.php:185
290
- msgid "Save Settings"
291
  msgstr ""
292
 
293
- #: src/Admin/Pages/Misc.php:95, src/Admin/Pages/Settings.php:251
294
- msgid "Settings were successfully saved."
295
  msgstr ""
296
 
297
- #: src/Admin/Pages/Settings.php:51
298
- msgid "Mail"
299
  msgstr ""
300
 
301
- #: src/Admin/Pages/Settings.php:67
302
- msgid "You can specify the email address that emails should be sent from."
303
  msgstr ""
304
 
305
- #: src/Admin/Pages/Settings.php:71
306
- msgid "If you leave this blank, the default one will be used: %s."
307
  msgstr ""
308
 
309
- #: src/Admin/Pages/Settings.php:77
310
- msgid "Please note if you are sending using an email provider (Gmail, Yahoo, Hotmail, Outlook.com, etc) this setting should be your email address for that account."
311
  msgstr ""
312
 
313
- #: src/Admin/Pages/Settings.php:94
314
- msgid "You can specify the name that emails should be sent from."
315
  msgstr ""
316
 
317
- #: src/Admin/Pages/Settings.php:98
318
- msgid "If you leave this blank, the emails will be sent from %s."
319
  msgstr ""
320
 
321
- #: src/Admin/Pages/Settings.php:155
322
- msgid "If unchecked bounce messages may be lost."
323
  msgstr ""
324
 
325
- #: src/Admin/Pages/Test.php:27
326
- msgid "Email Test"
327
  msgstr ""
328
 
329
- #: src/Admin/Pages/Test.php:56
330
- msgid "Send To"
331
  msgstr ""
332
 
333
- #: src/Admin/Pages/Test.php:61
334
- msgid "Type an email address here and then click a button below to generate a test email."
335
  msgstr ""
336
 
337
- #: src/Admin/Pages/Test.php:67
338
- msgid "Send Email"
339
  msgstr ""
340
 
341
- #: src/Admin/Pages/Test.php:87
342
- msgid "Test failed. Please use a valid email address and try to resend the test email."
343
  msgstr ""
344
 
345
- #: src/Admin/Pages/Test.php:111
346
- msgid "Test email to %s"
 
347
  msgstr ""
348
 
349
- #: src/Admin/Pages/Test.php:114
350
- msgid "This email was sent by %s mailer, and generated by the WP Mail SMTP WordPress plugin."
351
  msgstr ""
352
 
353
- #: src/Admin/Pages/Test.php:127
354
- msgid "Your email was sent successfully!"
 
355
  msgstr ""
356
 
357
- #: src/Admin/Pages/Test.php:134
358
- msgid "There was a problem while sending a test email. Related debugging output is shown below:"
359
  msgstr ""
360
 
361
- #: src/Admin/Pages/Test.php:136
362
- msgid "Please copy only the content of the error debug message above, identified with an orange left border, into the support forum topic if you experience any issues."
363
  msgstr ""
364
 
365
- #: src/Providers/Gmail/Options.php:25
366
- msgid "Gmail"
 
367
  msgstr ""
368
 
369
- #: src/Providers/Gmail/Options.php:29
370
- msgid "Send emails using your Gmail or G Suite (formerly Google Apps) account, all while keeping your login credentials safe. Other Google SMTP methods require enabling less secure apps in your account and entering your password. However, this integration uses the Google API to improve email delivery issues while keeping your site secure.<br><br>Read our %1$sGmail documentation%2$s to learn how to configure Gmail or G Suite."
371
  msgstr ""
372
 
373
- #: src/Providers/Gmail/Options.php:63
374
- msgid "Client ID"
375
  msgstr ""
376
 
377
- #: src/Providers/Gmail/Options.php:77
378
- msgid "Client Secret"
379
  msgstr ""
380
 
381
- #: src/Providers/Gmail/Options.php:91
382
- msgid "Authorized redirect URI"
383
  msgstr ""
384
 
385
- #: src/Providers/Gmail/Options.php:99
386
- msgid "Copy URL to clipboard"
387
  msgstr ""
388
 
389
- #: src/Providers/Gmail/Options.php:104
390
- msgid "This is the path on your site that you will be redirected to after you have authenticated with Google."
391
  msgstr ""
392
 
393
- #: src/Providers/Gmail/Options.php:106
394
- msgid "You need to copy this URL into \"Authorized redirect URIs\" field for you web application on Google APIs site for your project there."
395
  msgstr ""
396
 
397
- #: src/Providers/Gmail/Options.php:116
398
- msgid "Authorize"
399
  msgstr ""
400
 
401
- #: src/Providers/Gmail/Options.php:120
402
- msgid "Allow plugin to send emails using your Google account"
403
  msgstr ""
404
 
405
- #: src/Providers/Gmail/Options.php:123
406
- msgid "Click the button above to confirm authorization."
407
  msgstr ""
408
 
409
- #: src/Providers/Mail/Options.php:25
410
- msgid "Default (none)"
411
  msgstr ""
412
 
413
- #: src/Providers/Mail/Options.php:37
414
- msgid "You currently have the native WordPress option selected. Please select any other Mailer option above to continue the setup."
415
  msgstr ""
416
 
417
- #: src/Providers/Mailgun/Options.php:25
418
- msgid "Mailgun"
419
  msgstr ""
420
 
421
- #: src/Providers/Mailgun/Options.php:29
422
- msgid "%1$sMailgun%2$s is one of the leading transactional email services trusted by over 10,000 website and application developers. They provide users 10,000 free emails per month.<br><br>Read our %3$sMailgun documentation%4$s to learn how to configure Mailgun and improve your email deliverability."
423
  msgstr ""
424
 
425
- #: src/Providers/Mailgun/Options.php:57
426
- msgid "Private API Key"
427
  msgstr ""
428
 
429
- #: src/Providers/Mailgun/Options.php:69
430
- msgid "Follow this link to get an API Key from Mailgun: %s."
431
  msgstr ""
432
 
433
- #: src/Providers/Mailgun/Options.php:71
434
- msgid "Get a Private API Key"
435
  msgstr ""
436
 
437
- #: src/Providers/Mailgun/Options.php:82
438
- msgid "Domain Name"
 
439
  msgstr ""
440
 
441
- #: src/Providers/Mailgun/Options.php:94
442
- msgid "Follow this link to get a Domain Name from Mailgun: %s."
 
443
  msgstr ""
444
 
445
- #: src/Providers/Mailgun/Options.php:96
446
- msgid "Get a Domain Name"
447
  msgstr ""
448
 
449
  #: src/Providers/Pepipost/Options.php:25
@@ -454,6 +473,7 @@ msgstr ""
454
  msgid "SendGrid"
455
  msgstr ""
456
 
 
457
  #: src/Providers/Sendgrid/Options.php:29
458
  msgid "%1$sSendGrid%2$s is one of the leading transactional email services, sending over 35 billion emails every month. They provide users 100 free emails per month.<br><br>Read our %3$sSendGrid documentation%4$s to learn how to set up SendGrid and improve your email deliverability."
459
  msgstr ""
@@ -462,6 +482,7 @@ msgstr ""
462
  msgid "API Key"
463
  msgstr ""
464
 
 
465
  #: src/Providers/Sendgrid/Options.php:69
466
  msgid "Follow this link to get an API Key from SendGrid: %s."
467
  msgstr ""
@@ -470,6 +491,7 @@ msgstr ""
470
  msgid "Create API Key"
471
  msgstr ""
472
 
 
473
  #: src/Providers/Sendgrid/Options.php:79
474
  msgid "To send emails you will need only a %s access level for this API key."
475
  msgstr ""
@@ -481,3 +503,134 @@ msgstr ""
481
  #: src/Providers/SMTP/Options.php:29
482
  msgid "Use the SMTP details provided by your hosting provider or email service.<br><br>To see recommended settings for the popular services as well as troubleshooting tips, check out our %1$sSMTP documentation%2$s."
483
  msgstr ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  "X-Poedit-SourceCharset: UTF-8\n"
15
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
16
 
17
+ #. translators: %s - error code, returned by Google API.
18
+ #: src/Admin/Area.php:95
19
+ msgid "There was an error while processing the authentication request: %s. Please try again."
20
  msgstr ""
21
 
22
+ #: src/Admin/Area.php:102
23
+ msgid "There was an error while processing the authentication request. Please try again."
24
  msgstr ""
25
 
26
+ #: src/Admin/Area.php:109
27
+ msgid "There was an error while processing the authentication request. Please make sure that you have Client ID and Client Secret both valid and saved."
28
  msgstr ""
29
 
30
+ #: src/Admin/Area.php:118
31
+ msgid "You have successfully linked the current site with your Google API project. Now you can start sending emails through Google."
32
  msgstr ""
33
 
34
+ #. translators: %s - Mailer anchor link.
35
+ #: src/Admin/Area.php:147
36
+ msgid "Thanks for using WP Mail SMTP! To complete the plugin setup and start sending emails, <strong>please select and configure your <a href=\"%s\">Mailer</a></strong>."
37
  msgstr ""
38
 
39
+ #: src/Admin/Area.php:169
40
+ msgid "WP Mail SMTP Options"
41
  msgstr ""
42
 
43
+ #: src/Admin/Area.php:170, wp_mail_smtp.php:652
44
+ msgid "WP Mail SMTP"
45
  msgstr ""
46
 
47
+ #. translators: %1$s - WP.org link; %2$s - same WP.org link.
48
+ #: src/Admin/Area.php:242
49
+ msgid "Please rate <strong>WP Mail SMTP</strong> <a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">&#9733;&#9733;&#9733;&#9733;&#9733;</a> on <a href=\"%2$s\" target=\"_blank\">WordPress.org</a> to help us spread the word. Thank you from the WP Mail SMTP team!"
50
  msgstr ""
51
 
52
+ #: src/Admin/Area.php:410
53
+ msgid "WPForms related message was successfully dismissed"
54
  msgstr ""
55
 
56
+ #: src/Admin/Area.php:444, src/Admin/Pages/Settings.php:26, wp_mail_smtp.php:758
57
+ msgid "Settings"
58
  msgstr ""
59
 
60
+ #: src/Admin/Pages/Misc.php:24
61
+ msgid "Misc"
62
  msgstr ""
63
 
64
+ #: src/Admin/Pages/Misc.php:48
65
+ msgid "General"
66
  msgstr ""
67
 
68
+ #: src/Admin/Pages/Misc.php:55, wp_mail_smtp.php:395, wp_mail_smtp.php:400
69
+ msgid "Hide Announcements"
70
  msgstr ""
71
 
72
+ #: src/Admin/Pages/Misc.php:62, wp_mail_smtp.php:405
73
+ msgid "Check this if you would like to hide plugin announcements and update details."
74
  msgstr ""
75
 
76
+ #: src/Admin/Pages/Misc.php:69
77
+ msgid "Uninstall WP Mail SMTP"
78
  msgstr ""
79
 
80
+ #: src/Admin/Pages/Misc.php:75
81
+ msgid "Check this if you would like to remove ALL WP Mail SMTP data upon plugin deletion. All settings will be unrecoverable."
82
  msgstr ""
83
 
84
+ #: src/Admin/Pages/Misc.php:80, src/Admin/Pages/Settings.php:206
85
+ msgid "Save Settings"
86
  msgstr ""
87
 
88
+ #: src/Admin/Pages/Misc.php:111, src/Admin/Pages/Settings.php:387
89
+ msgid "Settings were successfully saved."
90
  msgstr ""
91
 
92
+ #: src/Admin/Pages/Settings.php:51
93
+ msgid "Mail"
94
  msgstr ""
95
 
96
+ #: src/Admin/Pages/Settings.php:58, wp_mail_smtp.php:296
97
+ msgid "From Email"
98
  msgstr ""
99
 
100
+ #: src/Admin/Pages/Settings.php:68
101
+ msgid "The email address which emails are sent from."
102
  msgstr ""
103
 
104
+ #: src/Admin/Pages/Settings.php:69
105
+ msgid "If you using an email provider (Gmail, Yahoo, Outlook.com, etc) this should be your email address for that account."
106
  msgstr ""
107
 
108
+ #: src/Admin/Pages/Settings.php:73
109
+ msgid "Please note that other plugins can change this, to prevent this use the setting below."
110
  msgstr ""
111
 
112
+ #: src/Admin/Pages/Settings.php:84
113
+ msgid "Force From Email"
114
  msgstr ""
115
 
116
+ #: src/Admin/Pages/Settings.php:88
117
+ msgid "If checked, the From Email setting above will be used for all emails, ignoring values set by other plugins."
118
  msgstr ""
119
 
120
+ #: src/Admin/Pages/Settings.php:96, wp_mail_smtp.php:315
121
+ msgid "From Name"
122
  msgstr ""
123
 
124
+ #: src/Admin/Pages/Settings.php:106
125
+ msgid "The name which emails are sent from."
126
  msgstr ""
127
 
128
+ #: src/Admin/Pages/Settings.php:117
129
+ msgid "Force From Name"
130
  msgstr ""
131
 
132
+ #: src/Admin/Pages/Settings.php:121
133
+ msgid "If checked, the From Name setting above will be used for all emails, ignoring values set by other plugins."
134
  msgstr ""
135
 
136
+ #: src/Admin/Pages/Settings.php:129, wp_mail_smtp.php:330, wp_mail_smtp.php:335
137
+ msgid "Mailer"
138
  msgstr ""
139
 
140
+ #: src/Admin/Pages/Settings.php:162, wp_mail_smtp.php:371, wp_mail_smtp.php:376
141
+ msgid "Return Path"
142
  msgstr ""
143
 
144
+ #: src/Admin/Pages/Settings.php:171, wp_mail_smtp.php:381
145
+ msgid "Set the return-path to match the From Email"
146
  msgstr ""
147
 
148
+ #: src/Admin/Pages/Settings.php:175, wp_mail_smtp.php:385
149
+ msgid "Return Path indicates where non-delivery receipts - or bounce messages - are to be sent."
150
  msgstr ""
151
 
152
+ #: src/Admin/Pages/Settings.php:176
153
+ msgid "If unchecked bounce messages may be lost."
154
  msgstr ""
155
 
156
+ #: src/Admin/Pages/Settings.php:244
157
+ msgid "Get WPForms Pro and Support WP Mail SMTP"
158
  msgstr ""
159
 
160
+ #: src/Admin/Pages/Settings.php:248
161
+ msgid "WP Mail SMTP is a free plugin, and the team behind WPForms maintain it to give back to the WordPress community."
162
  msgstr ""
163
 
164
+ #. translators: %s - WPForms.com URL.
165
+ #: src/Admin/Pages/Settings.php:256
166
+ msgid "Please consider supporting us by <a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer\">purchasing a WPForms Pro license</a>. Aside from getting access to the best drag & drop WordPress form builder plugin, your purchase will help us continue to maintain and add new features to the WP Mail SMTP plugin while keeping this SMTP plugin free for the larger WordPress community."
167
  msgstr ""
168
 
169
+ #. translators: %s - link to WP.org repo and 5 HTML encoded stars as a label.
170
+ #: src/Admin/Pages/Settings.php:274
171
+ msgid "We know that you will truly love WPForms. It has over 2000+ five star ratings (%s) and is active on over 1 million websites."
172
  msgstr ""
173
 
174
+ #: src/Admin/Pages/Settings.php:280
175
+ msgid "Other Benefits:"
176
  msgstr ""
177
 
178
+ #: src/Admin/Pages/Settings.php:284
179
+ msgid "Access to premium support for WP Mail SMTP"
180
  msgstr ""
181
 
182
+ #: src/Admin/Pages/Settings.php:285
183
+ msgid "Get the best drag & drop form builder"
184
  msgstr ""
185
 
186
+ #: src/Admin/Pages/Settings.php:286
187
+ msgid "All form features like file upload, pagination, etc"
188
  msgstr ""
189
 
190
+ #: src/Admin/Pages/Settings.php:287
191
+ msgid "Create surveys & polls with the surveys addon"
192
  msgstr ""
193
 
194
+ #: src/Admin/Pages/Settings.php:290
195
+ msgid "No future ads inside WP Mail SMTP admin"
196
  msgstr ""
197
 
198
+ #: src/Admin/Pages/Settings.php:291
199
+ msgid "Pre-made form templates and smart conditional logic"
200
  msgstr ""
201
 
202
+ #: src/Admin/Pages/Settings.php:292
203
+ msgid "500+ integrations with different marketing & payment services"
204
  msgstr ""
205
 
206
+ #: src/Admin/Pages/Settings.php:293
207
+ msgid "Collect signatures, geo-location data, and more"
208
  msgstr ""
209
 
210
+ #. translators: %1$s - WPForms.com URL, %2$s - percents off.
211
+ #: src/Admin/Pages/Settings.php:302
212
+ msgid "<a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">Get WPForms Pro and support WP Mail SMTP</a> - use coupon \"<strong>thankyou</strong>\" to save %2$s off your purchase."
213
  msgstr ""
214
 
215
+ #: src/Admin/Pages/Test.php:27
216
+ msgid "Email Test"
 
 
 
 
217
  msgstr ""
218
 
219
+ #: src/Admin/Pages/Test.php:49, wp_mail_smtp.php:598
220
+ msgid "Send a Test Email"
221
  msgstr ""
222
 
223
+ #: src/Admin/Pages/Test.php:56
224
+ msgid "Send To"
225
  msgstr ""
226
 
227
+ #: src/Admin/Pages/Test.php:61
228
+ msgid "Type an email address here and then click a button below to generate a test email."
229
  msgstr ""
230
 
231
+ #: src/Admin/Pages/Test.php:67
232
+ msgid "Send Email"
233
  msgstr ""
234
 
235
+ #: src/Admin/Pages/Test.php:87
236
+ msgid "Test failed. Please use a valid email address and try to resend the test email."
237
  msgstr ""
238
 
239
+ #. translators: %s - email address a test email will be sent to.
240
+ #: src/Admin/Pages/Test.php:111
241
+ msgid "Test email to %s"
242
  msgstr ""
243
 
244
+ #. translators: %s - mailer name.
245
+ #: src/Admin/Pages/Test.php:114
246
+ msgid "This email was sent by %s mailer, and generated by the WP Mail SMTP WordPress plugin."
247
  msgstr ""
248
 
249
+ #: src/Admin/Pages/Test.php:127
250
+ msgid "Your email was sent successfully!"
251
  msgstr ""
252
 
253
+ #: src/Admin/Pages/Test.php:134
254
+ msgid "There was a problem while sending a test email. Related debugging output is shown below:"
255
  msgstr ""
256
 
257
+ #: src/Admin/Pages/Test.php:136
258
+ msgid "Please copy only the content of the error debug message above, identified with an orange left border, into the support forum topic if you experience any issues."
259
  msgstr ""
260
 
261
+ #. translators: 1: plugin name(s).
262
+ #. translators: 1: plugin name(s).
263
+ #: src/Core.php:243, src/Core.php:249
264
+ msgid "Thanks for installing WP Mail SMTP. We also recommend using %1$s. It's the best drag & drop form builder, has over 1 million active installs, and over 2000+ 5 star ratings."
265
+ msgid_plural "Thanks for installing WP Mail SMTP. We also recommend using %1$s. It's the best drag & drop form builder, has over 1 million active installs, and over 2000+ 5 star ratings."
266
+ msgstr[0] ""
267
+ msgstr[1] ""
268
 
269
+ #: src/Core.php:254
270
+ msgid "Install WPForms Now"
271
+ msgid_plural "Begin installing plugins"
272
+ msgstr[0] ""
273
+ msgstr[1] ""
274
 
275
+ #: src/Core.php:259
276
+ msgid "Activate WPForms"
277
+ msgid_plural "Begin activating plugins"
278
+ msgstr[0] ""
279
+ msgstr[1] ""
280
 
281
+ #: src/Core.php:289
282
+ msgid "<strong>EMAIL DELIVERY ERROR:</strong> WP Mail SMTP plugin logged this error during the last time it tried to send an email: "
283
  msgstr ""
284
 
285
+ #: src/Core.php:318
286
+ msgid "Consider running an email test after fixing it."
287
  msgstr ""
288
 
289
+ #. translators: %1$s - Plugin name causing conflict; %2$s - Plugin name causing conflict.
290
+ #: src/Core.php:468
291
+ msgid "Heads up! WP Mail SMTP has detected %1$s is activated. Please deactivate %2$s to prevent conflicts."
292
  msgstr ""
293
 
294
+ #: src/Providers/Gmail/Options.php:25
295
+ msgid "Gmail"
296
  msgstr ""
297
 
298
+ #. translators: %1$s - opening link tag; %2$s - closing link tag.
299
+ #: src/Providers/Gmail/Options.php:29
300
+ msgid "Send emails using your Gmail or G Suite (formerly Google Apps) account, all while keeping your login credentials safe. Other Google SMTP methods require enabling less secure apps in your account and entering your password. However, this integration uses the Google API to improve email delivery issues while keeping your site secure.<br><br>Read our %1$sGmail documentation%2$s to learn how to configure Gmail or G Suite."
301
  msgstr ""
302
 
303
+ #: src/Providers/Gmail/Options.php:64
304
+ msgid "Client ID"
305
  msgstr ""
306
 
307
+ #: src/Providers/Gmail/Options.php:79
308
+ msgid "Client Secret"
309
  msgstr ""
310
 
311
+ #: src/Providers/Gmail/Options.php:94
312
+ msgid "Authorized redirect URI"
313
  msgstr ""
314
 
315
+ #: src/Providers/Gmail/Options.php:102
316
+ msgid "Copy URL to clipboard"
317
  msgstr ""
318
 
319
+ #: src/Providers/Gmail/Options.php:107
320
+ msgid "This is the path on your site that you will be redirected to after you have authenticated with Google."
321
  msgstr ""
322
 
323
+ #: src/Providers/Gmail/Options.php:109
324
+ msgid "You need to copy this URL into \"Authorized redirect URIs\" field for you web application on Google APIs site for your project there."
325
  msgstr ""
326
 
327
+ #: src/Providers/Gmail/Options.php:118
328
+ msgid "Authorization"
329
  msgstr ""
330
 
331
+ #: src/Providers/Gmail/Options.php:143
332
+ msgid "Are you sure you want to reset the current Gmail connection? You will need to immediately create a new one to be able to send emails."
333
  msgstr ""
334
 
335
+ #: src/Providers/Gmail/Options.php:151
336
+ msgid "Allow plugin to send emails using your Google account"
337
  msgstr ""
338
 
339
+ #: src/Providers/Gmail/Options.php:154
340
+ msgid "Click the button above to confirm authorization."
341
  msgstr ""
342
 
343
+ #: src/Providers/Gmail/Options.php:160
344
+ msgid "Remove Connection"
345
  msgstr ""
346
 
347
+ #: src/Providers/Gmail/Options.php:163
348
+ msgid "Removing the connection will give you an ability to redo the connection or link to another Google account."
349
  msgstr ""
350
 
351
+ #: src/Providers/Gmail/Options.php:171
352
+ msgid "To setup Gmail integration properly you should save Client ID and Client Secret."
353
  msgstr ""
354
 
355
+ #: src/Providers/Mailgun/Options.php:25
356
+ msgid "Mailgun"
357
  msgstr ""
358
 
359
+ #. translators: %1$s - opening link tag; %2$s - closing link tag; %3$s - opening link tag; %4$s - closing link tag.
360
+ #: src/Providers/Mailgun/Options.php:29
361
+ msgid "%1$sMailgun%2$s is one of the leading transactional email services trusted by over 10,000 website and application developers. They provide users 10,000 free emails per month.<br><br>Read our %3$sMailgun documentation%4$s to learn how to configure Mailgun and improve your email deliverability."
362
  msgstr ""
363
 
364
+ #: src/Providers/Mailgun/Options.php:57
365
+ msgid "Private API Key"
366
  msgstr ""
367
 
368
+ #. translators: %s - API key link.
369
+ #: src/Providers/Mailgun/Options.php:69
370
+ msgid "Follow this link to get an API Key from Mailgun: %s."
371
  msgstr ""
372
 
373
+ #: src/Providers/Mailgun/Options.php:71
374
+ msgid "Get a Private API Key"
375
  msgstr ""
376
 
377
+ #: src/Providers/Mailgun/Options.php:82
378
+ msgid "Domain Name"
379
  msgstr ""
380
 
381
+ #. translators: %s - Domain Name link.
382
+ #: src/Providers/Mailgun/Options.php:94
383
+ msgid "Follow this link to get a Domain Name from Mailgun: %s."
384
  msgstr ""
385
 
386
+ #: src/Providers/Mailgun/Options.php:96
387
+ msgid "Get a Domain Name"
388
  msgstr ""
389
 
390
+ #: src/Providers/Mail/Options.php:25
391
+ msgid "Default (none)"
392
  msgstr ""
393
 
394
+ #: src/Providers/Mail/Options.php:37
395
+ msgid "You currently have the native WordPress option selected. Please select any other Mailer option above to continue the setup."
396
  msgstr ""
397
 
398
+ #: src/Providers/OptionsAbstract.php:126, wp_mail_smtp.php:425
399
+ msgid "SMTP Host"
400
  msgstr ""
401
 
402
+ #: src/Providers/OptionsAbstract.php:140, wp_mail_smtp.php:440, wp_mail_smtp.php:444, wp_mail_smtp.php:559, wp_mail_smtp.php:565
403
+ msgid "Encryption"
404
  msgstr ""
405
 
406
+ #: src/Providers/OptionsAbstract.php:150
407
+ msgid "None"
408
  msgstr ""
409
 
410
+ #: src/Providers/OptionsAbstract.php:159
411
+ msgid "SSL"
412
  msgstr ""
413
 
414
+ #: src/Providers/OptionsAbstract.php:168
415
+ msgid "TLS"
416
  msgstr ""
417
 
418
+ #: src/Providers/OptionsAbstract.php:172
419
+ msgid "For most servers TLS is the recommended option. If your SMTP provider offers both SSL and TLS options, we recommend using TLS."
420
  msgstr ""
421
 
422
+ #: src/Providers/OptionsAbstract.php:180, wp_mail_smtp.php:433, wp_mail_smtp.php:551
423
+ msgid "SMTP Port"
424
  msgstr ""
425
 
426
+ #: src/Providers/OptionsAbstract.php:194
427
+ msgid "Auto TLS"
428
  msgstr ""
429
 
430
+ #: src/Providers/OptionsAbstract.php:204, src/Providers/OptionsAbstract.php:226
431
+ msgid "On"
432
  msgstr ""
433
 
434
+ #: src/Providers/OptionsAbstract.php:205, src/Providers/OptionsAbstract.php:227
435
+ msgid "Off"
436
  msgstr ""
437
 
438
+ #: src/Providers/OptionsAbstract.php:208
439
+ msgid "By default TLS encryption is automatically used if the server supports it, which is recommended. In some cases, due to server misconfigurations, this can cause issues and may need to be disabled."
440
  msgstr ""
441
 
442
+ #: src/Providers/OptionsAbstract.php:216, wp_mail_smtp.php:467, wp_mail_smtp.php:471
443
+ msgid "Authentication"
444
  msgstr ""
445
 
446
+ #: src/Providers/OptionsAbstract.php:235
447
+ msgid "SMTP Username"
448
  msgstr ""
449
 
450
+ #: src/Providers/OptionsAbstract.php:249
451
+ msgid "SMTP Password"
452
  msgstr ""
453
 
454
+ #. translators: %s - wp-config.php.
455
+ #: src/Providers/OptionsAbstract.php:263
456
+ msgid "The password is stored in plain text. We highly recommend you setup your password in your WordPress configuration file for improved security; to do this add the lines below to your %s file."
457
  msgstr ""
458
 
459
+ #. translators: %1$s - Provider name; %2$s - PHP version required by Provider; %3$s - current PHP version.
460
+ #: src/Providers/OptionsAbstract.php:300
461
+ msgid "%1$s requires PHP %2$s to work and does not support your current PHP version %3$s. Please contact your host and request a PHP upgrade to the latest one."
462
  msgstr ""
463
 
464
+ #: src/Providers/OptionsAbstract.php:307
465
+ msgid "Meanwhile you can switch to the \"Other SMTP\" Mailer option."
466
  msgstr ""
467
 
468
  #: src/Providers/Pepipost/Options.php:25
473
  msgid "SendGrid"
474
  msgstr ""
475
 
476
+ #. translators: %1$s - opening link tag; %2$s - closing link tag; %3$s - opening link tag; %4$s - closing link tag.
477
  #: src/Providers/Sendgrid/Options.php:29
478
  msgid "%1$sSendGrid%2$s is one of the leading transactional email services, sending over 35 billion emails every month. They provide users 100 free emails per month.<br><br>Read our %3$sSendGrid documentation%4$s to learn how to set up SendGrid and improve your email deliverability."
479
  msgstr ""
482
  msgid "API Key"
483
  msgstr ""
484
 
485
+ #. translators: %s - API key link.
486
  #: src/Providers/Sendgrid/Options.php:69
487
  msgid "Follow this link to get an API Key from SendGrid: %s."
488
  msgstr ""
491
  msgid "Create API Key"
492
  msgstr ""
493
 
494
+ #. translators: %s - SendGrid access level.
495
  #: src/Providers/Sendgrid/Options.php:79
496
  msgid "To send emails you will need only a %s access level for this API key."
497
  msgstr ""
503
  #: src/Providers/SMTP/Options.php:29
504
  msgid "Use the SMTP details provided by your hosting provider or email service.<br><br>To see recommended settings for the popular services as well as troubleshooting tips, check out our %1$sSMTP documentation%2$s."
505
  msgstr ""
506
+
507
+ #. translators: %s - email address where test mail will be sent to.
508
+ #: wp_mail_smtp.php:251
509
+ msgid "Test mail to %s"
510
+ msgstr ""
511
+
512
+ #: wp_mail_smtp.php:252
513
+ msgid "This is a test email generated by the WP Mail SMTP WordPress plugin."
514
+ msgstr ""
515
+
516
+ #: wp_mail_smtp.php:268
517
+ msgid "Test Message Sent"
518
+ msgstr ""
519
+
520
+ #: wp_mail_smtp.php:269
521
+ msgid "The result was:"
522
+ msgstr ""
523
+
524
+ #: wp_mail_smtp.php:272
525
+ msgid "The full debugging output is shown below:"
526
+ msgstr ""
527
+
528
+ #: wp_mail_smtp.php:275
529
+ msgid "The SMTP debugging output is shown below:"
530
+ msgstr ""
531
+
532
+ #: wp_mail_smtp.php:242, wp_mail_smtp.php:616
533
+ msgid "Send Test"
534
+ msgstr ""
535
+
536
+ #: wp_mail_smtp.php:287, wp_mail_smtp.php:652
537
+ msgid "WP Mail SMTP Settings"
538
+ msgstr ""
539
+
540
+ #: wp_mail_smtp.php:303
541
+ msgid "You can specify the email address that emails should be sent from. If you leave this blank, the default email will be used."
542
+ msgstr ""
543
+
544
+ #: wp_mail_smtp.php:306
545
+ msgid "<strong>Please Note:</strong> You appear to be using a version of WordPress prior to 2.3. Please ignore the From Name field and instead enter Name&lt;email@domain.com&gt; in this field."
546
+ msgstr ""
547
+
548
+ #: wp_mail_smtp.php:321
549
+ msgid "You can specify the name that emails should be sent from. If you leave this blank, the emails will be sent from WordPress."
550
+ msgstr ""
551
+
552
+ #: wp_mail_smtp.php:340
553
+ msgid "Send all WordPress emails via SMTP."
554
+ msgstr ""
555
+
556
+ #: wp_mail_smtp.php:344
557
+ msgid "Use the PHP mail() function to send emails."
558
+ msgstr ""
559
+
560
+ #: wp_mail_smtp.php:350
561
+ msgid "Use Pepipost SMTP to send emails."
562
+ msgstr ""
563
+
564
+ #. translators: %1$s - link start; %2$s - link end.
565
+ #: wp_mail_smtp.php:356
566
+ msgid "Looking for high inbox delivery? Try Pepipost with easy setup and free emails. Learn more %1$shere%2$s."
567
+ msgstr ""
568
+
569
+ #: wp_mail_smtp.php:413, wp_mail_smtp.php:513, wp_mail_smtp.php:589
570
+ msgid "Save Changes"
571
+ msgstr ""
572
+
573
+ #: wp_mail_smtp.php:418
574
+ msgid "SMTP Options"
575
+ msgstr ""
576
+
577
+ #: wp_mail_smtp.php:420
578
+ msgid "These options only apply if you have chosen to send mail by SMTP above."
579
+ msgstr ""
580
+
581
+ #: wp_mail_smtp.php:449, wp_mail_smtp.php:571
582
+ msgid "No encryption."
583
+ msgstr ""
584
+
585
+ #: wp_mail_smtp.php:454, wp_mail_smtp.php:576
586
+ msgid "Use SSL encryption."
587
+ msgstr ""
588
+
589
+ #: wp_mail_smtp.php:459, wp_mail_smtp.php:581
590
+ msgid "Use TLS encryption."
591
+ msgstr ""
592
+
593
+ #: wp_mail_smtp.php:462
594
+ msgid "TLS is not the same as STARTTLS. For most servers SSL is the recommended option."
595
+ msgstr ""
596
+
597
+ #: wp_mail_smtp.php:476
598
+ msgid "No: Do not use SMTP authentication."
599
+ msgstr ""
600
+
601
+ #: wp_mail_smtp.php:481
602
+ msgid "Yes: Use SMTP authentication."
603
+ msgstr ""
604
+
605
+ #: wp_mail_smtp.php:485
606
+ msgid "If this is set to no, the values below are ignored."
607
+ msgstr ""
608
+
609
+ #: wp_mail_smtp.php:492, wp_mail_smtp.php:535
610
+ msgid "Username"
611
+ msgstr ""
612
+
613
+ #: wp_mail_smtp.php:500, wp_mail_smtp.php:543
614
+ msgid "Password"
615
+ msgstr ""
616
+
617
+ #: wp_mail_smtp.php:506
618
+ msgid "This is in plain text because it must not be stored encrypted."
619
+ msgstr ""
620
+
621
+ #: wp_mail_smtp.php:520
622
+ msgid "Pepipost SMTP Options"
623
+ msgstr ""
624
+
625
+ #. translators: %s - Pepipost registration URL.
626
+ #: wp_mail_smtp.php:526
627
+ msgid "You need to signup on %s to get the SMTP username/password."
628
+ msgstr ""
629
+
630
+ #: wp_mail_smtp.php:606
631
+ msgid "To"
632
+ msgstr ""
633
+
634
+ #: wp_mail_smtp.php:610
635
+ msgid "Type an email address here and then click Send Test to generate a test email."
636
+ msgstr ""
readme.txt CHANGED
@@ -6,13 +6,13 @@ Tested up to: 4.9
6
  Stable tag: trunk
7
  Requires PHP: 5.3
8
 
9
- The most popular WordPress SMTP and PHP Mailer plugin. Trusted by over 700k sites.
10
 
11
  == Description ==
12
 
13
  = WordPress Mail SMTP Plugin =
14
 
15
- Having problems with your WordPress site not sending emails? You're not alone. Over 700,000 websites use WP Mail SMTP to fix their email deliverability issues.
16
 
17
  WP Mail SMTP fixes your email deliverability by reconfiguring the wp_mail() PHP function to use a proper SMTP provider.
18
 
@@ -146,7 +146,31 @@ By all means please contact us to discuss features or options you'd like to see
146
 
147
  == Changelog ==
148
 
149
- = 1.2.5 - 2018-02-05 =
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  * Fixed: `Return path` can't be turned off.
151
  * Fixed: `Authentication` sometimes can't be turned off.
152
  * Fixed: `Auto TLS` sometimes can't be turned off.
@@ -161,10 +185,10 @@ By all means please contact us to discuss features or options you'd like to see
161
  * Changed: Do not autoload on each page request plugin settings from WordPress options table.
162
  * Changed: Do not autoload Pepipost classes unless it's saved as active mailer in settings.
163
 
164
- = 1.2.4 - 2018-01-28 =
165
  * Fixed: Improved escaping in debug reporting.
166
 
167
- = 1.2.3 - 2018-01-22 =
168
  * Fixed: Gmail tokens were reset after clicking Save Settings.
169
  * Fixed: Slight typo in Gmail success message.
170
 
6
  Stable tag: trunk
7
  Requires PHP: 5.3
8
 
9
+ The most popular WordPress SMTP and PHP Mailer plugin. Trusted by over 900k sites.
10
 
11
  == Description ==
12
 
13
  = WordPress Mail SMTP Plugin =
14
 
15
+ Having problems with your WordPress site not sending emails? You're not alone. Over 900,000 websites use WP Mail SMTP to fix their email deliverability issues.
16
 
17
  WP Mail SMTP fixes your email deliverability by reconfiguring the wp_mail() PHP function to use a proper SMTP provider.
18
 
146
 
147
  == Changelog ==
148
 
149
+ = 1.3.0 - 2018-06-28 =
150
+ * Added: New option: force From Email rewrite regardless of the current value.
151
+ * Added: New option: force From Name rewrite regardless of the current value.
152
+ * Added: New option: remove all plugin data on plugin uninstall (when user deletes it).
153
+ * Added: Notify site admins in wp-admin area with a notice about last failed email delivery. Cleans up on successful delivery.
154
+ * Added: Notify site admins in wp-admin area with a notice about possible compatibility issues with other SMTP and email delivery plugins.
155
+ * Added: Improve User Debug Experience when doing Email Test - display helpful description and steps to fix the issue.
156
+ * Added: New users: provide default SMTP Port value for new users based on Encryption selection.
157
+ * Added: New users: notify about not configured plugin settings.
158
+ * Added: New users: Recommend free WPForms Lite plugin for those who don't have it.
159
+ * Added: SendGrid/Mailgun: provide support for multipart/alternative types of emails.
160
+ * Added: Gmail: new button to remove connection and to connect a new Google account.
161
+ * Fixed: Support plugin installation into /mu-plugins/ directory.
162
+ * Fixed: SendGrid: required text/plain part of email being the first one - fixes plain text emails not having links.
163
+ * Fixed: SendGrid and Mailgun: improperly sending plain text emails in html format.
164
+ * Fixed: SMTP Debug output was empty in some cases.
165
+ * Fixed: Compatibility with lots of other plugins that use Google Analytics library of different versions.
166
+ * Fixed: "client_id is empty" is no more a problem, should be fixed.
167
+ * Changed: For SendGrid and Mailgun allow using custom defined attachments names if present. Fallback to file name.
168
+ * Changed: Gmail: switch to a wider scope to prevent possible issues in certain circumstances.
169
+ * Changed: Remove whitespaces start/end of keys, secrets etc.
170
+ * Changed: Improved helpful description tests of various options.
171
+ * Changed: Improved plugin autoloading functionality.
172
+
173
+ = 1.2.5 - 2017-02-05 =
174
  * Fixed: `Return path` can't be turned off.
175
  * Fixed: `Authentication` sometimes can't be turned off.
176
  * Fixed: `Auto TLS` sometimes can't be turned off.
185
  * Changed: Do not autoload on each page request plugin settings from WordPress options table.
186
  * Changed: Do not autoload Pepipost classes unless it's saved as active mailer in settings.
187
 
188
+ = 1.2.4 - 2017-01-28 =
189
  * Fixed: Improved escaping in debug reporting.
190
 
191
+ = 1.2.3 - 2017-01-22 =
192
  * Fixed: Gmail tokens were reset after clicking Save Settings.
193
  * Fixed: Slight typo in Gmail success message.
194
 
src/Admin/Area.php CHANGED
@@ -3,6 +3,7 @@
3
  namespace WPMailSMTP\Admin;
4
 
5
  use WPMailSMTP\WP;
 
6
 
7
  /**
8
  * Class Area registers and process all wp-admin display functionality.
@@ -60,11 +61,17 @@ class Area {
60
  // Display custom notices based on the error/success codes.
61
  add_action( 'admin_init', array( $this, 'display_custom_auth_notices' ) );
62
 
 
 
 
63
  // Outputs the plugin admin header.
64
  add_action( 'in_admin_header', array( $this, 'display_admin_header' ), 100 );
65
 
66
  // Hide all unrelated to the plugin notices on the plugin admin pages.
67
  add_action( 'admin_print_scripts', array( $this, 'hide_unrelated_notices' ) );
 
 
 
68
  }
69
 
70
  /**
@@ -115,6 +122,42 @@ class Area {
115
  }
116
  }
117
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  /**
119
  * Add admin area menu item.
120
  *
@@ -351,6 +394,37 @@ class Area {
351
  $this->pages[ $this->get_current_tab() ]->process_auth();
352
  }
353
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
  /**
355
  * Add a link to Settings page of a plugin on Plugins page.
356
  *
3
  namespace WPMailSMTP\Admin;
4
 
5
  use WPMailSMTP\WP;
6
+ use WPMailSMTP\Options;
7
 
8
  /**
9
  * Class Area registers and process all wp-admin display functionality.
61
  // Display custom notices based on the error/success codes.
62
  add_action( 'admin_init', array( $this, 'display_custom_auth_notices' ) );
63
 
64
+ // Display notice instructing the user to complete plugin setup.
65
+ add_action( 'admin_init', array( $this, 'display_setup_notice' ) );
66
+
67
  // Outputs the plugin admin header.
68
  add_action( 'in_admin_header', array( $this, 'display_admin_header' ), 100 );
69
 
70
  // Hide all unrelated to the plugin notices on the plugin admin pages.
71
  add_action( 'admin_print_scripts', array( $this, 'hide_unrelated_notices' ) );
72
+
73
+ // Process all AJAX requests.
74
+ add_action( 'wp_ajax_wp_mail_smtp_ajax', array( $this, 'process_ajax' ) );
75
  }
76
 
77
  /**
122
  }
123
  }
124
 
125
+ /**
126
+ * Display notice instructing the user to complete plugin setup.
127
+ *
128
+ * @since 1.3.0
129
+ */
130
+ public function display_setup_notice() {
131
+
132
+ // Bail if we're not on a plugin page.
133
+ if ( ! $this->is_admin_page() ) {
134
+ return;
135
+ }
136
+
137
+ // Check if the current settings are the same as the default settings.
138
+ if ( wp_json_encode( Options::init()->get_all() ) !== wp_json_encode( Options::get_defaults() ) ) {
139
+ return;
140
+ }
141
+
142
+ // Display notice informing user further action is needed.
143
+ WP::add_admin_notice(
144
+ sprintf(
145
+ wp_kses(
146
+ /* translators: %s - Mailer anchor link. */
147
+ __( 'Thanks for using WP Mail SMTP! To complete the plugin setup and start sending emails, <strong>please select and configure your <a href="%s">Mailer</a></strong>.', 'wp-mail-smtp' ),
148
+ array(
149
+ 'a' => array(
150
+ 'href' => array(),
151
+ ),
152
+ 'strong' => array(),
153
+ )
154
+ ),
155
+ '#wp-mail-smtp-setting-row-mailer'
156
+ ),
157
+ WP::ADMIN_NOTICE_INFO
158
+ );
159
+ }
160
+
161
  /**
162
  * Add admin area menu item.
163
  *
394
  $this->pages[ $this->get_current_tab() ]->process_auth();
395
  }
396
 
397
+ /**
398
+ * Process all AJAX requests.
399
+ *
400
+ * @since 1.3.0
401
+ */
402
+ public function process_ajax() {
403
+
404
+ $task = sanitize_key( $_POST['task'] );
405
+ $data = array();
406
+
407
+ switch ( $task ) {
408
+ case 'wpforms_dismiss':
409
+ update_user_meta( get_current_user_id(), 'wp_mail_smtp_wpforms_dismissed', true );
410
+ $data['message'] = esc_html__( 'WPForms related message was successfully dismissed', 'wp-mail-smtp' );
411
+ break;
412
+
413
+ default:
414
+ // Allow custom tasks data processing being added here.
415
+ $data = apply_filters( 'wp_mail_smtp_admin_process_ajax_' . $task . '_data', $data );
416
+ }
417
+
418
+ // Final ability to rewrite all the data, just in case.
419
+ $data = (array) apply_filters( 'wp_mail_smtp_admin_process_ajax_data', $data, $task );
420
+
421
+ if ( empty( $data ) ) {
422
+ wp_send_json_error( $data );
423
+ }
424
+
425
+ wp_send_json_success( $data );
426
+ }
427
+
428
  /**
429
  * Add a link to Settings page of a plugin on Plugins page.
430
  *
src/Admin/Pages/Misc.php CHANGED
@@ -58,11 +58,24 @@ class Misc extends PageAbstract {
58
  <input name="wp-mail-smtp[general][am_notifications_hidden]" type="checkbox"
59
  value="true" <?php checked( true, $options->get( 'general', 'am_notifications_hidden' ) ); ?>
60
  id="wp-mail-smtp-setting-am_notifications_hidden"
61
- />
62
  <label for="wp-mail-smtp-setting-am_notifications_hidden"><?php esc_html_e( 'Check this if you would like to hide plugin announcements and update details.', 'wp-mail-smtp' ); ?></label>
63
  </div>
64
  </div>
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  <p class="wp-mail-smtp-submit">
67
  <button type="submit" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange"><?php esc_html_e( 'Save Settings', 'wp-mail-smtp' ); ?></button>
68
  </p>
@@ -81,10 +94,13 @@ class Misc extends PageAbstract {
81
 
82
  $options = new Options();
83
 
84
- // Unchecked checkbox doesn't exist in $_POST, so we need to ensure we actually have it.
85
  if ( empty( $data['general']['am_notifications_hidden'] ) ) {
86
  $data['general']['am_notifications_hidden'] = false;
87
  }
 
 
 
88
 
89
  $to_save = array_merge( $options->get_all(), $data );
90
 
58
  <input name="wp-mail-smtp[general][am_notifications_hidden]" type="checkbox"
59
  value="true" <?php checked( true, $options->get( 'general', 'am_notifications_hidden' ) ); ?>
60
  id="wp-mail-smtp-setting-am_notifications_hidden"
61
+ >
62
  <label for="wp-mail-smtp-setting-am_notifications_hidden"><?php esc_html_e( 'Check this if you would like to hide plugin announcements and update details.', 'wp-mail-smtp' ); ?></label>
63
  </div>
64
  </div>
65
 
66
+ <!-- Uninstall -->
67
+ <div id="wp-mail-smtp-setting-row-uninstall" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox wp-mail-smtp-clear">
68
+ <div class="wp-mail-smtp-setting-label">
69
+ <label for="wp-mail-smtp-setting-uninstall"><?php esc_html_e( 'Uninstall WP Mail SMTP', 'wp-mail-smtp' ); ?></label>
70
+ </div>
71
+ <div class="wp-mail-smtp-setting-field">
72
+ <input name="wp-mail-smtp[general][uninstall]" type="checkbox"
73
+ value="true" <?php checked( true, $options->get( 'general', 'uninstall' ) ); ?>
74
+ id="wp-mail-smtp-setting-uninstall">
75
+ <label for="wp-mail-smtp-setting-uninstall"><?php esc_html_e( 'Check this if you would like to remove ALL WP Mail SMTP data upon plugin deletion. All settings will be unrecoverable.', 'wp-mail-smtp' ); ?></label>
76
+ </div>
77
+ </div>
78
+
79
  <p class="wp-mail-smtp-submit">
80
  <button type="submit" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange"><?php esc_html_e( 'Save Settings', 'wp-mail-smtp' ); ?></button>
81
  </p>
94
 
95
  $options = new Options();
96
 
97
+ // Unchecked checkboxes doesn't exist in $_POST, so we need to ensure we actually have them in data to save.
98
  if ( empty( $data['general']['am_notifications_hidden'] ) ) {
99
  $data['general']['am_notifications_hidden'] = false;
100
  }
101
+ if ( empty( $data['general']['uninstall'] ) ) {
102
+ $data['general']['uninstall'] = false;
103
+ }
104
 
105
  $to_save = array_merge( $options->get_all(), $data );
106
 
src/Admin/Pages/Settings.php CHANGED
@@ -42,7 +42,7 @@ class Settings extends PageAbstract {
42
  $mailer = $options->get( 'mail', 'mailer' );
43
  ?>
44
 
45
- <form method="POST" action="">
46
  <?php $this->wp_nonce_field(); ?>
47
 
48
  <!-- Mail Section Title -->
@@ -62,19 +62,30 @@ class Settings extends PageAbstract {
62
  value="<?php echo esc_attr( $options->get( 'mail', 'from_email' ) ); ?>"
63
  <?php echo $options->is_const_defined( 'mail', 'from_email' ) ? 'disabled' : ''; ?>
64
  id="wp-mail-smtp-setting-from_email" spellcheck="false"
65
- />
 
 
 
 
 
 
66
  <p class="desc">
67
- <?php esc_html_e( 'You can specify the email address that emails should be sent from.', 'wp-mail-smtp' ); ?><br/>
68
- <?php
69
- printf(
70
- /* translators: %s - default email address. */
71
- esc_html__( 'If you leave this blank, the default one will be used: %s.', 'wp-mail-smtp' ),
72
- '<code>' . wp_mail_smtp()->get_processor()->get_default_email() . '</code>'
73
- );
74
- ?>
75
  </p>
 
 
 
 
 
 
 
 
 
 
 
 
76
  <p class="desc">
77
- <?php esc_html_e( 'Please note if you are sending using an email provider (Gmail, Yahoo, Hotmail, Outlook.com, etc) this setting should be your email address for that account.', 'wp-mail-smtp' ); ?>
78
  </p>
79
  </div>
80
  </div>
@@ -89,16 +100,25 @@ class Settings extends PageAbstract {
89
  value="<?php echo esc_attr( $options->get( 'mail', 'from_name' ) ); ?>"
90
  <?php echo $options->is_const_defined( 'mail', 'from_name' ) ? 'disabled' : ''; ?>
91
  id="wp-mail-smtp-setting-from_name" spellcheck="false"
92
- />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  <p class="desc">
94
- <?php esc_html_e( 'You can specify the name that emails should be sent from.', 'wp-mail-smtp' ); ?><br/>
95
- <?php
96
- printf(
97
- /* translators: %s - WordPress. */
98
- esc_html__( 'If you leave this blank, the emails will be sent from %s.', 'wp-mail-smtp' ),
99
- '<code>WordPress</code>'
100
- );
101
- ?>
102
  </p>
103
  </div>
104
  </div>
@@ -145,11 +165,12 @@ class Settings extends PageAbstract {
145
  <input name="wp-mail-smtp[mail][return_path]" type="checkbox"
146
  value="true" <?php checked( true, (bool) $options->get( 'mail', 'return_path' ) ); ?>
147
  <?php echo $options->is_const_defined( 'mail', 'return_path' ) ? 'disabled' : ''; ?>
148
- id="wp-mail-smtp-setting-return_path"
149
- />
150
  <label for="wp-mail-smtp-setting-return_path">
151
  <?php esc_html_e( 'Set the return-path to match the From Email', 'wp-mail-smtp' ); ?>
152
  </label>
 
153
  <p class="desc">
154
  <?php esc_html_e( 'Return Path indicates where non-delivery receipts - or bounce messages - are to be sent.', 'wp-mail-smtp' ); ?><br/>
155
  <?php esc_html_e( 'If unchecked bounce messages may be lost.', 'wp-mail-smtp' ); ?>
@@ -187,6 +208,115 @@ class Settings extends PageAbstract {
187
 
188
  </form>
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  <?php
191
  }
192
 
@@ -201,6 +331,12 @@ class Settings extends PageAbstract {
201
  $old_opt = $options->get_all();
202
 
203
  // When checkbox is unchecked - it's not submitted at all, so we need to define its default false value.
 
 
 
 
 
 
204
  if ( ! isset( $data['mail']['return_path'] ) ) {
205
  $data['mail']['return_path'] = false;
206
  }
42
  $mailer = $options->get( 'mail', 'mailer' );
43
  ?>
44
 
45
+ <form method="POST" action="" autocomplete="off">
46
  <?php $this->wp_nonce_field(); ?>
47
 
48
  <!-- Mail Section Title -->
62
  value="<?php echo esc_attr( $options->get( 'mail', 'from_email' ) ); ?>"
63
  <?php echo $options->is_const_defined( 'mail', 'from_email' ) ? 'disabled' : ''; ?>
64
  id="wp-mail-smtp-setting-from_email" spellcheck="false"
65
+ placeholder="<?php echo esc_attr( wp_mail_smtp()->get_processor()->get_default_email() ); ?>">
66
+
67
+ <p class="desc">
68
+ <?php esc_html_e( 'The email address which emails are sent from.', 'wp-mail-smtp' ); ?><br/>
69
+ <?php esc_html_e( 'If you using an email provider (Gmail, Yahoo, Outlook.com, etc) this should be your email address for that account.', 'wp-mail-smtp' ); ?>
70
+ </p>
71
+
72
  <p class="desc">
73
+ <?php esc_html_e( 'Please note that other plugins can change this, to prevent this use the setting below.', 'wp-mail-smtp' ); ?>
 
 
 
 
 
 
 
74
  </p>
75
+
76
+ <hr class="wp-mail-smtp-setting-mid-row-sep">
77
+
78
+ <input name="wp-mail-smtp[mail][from_email_force]" type="checkbox"
79
+ value="true" <?php checked( true, (bool) $options->get( 'mail', 'from_email_force' ) ); ?>
80
+ <?php echo $options->is_const_defined( 'mail', 'from_email_force' ) ? 'disabled' : ''; ?>
81
+ id="wp-mail-smtp-setting-from_email_force">
82
+
83
+ <label for="wp-mail-smtp-setting-from_email_force">
84
+ <?php esc_html_e( 'Force From Email', 'wp-mail-smtp' ); ?>
85
+ </label>
86
+
87
  <p class="desc">
88
+ <?php esc_html_e( 'If checked, the From Email setting above will be used for all emails, ignoring values set by other plugins.', 'wp-mail-smtp' ); ?>
89
  </p>
90
  </div>
91
  </div>
100
  value="<?php echo esc_attr( $options->get( 'mail', 'from_name' ) ); ?>"
101
  <?php echo $options->is_const_defined( 'mail', 'from_name' ) ? 'disabled' : ''; ?>
102
  id="wp-mail-smtp-setting-from_name" spellcheck="false"
103
+ placeholder="<?php echo esc_attr( wp_mail_smtp()->get_processor()->get_default_name() ); ?>">
104
+
105
+ <p class="desc">
106
+ <?php esc_html_e( 'The name which emails are sent from.', 'wp-mail-smtp' ); ?>
107
+ </p>
108
+
109
+ <hr class="wp-mail-smtp-setting-mid-row-sep">
110
+
111
+ <input name="wp-mail-smtp[mail][from_name_force]" type="checkbox"
112
+ value="true" <?php checked( true, (bool) $options->get( 'mail', 'from_name_force' ) ); ?>
113
+ <?php echo $options->is_const_defined( 'mail', 'from_name_force' ) ? 'disabled' : ''; ?>
114
+ id="wp-mail-smtp-setting-from_name_force">
115
+
116
+ <label for="wp-mail-smtp-setting-from_name_force">
117
+ <?php esc_html_e( 'Force From Name', 'wp-mail-smtp' ); ?>
118
+ </label>
119
+
120
  <p class="desc">
121
+ <?php esc_html_e( 'If checked, the From Name setting above will be used for all emails, ignoring values set by other plugins.', 'wp-mail-smtp' ); ?>
 
 
 
 
 
 
 
122
  </p>
123
  </div>
124
  </div>
165
  <input name="wp-mail-smtp[mail][return_path]" type="checkbox"
166
  value="true" <?php checked( true, (bool) $options->get( 'mail', 'return_path' ) ); ?>
167
  <?php echo $options->is_const_defined( 'mail', 'return_path' ) ? 'disabled' : ''; ?>
168
+ id="wp-mail-smtp-setting-return_path">
169
+
170
  <label for="wp-mail-smtp-setting-return_path">
171
  <?php esc_html_e( 'Set the return-path to match the From Email', 'wp-mail-smtp' ); ?>
172
  </label>
173
+
174
  <p class="desc">
175
  <?php esc_html_e( 'Return Path indicates where non-delivery receipts - or bounce messages - are to be sent.', 'wp-mail-smtp' ); ?><br/>
176
  <?php esc_html_e( 'If unchecked bounce messages may be lost.', 'wp-mail-smtp' ); ?>
208
 
209
  </form>
210
 
211
+ <?php
212
+ $this->display_wpforms();
213
+ }
214
+
215
+ /**
216
+ * Display a WPForms-related message.
217
+ *
218
+ * @since 1.3.0
219
+ */
220
+ protected function display_wpforms() {
221
+
222
+ // Do not display if WPForms Pro already installed.
223
+ if ( class_exists( 'WPForms_Pro', false ) ) {
224
+ return;
225
+ }
226
+
227
+ $is_dismissed = get_user_meta( get_current_user_id(), 'wp_mail_smtp_wpforms_dismissed', true );
228
+
229
+ // Do not display if user dismissed.
230
+ if ( (bool) $is_dismissed === true ) {
231
+ return;
232
+ }
233
+ ?>
234
+
235
+ <div id="wp-mail-smtp-wpforms">
236
+
237
+ <span class="wp-mail-smtp-wpforms-dismiss">
238
+ <button id="wp-mail-smtp-wpforms-dismiss">
239
+ <span class="dashicons dashicons-dismiss"></span>
240
+ </button>
241
+ </span>
242
+
243
+ <h2>
244
+ <?php esc_html_e( 'Get WPForms Pro and Support WP Mail SMTP', 'wp-mail-smtp' ); ?>
245
+ </h2>
246
+
247
+ <p>
248
+ <?php esc_html_e( 'WP Mail SMTP is a free plugin, and the team behind WPForms maintain it to give back to the WordPress community.', 'wp-mail-smtp' ); ?>
249
+ </p>
250
+
251
+ <p>
252
+ <?php
253
+ printf(
254
+ wp_kses(
255
+ /* translators: %s - WPForms.com URL. */
256
+ __( 'Please consider supporting us by <a href="%s" target="_blank" rel="noopener noreferrer">purchasing a WPForms Pro license</a>. Aside from getting access to the best drag & drop WordPress form builder plugin, your purchase will help us continue to maintain and add new features to the WP Mail SMTP plugin while keeping this SMTP plugin free for the larger WordPress community.', 'wp-mail-smtp' ),
257
+ array(
258
+ 'a' => array(
259
+ 'href' => array(),
260
+ 'target' => array(),
261
+ 'rel' => array(),
262
+ ),
263
+ )
264
+ ),
265
+ 'https://wpforms.com/?discount=THANKYOU&utm_source=WordPress&utm_medium=settings-cta&utm_campaign=smtpplugin'
266
+ );
267
+ ?>
268
+ </p>
269
+
270
+ <p>
271
+ <?php
272
+ printf(
273
+ /* translators: %s - link to WP.org repo and 5 HTML encoded stars as a label. */
274
+ esc_html__( 'We know that you will truly love WPForms. It has over 2000+ five star ratings (%s) and is active on over 1 million websites.', 'wp-mail-smtp' ),
275
+ '<a href="https://wordpress.org/support/plugin/wpforms-lite/reviews/?filter=5" target="_blank" rel="noopener noreferrer" class="stars"><span class="dashicons dashicons-star-filled"></span><span class="dashicons dashicons-star-filled"></span><span class="dashicons dashicons-star-filled"></span><span class="dashicons dashicons-star-filled"></span><span class="dashicons dashicons-star-filled"></span></a>'
276
+ );
277
+ ?>
278
+ </p>
279
+
280
+ <p><strong><?php esc_html_e( 'Other Benefits:', 'wp-mail-smtp' ); ?></strong></p>
281
+
282
+ <div class="benefits">
283
+ <ul>
284
+ <li><?php esc_html_e( 'Access to premium support for WP Mail SMTP', 'wp-mail-smtp' ); ?></li>
285
+ <li><?php esc_html_e( 'Get the best drag & drop form builder', 'wp-mail-smtp' ); ?></li>
286
+ <li><?php esc_html_e( 'All form features like file upload, pagination, etc', 'wp-mail-smtp' ); ?></li>
287
+ <li><?php esc_html_e( 'Create surveys & polls with the surveys addon', 'wp-mail-smtp' ); ?></li>
288
+ </ul>
289
+ <ul>
290
+ <li><?php esc_html_e( 'No future ads inside WP Mail SMTP admin', 'wp-mail-smtp' ); ?></li>
291
+ <li><?php esc_html_e( 'Pre-made form templates and smart conditional logic', 'wp-mail-smtp' ); ?></li>
292
+ <li><?php esc_html_e( '500+ integrations with different marketing & payment services', 'wp-mail-smtp' ); ?></li>
293
+ <li><?php esc_html_e( 'Collect signatures, geo-location data, and more', 'wp-mail-smtp' ); ?></li>
294
+ </ul>
295
+ </div>
296
+
297
+ <p>
298
+ <?php
299
+ printf(
300
+ wp_kses(
301
+ /* translators: %1$s - WPForms.com URL, %2$s - percents off. */
302
+ __( '<a href="%1$s" target="_blank" rel="noopener noreferrer">Get WPForms Pro and support WP Mail SMTP</a> - use coupon "<strong>thankyou</strong>" to save %2$s off your purchase.', 'wp-mail-smtp' ),
303
+ array(
304
+ 'a' => array(
305
+ 'href' => array(),
306
+ 'target' => array(),
307
+ 'rel' => array(),
308
+ ),
309
+ 'strong' => array(),
310
+ )
311
+ ),
312
+ 'https://wpforms.com/?discount=THANKYOU&utm_source=WordPress&utm_medium=settings-cta&utm_campaign=smtpplugin',
313
+ '20%'
314
+ );
315
+ ?>
316
+ </p>
317
+
318
+ </div>
319
+
320
  <?php
321
  }
322
 
331
  $old_opt = $options->get_all();
332
 
333
  // When checkbox is unchecked - it's not submitted at all, so we need to define its default false value.
334
+ if ( ! isset( $data['mail']['from_email_force'] ) ) {
335
+ $data['mail']['from_email_force'] = false;
336
+ }
337
+ if ( ! isset( $data['mail']['from_name_force'] ) ) {
338
+ $data['mail']['from_name_force'] = false;
339
+ }
340
  if ( ! isset( $data['mail']['return_path'] ) ) {
341
  $data['mail']['return_path'] = false;
342
  }
src/Admin/Pages/Test.php CHANGED
@@ -20,6 +20,15 @@ class Test extends PageAbstract {
20
  */
21
  protected $slug = 'test';
22
 
 
 
 
 
 
 
 
 
 
23
  /**
24
  * @inheritdoc
25
  */
@@ -56,7 +65,7 @@ class Test extends PageAbstract {
56
  <label for="wp-mail-smtp-setting-test_email"><?php esc_html_e( 'Send To', 'wp-mail-smtp' ); ?></label>
57
  </div>
58
  <div class="wp-mail-smtp-setting-field">
59
- <input name="wp-mail-smtp[test_email]" type="email" id="wp-mail-smtp-setting-test_email" spellcheck="false" required />
60
  <p class="desc">
61
  <?php esc_html_e( 'Type an email address here and then click a button below to generate a test email.', 'wp-mail-smtp' ); ?>
62
  </p>
@@ -69,6 +78,7 @@ class Test extends PageAbstract {
69
  </form>
70
 
71
  <?php
 
72
  }
73
 
74
  /**
@@ -116,7 +126,6 @@ class Test extends PageAbstract {
116
  )
117
  );
118
 
119
- // Grab the smtp debugging output.
120
  $smtp_debug = ob_get_clean();
121
 
122
  /*
@@ -128,14 +137,10 @@ class Test extends PageAbstract {
128
  WP::ADMIN_NOTICE_SUCCESS
129
  );
130
  } else {
131
- $error = $this->get_debug_messages( $phpmailer, $smtp_debug );
132
-
133
- WP::add_admin_notice(
134
- '<p><strong>' . esc_html__( 'There was a problem while sending a test email. Related debugging output is shown below:', 'wp-mail-smtp' ) . '</strong></p>' .
135
- '<blockquote style="border-left:1px solid orange;padding-left:10px">' . $error . '</blockquote>' .
136
- '<p class="description">' . esc_html__( 'Please copy only the content of the error debug message above, identified with an orange left border, into the support forum topic if you experience any issues.', 'wp-mail-smtp' ) . '</p>',
137
- WP::ADMIN_NOTICE_ERROR
138
- );
139
  }
140
  }
141
 
@@ -153,6 +158,8 @@ class Test extends PageAbstract {
153
 
154
  $options = new Options();
155
 
 
 
156
  /*
157
  * Versions Debug.
158
  */
@@ -170,11 +177,11 @@ class Test extends PageAbstract {
170
 
171
  $mailer_text = '<strong>Params:</strong><br>';
172
 
173
- $mailer_text .= '<strong>Mailer:</strong> ' . $options->get( 'mail', 'mailer' ) . '<br>';
174
  $mailer_text .= '<strong>Constants:</strong> ' . ( $options->is_const_enabled() ? 'Yes' : 'No' ) . '<br>';
175
 
176
  // Display different debug info based on the mailer.
177
- $mailer = wp_mail_smtp()->get_providers()->get_mailer( $options->get( 'mail', 'mailer' ), $phpmailer );
178
 
179
  if ( $mailer ) {
180
  $mailer_text .= $mailer->get_debug_info();
@@ -198,7 +205,7 @@ class Test extends PageAbstract {
198
  if ( $options->is_mailer_smtp() ) {
199
  $smtp_text = '<strong>SMTP Debug:</strong><br>';
200
  if ( ! empty( $smtp_debug ) ) {
201
- $smtp_text .= esc_textarea( $smtp_debug );
202
  } else {
203
  $smtp_text .= '[empty]';
204
  }
@@ -213,4 +220,631 @@ class Test extends PageAbstract {
213
 
214
  return '<pre>' . implode( '<br>', array_filter( $errors ) ) . '</pre>';
215
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  }
20
  */
21
  protected $slug = 'test';
22
 
23
+ /**
24
+ * Mailer debug error data.
25
+ *
26
+ * @since 1.3.0
27
+ *
28
+ * @var array
29
+ */
30
+ private $debug = array();
31
+
32
  /**
33
  * @inheritdoc
34
  */
65
  <label for="wp-mail-smtp-setting-test_email"><?php esc_html_e( 'Send To', 'wp-mail-smtp' ); ?></label>
66
  </div>
67
  <div class="wp-mail-smtp-setting-field">
68
+ <input name="wp-mail-smtp[test_email]" type="email" id="wp-mail-smtp-setting-test_email" spellcheck="false" required>
69
  <p class="desc">
70
  <?php esc_html_e( 'Type an email address here and then click a button below to generate a test email.', 'wp-mail-smtp' ); ?>
71
  </p>
78
  </form>
79
 
80
  <?php
81
+ $this->display_debug_details();
82
  }
83
 
84
  /**
126
  )
127
  );
128
 
 
129
  $smtp_debug = ob_get_clean();
130
 
131
  /*
137
  WP::ADMIN_NOTICE_SUCCESS
138
  );
139
  } else {
140
+ // Grab the smtp debugging output.
141
+ $this->debug['smtp_debug'] = $smtp_debug;
142
+ $this->debug['smtp_error'] = wp_strip_all_tags( $phpmailer->ErrorInfo );
143
+ $this->debug['error_log'] = $this->get_debug_messages( $phpmailer, $this->debug['smtp_debug'] );
 
 
 
 
144
  }
145
  }
146
 
158
 
159
  $options = new Options();
160
 
161
+ $this->debug['mailer'] = $options->get( 'mail', 'mailer' );
162
+
163
  /*
164
  * Versions Debug.
165
  */
177
 
178
  $mailer_text = '<strong>Params:</strong><br>';
179
 
180
+ $mailer_text .= '<strong>Mailer:</strong> ' . $this->debug['mailer'] . '<br>';
181
  $mailer_text .= '<strong>Constants:</strong> ' . ( $options->is_const_enabled() ? 'Yes' : 'No' ) . '<br>';
182
 
183
  // Display different debug info based on the mailer.
184
+ $mailer = wp_mail_smtp()->get_providers()->get_mailer( $this->debug['mailer'], $phpmailer );
185
 
186
  if ( $mailer ) {
187
  $mailer_text .= $mailer->get_debug_info();
205
  if ( $options->is_mailer_smtp() ) {
206
  $smtp_text = '<strong>SMTP Debug:</strong><br>';
207
  if ( ! empty( $smtp_debug ) ) {
208
+ $smtp_text .= '<pre>' . $smtp_debug . '</pre>';
209
  } else {
210
  $smtp_text .= '[empty]';
211
  }
220
 
221
  return '<pre>' . implode( '<br>', array_filter( $errors ) ) . '</pre>';
222
  }
223
+
224
+ /**
225
+ * Returns debug information for detection, processing, and display.
226
+ *
227
+ * @since 1.3.0
228
+ *
229
+ * @return array
230
+ */
231
+ protected function get_debug_details() {
232
+
233
+ $options = new Options();
234
+ $smtp_host = $options->get( 'smtp', 'host' );
235
+ $smtp_port = $options->get( 'smtp', 'port' );
236
+ $smtp_encryption = $options->get( 'smtp', 'encryption' );
237
+
238
+ $details = array(
239
+ // [any] - cURL error 60/77.
240
+ array(
241
+ 'mailer' => 'any',
242
+ 'errors' => array(
243
+ array( 'cURL error 60' ),
244
+ array( 'cURL error 77' ),
245
+ ),
246
+ 'description' => array(
247
+ '<strong>' . esc_html__( 'SSL certificate issue.', 'wp-mail-smtp' ) . '</strong>',
248
+ esc_html__( 'This means your web server cannot reliably make secure connections (make requests to HTTPS sites).', 'wp-mail-smtp' ),
249
+ esc_html__( 'Typically this error is returned when web server is not configured properly.', 'wp-mail-smtp' ),
250
+ ),
251
+ 'steps' => array(
252
+ esc_html__( 'Contact your web hosting provider and inform them your site has an issue with SSL certificates.', 'wp-mail-smtp' ),
253
+ esc_html__( 'The exact error you can provide them is in the Error log, available at the bottom of this page.', 'wp-mail-smtp' ),
254
+ esc_html__( 'Ask them to resolve the issue then try again.', 'wp-mail-smtp' ),
255
+ ),
256
+ ),
257
+ // [any] - cURL error 6/7.
258
+ array(
259
+ 'mailer' => 'any',
260
+ 'errors' => array(
261
+ array( 'cURL error 6' ),
262
+ array( 'cURL error 7' ),
263
+ ),
264
+ 'description' => array(
265
+ '<strong>' . esc_html__( 'Could not connect to host.', 'wp-mail-smtp' ) . '</strong>',
266
+ sprintf(
267
+ /* translators: %s - SMTP host address. */
268
+ esc_html__( 'This means your web server was unable to connect to %s.', 'wp-mail-smtp' ),
269
+ $smtp_host
270
+ ),
271
+ esc_html__( 'Typically this error is returned your web server is blocking the connections or the SMTP host denying the request.', 'wp-mail-smtp' ),
272
+ ),
273
+ 'steps' => array(
274
+ sprintf(
275
+ /* translators: %s - SMTP host address. */
276
+ esc_html__( 'Contact your web hosting provider and ask them to verify your server can connect to %s. Additionally, ask them if a firewall or security policy may be preventing the connection.', 'wp-mail-smtp' ),
277
+ $smtp_host
278
+ ),
279
+ esc_html__( 'If using "Other SMTP" Mailer, triple check your SMTP settings including host address, email, and password.', 'wp-mail-smtp' ),
280
+ esc_html__( 'If using "Other SMTP" Mailer, contact your SMTP host to confirm they are accepting outside connections with the settings you have configured (address, username, port, security, etc).', 'wp-mail-smtp' ),
281
+ ),
282
+ ),
283
+ // [any] - cURL error XX (other).
284
+ array(
285
+ 'mailer' => 'any',
286
+ 'errors' => array(
287
+ array( 'cURL error' ),
288
+ ),
289
+ 'description' => array(
290
+ '<strong>' . esc_html__( 'Could not connect to your host.', 'wp-mail-smtp' ) . '</strong>',
291
+ sprintf(
292
+ /* translators: %s - SMTP host address. */
293
+ esc_html__( 'This means your web server was unable to connect to %s.', 'wp-mail-smtp' ),
294
+ $smtp_host
295
+ ),
296
+ esc_html__( 'Typically this error is returned when web server is not configured properly.', 'wp-mail-smtp' ),
297
+ ),
298
+ 'steps' => array(
299
+ esc_html__( 'Contact your web hosting provider and inform them you are having issues making outbound connections.', 'wp-mail-smtp' ),
300
+ esc_html__( 'The exact error you can provide them is in the Error log, available at the bottom of this page.', 'wp-mail-smtp' ),
301
+ esc_html__( 'Ask them to resolve the issue then try again.', 'wp-mail-smtp' ),
302
+ ),
303
+ ),
304
+ // [smtp] - SMTP Error: Count not authenticate.
305
+ array(
306
+ 'mailer' => 'smtp',
307
+ 'errors' => array(
308
+ array( 'SMTP Error: Could not authenticate.' ),
309
+ ),
310
+ 'description' => array(
311
+ '<strong>' . esc_html__( 'Could not authenticate your SMTP account.', 'wp-mail-smtp' ) . '</strong>',
312
+ esc_html__( 'This means we were able to connect to your SMTP host, but were not able to proceed using the email/password in the settings.', 'wp-mail-smtp' ),
313
+ esc_html__( 'Typically this error is returned when the email or password is not correct or is not what the SMTP host is expecting.', 'wp-mail-smtp' ),
314
+ ),
315
+ 'steps' => array(
316
+ esc_html__( 'Triple check your SMTP settings including host address, email, and password. If you have recently reset your password you will need to update the settings.', 'wp-mail-smtp' ),
317
+ esc_html__( 'Contact your SMTP host to confirm you are using the correct username and password.', 'wp-mail-smtp' ),
318
+ esc_html__( 'Verify with your SMTP host that your account has permissions to send emails using outside connections.', 'wp-mail-smtp' ),
319
+ ),
320
+ ),
321
+ // [smtp] - Sending bulk email, hitting rate limit.
322
+ array(
323
+ 'mailer' => 'smtp',
324
+ 'errors' => array(
325
+ array( 'We do not authorize the use of this system to transport unsolicited' ),
326
+ ),
327
+ 'description' => array(
328
+ '<strong>' . esc_html__( 'Error due to unsolicited and/or bulk e-mail.', 'wp-mail-smtp' ) . '</strong>',
329
+ esc_html__( 'This means the connection to your SMTP host was made successfully, but the host rejected the email.', 'wp-mail-smtp' ),
330
+ esc_html__( 'Typically this error is returned when your are sending too many e-mails or e-mails that have been identified as spam.', 'wp-mail-smtp' ),
331
+ ),
332
+ 'steps' => array(
333
+ esc_html__( 'Check the emails that are sending are sending individually. Example: email is not sending to 30 recipients. You can install any WordPress e-mail logging plugin to do that.', 'wp-mail-smtp' ),
334
+ esc_html__( 'Contact your SMTP host to ask about sending/rate limits.', 'wp-mail-smtp' ),
335
+ esc_html__( 'Verify with them your SMTP account is in good standing and your account has not been flagged.', 'wp-mail-smtp' ),
336
+ ),
337
+ ),
338
+ // [smtp] - Unauthenticated senders not allowed.
339
+ array(
340
+ 'mailer' => 'smtp',
341
+ 'errors' => array(
342
+ array( 'Unauthenticated senders not allowed' ),
343
+ ),
344
+ 'description' => array(
345
+ '<strong>' . esc_html__( 'Unauthenticated senders are not allowed.', 'wp-mail-smtp' ) . '</strong>',
346
+ esc_html__( 'This means the connection to your SMTP host was made successfully, but you should enable Authentication and provide correct Username and Password.', 'wp-mail-smtp' ),
347
+ ),
348
+ 'steps' => array(
349
+ esc_html__( 'Go to WP Mail SMTP plugin Settings page.', 'wp-mail-smtp' ),
350
+ esc_html__( 'Enable Authentication', 'wp-mail-smtp' ),
351
+ esc_html__( 'Enter correct SMTP Username (usually this is an email address) and Password in the appropriate fields.', 'wp-mail-smtp' ),
352
+ ),
353
+ ),
354
+ // [smtp] - SMTP connect() failed.
355
+ array(
356
+ 'mailer' => 'smtp',
357
+ 'errors' => array(
358
+ array( 'SMTP connect() failed' ),
359
+ ),
360
+ 'description' => array(
361
+ '<strong>' . esc_html__( 'Could not connect to the SMTP host.', 'wp-mail-smtp' ) . '</strong>',
362
+ sprintf(
363
+ /* translators: %s - SMTP host address. */
364
+ esc_html__( 'This means your web server was unable to connect to %s.', 'wp-mail-smtp' ),
365
+ $smtp_host
366
+ ),
367
+ esc_html__( 'Typically this error is returned for one of the following reasons:', 'wp-mail-smtp' ),
368
+ '-' . esc_html__( 'SMTP settings are incorrect (wrong port, security setting, incorrect host).', 'wp-mail-smtp' ) . '<br>' .
369
+ '-' . esc_html__( 'Your web server is blocking the connection.', 'wp-mail-smtp' ) . '<br>' .
370
+ '-' . esc_html__( 'Your SMTP host is rejecting the connection.', 'wp-mail-smtp' ),
371
+ ),
372
+ 'steps' => array(
373
+ esc_html__( 'Triple check your SMTP settings including host address, email, and password, port, and security.', 'wp-mail-smtp' ),
374
+ sprintf(
375
+ wp_kses(
376
+ /* translators: %1$s - SMTP host address, %2$s - SMTP port, %3$s - SMTP encryption. */
377
+ __( 'Contact your web hosting provider and ask them to verify your server can connect to %1$s on port %2$s using %3$s encryption. Additionally, ask them if a firewall or security policy may be preventing the connection - many shared hosts block certain ports.<br><strong>Note: this is the most common cause of this issue.</strong>', 'wp-mail-smtp' ),
378
+ array(
379
+ 'a' => array(
380
+ 'href' => array(),
381
+ 'rel' => array(),
382
+ 'target' => array(),
383
+ ),
384
+ 'strong' => array(),
385
+ 'br' => array(),
386
+ )
387
+ ),
388
+ $smtp_host,
389
+ $smtp_port,
390
+ 'none' === $smtp_encryption ? esc_html__( 'no', 'wp-mail-smtp' ) : $smtp_encryption
391
+ ),
392
+ esc_html__( 'Contact your SMTP host to confirm you are using the correct username and password.', 'wp-mail-smtp' ),
393
+ esc_html__( 'Verify with your SMTP host that your account has permissions to send emails using outside connections.', 'wp-mail-smtp' ),
394
+ ),
395
+ ),
396
+ // [mailgun] - Forbidden.
397
+ array(
398
+ 'mailer' => 'mailgun',
399
+ 'errors' => array(
400
+ array( 'Forbidden' ),
401
+ ),
402
+ 'description' => array(
403
+ '<strong>' . esc_html__( 'Mailgun failed.', 'wp-mail-smtp' ) . '</strong>',
404
+ esc_html__( 'Typically this error is because there is an issue with your Mailgun settings, in many cases the API key.', 'wp-mail-smtp' ),
405
+ ),
406
+ 'steps' => array(
407
+ esc_html__( 'Verify your API key is correct.', 'wp-mail-smtp' ),
408
+ esc_html__( 'Go to your Mailgun account and view your API key.', 'wp-mail-smtp' ),
409
+ esc_html__( 'Note that the API key includes the "key" prefix, so make sure that it is in the WP Mail SMTP Mailgun API setting.', 'wp-mail-smtp' ),
410
+ ),
411
+ ),
412
+ // [mailgun] - Free accounts are for test purposes only.
413
+ array(
414
+ 'mailer' => 'mailgun',
415
+ 'errors' => array(
416
+ array( 'Free accounts are for test purposes only' ),
417
+ ),
418
+ 'description' => array(
419
+ '<strong>' . esc_html__( 'Mailgun failed.', 'wp-mail-smtp' ) . '</strong>',
420
+ esc_html__( 'Your Mailgun account does not have access to send emails.', 'wp-mail-smtp' ),
421
+ esc_html__( 'Typically this error is because you have not setup and/or complete domain name verification for your Mailgun account.', 'wp-mail-smtp' ),
422
+ ),
423
+ 'steps' => array(
424
+ sprintf(
425
+ wp_kses(
426
+ /* translators: %s - Mailgun documentation URL. */
427
+ __( 'Go to our how-to guide for setting up <a href="%s" target="_blank" rel="noopener noreferrer">Mailgun with WP Mail SMTP</a>.', 'wp-mail-smtp' ),
428
+ array(
429
+ 'a' => array(
430
+ 'href' => array(),
431
+ 'rel' => array(),
432
+ 'target' => array(),
433
+ ),
434
+ )
435
+ ),
436
+ 'https://wpforms.com/how-to-send-wordpress-emails-with-mailgun/'
437
+ ),
438
+ esc_html__( 'Complete the steps in section "2. Verify Your Domain".', 'wp-mail-smtp' ),
439
+ ),
440
+ ),
441
+ // [gmail] - 401: Login Required.
442
+ array(
443
+ 'mailer' => 'gmail',
444
+ 'errors' => array(
445
+ array( '401', 'Login Required' ),
446
+ ),
447
+ 'description' => array(
448
+ '<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>',
449
+ esc_html__( 'You have not properly configured Gmail mailer.', 'wp-mail-smtp' ),
450
+ esc_html__( 'Make sure that you have clicked the "Allow plugin to send emails using your Google account" button under Gmail settings.', 'wp-mail-smtp' ),
451
+ ),
452
+ 'steps' => array(
453
+ esc_html__( 'Go to plugin Settings page and click the "Allow plugin to send emails using your Google account" button.', 'wp-mail-smtp' ),
454
+ esc_html__( 'After the click you should be redirected to a Gmail authorization screen, where you will be asked a permission to send emails on your behalf.', 'wp-mail-smtp' ),
455
+ esc_html__( 'Please click "Agree", if you see that button. If not - you will need to enable less secure apps first:', 'wp-mail-smtp' )
456
+ . '<ul>'
457
+ . '<li>' .
458
+ sprintf(
459
+ wp_kses(
460
+ /* translators: %s - Google support article URL. */
461
+ __( 'if you are using regular Gmail account, please <a href="%s" target="_blank" rel="noopener noreferrer">read this article</a> to proceed.', 'wp-mail-smtp' ),
462
+ array(
463
+ 'a' => array(
464
+ 'href' => array(),
465
+ 'target' => array(),
466
+ 'rel' => array(),
467
+ ),
468
+ )
469
+ ),
470
+ 'https://support.google.com/accounts/answer/6010255?hl=en'
471
+ )
472
+ . '</li>'
473
+ . '<li>' .
474
+ sprintf(
475
+ wp_kses(
476
+ /* translators: %s - Google support article URL. */
477
+ __( 'if you are using G Suite, please <a href="%s" target="_blank" rel="noopener noreferrer">read this article</a> to proceed.', 'wp-mail-smtp' ),
478
+ array(
479
+ 'a' => array(
480
+ 'href' => array(),
481
+ 'target' => array(),
482
+ 'rel' => array(),
483
+ ),
484
+ )
485
+ ),
486
+ 'https://support.google.com/cloudidentity/answer/6260879?hl=en'
487
+ )
488
+ . '</li>'
489
+ . '</ul>',
490
+ ),
491
+ ),
492
+ // [gmail] - 400: Recipient address required.
493
+ array(
494
+ 'mailer' => 'gmail',
495
+ 'errors' => array(
496
+ array( '400', 'Recipient address required' ),
497
+ ),
498
+ 'description' => array(
499
+ '<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>',
500
+ esc_html__( 'Typically this error is because address the email was sent to is invalid or was empty.', 'wp-mail-smtp' ),
501
+ ),
502
+ 'steps' => array(
503
+ esc_html__( 'Check the "Send To" email address used and confirm it is a valid email and was not empty.', 'wp-mail-smtp' ),
504
+ sprintf(
505
+ /* translators: 1 - correct email address example. 2 - incorrect email address example. */
506
+ esc_html__( 'It should be something like this: %1$s. These are incorrect values: %2$s.', 'wp-mail-smtp' ),
507
+ '<code>info@example.com</code>',
508
+ '<code>info@localhost</code>, <code>info@192.168.1.1</code>'
509
+ ),
510
+ esc_html__( 'Make sure that the generated email has a TO header, useful when you are responsible for email creation.', 'wp-mail-smtp' ),
511
+ ),
512
+ ),
513
+ // [gmail] - Token has been expired or revoked.
514
+ array(
515
+ 'mailer' => 'gmail',
516
+ 'errors' => array(
517
+ array( 'invalid_grant', 'Token has been expired or revoked' ),
518
+ ),
519
+ 'description' => array(
520
+ '<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>',
521
+ esc_html__( 'Unfortunately, this error can be due to many different reasons.', 'wp-mail-smtp' ),
522
+ ),
523
+ 'steps' => array(
524
+ sprintf(
525
+ wp_kses(
526
+ /* translators: %s - Blog article URL. */
527
+ __( 'Please <a href="%s" target="_blank" rel="noopener noreferrer">read this article</a> to learn more about what can cause this error and how it can be resolved.', 'wp-mail-smtp' ),
528
+ array(
529
+ 'a' => array(
530
+ 'href' => array(),
531
+ 'target' => array(),
532
+ 'rel' => array(),
533
+ ),
534
+ )
535
+ ),
536
+ 'https://blog.timekit.io/google-oauth-invalid-grant-nightmare-and-how-to-fix-it-9f4efaf1da35'
537
+ ),
538
+ ),
539
+ ),
540
+ // [gmail] - Code was already redeemed.
541
+ array(
542
+ 'mailer' => 'gmail',
543
+ 'errors' => array(
544
+ array( 'invalid_grant', 'Code was already redeemed' ),
545
+ ),
546
+ 'description' => array(
547
+ '<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>',
548
+ esc_html__( 'Authentication code that Google returned to you has already been used on your previous auth attempt.', 'wp-mail-smtp' ),
549
+ ),
550
+ 'steps' => array(
551
+ esc_html__( 'Make sure that you are not trying to manually clean up the plugin options to retry the "Allow..." step.', 'wp-mail-smtp' ),
552
+ esc_html__( 'Reinstall the plugin with clean plugin data turned on on Misc page. This will remove all the plugin options and you will be safe to retry.', 'wp-mail-smtp' ),
553
+ esc_html__( 'Make sure there is no aggressive caching on site admin area pages or try to clean cache between attempts.', 'wp-mail-smtp' ),
554
+ ),
555
+ ),
556
+ // [gmail] - 400: Mail service not enabled.
557
+ array(
558
+ 'mailer' => 'gmail',
559
+ 'errors' => array(
560
+ array( '400', 'Mail service not enabled' ),
561
+ ),
562
+ 'description' => array(
563
+ '<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>',
564
+ esc_html__( 'There are various reasons for that, please review the steps below.', 'wp-mail-smtp' ),
565
+ ),
566
+ 'steps' => array(
567
+ sprintf(
568
+ wp_kses(
569
+ /* translators: %s - Google G Suite Admin area URL. */
570
+ __( 'Make sure that your G Suite trial period has not expired. You can check the status <a href="%s" target="_blank" rel="noopener noreferrer">here</a>.', 'wp-mail-smtp' ),
571
+ array(
572
+ 'a' => array(
573
+ 'href' => array(),
574
+ 'rel' => array(),
575
+ 'target' => array(),
576
+ ),
577
+ )
578
+ ),
579
+ 'https://admin.google.com'
580
+ ),
581
+ sprintf(
582
+ wp_kses(
583
+ /* translators: %s - Google G Suite Admin area URL. */
584
+ __( 'Make sure that Gmail app in your G Suite is actually enabled. You can check that in Apps list in <a href="%s" target="_blank" rel="noopener noreferrer">G Suite Admin</a> area.', 'wp-mail-smtp' ),
585
+ array(
586
+ 'a' => array(
587
+ 'href' => array(),
588
+ 'rel' => array(),
589
+ 'target' => array(),
590
+ ),
591
+ )
592
+ ),
593
+ 'https://admin.google.com'
594
+ ),
595
+ sprintf(
596
+ wp_kses(
597
+ /* translators: %s - Google Developers Console URL. */
598
+ __( 'Make sure that you have Gmail API enabled, and you can do that <a href="%s" target="_blank" rel="noopener noreferrer">here</a>.', 'wp-mail-smtp' ),
599
+ array(
600
+ 'a' => array(
601
+ 'href' => array(),
602
+ 'rel' => array(),
603
+ 'target' => array(),
604
+ ),
605
+ )
606
+ ),
607
+ 'https://console.developers.google.com/'
608
+ ),
609
+ ),
610
+ ),
611
+ // [gmail] - 403: Project X is not found and cannot be used for API calls.
612
+ array(
613
+ 'mailer' => 'gmail',
614
+ 'errors' => array(
615
+ array( '403', 'is not found and cannot be used for API calls' ),
616
+ ),
617
+ 'description' => array(
618
+ '<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>',
619
+ ),
620
+ 'steps' => array(
621
+ esc_html__( 'Make sure that the used Client ID/Secret correspond to a proper project that has Gmail API enabled.', 'wp-mail-smtp' ),
622
+ sprintf(
623
+ wp_kses(
624
+ /* translators: %s - WPForms.com tutorial URL. */
625
+ esc_html__( 'Please follow our <a href="%s" target="_blank" rel="noopener noreferrer">Gmail tutorial</a> to be sure that all the correct project and data is applied.', 'wp-mail-smtp' ),
626
+ array(
627
+ 'a' => array(
628
+ 'href' => array(),
629
+ 'rel' => array(),
630
+ 'target' => array(),
631
+ ),
632
+ )
633
+ ),
634
+ 'https://wpforms.com/how-to-securely-send-wordpress-emails-using-gmail-smtp/'
635
+ ),
636
+ ),
637
+ ),
638
+ // [gmail] - The OAuth client was disabled.
639
+ array(
640
+ 'mailer' => 'gmail',
641
+ 'errors' => array(
642
+ array( 'disabled_client', 'The OAuth client was disabled' ),
643
+ ),
644
+ 'description' => array(
645
+ '<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>',
646
+ esc_html__( 'You may have added a new API to a project', 'wp-mail-smtp' ),
647
+ ),
648
+ 'steps' => array(
649
+ esc_html__( 'Make sure that the used Client ID/Secret correspond to a proper project that has Gmail API enabled.', 'wp-mail-smtp' ),
650
+ esc_html__( 'Try to use a separate project for your emails, so the project has only 1 Gmail API in it enabled. You will need to remove the old project and create a new one from scratch.', 'wp-mail-smtp' ),
651
+ ),
652
+ ),
653
+ );
654
+
655
+ // Error detection logic.
656
+ foreach ( $details as $data ) {
657
+
658
+ // Check for appropriate mailer.
659
+ if ( 'any' !== $data['mailer'] && $this->debug['mailer'] !== $data['mailer'] ) {
660
+ continue;
661
+ }
662
+
663
+ $match = false;
664
+
665
+ // Attempt to detect errors.
666
+ foreach ( $data['errors'] as $error_group ) {
667
+ foreach ( $error_group as $error_code => $error_message ) {
668
+ $match = ( false !== strpos( $this->debug['error_log'], $error_message ) || false !== strpos( $this->debug['error_log'], $error_message ) );
669
+ if ( ! $match ) {
670
+ break;
671
+ }
672
+ }
673
+ if ( $match ) {
674
+ break;
675
+ }
676
+ }
677
+
678
+ if ( $match ) {
679
+ return $data;
680
+ }
681
+ }
682
+
683
+ // Return defaults.
684
+ return array(
685
+ 'description' => array(
686
+ '<strong>' . esc_html__( 'An issue was detected.', 'wp-mail-smtp' ) . '</strong>',
687
+ esc_html__( 'This means your test email was unable to be sent.', 'wp-mail-smtp' ),
688
+ esc_html__( 'Typically this error is returned for one of the following reasons:', 'wp-mail-smtp' ),
689
+ '- ' . esc_html__( 'Plugin settings are incorrect (wrong SMTP settings, invalid Mailer configuration, etc).', 'wp-mail-smtp' ) . '<br>' .
690
+ '- ' . esc_html__( 'Your web server is blocking the connection.', 'wp-mail-smtp' ) . '<br>' .
691
+ '- ' . esc_html__( 'Your host is rejecting the connection.', 'wp-mail-smtp' ),
692
+ ),
693
+ 'steps' => array(
694
+ esc_html__( 'Triple check the plugin settings, consider reconfiguring to make sure everything is correct (eg bad copy and paste).', 'wp-mail-smtp' ),
695
+ wp_kses(
696
+ __( 'Contact your web hosting provider and ask them to verify your server can make outside connections. Additionally, ask them if a firewall or security policy may be preventing the connection - many shared hosts block certain ports.<br><strong>Note: this is the most common cause of this issue.</strong>', 'wp-mail-smtp' ),
697
+ array(
698
+ 'strong' => array(),
699
+ 'br' => array(),
700
+ )
701
+ ),
702
+ esc_html__( 'Try using a different mailer.', 'wp-mail-smtp' ),
703
+ ),
704
+ );
705
+ }
706
+
707
+ /**
708
+ * Displays all the various error and debug details.
709
+ *
710
+ * @since 1.3.0
711
+ */
712
+ protected function display_debug_details() {
713
+
714
+ if ( empty( $this->debug ) ) {
715
+ return;
716
+ }
717
+
718
+ $debug = $this->get_debug_details();
719
+ ?>
720
+ <div id="message" class="notice-error notice-inline">
721
+ <p><strong><?php esc_html_e( 'There was a problem while sending the test email.', 'wp-mail-smtp' ); ?></strong></p>
722
+ </div>
723
+
724
+ <div id="wp-mail-smtp-debug">
725
+ <?php
726
+ foreach ( $debug['description'] as $description ) {
727
+ echo '<p>' . $description . '</p>';
728
+ }
729
+ ?>
730
+
731
+ <h2><?php esc_html_e( 'Recommended next steps:', 'wp-mail-smtp' ); ?></h2>
732
+
733
+ <ol>
734
+ <?php
735
+ foreach ( $debug['steps'] as $step ) {
736
+ echo '<li>' . $step . '</li>';
737
+ }
738
+ ?>
739
+ </ol>
740
+
741
+ <h2><?php esc_html_e( 'Need support?', 'wp-mail-smtp' ); ?></h2>
742
+
743
+ <?php if ( class_exists( 'WPForms_Pro' ) ) : ?>
744
+
745
+ <p>
746
+ <?php
747
+ printf(
748
+ wp_kses(
749
+ /* translators: %s - WPForms account area link. */
750
+ __( 'As a WPForms Pro user you have access to WP Mail SMTP priority support. Please log in to your WPForms.com account and <a href="%s" target="_blank" rel="noopener noreferrer">submit a support ticket</a>.', 'wp-mail-smtp' ),
751
+ array(
752
+ 'a' => array(
753
+ 'href' => array(),
754
+ 'rel' => array(),
755
+ 'target' => array(),
756
+ ),
757
+ )
758
+ ),
759
+ 'https://wpforms.com/account/support/'
760
+ );
761
+ ?>
762
+ </p>
763
+
764
+ <?php else : ?>
765
+
766
+ <p>
767
+ <?php esc_html_e( 'WP Mail SMTP is a free plugin, and the team behind WPForms maintain it to give back to the WordPress community.', 'wp-mail-smtp' ); ?>
768
+ </p>
769
+
770
+ <p>
771
+ <?php
772
+ printf(
773
+ wp_kses(
774
+ /* translators: %s - WPForms URL. */
775
+ __( 'To access priority support from our team, please <a href="%s" target="_blank" rel="noopener noreferrer">purchase a WPForms license</a>. Along with getting priority support for WP Mail SMTP, you will also get access to the best drag & drop WordPress form builder plugin.', 'wp-mail-smtp' ),
776
+ array(
777
+ 'a' => array(
778
+ 'href' => array(),
779
+ 'rel' => array(),
780
+ 'target' => array(),
781
+ ),
782
+ )
783
+ ),
784
+ 'https://wpforms.com/?discount=THANKYOU&utm_source=WordPress&utm_medium=debug-cta&utm_campaign=smtpplugin'
785
+ );
786
+ ?>
787
+ </p>
788
+
789
+ <p>
790
+ <?php
791
+ printf(
792
+ wp_kses(
793
+ /* translators: %s - Star icons. */
794
+ __( 'WPForms is being used on over 1 million websites and has over 2000+ five star ratings (%s).', 'wp-mail-smtp' ),
795
+ array(
796
+ 'span' => array(
797
+ 'class' => array(),
798
+ ),
799
+ )
800
+ ),
801
+ str_repeat( '<span class="dashicons dashicons-star-filled"></span>', 5 )
802
+ );
803
+ ?>
804
+ </p>
805
+
806
+ <p>
807
+ <?php esc_html_e( 'You will truly love the WPForms plugin, but most importantly your support will help us continue to maintain and add new features to the WP Mail SMTP plugin while keeping it free for the larger WordPress community.', 'wp-mail-smtp' ); ?>
808
+ </p>
809
+
810
+ <p>
811
+ <?php
812
+ printf(
813
+ wp_kses(
814
+ /* translators: %1$s - WP Mail SMTP support policy URL, %2$s - WP Mail SMTP support forum URL, %3$s - WPForms URL. */
815
+ __( 'Alternatively, we also offer <a href="%1$s" target="_blank" rel="noopener noreferrer">limited support</a> on the WordPress.org support forums. You can <a href="%2$s" target="_blank" rel="noopener noreferrer">create a support thread</a> there, but please understand that free support is not guaranteed and is limited to simple issues. If you have an urgent or complex issue, then please consider <a href="%3$s" target="_blank" rel="noopener noreferrer">purchasing a WPForms license</a> to access our priority support ticket system.', 'wp-mail-smtp' ),
816
+ array(
817
+ 'a' => array(
818
+ 'href' => array(),
819
+ 'rel' => array(),
820
+ 'target' => array(),
821
+ ),
822
+ )
823
+ ),
824
+ 'https://wordpress.org/support/topic/wp-mail-smtp-support-policy/',
825
+ 'https://wordpress.org/support/plugin/wp-mail-smtp/',
826
+ 'https://wpforms.com/?discount=THANKYOU&utm_source=WordPress&utm_medium=debug-cta&utm_campaign=smtpplugin'
827
+ );
828
+ ?>
829
+ </p>
830
+
831
+ <?php endif; ?>
832
+
833
+ <p>
834
+ <a href="#" class="error-log-toggle">
835
+ <span class="dashicons dashicons-arrow-right-alt2"></span>
836
+ <strong><?php esc_html_e( 'Click here to view the full Error Log for debugging', 'wp-mail-smtp' ); ?></strong>
837
+ </a>
838
+ </p>
839
+
840
+ <div class="error-log">
841
+ <?php echo $this->debug['error_log']; ?>
842
+ </div>
843
+
844
+ <p class="error-log-note">
845
+ <em><?php esc_html_e( 'Please copy only the content of the error debug message above, identified with an orange left border, into the support forum topic if you experience any issues.', 'wp-mail-smtp' ); ?></em>
846
+ </p>
847
+ </div>
848
+ <?php
849
+ }
850
  }
src/Core.php CHANGED
@@ -45,11 +45,18 @@ class Core {
45
  // Activation hook.
46
  add_action( 'activate_wp-mail-smtp/wp_mail_smtp.php', array( $this, 'activate' ) );
47
 
 
48
  add_action( 'plugins_loaded', array( $this, 'get_processor' ) );
49
  add_action( 'plugins_loaded', array( $this, 'replace_phpmailer' ) );
 
 
50
  add_action( 'plugins_loaded', array( $this, 'init_notifications' ) );
51
 
52
- add_action( 'admin_notices', array( '\WPMailSMTP\WP', 'display_admin_notices' ) );
 
 
 
 
53
 
54
  add_action( 'init', array( $this, 'init' ) );
55
  }
@@ -68,12 +75,24 @@ class Core {
68
  * Constantly check in admin area, that we don't need to upgrade DB.
69
  * Do not wait for the `admin_init` hook, because some actions are already done
70
  * on `plugins_loaded`, so migration has to be done before.
 
71
  */
72
  if ( WP::in_wp_admin() ) {
73
  $this->get_migration();
74
  $this->get_upgrade();
 
 
 
 
 
75
  $this->get_admin();
76
  }
 
 
 
 
 
 
77
  }
78
 
79
  /**
@@ -184,6 +203,279 @@ class Core {
184
  }
185
  }
186
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  /**
188
  * Init the \PHPMailer replacement.
189
  *
@@ -220,22 +512,13 @@ class Core {
220
  */
221
  public function activate() {
222
 
223
- // Store the plugin version activated to reference with upgrades.
224
- update_option( 'wp_mail_smtp_version', WPMS_PLUGIN_VER );
225
 
226
- // Create and store initial plugin settings.
227
- $options = array(
228
- 'mail' => array(
229
- 'from_email' => get_option( 'admin_email' ),
230
- 'from_name' => get_bloginfo( 'name' ),
231
- 'mailer' => 'mail',
232
- 'return_path' => false,
233
- ),
234
- 'smtp' => array(
235
- 'autotls' => true,
236
- ),
237
- );
238
 
239
- Options::init()->set( $options, true );
 
240
  }
241
  }
45
  // Activation hook.
46
  add_action( 'activate_wp-mail-smtp/wp_mail_smtp.php', array( $this, 'activate' ) );
47
 
48
+ // Redefine PHPMailer.
49
  add_action( 'plugins_loaded', array( $this, 'get_processor' ) );
50
  add_action( 'plugins_loaded', array( $this, 'replace_phpmailer' ) );
51
+
52
+ // Awesome Motive Notifications.
53
  add_action( 'plugins_loaded', array( $this, 'init_notifications' ) );
54
 
55
+ // Recommendations.
56
+ if ( ! class_exists( 'WPMailSMTP\TGM_Plugin_Activation', false ) ) {
57
+ require_once __DIR__ . '/TGMPA.php';
58
+ }
59
+ add_action( 'tgmpa_register', array( $this, 'init_recommendations' ) );
60
 
61
  add_action( 'init', array( $this, 'init' ) );
62
  }
75
  * Constantly check in admin area, that we don't need to upgrade DB.
76
  * Do not wait for the `admin_init` hook, because some actions are already done
77
  * on `plugins_loaded`, so migration has to be done before.
78
+ * We should not fire this in AJAX requests.
79
  */
80
  if ( WP::in_wp_admin() ) {
81
  $this->get_migration();
82
  $this->get_upgrade();
83
+ $this->detect_conflicts();
84
+ }
85
+
86
+ // In admin area, regardless of AJAX or not AJAX request.
87
+ if ( is_admin() ) {
88
  $this->get_admin();
89
  }
90
+
91
+ // Plugin admin area notices. Display to "admins" only.
92
+ if ( current_user_can( 'manage_options' ) ) {
93
+ add_action( 'admin_notices', array( '\WPMailSMTP\WP', 'display_admin_notices' ) );
94
+ add_action( 'admin_notices', array( $this, 'display_debug_notices' ) );
95
+ }
96
  }
97
 
98
  /**
203
  }
204
  }
205
 
206
+ /**
207
+ * Recommend WPForms Lite using TGM Activation.
208
+ *
209
+ * @since 1.3.0
210
+ */
211
+ public function init_recommendations() {
212
+
213
+ // Recommend only for new installs.
214
+ if ( ! $this->is_new_install() ) {
215
+ return;
216
+ }
217
+
218
+ // Specify a plugin that we want to recommend.
219
+ $plugins = apply_filters( 'wp_mail_smtp_core_recommendations_plugins', array(
220
+ array(
221
+ 'name' => 'Contact Form by WPForms',
222
+ 'slug' => 'wpforms-lite',
223
+ 'required' => false,
224
+ 'is_callable' => 'wpforms', // This will target the Pro version as well, not only the one from WP.org repository.
225
+ ),
226
+ ) );
227
+
228
+ /*
229
+ * Array of configuration settings.
230
+ */
231
+ $config = apply_filters( 'wp_mail_smtp_core_recommendations_config', array(
232
+ 'id' => 'wp-mail-smtp', // Unique ID for hashing notices for multiple instances of TGMPA.
233
+ 'menu' => 'wp-mail-smtp-install-plugins', // Menu slug.
234
+ 'parent_slug' => 'plugins.php', // Parent menu slug.
235
+ 'capability' => 'manage_options', // Capability needed to view plugin install page, should be a capability associated with the parent menu used.
236
+ 'has_notices' => true, // Show admin notices or not.
237
+ 'dismissable' => true, // If false, a user cannot dismiss the nag message.
238
+ 'dismiss_msg' => '', // If 'dismissable' is false, this message will be output at top of nag.
239
+ 'is_automatic' => false, // Automatically activate plugins after installation or not.
240
+ 'message' => '', // Message to output right before the plugins table.
241
+ 'strings' => array(
242
+ /* translators: 1: plugin name(s). */
243
+ 'notice_can_install_recommended' => _n_noop(
244
+ 'Thanks for installing WP Mail SMTP. We also recommend using %1$s. It\'s the best drag & drop form builder, has over 1 million active installs, and over 2000+ 5 star ratings.',
245
+ 'Thanks for installing WP Mail SMTP. We also recommend using %1$s. It\'s the best drag & drop form builder, has over 1 million active installs, and over 2000+ 5 star ratings.',
246
+ 'wp-mail-smtp'
247
+ ),
248
+ /* translators: 1: plugin name(s). */
249
+ 'notice_can_activate_recommended' => _n_noop(
250
+ 'Thanks for installing WP Mail SMTP. We also recommend using %1$s. It\'s the best drag & drop form builder, has over 1 million active installs, and over 2000+ 5 star ratings.',
251
+ 'Thanks for installing WP Mail SMTP. We also recommend using %1$s. It\'s the best drag & drop form builder, has over 1 million active installs, and over 2000+ 5 star ratings.',
252
+ 'wp-mail-smtp'
253
+ ),
254
+ 'install_link' => _n_noop(
255
+ 'Install WPForms Now',
256
+ 'Begin installing plugins',
257
+ 'wp-mail-smtp'
258
+ ),
259
+ 'activate_link' => _n_noop(
260
+ 'Activate WPForms',
261
+ 'Begin activating plugins',
262
+ 'wp-mail-smtp'
263
+ ),
264
+ 'nag_type' => 'notice-info',
265
+ ),
266
+ ) );
267
+
268
+ tgmpa( (array) $plugins, (array) $config );
269
+ }
270
+
271
+ /**
272
+ * Display all debug mail-delivery related notices.
273
+ *
274
+ * @since 1.3.0
275
+ */
276
+ public static function display_debug_notices() {
277
+
278
+ $notice = Debug::get_last();
279
+
280
+ if ( empty( $notice ) ) {
281
+ return;
282
+ }
283
+ ?>
284
+
285
+ <div id="message" class="<?php echo WP::ADMIN_NOTICE_ERROR; ?> notice">
286
+ <p>
287
+ <?php
288
+ echo wp_kses(
289
+ __( '<strong>EMAIL DELIVERY ERROR:</strong> WP Mail SMTP plugin logged this error during the last time it tried to send an email: ', 'wp-mail-smtp' ),
290
+ array(
291
+ 'strong' => array(),
292
+ )
293
+ );
294
+ ?>
295
+ </p>
296
+
297
+ <blockquote>
298
+ <pre><?php echo $notice; ?></pre>
299
+ </blockquote>
300
+
301
+ <p>
302
+ <?php
303
+ if ( ! wp_mail_smtp()->get_admin()->is_admin_page() ) {
304
+ printf(
305
+ wp_kses(
306
+ /* translators: %s - plugin admin page URL. */
307
+ __( 'Please review your WP Mail SMTP settings in <a href="%s">plugin admin area</a>.' ) . ' ',
308
+ array(
309
+ 'a' => array(
310
+ 'href' => array(),
311
+ ),
312
+ )
313
+ ),
314
+ wp_mail_smtp()->get_admin()->get_admin_page_url()
315
+ );
316
+ }
317
+
318
+ esc_html_e( 'Consider running an email test after fixing it.', 'wp-mail-smtp' );
319
+ ?>
320
+ </p>
321
+ </div>
322
+
323
+ <?php
324
+ }
325
+
326
+ /**
327
+ * Check whether we are working with a new plugin install.
328
+ *
329
+ * @since 1.3.0
330
+ *
331
+ * @return bool
332
+ */
333
+ protected function is_new_install() {
334
+ /*
335
+ * No previously installed 0.*.
336
+ * 'wp_mail_smtp_initial_version' option appeared in 1.3.0. So we make sure it exists.
337
+ * No previous plugin upgrades.
338
+ */
339
+ if (
340
+ ! get_option( 'mailer', false ) &&
341
+ get_option( 'wp_mail_smtp_initial_version', false ) &&
342
+ version_compare( WPMS_PLUGIN_VER, get_option( 'wp_mail_smtp_initial_version' ), '=' )
343
+ ) {
344
+ return true;
345
+ }
346
+
347
+ return false;
348
+ }
349
+
350
+ /**
351
+ * Detect if there are plugins activated that will cause a conflict.
352
+ *
353
+ * @since 1.3.0
354
+ */
355
+ public function detect_conflicts() {
356
+
357
+ // Display only for those who can actually deactivate plugins.
358
+ if ( ! current_user_can( 'manage_options' ) ) {
359
+ return;
360
+ }
361
+
362
+ $conflicts = array(
363
+ 'swpsmtp_init_smtp' => array(
364
+ 'name' => 'Easy WP SMTP',
365
+ ),
366
+ 'postman_start' => array(
367
+ 'name' => 'Postman SMTP',
368
+ ),
369
+ 'post_start' => array(
370
+ 'name' => 'Post SMTP Mailer/Email Log',
371
+ ),
372
+ 'mail_bank' => array(
373
+ 'name' => 'WP Mail Bank',
374
+ ),
375
+ 'SMTP_MAILER' => array(
376
+ 'name' => 'SMTP Mailer',
377
+ 'class' => true,
378
+ ),
379
+ 'GMAIL_SMTP' => array(
380
+ 'name' => 'Gmail SMTP',
381
+ 'class' => true,
382
+ ),
383
+ 'WP_Email_Smtp' => array(
384
+ 'name' => 'WP Email SMTP',
385
+ 'class' => true,
386
+ ),
387
+ 'smtpmail_include' => array(
388
+ 'name' => 'SMTP Mail',
389
+ ),
390
+ 'bwssmtp_init' => array(
391
+ 'name' => 'SMTP by BestWebSoft',
392
+ ),
393
+ 'WPSendGrid_SMTP' => array(
394
+ 'name' => 'WP SendGrid SMTP',
395
+ 'class' => true,
396
+ ),
397
+ 'sar_friendly_smtp' => array(
398
+ 'name' => 'SAR Friendly SMTP',
399
+ ),
400
+ 'WPGmail_SMTP' => array(
401
+ 'name' => 'WP Gmail SMTP',
402
+ 'class' => true,
403
+ ),
404
+ 'st_smtp_check_config' => array(
405
+ 'name' => 'Cimy Swift SMTP',
406
+ ),
407
+ 'WP_Easy_SMTP' => array(
408
+ 'name' => 'WP Easy SMTP',
409
+ 'class' => true,
410
+ ),
411
+ 'WPMailgun_SMTP' => array(
412
+ 'name' => 'WP Mailgun SMTP',
413
+ 'class' => true,
414
+ ),
415
+ 'my_smtp_wp' => array(
416
+ 'name' => 'MY SMTP WP',
417
+ ),
418
+ 'mail_booster' => array(
419
+ 'name' => 'WP Mail Booster',
420
+ ),
421
+ 'Sendgrid_Settings' => array(
422
+ 'name' => 'SendGrid',
423
+ 'class' => true,
424
+ ),
425
+ 'WPMS_php_mailer' => array(
426
+ 'name' => 'WP Mail Smtp Mailer',
427
+ ),
428
+ 'WPAmazonSES_SMTP' => array(
429
+ 'name' => 'WP Amazon SES SMTP',
430
+ 'class' => true,
431
+ ),
432
+ 'Postmark_Mail' => array(
433
+ 'name' => 'Postmark for WordPress',
434
+ 'class' => true,
435
+ ),
436
+ 'Mailgun' => array(
437
+ 'name' => 'Mailgun',
438
+ 'class' => true,
439
+ ),
440
+ 'SparkPost' => array(
441
+ 'name' => 'SparkPost',
442
+ 'class' => true,
443
+ ),
444
+ 'WPYahoo_SMTP' => array(
445
+ 'name' => 'WP Yahoo SMTP',
446
+ 'class' => true,
447
+ ),
448
+ 'wpses_init' => array(
449
+ 'name' => 'WP SES',
450
+ 'class' => true,
451
+ ),
452
+ 'TSPHPMailer' => array(
453
+ 'name' => 'turboSMTP',
454
+ ),
455
+ );
456
+
457
+ foreach ( $conflicts as $id => $conflict ) {
458
+ if ( ! empty( $conflict['class'] ) ) {
459
+ $detected = class_exists( $id, false );
460
+ } else {
461
+ $detected = function_exists( $id );
462
+ }
463
+
464
+ if ( $detected ) {
465
+ WP::add_admin_notice(
466
+ sprintf(
467
+ /* translators: %1$s - Plugin name causing conflict; %2$s - Plugin name causing conflict. */
468
+ esc_html__( 'Heads up! WP Mail SMTP has detected %1$s is activated. Please deactivate %2$s to prevent conflicts.', 'wp-mail-smtp' ),
469
+ $conflict['name'],
470
+ $conflict['name']
471
+ ),
472
+ WP::ADMIN_NOTICE_WARNING
473
+ );
474
+ return;
475
+ }
476
+ }
477
+ }
478
+
479
  /**
480
  * Init the \PHPMailer replacement.
481
  *
512
  */
513
  public function activate() {
514
 
515
+ // Store the plugin version when initial install occurred.
516
+ add_option( 'wp_mail_smtp_initial_version', WPMS_PLUGIN_VER, '', false );
517
 
518
+ // Store the plugin version activated to reference with upgrades.
519
+ update_option( 'wp_mail_smtp_version', WPMS_PLUGIN_VER, false );
 
 
 
 
 
 
 
 
 
 
520
 
521
+ // Save default options, only once.
522
+ Options::init()->set( Options::get_defaults(), true );
523
  }
524
  }
src/Debug.php CHANGED
@@ -21,7 +21,7 @@ class Debug {
21
  const OPTION_KEY = 'wp_mail_smtp_debug';
22
 
23
  /**
24
- * Save the debug message to a debug log.
25
  * Adds one more to a list, at the end.
26
  *
27
  * @since 1.2.0
@@ -40,7 +40,7 @@ class Debug {
40
 
41
  array_push( $all, $message );
42
 
43
- update_option( self::OPTION_KEY, $all, false );
44
  }
45
 
46
  /**
21
  const OPTION_KEY = 'wp_mail_smtp_debug';
22
 
23
  /**
24
+ * Save unique debug message to a debug log.
25
  * Adds one more to a list, at the end.
26
  *
27
  * @since 1.2.0
40
 
41
  array_push( $all, $message );
42
 
43
+ update_option( self::OPTION_KEY, array_unique( $all ), false );
44
  }
45
 
46
  /**
src/MailCatcher.php CHANGED
@@ -15,6 +15,18 @@ if ( ! class_exists( 'PHPMailer', false ) ) {
15
  */
16
  class MailCatcher extends \PHPMailer {
17
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  /**
19
  * Modify the default send() behaviour.
20
  * For those mailers, that relies on PHPMailer class - call it directly.
@@ -32,7 +44,7 @@ class MailCatcher extends \PHPMailer {
32
  $mail_mailer = $options->get( 'mail', 'mailer' );
33
 
34
  // Define a custom header, that will be used in Gmail/SMTP mailers.
35
- $this->XMailer = 'WPMailSMTP/Mailer/' . $mail_mailer . ' ' . WPMS_PLUGIN_VER;
36
 
37
  // Use the default PHPMailer, as we inject our settings there for certain providers.
38
  if (
15
  */
16
  class MailCatcher extends \PHPMailer {
17
 
18
+ /**
19
+ * Callback Action function name.
20
+ *
21
+ * The function that handles the result of the send email action.
22
+ * It is called out by send() for each email sent.
23
+ *
24
+ * @since 1.3.0
25
+ *
26
+ * @var string
27
+ */
28
+ public $action_function = '\WPMailSMTP\Processor::send_callback';
29
+
30
  /**
31
  * Modify the default send() behaviour.
32
  * For those mailers, that relies on PHPMailer class - call it directly.
44
  $mail_mailer = $options->get( 'mail', 'mailer' );
45
 
46
  // Define a custom header, that will be used in Gmail/SMTP mailers.
47
+ $this->XMailer = 'WPMailSMTP/Mailer/' . sanitize_key( $mail_mailer ) . ' ' . WPMS_PLUGIN_VER;
48
 
49
  // Use the default PHPMailer, as we inject our settings there for certain providers.
50
  if (
src/Migration.php CHANGED
@@ -12,6 +12,8 @@ class Migration {
12
  /**
13
  * All old values for pre 1.0 version of a plugin.
14
  *
 
 
15
  * @var array
16
  */
17
  protected $old_keys = array(
@@ -35,6 +37,8 @@ class Migration {
35
  /**
36
  * Old values, taken from $old_keys options.
37
  *
 
 
38
  * @var array
39
  */
40
  protected $old_values = array();
@@ -42,6 +46,8 @@ class Migration {
42
  /**
43
  * Converted array of data from previous option values.
44
  *
 
 
45
  * @var array
46
  */
47
  protected $new_values = array();
@@ -60,7 +66,7 @@ class Migration {
60
  $this->old_values = $this->get_old_values();
61
  $this->new_values = $this->get_converted_options();
62
 
63
- Options::init()->set( $this->new_values );
64
 
65
  // Removing all options will be enabled some time in the future.
66
  // $this->clean_deprecated_data();
@@ -97,7 +103,11 @@ class Migration {
97
  $old_values = array();
98
 
99
  foreach ( $this->old_keys as $old_key ) {
100
- $old_values[ $old_key ] = get_option( $old_key, '' );
 
 
 
 
101
  }
102
 
103
  return $old_values;
@@ -200,10 +210,10 @@ class Migration {
200
  $converted['mail']['from_name'] = WPMS_MAIL_FROM_NAME;
201
  }
202
  if ( defined( 'WPMS_MAILER' ) ) {
203
- $converted['mail']['return_path'] = WPMS_MAILER;
204
  }
205
  if ( defined( 'WPMS_SET_RETURN_PATH' ) ) {
206
- $converted['mail']['mailer'] = WPMS_SET_RETURN_PATH;
207
  }
208
 
209
  /*
12
  /**
13
  * All old values for pre 1.0 version of a plugin.
14
  *
15
+ * @since 1.0.0
16
+ *
17
  * @var array
18
  */
19
  protected $old_keys = array(
37
  /**
38
  * Old values, taken from $old_keys options.
39
  *
40
+ * @since 1.0.0
41
+ *
42
  * @var array
43
  */
44
  protected $old_values = array();
46
  /**
47
  * Converted array of data from previous option values.
48
  *
49
+ * @since 1.0.0
50
+ *
51
  * @var array
52
  */
53
  protected $new_values = array();
66
  $this->old_values = $this->get_old_values();
67
  $this->new_values = $this->get_converted_options();
68
 
69
+ Options::init()->set( $this->new_values, true );
70
 
71
  // Removing all options will be enabled some time in the future.
72
  // $this->clean_deprecated_data();
103
  $old_values = array();
104
 
105
  foreach ( $this->old_keys as $old_key ) {
106
+ $value = get_option( $old_key, '' );
107
+
108
+ if ( ! empty( $value ) ) {
109
+ $old_values[ $old_key ] = $value;
110
+ }
111
  }
112
 
113
  return $old_values;
210
  $converted['mail']['from_name'] = WPMS_MAIL_FROM_NAME;
211
  }
212
  if ( defined( 'WPMS_MAILER' ) ) {
213
+ $converted['mail']['mailer'] = WPMS_MAILER;
214
  }
215
  if ( defined( 'WPMS_SET_RETURN_PATH' ) ) {
216
+ $converted['mail']['return_path'] = WPMS_SET_RETURN_PATH;
217
  }
218
 
219
  /*
src/Options.php CHANGED
@@ -21,6 +21,8 @@ class Options {
21
  'from_email',
22
  'mailer',
23
  'return_path',
 
 
24
  ),
25
  'smtp' => array(
26
  'host',
@@ -68,6 +70,7 @@ class Options {
68
 
69
  /**
70
  * Init the Options class.
 
71
  *
72
  * @since 1.0.0
73
  */
@@ -101,6 +104,30 @@ class Options {
101
  return $instance;
102
  }
103
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  /**
105
  * Retrieve all options of the plugin.
106
  *
@@ -188,7 +215,12 @@ class Options {
188
  $value = $this->postprocess_key_defaults( $group, $key );
189
  }
190
  } else {
191
- $value = $this->postprocess_key_defaults( $group, $key );
 
 
 
 
 
192
  }
193
 
194
  if ( is_string( $value ) ) {
@@ -214,6 +246,8 @@ class Options {
214
  $value = '';
215
 
216
  switch ( $key ) {
 
 
217
  case 'return_path':
218
  $value = $group === 'mail' ? false : true;
219
  break;
@@ -268,7 +302,14 @@ class Options {
268
  /** @noinspection PhpUndefinedConstantInspection */
269
  return $this->is_const_defined( $group, $key ) ? WPMS_MAILER : $value;
270
  case 'return_path':
271
- return $this->is_const_defined( $group, $key ) ? true : $value;
 
 
 
 
 
 
 
272
  }
273
 
274
  break;
@@ -384,6 +425,10 @@ class Options {
384
  return defined( 'WPMS_MAILER' ) && WPMS_MAILER;
385
  case 'return_path':
386
  return defined( 'WPMS_SET_RETURN_PATH' ) && ( WPMS_SET_RETURN_PATH === 'true' || WPMS_SET_RETURN_PATH === true );
 
 
 
 
387
  }
388
 
389
  break;
@@ -466,6 +511,8 @@ class Options {
466
  }
467
  break;
468
  case 'return_path':
 
 
469
  $options[ $group ][ $key_name ] = $this->get_const_value( $group, $key_name, (bool) $options[ $group ][ $key_name ] );
470
  break;
471
  }
@@ -474,6 +521,7 @@ class Options {
474
  case 'general':
475
  switch ( $key_name ) {
476
  case 'am_notifications_hidden':
 
477
  $options[ $group ][ $key_name ] = (bool) $options[ $group ][ $key_name ];
478
  break;
479
  }
@@ -514,8 +562,14 @@ class Options {
514
  case 'client_secret':
515
  case 'auth_code':
516
  case 'access_token':
 
 
 
 
 
 
517
  // Do not process as they may contain certain special characters, but allow to be overwritten using constants.
518
- $options[ $mailer ][ $key_name ] = $this->get_const_value( $mailer, $key_name, $options[ $mailer ][ $key_name ] );
519
  break;
520
  }
521
  }
21
  'from_email',
22
  'mailer',
23
  'return_path',
24
+ 'from_name_force',
25
+ 'from_email_force',
26
  ),
27
  'smtp' => array(
28
  'host',
70
 
71
  /**
72
  * Init the Options class.
73
+ * TODO: add a flag to process without retrieving const values.
74
  *
75
  * @since 1.0.0
76
  */
104
  return $instance;
105
  }
106
 
107
+ /**
108
+ * Default options that are saved on plugin activation.
109
+ *
110
+ * @since 1.3.0
111
+ *
112
+ * @return array
113
+ */
114
+ public static function get_defaults() {
115
+
116
+ return array(
117
+ 'mail' => array(
118
+ 'from_email' => get_option( 'admin_email' ),
119
+ 'from_name' => get_bloginfo( 'name' ),
120
+ 'mailer' => 'mail',
121
+ 'return_path' => false,
122
+ 'from_email_force' => false,
123
+ 'from_name_force' => false,
124
+ ),
125
+ 'smtp' => array(
126
+ 'autotls' => true,
127
+ ),
128
+ );
129
+ }
130
+
131
  /**
132
  * Retrieve all options of the plugin.
133
  *
215
  $value = $this->postprocess_key_defaults( $group, $key );
216
  }
217
  } else {
218
+ // check on maps
219
+ if ( isset( self::$map[ $group ] ) && in_array( $key, self::$map[ $group ] ) ) {
220
+ $value = $this->get_const_value( $group, $key, false );
221
+ } else {
222
+ $value = $this->postprocess_key_defaults( $group, $key );
223
+ }
224
  }
225
 
226
  if ( is_string( $value ) ) {
246
  $value = '';
247
 
248
  switch ( $key ) {
249
+ case 'from_email_force':
250
+ case 'from_name_force':
251
  case 'return_path':
252
  $value = $group === 'mail' ? false : true;
253
  break;
302
  /** @noinspection PhpUndefinedConstantInspection */
303
  return $this->is_const_defined( $group, $key ) ? WPMS_MAILER : $value;
304
  case 'return_path':
305
+ /** @noinspection PhpUndefinedConstantInspection */
306
+ return $this->is_const_defined( $group, $key ) ? WPMS_SET_RETURN_PATH : $value;
307
+ case 'from_name_force':
308
+ /** @noinspection PhpUndefinedConstantInspection */
309
+ return $this->is_const_defined( $group, $key ) ? WPMS_MAIL_FROM_NAME_FORCE : $value;
310
+ case 'from_email_force':
311
+ /** @noinspection PhpUndefinedConstantInspection */
312
+ return $this->is_const_defined( $group, $key ) ? WPMS_MAIL_FROM_FORCE : $value;
313
  }
314
 
315
  break;
425
  return defined( 'WPMS_MAILER' ) && WPMS_MAILER;
426
  case 'return_path':
427
  return defined( 'WPMS_SET_RETURN_PATH' ) && ( WPMS_SET_RETURN_PATH === 'true' || WPMS_SET_RETURN_PATH === true );
428
+ case 'from_name_force':
429
+ return defined( 'WPMS_MAIL_FROM_NAME_FORCE' ) && ( WPMS_MAIL_FROM_NAME_FORCE === 'true' || WPMS_MAIL_FROM_NAME_FORCE === true );
430
+ case 'from_email_force':
431
+ return defined( 'WPMS_MAIL_FROM_FORCE' ) && ( WPMS_MAIL_FROM_FORCE === 'true' || WPMS_MAIL_FROM_FORCE === true );
432
  }
433
 
434
  break;
511
  }
512
  break;
513
  case 'return_path':
514
+ case 'from_name_force':
515
+ case 'from_email_force':
516
  $options[ $group ][ $key_name ] = $this->get_const_value( $group, $key_name, (bool) $options[ $group ][ $key_name ] );
517
  break;
518
  }
521
  case 'general':
522
  switch ( $key_name ) {
523
  case 'am_notifications_hidden':
524
+ case 'uninstall':
525
  $options[ $group ][ $key_name ] = (bool) $options[ $group ][ $key_name ];
526
  break;
527
  }
562
  case 'client_secret':
563
  case 'auth_code':
564
  case 'access_token':
565
+ if ( is_string( $options[ $mailer ][ $key_name ] ) ) {
566
+ $value = trim( $options[ $mailer ][ $key_name ] );
567
+ } else {
568
+ $value = $options[ $mailer ][ $key_name ];
569
+ }
570
+
571
  // Do not process as they may contain certain special characters, but allow to be overwritten using constants.
572
+ $options[ $mailer ][ $key_name ] = $this->get_const_value( $mailer, $key_name, $value );
573
  break;
574
  }
575
  }
src/Processor.php CHANGED
@@ -27,8 +27,8 @@ class Processor {
27
 
28
  add_action( 'phpmailer_init', array( $this, 'phpmailer_init' ) );
29
 
30
- add_filter( 'wp_mail_from', array( $this, 'filter_mail_from_email' ) );
31
- add_filter( 'wp_mail_from_name', array( $this, 'filter_mail_from_name' ), 11 );
32
  }
33
 
34
  /**
@@ -109,10 +109,35 @@ class Processor {
109
  $phpmailer = apply_filters( 'wp_mail_smtp_custom_options', $phpmailer );
110
  }
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  /**
113
  * Modify the email address that is used for sending emails.
114
  *
115
  * @since 1.0.0
 
116
  *
117
  * @param string $email
118
  *
@@ -120,15 +145,18 @@ class Processor {
120
  */
121
  public function filter_mail_from_email( $email ) {
122
 
123
- // If the from email is not the default, return it unchanged.
124
- if ( $email !== $this->get_default_email() ) {
 
 
 
125
  return $email;
126
  }
127
 
128
- $from_email = Options::init()->get( 'mail', 'from_email' );
129
 
130
  if ( ! empty( $from_email ) ) {
131
- return $from_email;
132
  }
133
 
134
  return $email;
@@ -138,6 +166,7 @@ class Processor {
138
  * Modify the sender name that is used for sending emails.
139
  *
140
  * @since 1.0.0
 
141
  *
142
  * @param string $name
143
  *
@@ -145,10 +174,16 @@ class Processor {
145
  */
146
  public function filter_mail_from_name( $name ) {
147
 
148
- if ( 'WordPress' === $name ) {
149
- $name = Options::init()->get( 'mail', 'from_name' );
 
 
 
 
150
  }
151
 
 
 
152
  return $name;
153
  }
154
 
@@ -172,4 +207,15 @@ class Processor {
172
 
173
  return 'wordpress@' . $sitename;
174
  }
 
 
 
 
 
 
 
 
 
 
 
175
  }
27
 
28
  add_action( 'phpmailer_init', array( $this, 'phpmailer_init' ) );
29
 
30
+ add_filter( 'wp_mail_from', array( $this, 'filter_mail_from_email' ), 1000 );
31
+ add_filter( 'wp_mail_from_name', array( $this, 'filter_mail_from_name' ), 1000 );
32
  }
33
 
34
  /**
109
  $phpmailer = apply_filters( 'wp_mail_smtp_custom_options', $phpmailer );
110
  }
111
 
112
+ /**
113
+ * This method will be called every time 'smtp' and 'mail' mailers will be used to send emails.
114
+ *
115
+ * @since 1.3.0
116
+ *
117
+ * @param bool $is_sent
118
+ * @param array $to
119
+ * @param array $cc
120
+ * @param array $bcc
121
+ * @param string $subject
122
+ * @param string $body
123
+ * @param string $from
124
+ */
125
+ public static function send_callback( $is_sent, $to, $cc, $bcc, $subject, $body, $from ) {
126
+
127
+ if ( ! $is_sent ) {
128
+ // Add mailer to the beginning and save to display later.
129
+ Debug::set(
130
+ 'Mailer: ' . esc_html( wp_mail_smtp()->get_providers()->get_options( Options::init()->get( 'mail', 'mailer' ) )->get_title() ) . "\r\n" .
131
+ 'PHPMailer was able to connect to SMTP server but failed while trying to send an email.'
132
+ );
133
+ }
134
+ }
135
+
136
  /**
137
  * Modify the email address that is used for sending emails.
138
  *
139
  * @since 1.0.0
140
+ * @since 1.3.0 Forcing email rewrite if option is selected.
141
  *
142
  * @param string $email
143
  *
145
  */
146
  public function filter_mail_from_email( $email ) {
147
 
148
+ $options = new Options();
149
+ $force = $options->get( 'mail', 'from_email_force' );
150
+
151
+ // If the FROM EMAIL is not the default and not forced, return it unchanged.
152
+ if ( ! $force && $email !== $this->get_default_email() ) {
153
  return $email;
154
  }
155
 
156
+ $from_email = $options->get( 'mail', 'from_email' );
157
 
158
  if ( ! empty( $from_email ) ) {
159
+ $email = $from_email;
160
  }
161
 
162
  return $email;
166
  * Modify the sender name that is used for sending emails.
167
  *
168
  * @since 1.0.0
169
+ * @since 1.3.0 Forcing name rewrite if option is selected.
170
  *
171
  * @param string $name
172
  *
174
  */
175
  public function filter_mail_from_name( $name ) {
176
 
177
+ $options = new Options();
178
+ $force = $options->get( 'mail', 'from_name_force' );
179
+
180
+ // If the FROM NAME is not the default and not forced, return it unchanged.
181
+ if ( ! $force && $name !== $this->get_default_name() ) {
182
+ return $name;
183
  }
184
 
185
+ $name = $options->get( 'mail', 'from_name' );
186
+
187
  return $name;
188
  }
189
 
207
 
208
  return 'wordpress@' . $sitename;
209
  }
210
+
211
+ /**
212
+ * Get the default email FROM NAME generated by WordPress.
213
+ *
214
+ * @since 1.3.0
215
+ *
216
+ * @return string
217
+ */
218
+ public function get_default_name() {
219
+ return 'WordPress';
220
+ }
221
  }
src/Providers/Gmail/Auth.php CHANGED
@@ -88,7 +88,7 @@ class Auth extends AuthAbstract {
88
  $client->setApprovalPrompt( 'force' );
89
  $client->setIncludeGrantedScopes( true );
90
  // We request only the sending capability, as it's what we only need to do.
91
- $client->setScopes( array( \Google_Service_Gmail::GMAIL_SEND ) );
92
  $client->setRedirectUri( self::get_plugin_auth_url() );
93
 
94
  if (
@@ -99,12 +99,14 @@ class Auth extends AuthAbstract {
99
  $creds = $client->fetchAccessTokenWithAuthCode( $this->gmail['auth_code'] );
100
  } catch ( \Exception $e ) {
101
  $creds['error'] = $e->getMessage();
102
- Debug::set( $e->getMessage() );
 
 
 
103
  }
104
 
105
  // Bail if we have an error.
106
  if ( ! empty( $creds['error'] ) ) {
107
- // TODO: save this error to display to a user later.
108
  return $client;
109
  }
110
 
@@ -128,7 +130,10 @@ class Auth extends AuthAbstract {
128
  $creds = $client->fetchAccessTokenWithRefreshToken( $refresh );
129
  } catch ( \Exception $e ) {
130
  $creds['error'] = $e->getMessage();
131
- Debug::set( $e->getMessage() );
 
 
 
132
  }
133
 
134
  // Bail if we have an error.
@@ -196,8 +201,10 @@ class Auth extends AuthAbstract {
196
  if (
197
  ! empty( $code ) &&
198
  (
199
- $scope === ( \Google_Service_Gmail::GMAIL_SEND . ' ' . \Google_Service_Gmail::MAIL_GOOGLE_COM ) ||
200
- $scope === \Google_Service_Gmail::GMAIL_SEND
 
 
201
  )
202
  ) {
203
  // Save the auth code. So \Google_Client can reuse it to retrieve the access token.
@@ -246,7 +253,7 @@ class Auth extends AuthAbstract {
246
  *
247
  * @since 1.0.0
248
  *
249
- * @param array $token
250
  */
251
  protected function update_refresh_token( $token ) {
252
 
@@ -285,6 +292,7 @@ class Auth extends AuthAbstract {
285
  * @return string
286
  */
287
  public function get_google_auth_url() {
 
288
  if (
289
  ! empty( $this->client ) &&
290
  class_exists( 'Google_Client', false ) &&
@@ -293,7 +301,7 @@ class Auth extends AuthAbstract {
293
  return filter_var( $this->client->createAuthUrl(), FILTER_SANITIZE_URL );
294
  }
295
 
296
- return '';
297
  }
298
 
299
  /**
88
  $client->setApprovalPrompt( 'force' );
89
  $client->setIncludeGrantedScopes( true );
90
  // We request only the sending capability, as it's what we only need to do.
91
+ $client->setScopes( array( \Google_Service_Gmail::MAIL_GOOGLE_COM ) );
92
  $client->setRedirectUri( self::get_plugin_auth_url() );
93
 
94
  if (
99
  $creds = $client->fetchAccessTokenWithAuthCode( $this->gmail['auth_code'] );
100
  } catch ( \Exception $e ) {
101
  $creds['error'] = $e->getMessage();
102
+ Debug::set(
103
+ 'Mailer: Gmail' . "\r\n" .
104
+ $creds['error']
105
+ );
106
  }
107
 
108
  // Bail if we have an error.
109
  if ( ! empty( $creds['error'] ) ) {
 
110
  return $client;
111
  }
112
 
130
  $creds = $client->fetchAccessTokenWithRefreshToken( $refresh );
131
  } catch ( \Exception $e ) {
132
  $creds['error'] = $e->getMessage();
133
+ Debug::set(
134
+ 'Mailer: Gmail' . "\r\n" .
135
+ $e->getMessage()
136
+ );
137
  }
138
 
139
  // Bail if we have an error.
201
  if (
202
  ! empty( $code ) &&
203
  (
204
+ $scope === \Google_Service_Gmail::MAIL_GOOGLE_COM . ' ' . \Google_Service_Gmail::GMAIL_SEND ||
205
+ $scope === \Google_Service_Gmail::GMAIL_SEND . ' ' . \Google_Service_Gmail::MAIL_GOOGLE_COM ||
206
+ $scope === \Google_Service_Gmail::GMAIL_SEND ||
207
+ $scope === \Google_Service_Gmail::MAIL_GOOGLE_COM
208
  )
209
  ) {
210
  // Save the auth code. So \Google_Client can reuse it to retrieve the access token.
253
  *
254
  * @since 1.0.0
255
  *
256
+ * @param string $token
257
  */
258
  protected function update_refresh_token( $token ) {
259
 
292
  * @return string
293
  */
294
  public function get_google_auth_url() {
295
+
296
  if (
297
  ! empty( $this->client ) &&
298
  class_exists( 'Google_Client', false ) &&
301
  return filter_var( $this->client->createAuthUrl(), FILTER_SANITIZE_URL );
302
  }
303
 
304
+ return '#';
305
  }
306
 
307
  /**
src/Providers/Gmail/Mailer.php CHANGED
@@ -94,7 +94,10 @@ class Mailer extends MailerAbstract {
94
 
95
  $this->process_response( $response );
96
  } catch ( \Exception $e ) {
97
- Debug::set( 'Error while sending via Gmail mailer: ' . $e->getMessage() );
 
 
 
98
 
99
  return;
100
  }
@@ -119,15 +122,21 @@ class Mailer extends MailerAbstract {
119
  * @return bool
120
  */
121
  public function is_email_sent() {
 
122
  $is_sent = false;
123
 
124
  if ( method_exists( $this->response, 'getId' ) ) {
125
  $message_id = $this->response->getId();
126
  if ( ! empty( $message_id ) ) {
127
- return true;
128
  }
129
  }
130
 
 
 
 
 
 
131
  return $is_sent;
132
  }
133
 
94
 
95
  $this->process_response( $response );
96
  } catch ( \Exception $e ) {
97
+ Debug::set(
98
+ 'Mailer: Gmail' . "\r\n" .
99
+ $e->getMessage()
100
+ );
101
 
102
  return;
103
  }
122
  * @return bool
123
  */
124
  public function is_email_sent() {
125
+
126
  $is_sent = false;
127
 
128
  if ( method_exists( $this->response, 'getId' ) ) {
129
  $message_id = $this->response->getId();
130
  if ( ! empty( $message_id ) ) {
131
+ $is_sent = true;
132
  }
133
  }
134
 
135
+ // Clear debug messages if email is successfully sent.
136
+ if ( $is_sent ) {
137
+ Debug::clear();
138
+ }
139
+
140
  return $is_sent;
141
  }
142
 
src/Providers/Gmail/Options.php CHANGED
@@ -58,7 +58,8 @@ class Options extends OptionsAbstract {
58
  ?>
59
 
60
  <!-- Client ID -->
61
- <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_id" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
 
62
  <div class="wp-mail-smtp-setting-label">
63
  <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_id"><?php esc_html_e( 'Client ID', 'wp-mail-smtp' ); ?></label>
64
  </div>
@@ -72,7 +73,8 @@ class Options extends OptionsAbstract {
72
  </div>
73
 
74
  <!-- Client Secret -->
75
- <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
 
76
  <div class="wp-mail-smtp-setting-label">
77
  <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret"><?php esc_html_e( 'Client Secret', 'wp-mail-smtp' ); ?></label>
78
  </div>
@@ -86,7 +88,8 @@ class Options extends OptionsAbstract {
86
  </div>
87
 
88
  <!-- Authorized redirect URI -->
89
- <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
 
90
  <div class="wp-mail-smtp-setting-label">
91
  <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect"><?php esc_html_e( 'Authorized redirect URI', 'wp-mail-smtp' ); ?></label>
92
  </div>
@@ -109,23 +112,98 @@ class Options extends OptionsAbstract {
109
  </div>
110
 
111
  <!-- Auth users button -->
112
- <?php $auth = new Auth(); ?>
113
- <?php if ( $auth->is_clients_saved() && $auth->is_auth_required() ) : ?>
114
- <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-authorize" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
115
- <div class="wp-mail-smtp-setting-label">
116
- <label><?php esc_html_e( 'Authorize', 'wp-mail-smtp' ); ?></label>
117
- </div>
118
- <div class="wp-mail-smtp-setting-field">
119
- <a href="<?php echo esc_url( $auth->get_google_auth_url() ); ?>" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange">
120
- <?php esc_html_e( 'Allow plugin to send emails using your Google account', 'wp-mail-smtp' ); ?>
121
- </a>
122
- <p class="desc">
123
- <?php esc_html_e( 'Click the button above to confirm authorization.', 'wp-mail-smtp' ); ?>
124
- </p>
125
- </div>
126
  </div>
127
- <?php endif; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  }
131
  }
58
  ?>
59
 
60
  <!-- Client ID -->
61
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_id"
62
+ class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
63
  <div class="wp-mail-smtp-setting-label">
64
  <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_id"><?php esc_html_e( 'Client ID', 'wp-mail-smtp' ); ?></label>
65
  </div>
73
  </div>
74
 
75
  <!-- Client Secret -->
76
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret"
77
+ class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
78
  <div class="wp-mail-smtp-setting-label">
79
  <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret"><?php esc_html_e( 'Client Secret', 'wp-mail-smtp' ); ?></label>
80
  </div>
88
  </div>
89
 
90
  <!-- Authorized redirect URI -->
91
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect"
92
+ class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
93
  <div class="wp-mail-smtp-setting-label">
94
  <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect"><?php esc_html_e( 'Authorized redirect URI', 'wp-mail-smtp' ); ?></label>
95
  </div>
112
  </div>
113
 
114
  <!-- Auth users button -->
115
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-authorize"
116
+ class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
117
+ <div class="wp-mail-smtp-setting-label">
118
+ <label><?php esc_html_e( 'Authorization', 'wp-mail-smtp' ); ?></label>
119
+ </div>
120
+ <div class="wp-mail-smtp-setting-field">
121
+ <?php $this->display_auth_setting_action(); ?>
 
 
 
 
 
 
 
122
  </div>
123
+ </div>
124
+
125
+ <?php
126
+ }
127
+
128
+ /**
129
+ * Display either an "Allow..." or "Remove..." button.
130
+ *
131
+ * @since 1.3.0
132
+ */
133
+ protected function display_auth_setting_action() {
134
+
135
+ // Do the processing on the fly, as having ajax here is too complicated.
136
+ $this->process_gmail_remove();
137
+
138
+ $auth = new Auth();
139
+ ?>
140
+
141
+ <script>
142
+ var wp_mail_smtp = window.wp_mail_smtp || {};
143
+ wp_mail_smtp.text_gmail_remove = "<?php esc_html_e( 'Are you sure you want to reset the current Gmail connection? You will need to immediately create a new one to be able to send emails.', 'wp-mail-smtp' ); ?>";
144
+ </script>
145
+
146
+ <?php if ( $auth->is_clients_saved() ) : ?>
147
+
148
+ <?php if ( $auth->is_auth_required() ) : ?>
149
+
150
+ <a href="<?php echo esc_url( $auth->get_google_auth_url() ); ?>" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange">
151
+ <?php esc_html_e( 'Allow plugin to send emails using your Google account', 'wp-mail-smtp' ); ?>
152
+ </a>
153
+ <p class="desc">
154
+ <?php esc_html_e( 'Click the button above to confirm authorization.', 'wp-mail-smtp' ); ?>
155
+ </p>
156
+
157
+ <?php else : ?>
158
+
159
+ <a href="<?php echo wp_nonce_url( wp_mail_smtp()->get_admin()->get_admin_page_url(), 'gmail_remove', 'gmail_remove_nonce' ); ?>#wp-mail-smtp-setting-row-gmail-authorize" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-red" id="wp-mail-smtp-gmail-remove">
160
+ <?php esc_html_e( 'Remove Connection', 'wp-mail-smtp' ); ?>
161
+ </a>
162
+ <p class="desc">
163
+ <?php esc_html_e( 'Removing the connection will give you an ability to redo the connection or link to another Google account.', 'wp-mail-smtp' ); ?>
164
+ </p>
165
+
166
+ <?php endif; ?>
167
+
168
+ <?php else : ?>
169
+
170
+ <p>
171
+ <?php esc_html_e( 'To setup Gmail integration properly you should save Client ID and Client Secret.', 'wp-mail-smtp' ); ?>
172
+ </p>
173
 
174
  <?php
175
+ endif;
176
+ }
177
+
178
+ /**
179
+ * Remove Gmail connection.
180
+ *
181
+ * @since 1.3.0
182
+ */
183
+ public function process_gmail_remove() {
184
+
185
+ if ( ! is_super_admin() ) {
186
+ return;
187
+ }
188
+
189
+ if (
190
+ ! isset( $_GET['gmail_remove_nonce'] ) ||
191
+ ! wp_verify_nonce( $_GET['gmail_remove_nonce'], 'gmail_remove' )
192
+ ) {
193
+ return;
194
+ }
195
+
196
+ $options = new \WPMailSMTP\Options();
197
+ $old_opt = $options->get_all();
198
+
199
+ if ( $options->get( 'mail', 'mailer' ) === 'gmail' ) {
200
+ foreach ( $old_opt['gmail'] as $key => $value ) {
201
+ if ( ! in_array( $key, array( 'client_id', 'client_secret' ), true ) ) {
202
+ unset( $old_opt['gmail'][ $key ] );
203
+ }
204
+ }
205
+ }
206
+
207
+ $options->set( $old_opt );
208
  }
209
  }
src/Providers/MailerAbstract.php CHANGED
@@ -105,12 +105,16 @@ abstract class MailerAbstract implements MailerInterface {
105
  )
106
  );
107
  $this->set_subject( $this->phpmailer->Subject );
108
- $this->set_content(
109
- array(
110
- 'html' => $this->phpmailer->Body,
111
- 'text' => $this->phpmailer->AltBody,
112
- )
113
- );
 
 
 
 
114
  $this->set_return_path( $this->phpmailer->From );
115
  $this->set_reply_to( $this->phpmailer->getReplyToAddresses() );
116
 
@@ -287,10 +291,19 @@ abstract class MailerAbstract implements MailerInterface {
287
  $error = $this->get_response_error();
288
 
289
  if ( ! empty( $error ) ) {
290
- Debug::set( $error );
 
 
 
 
291
  }
292
  }
293
 
 
 
 
 
 
294
  return apply_filters( 'wp_mail_smtp_providers_mailer_is_email_sent', $is_sent );
295
  }
296
 
105
  )
106
  );
107
  $this->set_subject( $this->phpmailer->Subject );
108
+ if ( $this->phpmailer->ContentType === 'text/html' ) {
109
+ $this->set_content(
110
+ array(
111
+ 'text' => $this->phpmailer->AltBody,
112
+ 'html' => $this->phpmailer->Body,
113
+ )
114
+ );
115
+ } else {
116
+ $this->set_content( $this->phpmailer->Body );
117
+ }
118
  $this->set_return_path( $this->phpmailer->From );
119
  $this->set_reply_to( $this->phpmailer->getReplyToAddresses() );
120
 
291
  $error = $this->get_response_error();
292
 
293
  if ( ! empty( $error ) ) {
294
+ // Add mailer to the beginning and save to display later.
295
+ Debug::set(
296
+ 'Mailer: ' . esc_html( wp_mail_smtp()->get_providers()->get_options( $this->mailer )->get_title() ) . "\r\n" .
297
+ $error
298
+ );
299
  }
300
  }
301
 
302
+ // Clear debug messages if email is successfully sent.
303
+ if ( $is_sent ) {
304
+ Debug::clear();
305
+ }
306
+
307
  return apply_filters( 'wp_mail_smtp_providers_mailer_is_email_sent', $is_sent );
308
  }
309
 
src/Providers/Mailgun/Mailer.php CHANGED
@@ -137,10 +137,11 @@ class Mailer extends MailerAbstract {
137
  );
138
  }
139
  } else {
140
- $type = 'text';
141
 
142
- if ( $this->phpmailer->ContentType === 'text/html' ) {
143
- $type = 'html';
 
 
144
  }
145
 
146
  if ( ! empty( $content ) ) {
@@ -190,7 +191,7 @@ class Mailer extends MailerAbstract {
190
 
191
  $data[] = array(
192
  'content' => $file,
193
- 'name' => $attachment[1],
194
  );
195
  }
196
 
137
  );
138
  }
139
  } else {
 
140
 
141
+ $type = 'html';
142
+
143
+ if ( $this->phpmailer->ContentType === 'text/plain' ) {
144
+ $type = 'text';
145
  }
146
 
147
  if ( ! empty( $content ) ) {
191
 
192
  $data[] = array(
193
  'content' => $file,
194
+ 'name' => $attachment[2],
195
  );
196
  }
197
 
src/Providers/OptionsAbstract.php CHANGED
@@ -134,20 +134,6 @@ abstract class OptionsAbstract implements OptionsInterface {
134
  </div>
135
  </div>
136
 
137
- <!-- SMTP Port -->
138
- <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-port" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-number wp-mail-smtp-clear">
139
- <div class="wp-mail-smtp-setting-label">
140
- <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-port"><?php esc_html_e( 'SMTP Port', 'wp-mail-smtp' ); ?></label>
141
- </div>
142
- <div class="wp-mail-smtp-setting-field">
143
- <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][port]" type="number"
144
- value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'port' ) ); ?>"
145
- <?php echo $this->options->is_const_defined( $this->get_slug(), 'port' ) ? 'disabled' : ''; ?>
146
- id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-port" class="small-text" spellcheck="false"
147
- />
148
- </div>
149
- </div>
150
-
151
  <!-- SMTP Encryption -->
152
  <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-encryption" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-radio wp-mail-smtp-clear">
153
  <div class="wp-mail-smtp-setting-label">
@@ -188,6 +174,20 @@ abstract class OptionsAbstract implements OptionsInterface {
188
  </div>
189
  </div>
190
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  <!-- PHPMailer SMTPAutoTLS -->
192
  <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-autotls" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox-toggle wp-mail-smtp-clear <?php echo $this->options->is_const_defined( $this->get_slug(), 'encryption' ) || 'tls' === $this->options->get( $this->get_slug(), 'encryption' ) ? 'inactive' : ''; ?>">
193
  <div class="wp-mail-smtp-setting-label">
@@ -238,7 +238,7 @@ abstract class OptionsAbstract implements OptionsInterface {
238
  <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][user]" type="text"
239
  value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'user' ) ); ?>"
240
  <?php echo $this->options->is_const_defined( $this->get_slug(), 'user' ) ? 'disabled' : ''; ?>
241
- id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-user" spellcheck="false" autocomplete="off"
242
  />
243
  </div>
244
  </div>
@@ -254,7 +254,7 @@ abstract class OptionsAbstract implements OptionsInterface {
254
  <?php else : ?>
255
  <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][pass]" type="password"
256
  value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'pass' ) ); ?>"
257
- id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-pass" spellcheck="false" autocomplete="off"
258
  />
259
  <p class="desc">
260
  <?php
134
  </div>
135
  </div>
136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  <!-- SMTP Encryption -->
138
  <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-encryption" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-radio wp-mail-smtp-clear">
139
  <div class="wp-mail-smtp-setting-label">
174
  </div>
175
  </div>
176
 
177
+ <!-- SMTP Port -->
178
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-port" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-number wp-mail-smtp-clear">
179
+ <div class="wp-mail-smtp-setting-label">
180
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-port"><?php esc_html_e( 'SMTP Port', 'wp-mail-smtp' ); ?></label>
181
+ </div>
182
+ <div class="wp-mail-smtp-setting-field">
183
+ <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][port]" type="number"
184
+ value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'port' ) ); ?>"
185
+ <?php echo $this->options->is_const_defined( $this->get_slug(), 'port' ) ? 'disabled' : ''; ?>
186
+ id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-port" class="small-text" spellcheck="false"
187
+ />
188
+ </div>
189
+ </div>
190
+
191
  <!-- PHPMailer SMTPAutoTLS -->
192
  <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-autotls" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox-toggle wp-mail-smtp-clear <?php echo $this->options->is_const_defined( $this->get_slug(), 'encryption' ) || 'tls' === $this->options->get( $this->get_slug(), 'encryption' ) ? 'inactive' : ''; ?>">
193
  <div class="wp-mail-smtp-setting-label">
238
  <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][user]" type="text"
239
  value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'user' ) ); ?>"
240
  <?php echo $this->options->is_const_defined( $this->get_slug(), 'user' ) ? 'disabled' : ''; ?>
241
+ id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-user" spellcheck="false" autocomplete="new-password"
242
  />
243
  </div>
244
  </div>
254
  <?php else : ?>
255
  <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][pass]" type="password"
256
  value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'pass' ) ); ?>"
257
+ id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-pass" spellcheck="false" autocomplete="new-password"
258
  />
259
  <p class="desc">
260
  <?php
src/Providers/Sendgrid/Mailer.php CHANGED
@@ -171,11 +171,11 @@ class Mailer extends MailerAbstract {
171
  )
172
  );
173
  } else {
174
- $data['type'] = 'text/plain';
175
  $data['value'] = $content;
176
 
177
- if ( $this->phpmailer->ContentType === 'text/html' ) {
178
- $data['type'] = 'text/html';
179
  }
180
 
181
  $this->set_body_param(
@@ -225,7 +225,7 @@ class Mailer extends MailerAbstract {
225
  $data[] = array(
226
  'content' => base64_encode( $file ),
227
  'type' => $attachment[4],
228
- 'filename' => $attachment[1],
229
  'disposition' => $attachment[6],
230
  );
231
  }
171
  )
172
  );
173
  } else {
174
+ $data['type'] = 'text/html';
175
  $data['value'] = $content;
176
 
177
+ if ( $this->phpmailer->ContentType === 'text/plain' ) {
178
+ $data['type'] = 'text/plain';
179
  }
180
 
181
  $this->set_body_param(
225
  $data[] = array(
226
  'content' => base64_encode( $file ),
227
  'type' => $attachment[4],
228
+ 'filename' => $attachment[2],
229
  'disposition' => $attachment[6],
230
  );
231
  }
src/TGMPA.php ADDED
@@ -0,0 +1,3857 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP;
4
+
5
+ /**
6
+ * Plugin installation and activation for WordPress themes.
7
+ *
8
+ * Please note that this is a drop-in library for a theme or plugin.
9
+ * The authors of this library (Thomas, Gary and Juliette) are NOT responsible
10
+ * for the support of your plugin or theme. Please contact the plugin
11
+ * or theme author for support.
12
+ *
13
+ * @package TGM-Plugin-Activation
14
+ * @version 2.6.1
15
+ * @link http://tgmpluginactivation.com/
16
+ * @author Thomas Griffin, Gary Jones, Juliette Reinders Folmer
17
+ * @copyright Copyright (c) 2011, Thomas Griffin
18
+ * @license GPL-2.0+
19
+ */
20
+
21
+ /*
22
+ Copyright 2011 Thomas Griffin (thomasgriffinmedia.com)
23
+
24
+ This program is free software; you can redistribute it and/or modify
25
+ it under the terms of the GNU General Public License, version 2, as
26
+ published by the Free Software Foundation.
27
+
28
+ This program is distributed in the hope that it will be useful,
29
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
30
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31
+ GNU General Public License for more details.
32
+
33
+ You should have received a copy of the GNU General Public License
34
+ along with this program; if not, write to the Free Software
35
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36
+ */
37
+
38
+ if ( ! class_exists( 'TGM_Plugin_Activation' ) ) {
39
+
40
+ /**
41
+ * Automatic plugin installation and activation library.
42
+ *
43
+ * Creates a way to automatically install and activate plugins from within themes.
44
+ * The plugins can be either bundled, downloaded from the WordPress
45
+ * Plugin Repository or downloaded from another external source.
46
+ *
47
+ * @since 1.0.0
48
+ *
49
+ * @package TGM-Plugin-Activation
50
+ * @author Thomas Griffin
51
+ * @author Gary Jones
52
+ */
53
+ class TGM_Plugin_Activation {
54
+ /**
55
+ * TGMPA version number.
56
+ *
57
+ * @since 2.5.0
58
+ *
59
+ * @const string Version number.
60
+ */
61
+ const TGMPA_VERSION = '2.6.1';
62
+
63
+ /**
64
+ * Regular expression to test if a URL is a WP plugin repo URL.
65
+ *
66
+ * @const string Regex.
67
+ *
68
+ * @since 2.5.0
69
+ */
70
+ const WP_REPO_REGEX = '|^http[s]?://wordpress\.org/(?:extend/)?plugins/|';
71
+
72
+ /**
73
+ * Arbitrary regular expression to test if a string starts with a URL.
74
+ *
75
+ * @const string Regex.
76
+ *
77
+ * @since 2.5.0
78
+ */
79
+ const IS_URL_REGEX = '|^http[s]?://|';
80
+
81
+ /**
82
+ * Holds a copy of itself, so it can be referenced by the class name.
83
+ *
84
+ * @since 1.0.0
85
+ *
86
+ * @var TGM_Plugin_Activation
87
+ */
88
+ public static $instance;
89
+
90
+ /**
91
+ * Holds arrays of plugin details.
92
+ *
93
+ * @since 1.0.0
94
+ * @since 2.5.0 the array has the plugin slug as an associative key.
95
+ *
96
+ * @var array
97
+ */
98
+ public $plugins = array();
99
+
100
+ /**
101
+ * Holds arrays of plugin names to use to sort the plugins array.
102
+ *
103
+ * @since 2.5.0
104
+ *
105
+ * @var array
106
+ */
107
+ protected $sort_order = array();
108
+
109
+ /**
110
+ * Whether any plugins have the 'force_activation' setting set to true.
111
+ *
112
+ * @since 2.5.0
113
+ *
114
+ * @var bool
115
+ */
116
+ protected $has_forced_activation = false;
117
+
118
+ /**
119
+ * Whether any plugins have the 'force_deactivation' setting set to true.
120
+ *
121
+ * @since 2.5.0
122
+ *
123
+ * @var bool
124
+ */
125
+ protected $has_forced_deactivation = false;
126
+
127
+ /**
128
+ * Name of the unique ID to hash notices.
129
+ *
130
+ * @since 2.4.0
131
+ *
132
+ * @var string
133
+ */
134
+ public $id = 'tgmpa';
135
+
136
+ /**
137
+ * Name of the query-string argument for the admin page.
138
+ *
139
+ * @since 1.0.0
140
+ *
141
+ * @var string
142
+ */
143
+ protected $menu = 'tgmpa-install-plugins';
144
+
145
+ /**
146
+ * Parent menu file slug.
147
+ *
148
+ * @since 2.5.0
149
+ *
150
+ * @var string
151
+ */
152
+ public $parent_slug = 'themes.php';
153
+
154
+ /**
155
+ * Capability needed to view the plugin installation menu item.
156
+ *
157
+ * @since 2.5.0
158
+ *
159
+ * @var string
160
+ */
161
+ public $capability = 'edit_theme_options';
162
+
163
+ /**
164
+ * Default absolute path to folder containing bundled plugin zip files.
165
+ *
166
+ * @since 2.0.0
167
+ *
168
+ * @var string Absolute path prefix to zip file location for bundled plugins. Default is empty string.
169
+ */
170
+ public $default_path = '';
171
+
172
+ /**
173
+ * Flag to show admin notices or not.
174
+ *
175
+ * @since 2.1.0
176
+ *
177
+ * @var boolean
178
+ */
179
+ public $has_notices = true;
180
+
181
+ /**
182
+ * Flag to determine if the user can dismiss the notice nag.
183
+ *
184
+ * @since 2.4.0
185
+ *
186
+ * @var boolean
187
+ */
188
+ public $dismissable = true;
189
+
190
+ /**
191
+ * Message to be output above nag notice if dismissable is false.
192
+ *
193
+ * @since 2.4.0
194
+ *
195
+ * @var string
196
+ */
197
+ public $dismiss_msg = '';
198
+
199
+ /**
200
+ * Flag to set automatic activation of plugins. Off by default.
201
+ *
202
+ * @since 2.2.0
203
+ *
204
+ * @var boolean
205
+ */
206
+ public $is_automatic = false;
207
+
208
+ /**
209
+ * Optional message to display before the plugins table.
210
+ *
211
+ * @since 2.2.0
212
+ *
213
+ * @var string Message filtered by wp_kses_post(). Default is empty string.
214
+ */
215
+ public $message = '';
216
+
217
+ /**
218
+ * Holds configurable array of strings.
219
+ *
220
+ * Default values are added in the constructor.
221
+ *
222
+ * @since 2.0.0
223
+ *
224
+ * @var array
225
+ */
226
+ public $strings = array();
227
+
228
+ /**
229
+ * Holds the version of WordPress.
230
+ *
231
+ * @since 2.4.0
232
+ *
233
+ * @var int
234
+ */
235
+ public $wp_version;
236
+
237
+ /**
238
+ * Holds the hook name for the admin page.
239
+ *
240
+ * @since 2.5.0
241
+ *
242
+ * @var string
243
+ */
244
+ public $page_hook;
245
+
246
+ /**
247
+ * Adds a reference of this object to $instance, populates default strings,
248
+ * does the tgmpa_init action hook, and hooks in the interactions to init.
249
+ *
250
+ * {@internal This method should be `protected`, but as too many TGMPA implementations
251
+ * haven't upgraded beyond v2.3.6 yet, this gives backward compatibility issues.
252
+ * Reverted back to public for the time being.}}
253
+ *
254
+ * @since 1.0.0
255
+ *
256
+ * @see TGM_Plugin_Activation::init()
257
+ */
258
+ public function __construct() {
259
+ // Set the current WordPress version.
260
+ $this->wp_version = $GLOBALS['wp_version'];
261
+
262
+ // Announce that the class is ready, and pass the object (for advanced use).
263
+ do_action_ref_array( 'tgmpa_init', array( $this ) );
264
+
265
+ /*
266
+ * Load our text domain and allow for overloading the fall-back file.
267
+ *
268
+ * {@internal IMPORTANT! If this code changes, review the regex in the custom TGMPA
269
+ * generator on the website.}}
270
+ */
271
+ add_action( 'init', array( $this, 'load_textdomain' ), 5 );
272
+ add_filter( 'load_textdomain_mofile', array( $this, 'overload_textdomain_mofile' ), 10, 2 );
273
+
274
+ // When the rest of WP has loaded, kick-start the rest of the class.
275
+ add_action( 'init', array( $this, 'init' ) );
276
+ }
277
+
278
+ /**
279
+ * Magic method to (not) set protected properties from outside of this class.
280
+ *
281
+ * {@internal hackedihack... There is a serious bug in v2.3.2 - 2.3.6 where the `menu` property
282
+ * is being assigned rather than tested in a conditional, effectively rendering it useless.
283
+ * This 'hack' prevents this from happening.}}
284
+ *
285
+ * @see https://github.com/TGMPA/TGM-Plugin-Activation/blob/2.3.6/tgm-plugin-activation/class-tgm-plugin-activation.php#L1593
286
+ *
287
+ * @since 2.5.2
288
+ *
289
+ * @param string $name Name of an inaccessible property.
290
+ * @param mixed $value Value to assign to the property.
291
+ * @return void Silently fail to set the property when this is tried from outside of this class context.
292
+ * (Inside this class context, the __set() method if not used as there is direct access.)
293
+ */
294
+ public function __set( $name, $value ) {
295
+ return;
296
+ }
297
+
298
+ /**
299
+ * Magic method to get the value of a protected property outside of this class context.
300
+ *
301
+ * @since 2.5.2
302
+ *
303
+ * @param string $name Name of an inaccessible property.
304
+ * @return mixed The property value.
305
+ */
306
+ public function __get( $name ) {
307
+ return $this->{$name};
308
+ }
309
+
310
+ /**
311
+ * Initialise the interactions between this class and WordPress.
312
+ *
313
+ * Hooks in three new methods for the class: admin_menu, notices and styles.
314
+ *
315
+ * @since 2.0.0
316
+ *
317
+ * @see TGM_Plugin_Activation::admin_menu()
318
+ * @see TGM_Plugin_Activation::notices()
319
+ * @see TGM_Plugin_Activation::styles()
320
+ */
321
+ public function init() {
322
+ /**
323
+ * By default TGMPA only loads on the WP back-end and not in an Ajax call. Using this filter
324
+ * you can overrule that behaviour.
325
+ *
326
+ * @since 2.5.0
327
+ *
328
+ * @param bool $load Whether or not TGMPA should load.
329
+ * Defaults to the return of `is_admin() && ! defined( 'DOING_AJAX' )`.
330
+ */
331
+ if ( true !== apply_filters( 'tgmpa_load', ( is_admin() && ! defined( 'DOING_AJAX' ) ) ) ) {
332
+ return;
333
+ }
334
+
335
+ // Load class strings.
336
+ $this->strings = array(
337
+ 'page_title' => __( 'Install Required Plugins', 'tgmpa' ),
338
+ 'menu_title' => __( 'Install Plugins', 'tgmpa' ),
339
+ /* translators: %s: plugin name. */
340
+ 'installing' => __( 'Installing Plugin: %s', 'tgmpa' ),
341
+ /* translators: %s: plugin name. */
342
+ 'updating' => __( 'Updating Plugin: %s', 'tgmpa' ),
343
+ 'oops' => __( 'Something went wrong with the plugin API.', 'tgmpa' ),
344
+ 'notice_can_install_required' => _n_noop(
345
+ /* translators: 1: plugin name(s). */
346
+ 'This theme requires the following plugin: %1$s.',
347
+ 'This theme requires the following plugins: %1$s.',
348
+ 'tgmpa'
349
+ ),
350
+ 'notice_can_install_recommended' => _n_noop(
351
+ /* translators: 1: plugin name(s). */
352
+ 'This theme recommends the following plugin: %1$s.',
353
+ 'This theme recommends the following plugins: %1$s.',
354
+ 'tgmpa'
355
+ ),
356
+ 'notice_ask_to_update' => _n_noop(
357
+ /* translators: 1: plugin name(s). */
358
+ 'The following plugin needs to be updated to its latest version to ensure maximum compatibility with this theme: %1$s.',
359
+ 'The following plugins need to be updated to their latest version to ensure maximum compatibility with this theme: %1$s.',
360
+ 'tgmpa'
361
+ ),
362
+ 'notice_ask_to_update_maybe' => _n_noop(
363
+ /* translators: 1: plugin name(s). */
364
+ 'There is an update available for: %1$s.',
365
+ 'There are updates available for the following plugins: %1$s.',
366
+ 'tgmpa'
367
+ ),
368
+ 'notice_can_activate_required' => _n_noop(
369
+ /* translators: 1: plugin name(s). */
370
+ 'The following required plugin is currently inactive: %1$s.',
371
+ 'The following required plugins are currently inactive: %1$s.',
372
+ 'tgmpa'
373
+ ),
374
+ 'notice_can_activate_recommended' => _n_noop(
375
+ /* translators: 1: plugin name(s). */
376
+ 'The following recommended plugin is currently inactive: %1$s.',
377
+ 'The following recommended plugins are currently inactive: %1$s.',
378
+ 'tgmpa'
379
+ ),
380
+ 'install_link' => _n_noop(
381
+ 'Begin installing plugin',
382
+ 'Begin installing plugins',
383
+ 'tgmpa'
384
+ ),
385
+ 'update_link' => _n_noop(
386
+ 'Begin updating plugin',
387
+ 'Begin updating plugins',
388
+ 'tgmpa'
389
+ ),
390
+ 'activate_link' => _n_noop(
391
+ 'Begin activating plugin',
392
+ 'Begin activating plugins',
393
+ 'tgmpa'
394
+ ),
395
+ 'return' => __( 'Return to Required Plugins Installer', 'tgmpa' ),
396
+ 'dashboard' => __( 'Return to the Dashboard', 'tgmpa' ),
397
+ 'plugin_activated' => __( 'Plugin activated successfully.', 'tgmpa' ),
398
+ 'activated_successfully' => __( 'The following plugin was activated successfully:', 'tgmpa' ),
399
+ /* translators: 1: plugin name. */
400
+ 'plugin_already_active' => __( 'No action taken. Plugin %1$s was already active.', 'tgmpa' ),
401
+ /* translators: 1: plugin name. */
402
+ 'plugin_needs_higher_version' => __( 'Plugin not activated. A higher version of %s is needed for this theme. Please update the plugin.', 'tgmpa' ),
403
+ /* translators: 1: dashboard link. */
404
+ 'complete' => __( 'All plugins installed and activated successfully. %1$s', 'tgmpa' ),
405
+ 'dismiss' => __( 'Dismiss this notice', 'tgmpa' ),
406
+ 'notice_cannot_install_activate' => __( 'There are one or more required or recommended plugins to install, update or activate.', 'tgmpa' ),
407
+ 'contact_admin' => __( 'Please contact the administrator of this site for help.', 'tgmpa' ),
408
+ );
409
+
410
+ do_action( 'tgmpa_register' );
411
+
412
+ /* After this point, the plugins should be registered and the configuration set. */
413
+
414
+ // Proceed only if we have plugins to handle.
415
+ if ( empty( $this->plugins ) || ! is_array( $this->plugins ) ) {
416
+ return;
417
+ }
418
+
419
+ // Set up the menu and notices if we still have outstanding actions.
420
+ if ( true !== $this->is_tgmpa_complete() ) {
421
+ // Sort the plugins.
422
+ array_multisort( $this->sort_order, SORT_ASC, $this->plugins );
423
+
424
+ add_action( 'admin_menu', array( $this, 'admin_menu' ) );
425
+ add_action( 'admin_head', array( $this, 'dismiss' ) );
426
+
427
+ // Prevent the normal links from showing underneath a single install/update page.
428
+ add_filter( 'install_plugin_complete_actions', array( $this, 'actions' ) );
429
+ add_filter( 'update_plugin_complete_actions', array( $this, 'actions' ) );
430
+
431
+ if ( $this->has_notices ) {
432
+ add_action( 'admin_notices', array( $this, 'notices' ) );
433
+ add_action( 'admin_init', array( $this, 'admin_init' ), 1 );
434
+ add_action( 'admin_enqueue_scripts', array( $this, 'thickbox' ) );
435
+ }
436
+ }
437
+
438
+ // If needed, filter plugin action links.
439
+ add_action( 'load-plugins.php', array( $this, 'add_plugin_action_link_filters' ), 1 );
440
+
441
+ // Make sure things get reset on switch theme.
442
+ add_action( 'switch_theme', array( $this, 'flush_plugins_cache' ) );
443
+
444
+ if ( $this->has_notices ) {
445
+ add_action( 'switch_theme', array( $this, 'update_dismiss' ) );
446
+ }
447
+
448
+ // Setup the force activation hook.
449
+ if ( true === $this->has_forced_activation ) {
450
+ add_action( 'admin_init', array( $this, 'force_activation' ) );
451
+ }
452
+
453
+ // Setup the force deactivation hook.
454
+ if ( true === $this->has_forced_deactivation ) {
455
+ add_action( 'switch_theme', array( $this, 'force_deactivation' ) );
456
+ }
457
+ }
458
+
459
+ /**
460
+ * Load translations.
461
+ *
462
+ * @since 2.6.0
463
+ *
464
+ * (@internal Uses `load_theme_textdomain()` rather than `load_plugin_textdomain()` to
465
+ * get round the different ways of handling the path and deprecated notices being thrown
466
+ * and such. For plugins, the actual file name will be corrected by a filter.}}
467
+ *
468
+ * {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA
469
+ * generator on the website.}}
470
+ */
471
+ public function load_textdomain() {
472
+ if ( is_textdomain_loaded( 'tgmpa' ) ) {
473
+ return;
474
+ }
475
+
476
+ if ( false !== strpos( __FILE__, WP_PLUGIN_DIR ) || false !== strpos( __FILE__, WPMU_PLUGIN_DIR ) ) {
477
+ // Plugin, we'll need to adjust the file name.
478
+ add_action( 'load_textdomain_mofile', array( $this, 'correct_plugin_mofile' ), 10, 2 );
479
+ load_theme_textdomain( 'tgmpa', dirname( __FILE__ ) . '/languages' );
480
+ remove_action( 'load_textdomain_mofile', array( $this, 'correct_plugin_mofile' ), 10 );
481
+ } else {
482
+ load_theme_textdomain( 'tgmpa', dirname( __FILE__ ) . '/languages' );
483
+ }
484
+ }
485
+
486
+ /**
487
+ * Correct the .mo file name for (must-use) plugins.
488
+ *
489
+ * Themese use `/path/{locale}.mo` while plugins use `/path/{text-domain}-{locale}.mo`.
490
+ *
491
+ * {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA
492
+ * generator on the website.}}
493
+ *
494
+ * @since 2.6.0
495
+ *
496
+ * @param string $mofile Full path to the target mofile.
497
+ * @param string $domain The domain for which a language file is being loaded.
498
+ * @return string $mofile
499
+ */
500
+ public function correct_plugin_mofile( $mofile, $domain ) {
501
+ // Exit early if not our domain (just in case).
502
+ if ( 'tgmpa' !== $domain ) {
503
+ return $mofile;
504
+ }
505
+ return preg_replace( '`/([a-z]{2}_[A-Z]{2}.mo)$`', '/tgmpa-$1', $mofile );
506
+ }
507
+
508
+ /**
509
+ * Potentially overload the fall-back translation file for the current language.
510
+ *
511
+ * WP, by default since WP 3.7, will load a local translation first and if none
512
+ * can be found, will try and find a translation in the /wp-content/languages/ directory.
513
+ * As this library is theme/plugin agnostic, translation files for TGMPA can exist both
514
+ * in the WP_LANG_DIR /plugins/ subdirectory as well as in the /themes/ subdirectory.
515
+ *
516
+ * This method makes sure both directories are checked.
517
+ *
518
+ * {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA
519
+ * generator on the website.}}
520
+ *
521
+ * @since 2.6.0
522
+ *
523
+ * @param string $mofile Full path to the target mofile.
524
+ * @param string $domain The domain for which a language file is being loaded.
525
+ * @return string $mofile
526
+ */
527
+ public function overload_textdomain_mofile( $mofile, $domain ) {
528
+ // Exit early if not our domain, not a WP_LANG_DIR load or if the file exists and is readable.
529
+ if ( 'tgmpa' !== $domain || false === strpos( $mofile, WP_LANG_DIR ) || @is_readable( $mofile ) ) {
530
+ return $mofile;
531
+ }
532
+
533
+ // Current fallback file is not valid, let's try the alternative option.
534
+ if ( false !== strpos( $mofile, '/themes/' ) ) {
535
+ return str_replace( '/themes/', '/plugins/', $mofile );
536
+ } elseif ( false !== strpos( $mofile, '/plugins/' ) ) {
537
+ return str_replace( '/plugins/', '/themes/', $mofile );
538
+ } else {
539
+ return $mofile;
540
+ }
541
+ }
542
+
543
+ /**
544
+ * Hook in plugin action link filters for the WP native plugins page.
545
+ *
546
+ * - Prevent activation of plugins which don't meet the minimum version requirements.
547
+ * - Prevent deactivation of force-activated plugins.
548
+ * - Add update notice if update available.
549
+ *
550
+ * @since 2.5.0
551
+ */
552
+ public function add_plugin_action_link_filters() {
553
+ foreach ( $this->plugins as $slug => $plugin ) {
554
+ if ( false === $this->can_plugin_activate( $slug ) ) {
555
+ add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_activate' ), 20 );
556
+ }
557
+
558
+ if ( true === $plugin['force_activation'] ) {
559
+ add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_deactivate' ), 20 );
560
+ }
561
+
562
+ if ( false !== $this->does_plugin_require_update( $slug ) ) {
563
+ add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_update' ), 20 );
564
+ }
565
+ }
566
+ }
567
+
568
+ /**
569
+ * Remove the 'Activate' link on the WP native plugins page if the plugin does not meet the
570
+ * minimum version requirements.
571
+ *
572
+ * @since 2.5.0
573
+ *
574
+ * @param array $actions Action links.
575
+ * @return array
576
+ */
577
+ public function filter_plugin_action_links_activate( $actions ) {
578
+ unset( $actions['activate'] );
579
+
580
+ return $actions;
581
+ }
582
+
583
+ /**
584
+ * Remove the 'Deactivate' link on the WP native plugins page if the plugin has been set to force activate.
585
+ *
586
+ * @since 2.5.0
587
+ *
588
+ * @param array $actions Action links.
589
+ * @return array
590
+ */
591
+ public function filter_plugin_action_links_deactivate( $actions ) {
592
+ unset( $actions['deactivate'] );
593
+
594
+ return $actions;
595
+ }
596
+
597
+ /**
598
+ * Add a 'Requires update' link on the WP native plugins page if the plugin does not meet the
599
+ * minimum version requirements.
600
+ *
601
+ * @since 2.5.0
602
+ *
603
+ * @param array $actions Action links.
604
+ * @return array
605
+ */
606
+ public function filter_plugin_action_links_update( $actions ) {
607
+ $actions['update'] = sprintf(
608
+ '<a href="%1$s" title="%2$s" class="edit">%3$s</a>',
609
+ esc_url( $this->get_tgmpa_status_url( 'update' ) ),
610
+ esc_attr__( 'This plugin needs to be updated to be compatible with your theme.', 'tgmpa' ),
611
+ esc_html__( 'Update Required', 'tgmpa' )
612
+ );
613
+
614
+ return $actions;
615
+ }
616
+
617
+ /**
618
+ * Handles calls to show plugin information via links in the notices.
619
+ *
620
+ * We get the links in the admin notices to point to the TGMPA page, rather
621
+ * than the typical plugin-install.php file, so we can prepare everything
622
+ * beforehand.
623
+ *
624
+ * WP does not make it easy to show the plugin information in the thickbox -
625
+ * here we have to require a file that includes a function that does the
626
+ * main work of displaying it, enqueue some styles, set up some globals and
627
+ * finally call that function before exiting.
628
+ *
629
+ * Down right easy once you know how...
630
+ *
631
+ * Returns early if not the TGMPA page.
632
+ *
633
+ * @since 2.1.0
634
+ *
635
+ * @global string $tab Used as iframe div class names, helps with styling
636
+ * @global string $body_id Used as the iframe body ID, helps with styling
637
+ *
638
+ * @return null Returns early if not the TGMPA page.
639
+ */
640
+ public function admin_init() {
641
+ if ( ! $this->is_tgmpa_page() ) {
642
+ return;
643
+ }
644
+
645
+ if ( isset( $_REQUEST['tab'] ) && 'plugin-information' === $_REQUEST['tab'] ) {
646
+ // Needed for install_plugin_information().
647
+ require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
648
+
649
+ wp_enqueue_style( 'plugin-install' );
650
+
651
+ global $tab, $body_id;
652
+ $body_id = 'plugin-information';
653
+ // @codingStandardsIgnoreStart
654
+ $tab = 'plugin-information';
655
+ // @codingStandardsIgnoreEnd
656
+
657
+ install_plugin_information();
658
+
659
+ exit;
660
+ }
661
+ }
662
+
663
+ /**
664
+ * Enqueue thickbox scripts/styles for plugin info.
665
+ *
666
+ * Thickbox is not automatically included on all admin pages, so we must
667
+ * manually enqueue it for those pages.
668
+ *
669
+ * Thickbox is only loaded if the user has not dismissed the admin
670
+ * notice or if there are any plugins left to install and activate.
671
+ *
672
+ * @since 2.1.0
673
+ */
674
+ public function thickbox() {
675
+ if ( ! get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, true ) ) {
676
+ add_thickbox();
677
+ }
678
+ }
679
+
680
+ /**
681
+ * Adds submenu page if there are plugin actions to take.
682
+ *
683
+ * This method adds the submenu page letting users know that a required
684
+ * plugin needs to be installed.
685
+ *
686
+ * This page disappears once the plugin has been installed and activated.
687
+ *
688
+ * @since 1.0.0
689
+ *
690
+ * @see TGM_Plugin_Activation::init()
691
+ * @see TGM_Plugin_Activation::install_plugins_page()
692
+ *
693
+ * @return null Return early if user lacks capability to install a plugin.
694
+ */
695
+ public function admin_menu() {
696
+ // Make sure privileges are correct to see the page.
697
+ if ( ! current_user_can( 'install_plugins' ) ) {
698
+ return;
699
+ }
700
+
701
+ $args = apply_filters(
702
+ 'tgmpa_admin_menu_args',
703
+ array(
704
+ 'parent_slug' => $this->parent_slug, // Parent Menu slug.
705
+ 'page_title' => $this->strings['page_title'], // Page title.
706
+ 'menu_title' => $this->strings['menu_title'], // Menu title.
707
+ 'capability' => $this->capability, // Capability.
708
+ 'menu_slug' => $this->menu, // Menu slug.
709
+ 'function' => array( $this, 'install_plugins_page' ), // Callback.
710
+ )
711
+ );
712
+
713
+ $this->add_admin_menu( $args );
714
+ }
715
+
716
+ /**
717
+ * Add the menu item.
718
+ *
719
+ * {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA
720
+ * generator on the website.}}
721
+ *
722
+ * @since 2.5.0
723
+ *
724
+ * @param array $args Menu item configuration.
725
+ */
726
+ protected function add_admin_menu( array $args ) {
727
+ if ( has_filter( 'tgmpa_admin_menu_use_add_theme_page' ) ) {
728
+ _deprecated_function( 'The "tgmpa_admin_menu_use_add_theme_page" filter', '2.5.0', esc_html__( 'Set the parent_slug config variable instead.', 'tgmpa' ) );
729
+ }
730
+
731
+ if ( 'themes.php' === $this->parent_slug ) {
732
+ $this->page_hook = call_user_func( 'add_theme_page', $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] );
733
+ } else {
734
+ $this->page_hook = call_user_func( 'add_submenu_page', $args['parent_slug'], $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] );
735
+ }
736
+ }
737
+
738
+ /**
739
+ * Echoes plugin installation form.
740
+ *
741
+ * This method is the callback for the admin_menu method function.
742
+ * This displays the admin page and form area where the user can select to install and activate the plugin.
743
+ * Aborts early if we're processing a plugin installation action.
744
+ *
745
+ * @since 1.0.0
746
+ *
747
+ * @return null Aborts early if we're processing a plugin installation action.
748
+ */
749
+ public function install_plugins_page() {
750
+ // Store new instance of plugin table in object.
751
+ $plugin_table = new TGMPA_List_Table;
752
+
753
+ // Return early if processing a plugin installation action.
754
+ if ( ( ( 'tgmpa-bulk-install' === $plugin_table->current_action() || 'tgmpa-bulk-update' === $plugin_table->current_action() ) && $plugin_table->process_bulk_actions() ) || $this->do_plugin_install() ) {
755
+ return;
756
+ }
757
+
758
+ // Force refresh of available plugin information so we'll know about manual updates/deletes.
759
+ wp_clean_plugins_cache( false );
760
+
761
+ ?>
762
+ <div class="tgmpa wrap">
763
+ <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
764
+ <?php $plugin_table->prepare_items(); ?>
765
+
766
+ <?php
767
+ if ( ! empty( $this->message ) && is_string( $this->message ) ) {
768
+ echo wp_kses_post( $this->message );
769
+ }
770
+ ?>
771
+ <?php $plugin_table->views(); ?>
772
+
773
+ <form id="tgmpa-plugins" action="" method="post">
774
+ <input type="hidden" name="tgmpa-page" value="<?php echo esc_attr( $this->menu ); ?>" />
775
+ <input type="hidden" name="plugin_status" value="<?php echo esc_attr( $plugin_table->view_context ); ?>" />
776
+ <?php $plugin_table->display(); ?>
777
+ </form>
778
+ </div>
779
+ <?php
780
+ }
781
+
782
+ /**
783
+ * Installs, updates or activates a plugin depending on the action link clicked by the user.
784
+ *
785
+ * Checks the $_GET variable to see which actions have been
786
+ * passed and responds with the appropriate method.
787
+ *
788
+ * Uses WP_Filesystem to process and handle the plugin installation
789
+ * method.
790
+ *
791
+ * @since 1.0.0
792
+ *
793
+ * @uses WP_Filesystem
794
+ * @uses WP_Error
795
+ * @uses WP_Upgrader
796
+ * @uses Plugin_Upgrader
797
+ * @uses Plugin_Installer_Skin
798
+ * @uses Plugin_Upgrader_Skin
799
+ *
800
+ * @return boolean True on success, false on failure.
801
+ */
802
+ protected function do_plugin_install() {
803
+ if ( empty( $_GET['plugin'] ) ) {
804
+ return false;
805
+ }
806
+
807
+ // All plugin information will be stored in an array for processing.
808
+ $slug = $this->sanitize_key( urldecode( $_GET['plugin'] ) );
809
+
810
+ if ( ! isset( $this->plugins[ $slug ] ) ) {
811
+ return false;
812
+ }
813
+
814
+ // Was an install or upgrade action link clicked?
815
+ if ( ( isset( $_GET['tgmpa-install'] ) && 'install-plugin' === $_GET['tgmpa-install'] ) || ( isset( $_GET['tgmpa-update'] ) && 'update-plugin' === $_GET['tgmpa-update'] ) ) {
816
+
817
+ $install_type = 'install';
818
+ if ( isset( $_GET['tgmpa-update'] ) && 'update-plugin' === $_GET['tgmpa-update'] ) {
819
+ $install_type = 'update';
820
+ }
821
+
822
+ check_admin_referer( 'tgmpa-' . $install_type, 'tgmpa-nonce' );
823
+
824
+ // Pass necessary information via URL if WP_Filesystem is needed.
825
+ $url = wp_nonce_url(
826
+ add_query_arg(
827
+ array(
828
+ 'plugin' => urlencode( $slug ),
829
+ 'tgmpa-' . $install_type => $install_type . '-plugin',
830
+ ),
831
+ $this->get_tgmpa_url()
832
+ ),
833
+ 'tgmpa-' . $install_type,
834
+ 'tgmpa-nonce'
835
+ );
836
+
837
+ $method = ''; // Leave blank so WP_Filesystem can populate it as necessary.
838
+
839
+ if ( false === ( $creds = request_filesystem_credentials( esc_url_raw( $url ), $method, false, false, array() ) ) ) {
840
+ return true;
841
+ }
842
+
843
+ if ( ! WP_Filesystem( $creds ) ) {
844
+ request_filesystem_credentials( esc_url_raw( $url ), $method, true, false, array() ); // Setup WP_Filesystem.
845
+ return true;
846
+ }
847
+
848
+ /* If we arrive here, we have the filesystem. */
849
+
850
+ // Prep variables for Plugin_Installer_Skin class.
851
+ $extra = array();
852
+ $extra['slug'] = $slug; // Needed for potentially renaming of directory name.
853
+ $source = $this->get_download_url( $slug );
854
+ $api = ( 'repo' === $this->plugins[ $slug ]['source_type'] ) ? $this->get_plugins_api( $slug ) : null;
855
+ $api = ( false !== $api ) ? $api : null;
856
+
857
+ $url = add_query_arg(
858
+ array(
859
+ 'action' => $install_type . '-plugin',
860
+ 'plugin' => urlencode( $slug ),
861
+ ),
862
+ 'update.php'
863
+ );
864
+
865
+ if ( ! class_exists( '\Plugin_Upgrader', false ) ) {
866
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
867
+ }
868
+
869
+ $title = ( 'update' === $install_type ) ? $this->strings['updating'] : $this->strings['installing'];
870
+ $skin_args = array(
871
+ 'type' => ( 'bundled' !== $this->plugins[ $slug ]['source_type'] ) ? 'web' : 'upload',
872
+ 'title' => sprintf( $title, $this->plugins[ $slug ]['name'] ),
873
+ 'url' => esc_url_raw( $url ),
874
+ 'nonce' => $install_type . '-plugin_' . $slug,
875
+ 'plugin' => '',
876
+ 'api' => $api,
877
+ 'extra' => $extra,
878
+ );
879
+ unset( $title );
880
+
881
+ if ( 'update' === $install_type ) {
882
+ $skin_args['plugin'] = $this->plugins[ $slug ]['file_path'];
883
+ $skin = new \Plugin_Upgrader_Skin( $skin_args );
884
+ } else {
885
+ $skin = new \Plugin_Installer_Skin( $skin_args );
886
+ }
887
+
888
+ // Create a new instance of Plugin_Upgrader.
889
+ $upgrader = new \Plugin_Upgrader( $skin );
890
+
891
+ // Perform the action and install the plugin from the $source urldecode().
892
+ add_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1, 3 );
893
+
894
+ if ( 'update' === $install_type ) {
895
+ // Inject our info into the update transient.
896
+ $to_inject = array( $slug => $this->plugins[ $slug ] );
897
+ $to_inject[ $slug ]['source'] = $source;
898
+ $this->inject_update_info( $to_inject );
899
+
900
+ $upgrader->upgrade( $this->plugins[ $slug ]['file_path'] );
901
+ } else {
902
+ $upgrader->install( $source );
903
+ }
904
+
905
+ remove_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1 );
906
+
907
+ // Make sure we have the correct file path now the plugin is installed/updated.
908
+ $this->populate_file_path( $slug );
909
+
910
+ // Only activate plugins if the config option is set to true and the plugin isn't
911
+ // already active (upgrade).
912
+ if ( $this->is_automatic && ! $this->is_plugin_active( $slug ) ) {
913
+ $plugin_activate = $upgrader->plugin_info(); // Grab the plugin info from the Plugin_Upgrader method.
914
+ if ( false === $this->activate_single_plugin( $plugin_activate, $slug, true ) ) {
915
+ return true; // Finish execution of the function early as we encountered an error.
916
+ }
917
+ }
918
+
919
+ $this->show_tgmpa_version();
920
+
921
+ // Display message based on if all plugins are now active or not.
922
+ if ( $this->is_tgmpa_complete() ) {
923
+ echo '<p>', sprintf( esc_html( $this->strings['complete'] ), '<a href="' . esc_url( self_admin_url() ) . '">' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '</a>' ), '</p>';
924
+ echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
925
+ } else {
926
+ echo '<p><a href="', esc_url( $this->get_tgmpa_url() ), '" target="_parent">', esc_html( $this->strings['return'] ), '</a></p>';
927
+ }
928
+
929
+ return true;
930
+ } elseif ( isset( $this->plugins[ $slug ]['file_path'], $_GET['tgmpa-activate'] ) && 'activate-plugin' === $_GET['tgmpa-activate'] ) {
931
+ // Activate action link was clicked.
932
+ check_admin_referer( 'tgmpa-activate', 'tgmpa-nonce' );
933
+
934
+ if ( false === $this->activate_single_plugin( $this->plugins[ $slug ]['file_path'], $slug ) ) {
935
+ return true; // Finish execution of the function early as we encountered an error.
936
+ }
937
+ }
938
+
939
+ return false;
940
+ }
941
+
942
+ /**
943
+ * Inject information into the 'update_plugins' site transient as WP checks that before running an update.
944
+ *
945
+ * @since 2.5.0
946
+ *
947
+ * @param array $plugins The plugin information for the plugins which are to be updated.
948
+ */
949
+ public function inject_update_info( $plugins ) {
950
+ $repo_updates = get_site_transient( 'update_plugins' );
951
+
952
+ if ( ! is_object( $repo_updates ) ) {
953
+ $repo_updates = new stdClass;
954
+ }
955
+
956
+ foreach ( $plugins as $slug => $plugin ) {
957
+ $file_path = $plugin['file_path'];
958
+
959
+ if ( empty( $repo_updates->response[ $file_path ] ) ) {
960
+ $repo_updates->response[ $file_path ] = new stdClass;
961
+ }
962
+
963
+ // We only really need to set package, but let's do all we can in case WP changes something.
964
+ $repo_updates->response[ $file_path ]->slug = $slug;
965
+ $repo_updates->response[ $file_path ]->plugin = $file_path;
966
+ $repo_updates->response[ $file_path ]->new_version = $plugin['version'];
967
+ $repo_updates->response[ $file_path ]->package = $plugin['source'];
968
+ if ( empty( $repo_updates->response[ $file_path ]->url ) && ! empty( $plugin['external_url'] ) ) {
969
+ $repo_updates->response[ $file_path ]->url = $plugin['external_url'];
970
+ }
971
+ }
972
+
973
+ set_site_transient( 'update_plugins', $repo_updates );
974
+ }
975
+
976
+ /**
977
+ * Adjust the plugin directory name if necessary.
978
+ *
979
+ * The final destination directory of a plugin is based on the subdirectory name found in the
980
+ * (un)zipped source. In some cases - most notably GitHub repository plugin downloads -, this
981
+ * subdirectory name is not the same as the expected slug and the plugin will not be recognized
982
+ * as installed. This is fixed by adjusting the temporary unzipped source subdirectory name to
983
+ * the expected plugin slug.
984
+ *
985
+ * @since 2.5.0
986
+ *
987
+ * @param string $source Path to upgrade/zip-file-name.tmp/subdirectory/.
988
+ * @param string $remote_source Path to upgrade/zip-file-name.tmp.
989
+ * @param \WP_Upgrader $upgrader Instance of the upgrader which installs the plugin.
990
+ * @return string $source
991
+ */
992
+ public function maybe_adjust_source_dir( $source, $remote_source, $upgrader ) {
993
+ if ( ! $this->is_tgmpa_page() || ! is_object( $GLOBALS['wp_filesystem'] ) ) {
994
+ return $source;
995
+ }
996
+
997
+ // Check for single file plugins.
998
+ $source_files = array_keys( $GLOBALS['wp_filesystem']->dirlist( $remote_source ) );
999
+ if ( 1 === count( $source_files ) && false === $GLOBALS['wp_filesystem']->is_dir( $source ) ) {
1000
+ return $source;
1001
+ }
1002
+
1003
+ // Multi-file plugin, let's see if the directory is correctly named.
1004
+ $desired_slug = '';
1005
+
1006
+ // Figure out what the slug is supposed to be.
1007
+ if ( false === $upgrader->bulk && ! empty( $upgrader->skin->options['extra']['slug'] ) ) {
1008
+ $desired_slug = $upgrader->skin->options['extra']['slug'];
1009
+ } else {
1010
+ // Bulk installer contains less info, so fall back on the info registered here.
1011
+ foreach ( $this->plugins as $slug => $plugin ) {
1012
+ if ( ! empty( $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) && $plugin['name'] === $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) {
1013
+ $desired_slug = $slug;
1014
+ break;
1015
+ }
1016
+ }
1017
+ unset( $slug, $plugin );
1018
+ }
1019
+
1020
+ if ( ! empty( $desired_slug ) ) {
1021
+ $subdir_name = untrailingslashit( str_replace( trailingslashit( $remote_source ), '', $source ) );
1022
+
1023
+ if ( ! empty( $subdir_name ) && $subdir_name !== $desired_slug ) {
1024
+ $from_path = untrailingslashit( $source );
1025
+ $to_path = trailingslashit( $remote_source ) . $desired_slug;
1026
+
1027
+ if ( true === $GLOBALS['wp_filesystem']->move( $from_path, $to_path ) ) {
1028
+ return trailingslashit( $to_path );
1029
+ } else {
1030
+ return new WP_Error( 'rename_failed', esc_html__( 'The remote plugin package does not contain a folder with the desired slug and renaming did not work.', 'tgmpa' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'tgmpa' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) );
1031
+ }
1032
+ } elseif ( empty( $subdir_name ) ) {
1033
+ return new WP_Error( 'packaged_wrong', esc_html__( 'The remote plugin package consists of more than one file, but the files are not packaged in a folder.', 'tgmpa' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'tgmpa' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) );
1034
+ }
1035
+ }
1036
+
1037
+ return $source;
1038
+ }
1039
+
1040
+ /**
1041
+ * Activate a single plugin and send feedback about the result to the screen.
1042
+ *
1043
+ * @since 2.5.0
1044
+ *
1045
+ * @param string $file_path Path within wp-plugins/ to main plugin file.
1046
+ * @param string $slug Plugin slug.
1047
+ * @param bool $automatic Whether this is an automatic activation after an install. Defaults to false.
1048
+ * This determines the styling of the output messages.
1049
+ * @return bool False if an error was encountered, true otherwise.
1050
+ */
1051
+ protected function activate_single_plugin( $file_path, $slug, $automatic = false ) {
1052
+ if ( $this->can_plugin_activate( $slug ) ) {
1053
+ $activate = activate_plugin( $file_path );
1054
+
1055
+ if ( is_wp_error( $activate ) ) {
1056
+ echo '<div id="message" class="error"><p>', wp_kses_post( $activate->get_error_message() ), '</p></div>',
1057
+ '<p><a href="', esc_url( $this->get_tgmpa_url() ), '" target="_parent">', esc_html( $this->strings['return'] ), '</a></p>';
1058
+
1059
+ return false; // End it here if there is an error with activation.
1060
+ } else {
1061
+ if ( ! $automatic ) {
1062
+ // Make sure message doesn't display again if bulk activation is performed
1063
+ // immediately after a single activation.
1064
+ if ( ! isset( $_POST['action'] ) ) { // WPCS: CSRF OK.
1065
+ echo '<div id="message" class="updated"><p>', esc_html( $this->strings['activated_successfully'] ), ' <strong>', esc_html( $this->plugins[ $slug ]['name'] ), '.</strong></p></div>';
1066
+ }
1067
+ } else {
1068
+ // Simpler message layout for use on the plugin install page.
1069
+ echo '<p>', esc_html( $this->strings['plugin_activated'] ), '</p>';
1070
+ }
1071
+ }
1072
+ } elseif ( $this->is_plugin_active( $slug ) ) {
1073
+ // No simpler message format provided as this message should never be encountered
1074
+ // on the plugin install page.
1075
+ echo '<div id="message" class="error"><p>',
1076
+ sprintf(
1077
+ esc_html( $this->strings['plugin_already_active'] ),
1078
+ '<strong>' . esc_html( $this->plugins[ $slug ]['name'] ) . '</strong>'
1079
+ ),
1080
+ '</p></div>';
1081
+ } elseif ( $this->does_plugin_require_update( $slug ) ) {
1082
+ if ( ! $automatic ) {
1083
+ // Make sure message doesn't display again if bulk activation is performed
1084
+ // immediately after a single activation.
1085
+ if ( ! isset( $_POST['action'] ) ) { // WPCS: CSRF OK.
1086
+ echo '<div id="message" class="error"><p>',
1087
+ sprintf(
1088
+ esc_html( $this->strings['plugin_needs_higher_version'] ),
1089
+ '<strong>' . esc_html( $this->plugins[ $slug ]['name'] ) . '</strong>'
1090
+ ),
1091
+ '</p></div>';
1092
+ }
1093
+ } else {
1094
+ // Simpler message layout for use on the plugin install page.
1095
+ echo '<p>', sprintf( esc_html( $this->strings['plugin_needs_higher_version'] ), esc_html( $this->plugins[ $slug ]['name'] ) ), '</p>';
1096
+ }
1097
+ }
1098
+
1099
+ return true;
1100
+ }
1101
+
1102
+ /**
1103
+ * Echoes required plugin notice.
1104
+ *
1105
+ * Outputs a message telling users that a specific plugin is required for
1106
+ * their theme. If appropriate, it includes a link to the form page where
1107
+ * users can install and activate the plugin.
1108
+ *
1109
+ * Returns early if we're on the Install page.
1110
+ *
1111
+ * @since 1.0.0
1112
+ *
1113
+ * @global object $current_screen
1114
+ *
1115
+ * @return null Returns early if we're on the Install page.
1116
+ */
1117
+ public function notices() {
1118
+ // Remove nag on the install page / Return early if the nag message has been dismissed or user < author.
1119
+ if ( ( $this->is_tgmpa_page() || $this->is_core_update_page() ) || get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, true ) || ! current_user_can( apply_filters( 'tgmpa_show_admin_notice_capability', 'publish_posts' ) ) ) {
1120
+ return;
1121
+ }
1122
+
1123
+ // Store for the plugin slugs by message type.
1124
+ $message = array();
1125
+
1126
+ // Initialize counters used to determine plurality of action link texts.
1127
+ $install_link_count = 0;
1128
+ $update_link_count = 0;
1129
+ $activate_link_count = 0;
1130
+ $total_required_action_count = 0;
1131
+
1132
+ foreach ( $this->plugins as $slug => $plugin ) {
1133
+ if ( $this->is_plugin_active( $slug ) && false === $this->does_plugin_have_update( $slug ) ) {
1134
+ continue;
1135
+ }
1136
+
1137
+ if ( ! $this->is_plugin_installed( $slug ) ) {
1138
+ if ( current_user_can( 'install_plugins' ) ) {
1139
+ $install_link_count++;
1140
+
1141
+ if ( true === $plugin['required'] ) {
1142
+ $message['notice_can_install_required'][] = $slug;
1143
+ } else {
1144
+ $message['notice_can_install_recommended'][] = $slug;
1145
+ }
1146
+ }
1147
+ if ( true === $plugin['required'] ) {
1148
+ $total_required_action_count++;
1149
+ }
1150
+ } else {
1151
+ if ( ! $this->is_plugin_active( $slug ) && $this->can_plugin_activate( $slug ) ) {
1152
+ if ( current_user_can( 'activate_plugins' ) ) {
1153
+ $activate_link_count++;
1154
+
1155
+ if ( true === $plugin['required'] ) {
1156
+ $message['notice_can_activate_required'][] = $slug;
1157
+ } else {
1158
+ $message['notice_can_activate_recommended'][] = $slug;
1159
+ }
1160
+ }
1161
+ if ( true === $plugin['required'] ) {
1162
+ $total_required_action_count++;
1163
+ }
1164
+ }
1165
+
1166
+ if ( $this->does_plugin_require_update( $slug ) || false !== $this->does_plugin_have_update( $slug ) ) {
1167
+
1168
+ if ( current_user_can( 'update_plugins' ) ) {
1169
+ $update_link_count++;
1170
+
1171
+ if ( $this->does_plugin_require_update( $slug ) ) {
1172
+ $message['notice_ask_to_update'][] = $slug;
1173
+ } elseif ( false !== $this->does_plugin_have_update( $slug ) ) {
1174
+ $message['notice_ask_to_update_maybe'][] = $slug;
1175
+ }
1176
+ }
1177
+ if ( true === $plugin['required'] ) {
1178
+ $total_required_action_count++;
1179
+ }
1180
+ }
1181
+ }
1182
+ }
1183
+ unset( $slug, $plugin );
1184
+
1185
+ // If we have notices to display, we move forward.
1186
+ if ( ! empty( $message ) || $total_required_action_count > 0 ) {
1187
+ krsort( $message ); // Sort messages.
1188
+ $rendered = '';
1189
+
1190
+ // As add_settings_error() wraps the final message in a <p> and as the final message can't be
1191
+ // filtered, using <p>'s in our html would render invalid html output.
1192
+ $line_template = '<span style="display: block; margin: 0.5em 0.5em 0 0; clear: both;">%s</span>' . "\n";
1193
+
1194
+ if ( ! current_user_can( 'activate_plugins' ) && ! current_user_can( 'install_plugins' ) && ! current_user_can( 'update_plugins' ) ) {
1195
+ $rendered = esc_html( $this->strings['notice_cannot_install_activate'] ) . ' ' . esc_html( $this->strings['contact_admin'] );
1196
+ $rendered .= $this->create_user_action_links_for_notice( 0, 0, 0, $line_template );
1197
+ } else {
1198
+
1199
+ // If dismissable is false and a message is set, output it now.
1200
+ if ( ! $this->dismissable && ! empty( $this->dismiss_msg ) ) {
1201
+ $rendered .= sprintf( $line_template, wp_kses_post( $this->dismiss_msg ) );
1202
+ }
1203
+
1204
+ // Render the individual message lines for the notice.
1205
+ foreach ( $message as $type => $plugin_group ) {
1206
+ $linked_plugins = array();
1207
+
1208
+ // Get the external info link for a plugin if one is available.
1209
+ foreach ( $plugin_group as $plugin_slug ) {
1210
+ $linked_plugins[] = $this->get_info_link( $plugin_slug );
1211
+ }
1212
+ unset( $plugin_slug );
1213
+
1214
+ $count = count( $plugin_group );
1215
+ $linked_plugins = array_map( array( 'WPMailSMTP\TGMPA_Utils', 'wrap_in_em' ), $linked_plugins );
1216
+ $last_plugin = array_pop( $linked_plugins ); // Pop off last name to prep for readability.
1217
+ $imploded = empty( $linked_plugins ) ? $last_plugin : ( implode( ', ', $linked_plugins ) . ' ' . esc_html_x( 'and', 'plugin A *and* plugin B', 'tgmpa' ) . ' ' . $last_plugin );
1218
+
1219
+ $rendered .= sprintf(
1220
+ $line_template,
1221
+ sprintf(
1222
+ translate_nooped_plural( $this->strings[ $type ], $count, 'tgmpa' ),
1223
+ $imploded,
1224
+ $count
1225
+ )
1226
+ );
1227
+
1228
+ }
1229
+ unset( $type, $plugin_group, $linked_plugins, $count, $last_plugin, $imploded );
1230
+
1231
+ $rendered .= $this->create_user_action_links_for_notice( $install_link_count, $update_link_count, $activate_link_count, $line_template );
1232
+ }
1233
+
1234
+ // Register the nag messages and prepare them to be processed.
1235
+ add_settings_error( 'tgmpa', 'tgmpa', $rendered, $this->get_admin_notice_class() );
1236
+ }
1237
+
1238
+ // Admin options pages already output settings_errors, so this is to avoid duplication.
1239
+ if ( 'options-general' !== $GLOBALS['current_screen']->parent_base ) {
1240
+ $this->display_settings_errors();
1241
+ }
1242
+ }
1243
+
1244
+ /**
1245
+ * Generate the user action links for the admin notice.
1246
+ *
1247
+ * @since 2.6.0
1248
+ *
1249
+ * @param int $install_count Number of plugins to install.
1250
+ * @param int $update_count Number of plugins to update.
1251
+ * @param int $activate_count Number of plugins to activate.
1252
+ * @param int $line_template Template for the HTML tag to output a line.
1253
+ * @return string Action links.
1254
+ */
1255
+ protected function create_user_action_links_for_notice( $install_count, $update_count, $activate_count, $line_template ) {
1256
+ // Setup action links.
1257
+ $action_links = array(
1258
+ 'install' => '',
1259
+ 'update' => '',
1260
+ 'activate' => '',
1261
+ 'dismiss' => $this->dismissable ? '<a href="' . esc_url( wp_nonce_url( add_query_arg( 'tgmpa-dismiss', 'dismiss_admin_notices' ), 'tgmpa-dismiss-' . get_current_user_id() ) ) . '" class="dismiss-notice" target="_parent">' . esc_html( $this->strings['dismiss'] ) . '</a>' : '',
1262
+ );
1263
+
1264
+ $link_template = '<a href="%2$s">%1$s</a>';
1265
+
1266
+ if ( current_user_can( 'install_plugins' ) ) {
1267
+ if ( $install_count > 0 ) {
1268
+ $action_links['install'] = sprintf(
1269
+ $link_template,
1270
+ translate_nooped_plural( $this->strings['install_link'], $install_count, 'tgmpa' ),
1271
+ esc_url( $this->get_tgmpa_status_url( 'install' ) )
1272
+ );
1273
+ }
1274
+ if ( $update_count > 0 ) {
1275
+ $action_links['update'] = sprintf(
1276
+ $link_template,
1277
+ translate_nooped_plural( $this->strings['update_link'], $update_count, 'tgmpa' ),
1278
+ esc_url( $this->get_tgmpa_status_url( 'update' ) )
1279
+ );
1280
+ }
1281
+ }
1282
+
1283
+ if ( current_user_can( 'activate_plugins' ) && $activate_count > 0 ) {
1284
+ $action_links['activate'] = sprintf(
1285
+ $link_template,
1286
+ translate_nooped_plural( $this->strings['activate_link'], $activate_count, 'tgmpa' ),
1287
+ esc_url( $this->get_tgmpa_status_url( 'activate' ) )
1288
+ );
1289
+ }
1290
+
1291
+ $action_links = apply_filters( 'tgmpa_notice_action_links', $action_links );
1292
+
1293
+ $action_links = array_filter( (array) $action_links ); // Remove any empty array items.
1294
+
1295
+ if ( ! empty( $action_links ) ) {
1296
+ $action_links = sprintf( $line_template, implode( ' | ', $action_links ) );
1297
+ return apply_filters( 'tgmpa_notice_rendered_action_links', $action_links );
1298
+ } else {
1299
+ return '';
1300
+ }
1301
+ }
1302
+
1303
+ /**
1304
+ * Get admin notice class.
1305
+ *
1306
+ * Work around all the changes to the various admin notice classes between WP 4.4 and 3.7
1307
+ * (lowest supported version by TGMPA).
1308
+ *
1309
+ * @since 2.6.0
1310
+ *
1311
+ * @return string
1312
+ */
1313
+ protected function get_admin_notice_class() {
1314
+ if ( ! empty( $this->strings['nag_type'] ) ) {
1315
+ return sanitize_html_class( strtolower( $this->strings['nag_type'] ) );
1316
+ } else {
1317
+ if ( version_compare( $this->wp_version, '4.2', '>=' ) ) {
1318
+ return 'notice-warning';
1319
+ } elseif ( version_compare( $this->wp_version, '4.1', '>=' ) ) {
1320
+ return 'notice';
1321
+ } else {
1322
+ return 'updated';
1323
+ }
1324
+ }
1325
+ }
1326
+
1327
+ /**
1328
+ * Display settings errors and remove those which have been displayed to avoid duplicate messages showing
1329
+ *
1330
+ * @since 2.5.0
1331
+ */
1332
+ protected function display_settings_errors() {
1333
+ global $wp_settings_errors;
1334
+
1335
+ settings_errors( 'tgmpa' );
1336
+
1337
+ foreach ( (array) $wp_settings_errors as $key => $details ) {
1338
+ if ( 'tgmpa' === $details['setting'] ) {
1339
+ unset( $wp_settings_errors[ $key ] );
1340
+ break;
1341
+ }
1342
+ }
1343
+ }
1344
+
1345
+ /**
1346
+ * Register dismissal of admin notices.
1347
+ *
1348
+ * Acts on the dismiss link in the admin nag messages.
1349
+ * If clicked, the admin notice disappears and will no longer be visible to this user.
1350
+ *
1351
+ * @since 2.1.0
1352
+ */
1353
+ public function dismiss() {
1354
+ if ( isset( $_GET['tgmpa-dismiss'] ) && check_admin_referer( 'tgmpa-dismiss-' . get_current_user_id() ) ) {
1355
+ update_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, 1 );
1356
+ }
1357
+ }
1358
+
1359
+ /**
1360
+ * Add individual plugin to our collection of plugins.
1361
+ *
1362
+ * If the required keys are not set or the plugin has already
1363
+ * been registered, the plugin is not added.
1364
+ *
1365
+ * @since 2.0.0
1366
+ *
1367
+ * @param array|null $plugin Array of plugin arguments or null if invalid argument.
1368
+ * @return null Return early if incorrect argument.
1369
+ */
1370
+ public function register( $plugin ) {
1371
+ if ( empty( $plugin['slug'] ) || empty( $plugin['name'] ) ) {
1372
+ return;
1373
+ }
1374
+
1375
+ if ( empty( $plugin['slug'] ) || ! is_string( $plugin['slug'] ) || isset( $this->plugins[ $plugin['slug'] ] ) ) {
1376
+ return;
1377
+ }
1378
+
1379
+ $defaults = array(
1380
+ 'name' => '', // String
1381
+ 'slug' => '', // String
1382
+ 'source' => 'repo', // String
1383
+ 'required' => false, // Boolean
1384
+ 'version' => '', // String
1385
+ 'force_activation' => false, // Boolean
1386
+ 'force_deactivation' => false, // Boolean
1387
+ 'external_url' => '', // String
1388
+ 'is_callable' => '', // String|Array.
1389
+ );
1390
+
1391
+ // Prepare the received data.
1392
+ $plugin = wp_parse_args( $plugin, $defaults );
1393
+
1394
+ // Standardize the received slug.
1395
+ $plugin['slug'] = $this->sanitize_key( $plugin['slug'] );
1396
+
1397
+ // Forgive users for using string versions of booleans or floats for version number.
1398
+ $plugin['version'] = (string) $plugin['version'];
1399
+ $plugin['source'] = empty( $plugin['source'] ) ? 'repo' : $plugin['source'];
1400
+ $plugin['required'] = TGMPA_Utils::validate_bool( $plugin['required'] );
1401
+ $plugin['force_activation'] = TGMPA_Utils::validate_bool( $plugin['force_activation'] );
1402
+ $plugin['force_deactivation'] = TGMPA_Utils::validate_bool( $plugin['force_deactivation'] );
1403
+
1404
+ // Enrich the received data.
1405
+ $plugin['file_path'] = $this->_get_plugin_basename_from_slug( $plugin['slug'] );
1406
+ $plugin['source_type'] = $this->get_plugin_source_type( $plugin['source'] );
1407
+
1408
+ // Set the class properties.
1409
+ $this->plugins[ $plugin['slug'] ] = $plugin;
1410
+ $this->sort_order[ $plugin['slug'] ] = $plugin['name'];
1411
+
1412
+ // Should we add the force activation hook ?
1413
+ if ( true === $plugin['force_activation'] ) {
1414
+ $this->has_forced_activation = true;
1415
+ }
1416
+
1417
+ // Should we add the force deactivation hook ?
1418
+ if ( true === $plugin['force_deactivation'] ) {
1419
+ $this->has_forced_deactivation = true;
1420
+ }
1421
+ }
1422
+
1423
+ /**
1424
+ * Determine what type of source the plugin comes from.
1425
+ *
1426
+ * @since 2.5.0
1427
+ *
1428
+ * @param string $source The source of the plugin as provided, either empty (= WP repo), a file path
1429
+ * (= bundled) or an external URL.
1430
+ * @return string 'repo', 'external', or 'bundled'
1431
+ */
1432
+ protected function get_plugin_source_type( $source ) {
1433
+ if ( 'repo' === $source || preg_match( self::WP_REPO_REGEX, $source ) ) {
1434
+ return 'repo';
1435
+ } elseif ( preg_match( self::IS_URL_REGEX, $source ) ) {
1436
+ return 'external';
1437
+ } else {
1438
+ return 'bundled';
1439
+ }
1440
+ }
1441
+
1442
+ /**
1443
+ * Sanitizes a string key.
1444
+ *
1445
+ * Near duplicate of WP Core `sanitize_key()`. The difference is that uppercase characters *are*
1446
+ * allowed, so as not to break upgrade paths from non-standard bundled plugins using uppercase
1447
+ * characters in the plugin directory path/slug. Silly them.
1448
+ *
1449
+ * @see https://developer.wordpress.org/reference/hooks/sanitize_key/
1450
+ *
1451
+ * @since 2.5.0
1452
+ *
1453
+ * @param string $key String key.
1454
+ * @return string Sanitized key
1455
+ */
1456
+ public function sanitize_key( $key ) {
1457
+ $raw_key = $key;
1458
+ $key = preg_replace( '`[^A-Za-z0-9_-]`', '', $key );
1459
+
1460
+ /**
1461
+ * Filter a sanitized key string.
1462
+ *
1463
+ * @since 2.5.0
1464
+ *
1465
+ * @param string $key Sanitized key.
1466
+ * @param string $raw_key The key prior to sanitization.
1467
+ */
1468
+ return apply_filters( 'tgmpa_sanitize_key', $key, $raw_key );
1469
+ }
1470
+
1471
+ /**
1472
+ * Amend default configuration settings.
1473
+ *
1474
+ * @since 2.0.0
1475
+ *
1476
+ * @param array $config Array of config options to pass as class properties.
1477
+ */
1478
+ public function config( $config ) {
1479
+ $keys = array(
1480
+ 'id',
1481
+ 'default_path',
1482
+ 'has_notices',
1483
+ 'dismissable',
1484
+ 'dismiss_msg',
1485
+ 'menu',
1486
+ 'parent_slug',
1487
+ 'capability',
1488
+ 'is_automatic',
1489
+ 'message',
1490
+ 'strings',
1491
+ );
1492
+
1493
+ foreach ( $keys as $key ) {
1494
+ if ( isset( $config[ $key ] ) ) {
1495
+ if ( is_array( $config[ $key ] ) ) {
1496
+ $this->$key = array_merge( $this->$key, $config[ $key ] );
1497
+ } else {
1498
+ $this->$key = $config[ $key ];
1499
+ }
1500
+ }
1501
+ }
1502
+ }
1503
+
1504
+ /**
1505
+ * Amend action link after plugin installation.
1506
+ *
1507
+ * @since 2.0.0
1508
+ *
1509
+ * @param array $install_actions Existing array of actions.
1510
+ * @return false|array Amended array of actions.
1511
+ */
1512
+ public function actions( $install_actions ) {
1513
+ // Remove action links on the TGMPA install page.
1514
+ if ( $this->is_tgmpa_page() ) {
1515
+ return false;
1516
+ }
1517
+
1518
+ return $install_actions;
1519
+ }
1520
+
1521
+ /**
1522
+ * Flushes the plugins cache on theme switch to prevent stale entries
1523
+ * from remaining in the plugin table.
1524
+ *
1525
+ * @since 2.4.0
1526
+ *
1527
+ * @param bool $clear_update_cache Optional. Whether to clear the Plugin updates cache.
1528
+ * Parameter added in v2.5.0.
1529
+ */
1530
+ public function flush_plugins_cache( $clear_update_cache = true ) {
1531
+ wp_clean_plugins_cache( $clear_update_cache );
1532
+ }
1533
+
1534
+ /**
1535
+ * Set file_path key for each installed plugin.
1536
+ *
1537
+ * @since 2.1.0
1538
+ *
1539
+ * @param string $plugin_slug Optional. If set, only (re-)populates the file path for that specific plugin.
1540
+ * Parameter added in v2.5.0.
1541
+ */
1542
+ public function populate_file_path( $plugin_slug = '' ) {
1543
+ if ( ! empty( $plugin_slug ) && is_string( $plugin_slug ) && isset( $this->plugins[ $plugin_slug ] ) ) {
1544
+ $this->plugins[ $plugin_slug ]['file_path'] = $this->_get_plugin_basename_from_slug( $plugin_slug );
1545
+ } else {
1546
+ // Add file_path key for all plugins.
1547
+ foreach ( $this->plugins as $slug => $values ) {
1548
+ $this->plugins[ $slug ]['file_path'] = $this->_get_plugin_basename_from_slug( $slug );
1549
+ }
1550
+ }
1551
+ }
1552
+
1553
+ /**
1554
+ * Helper function to extract the file path of the plugin file from the
1555
+ * plugin slug, if the plugin is installed.
1556
+ *
1557
+ * @since 2.0.0
1558
+ *
1559
+ * @param string $slug Plugin slug (typically folder name) as provided by the developer.
1560
+ * @return string Either file path for plugin if installed, or just the plugin slug.
1561
+ */
1562
+ protected function _get_plugin_basename_from_slug( $slug ) {
1563
+ $keys = array_keys( $this->get_plugins() );
1564
+
1565
+ foreach ( $keys as $key ) {
1566
+ if ( preg_match( '|^' . $slug . '/|', $key ) ) {
1567
+ return $key;
1568
+ }
1569
+ }
1570
+
1571
+ return $slug;
1572
+ }
1573
+
1574
+ /**
1575
+ * Retrieve plugin data, given the plugin name.
1576
+ *
1577
+ * Loops through the registered plugins looking for $name. If it finds it,
1578
+ * it returns the $data from that plugin. Otherwise, returns false.
1579
+ *
1580
+ * @since 2.1.0
1581
+ *
1582
+ * @param string $name Name of the plugin, as it was registered.
1583
+ * @param string $data Optional. Array key of plugin data to return. Default is slug.
1584
+ * @return string|boolean Plugin slug if found, false otherwise.
1585
+ */
1586
+ public function _get_plugin_data_from_name( $name, $data = 'slug' ) {
1587
+ foreach ( $this->plugins as $values ) {
1588
+ if ( $name === $values['name'] && isset( $values[ $data ] ) ) {
1589
+ return $values[ $data ];
1590
+ }
1591
+ }
1592
+
1593
+ return false;
1594
+ }
1595
+
1596
+ /**
1597
+ * Retrieve the download URL for a package.
1598
+ *
1599
+ * @since 2.5.0
1600
+ *
1601
+ * @param string $slug Plugin slug.
1602
+ * @return string Plugin download URL or path to local file or empty string if undetermined.
1603
+ */
1604
+ public function get_download_url( $slug ) {
1605
+ $dl_source = '';
1606
+
1607
+ switch ( $this->plugins[ $slug ]['source_type'] ) {
1608
+ case 'repo':
1609
+ return $this->get_wp_repo_download_url( $slug );
1610
+ case 'external':
1611
+ return $this->plugins[ $slug ]['source'];
1612
+ case 'bundled':
1613
+ return $this->default_path . $this->plugins[ $slug ]['source'];
1614
+ }
1615
+
1616
+ return $dl_source; // Should never happen.
1617
+ }
1618
+
1619
+ /**
1620
+ * Retrieve the download URL for a WP repo package.
1621
+ *
1622
+ * @since 2.5.0
1623
+ *
1624
+ * @param string $slug Plugin slug.
1625
+ * @return string Plugin download URL.
1626
+ */
1627
+ protected function get_wp_repo_download_url( $slug ) {
1628
+ $source = '';
1629
+ $api = $this->get_plugins_api( $slug );
1630
+
1631
+ if ( false !== $api && isset( $api->download_link ) ) {
1632
+ $source = $api->download_link;
1633
+ }
1634
+
1635
+ return $source;
1636
+ }
1637
+
1638
+ /**
1639
+ * Try to grab information from WordPress API.
1640
+ *
1641
+ * @since 2.5.0
1642
+ *
1643
+ * @param string $slug Plugin slug.
1644
+ * @return object Plugins_api response object on success, WP_Error on failure.
1645
+ */
1646
+ protected function get_plugins_api( $slug ) {
1647
+ static $api = array(); // Cache received responses.
1648
+
1649
+ if ( ! isset( $api[ $slug ] ) ) {
1650
+ if ( ! function_exists( 'plugins_api' ) ) {
1651
+ require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
1652
+ }
1653
+
1654
+ $response = plugins_api( 'plugin_information', array( 'slug' => $slug, 'fields' => array( 'sections' => false ) ) );
1655
+
1656
+ $api[ $slug ] = false;
1657
+
1658
+ if ( is_wp_error( $response ) ) {
1659
+ wp_die( esc_html( $this->strings['oops'] ) );
1660
+ } else {
1661
+ $api[ $slug ] = $response;
1662
+ }
1663
+ }
1664
+
1665
+ return $api[ $slug ];
1666
+ }
1667
+
1668
+ /**
1669
+ * Retrieve a link to a plugin information page.
1670
+ *
1671
+ * @since 2.5.0
1672
+ *
1673
+ * @param string $slug Plugin slug.
1674
+ * @return string Fully formed html link to a plugin information page if available
1675
+ * or the plugin name if not.
1676
+ */
1677
+ public function get_info_link( $slug ) {
1678
+ if ( ! empty( $this->plugins[ $slug ]['external_url'] ) && preg_match( self::IS_URL_REGEX, $this->plugins[ $slug ]['external_url'] ) ) {
1679
+ $link = sprintf(
1680
+ '<a href="%1$s" target="_blank">%2$s</a>',
1681
+ esc_url( $this->plugins[ $slug ]['external_url'] ),
1682
+ esc_html( $this->plugins[ $slug ]['name'] )
1683
+ );
1684
+ } elseif ( 'repo' === $this->plugins[ $slug ]['source_type'] ) {
1685
+ $url = add_query_arg(
1686
+ array(
1687
+ 'tab' => 'plugin-information',
1688
+ 'plugin' => urlencode( $slug ),
1689
+ 'TB_iframe' => 'true',
1690
+ 'width' => '640',
1691
+ 'height' => '500',
1692
+ ),
1693
+ self_admin_url( 'plugin-install.php' )
1694
+ );
1695
+
1696
+ $link = sprintf(
1697
+ '<a href="%1$s" class="thickbox">%2$s</a>',
1698
+ esc_url( $url ),
1699
+ esc_html( $this->plugins[ $slug ]['name'] )
1700
+ );
1701
+ } else {
1702
+ $link = esc_html( $this->plugins[ $slug ]['name'] ); // No hyperlink.
1703
+ }
1704
+
1705
+ return $link;
1706
+ }
1707
+
1708
+ /**
1709
+ * Determine if we're on the TGMPA Install page.
1710
+ *
1711
+ * @since 2.1.0
1712
+ *
1713
+ * @return boolean True when on the TGMPA page, false otherwise.
1714
+ */
1715
+ protected function is_tgmpa_page() {
1716
+ return isset( $_GET['page'] ) && $this->menu === $_GET['page'];
1717
+ }
1718
+
1719
+ /**
1720
+ * Determine if we're on a WP Core installation/upgrade page.
1721
+ *
1722
+ * @since 2.6.0
1723
+ *
1724
+ * @return boolean True when on a WP Core installation/upgrade page, false otherwise.
1725
+ */
1726
+ protected function is_core_update_page() {
1727
+ // Current screen is not always available, most notably on the customizer screen.
1728
+ if ( ! function_exists( 'get_current_screen' ) ) {
1729
+ return false;
1730
+ }
1731
+
1732
+ $screen = get_current_screen();
1733
+
1734
+ if ( 'update-core' === $screen->base ) {
1735
+ // Core update screen.
1736
+ return true;
1737
+ } elseif ( 'plugins' === $screen->base && ! empty( $_POST['action'] ) ) { // WPCS: CSRF ok.
1738
+ // Plugins bulk update screen.
1739
+ return true;
1740
+ } elseif ( 'update' === $screen->base && ! empty( $_POST['action'] ) ) { // WPCS: CSRF ok.
1741
+ // Individual updates (ajax call).
1742
+ return true;
1743
+ }
1744
+
1745
+ return false;
1746
+ }
1747
+
1748
+ /**
1749
+ * Retrieve the URL to the TGMPA Install page.
1750
+ *
1751
+ * I.e. depending on the config settings passed something along the lines of:
1752
+ * http://example.com/wp-admin/themes.php?page=tgmpa-install-plugins
1753
+ *
1754
+ * @since 2.5.0
1755
+ *
1756
+ * @return string Properly encoded URL (not escaped).
1757
+ */
1758
+ public function get_tgmpa_url() {
1759
+ static $url;
1760
+
1761
+ if ( ! isset( $url ) ) {
1762
+ $parent = $this->parent_slug;
1763
+ if ( false === strpos( $parent, '.php' ) ) {
1764
+ $parent = 'admin.php';
1765
+ }
1766
+ $url = add_query_arg(
1767
+ array(
1768
+ 'page' => urlencode( $this->menu ),
1769
+ ),
1770
+ self_admin_url( $parent )
1771
+ );
1772
+ }
1773
+
1774
+ return $url;
1775
+ }
1776
+
1777
+ /**
1778
+ * Retrieve the URL to the TGMPA Install page for a specific plugin status (view).
1779
+ *
1780
+ * I.e. depending on the config settings passed something along the lines of:
1781
+ * http://example.com/wp-admin/themes.php?page=tgmpa-install-plugins&plugin_status=install
1782
+ *
1783
+ * @since 2.5.0
1784
+ *
1785
+ * @param string $status Plugin status - either 'install', 'update' or 'activate'.
1786
+ * @return string Properly encoded URL (not escaped).
1787
+ */
1788
+ public function get_tgmpa_status_url( $status ) {
1789
+ return add_query_arg(
1790
+ array(
1791
+ 'plugin_status' => urlencode( $status ),
1792
+ ),
1793
+ $this->get_tgmpa_url()
1794
+ );
1795
+ }
1796
+
1797
+ /**
1798
+ * Determine whether there are open actions for plugins registered with TGMPA.
1799
+ *
1800
+ * @since 2.5.0
1801
+ *
1802
+ * @return bool True if complete, i.e. no outstanding actions. False otherwise.
1803
+ */
1804
+ public function is_tgmpa_complete() {
1805
+ $complete = true;
1806
+ foreach ( $this->plugins as $slug => $plugin ) {
1807
+ if ( ! $this->is_plugin_active( $slug ) || false !== $this->does_plugin_have_update( $slug ) ) {
1808
+ $complete = false;
1809
+ break;
1810
+ }
1811
+ }
1812
+
1813
+ return $complete;
1814
+ }
1815
+
1816
+ /**
1817
+ * Check if a plugin is installed. Does not take must-use plugins into account.
1818
+ *
1819
+ * @since 2.5.0
1820
+ *
1821
+ * @param string $slug Plugin slug.
1822
+ * @return bool True if installed, false otherwise.
1823
+ */
1824
+ public function is_plugin_installed( $slug ) {
1825
+ $installed_plugins = $this->get_plugins(); // Retrieve a list of all installed plugins (WP cached).
1826
+
1827
+ return ( ! empty( $installed_plugins[ $this->plugins[ $slug ]['file_path'] ] ) );
1828
+ }
1829
+
1830
+ /**
1831
+ * Check if a plugin is active.
1832
+ *
1833
+ * @since 2.5.0
1834
+ *
1835
+ * @param string $slug Plugin slug.
1836
+ * @return bool True if active, false otherwise.
1837
+ */
1838
+ public function is_plugin_active( $slug ) {
1839
+ return ( ( ! empty( $this->plugins[ $slug ]['is_callable'] ) && is_callable( $this->plugins[ $slug ]['is_callable'] ) ) || is_plugin_active( $this->plugins[ $slug ]['file_path'] ) );
1840
+ }
1841
+
1842
+ /**
1843
+ * Check if a plugin can be updated, i.e. if we have information on the minimum WP version required
1844
+ * available, check whether the current install meets them.
1845
+ *
1846
+ * @since 2.5.0
1847
+ *
1848
+ * @param string $slug Plugin slug.
1849
+ * @return bool True if OK to update, false otherwise.
1850
+ */
1851
+ public function can_plugin_update( $slug ) {
1852
+ // We currently can't get reliable info on non-WP-repo plugins - issue #380.
1853
+ if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
1854
+ return true;
1855
+ }
1856
+
1857
+ $api = $this->get_plugins_api( $slug );
1858
+
1859
+ if ( false !== $api && isset( $api->requires ) ) {
1860
+ return version_compare( $this->wp_version, $api->requires, '>=' );
1861
+ }
1862
+
1863
+ // No usable info received from the plugins API, presume we can update.
1864
+ return true;
1865
+ }
1866
+
1867
+ /**
1868
+ * Check to see if the plugin is 'updatetable', i.e. installed, with an update available
1869
+ * and no WP version requirements blocking it.
1870
+ *
1871
+ * @since 2.6.0
1872
+ *
1873
+ * @param string $slug Plugin slug.
1874
+ * @return bool True if OK to proceed with update, false otherwise.
1875
+ */
1876
+ public function is_plugin_updatetable( $slug ) {
1877
+ if ( ! $this->is_plugin_installed( $slug ) ) {
1878
+ return false;
1879
+ } else {
1880
+ return ( false !== $this->does_plugin_have_update( $slug ) && $this->can_plugin_update( $slug ) );
1881
+ }
1882
+ }
1883
+
1884
+ /**
1885
+ * Check if a plugin can be activated, i.e. is not currently active and meets the minimum
1886
+ * plugin version requirements set in TGMPA (if any).
1887
+ *
1888
+ * @since 2.5.0
1889
+ *
1890
+ * @param string $slug Plugin slug.
1891
+ * @return bool True if OK to activate, false otherwise.
1892
+ */
1893
+ public function can_plugin_activate( $slug ) {
1894
+ return ( ! $this->is_plugin_active( $slug ) && ! $this->does_plugin_require_update( $slug ) );
1895
+ }
1896
+
1897
+ /**
1898
+ * Retrieve the version number of an installed plugin.
1899
+ *
1900
+ * @since 2.5.0
1901
+ *
1902
+ * @param string $slug Plugin slug.
1903
+ * @return string Version number as string or an empty string if the plugin is not installed
1904
+ * or version unknown (plugins which don't comply with the plugin header standard).
1905
+ */
1906
+ public function get_installed_version( $slug ) {
1907
+ $installed_plugins = $this->get_plugins(); // Retrieve a list of all installed plugins (WP cached).
1908
+
1909
+ if ( ! empty( $installed_plugins[ $this->plugins[ $slug ]['file_path'] ]['Version'] ) ) {
1910
+ return $installed_plugins[ $this->plugins[ $slug ]['file_path'] ]['Version'];
1911
+ }
1912
+
1913
+ return '';
1914
+ }
1915
+
1916
+ /**
1917
+ * Check whether a plugin complies with the minimum version requirements.
1918
+ *
1919
+ * @since 2.5.0
1920
+ *
1921
+ * @param string $slug Plugin slug.
1922
+ * @return bool True when a plugin needs to be updated, otherwise false.
1923
+ */
1924
+ public function does_plugin_require_update( $slug ) {
1925
+ $installed_version = $this->get_installed_version( $slug );
1926
+ $minimum_version = $this->plugins[ $slug ]['version'];
1927
+
1928
+ return version_compare( $minimum_version, $installed_version, '>' );
1929
+ }
1930
+
1931
+ /**
1932
+ * Check whether there is an update available for a plugin.
1933
+ *
1934
+ * @since 2.5.0
1935
+ *
1936
+ * @param string $slug Plugin slug.
1937
+ * @return false|string Version number string of the available update or false if no update available.
1938
+ */
1939
+ public function does_plugin_have_update( $slug ) {
1940
+ // Presume bundled and external plugins will point to a package which meets the minimum required version.
1941
+ if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
1942
+ if ( $this->does_plugin_require_update( $slug ) ) {
1943
+ return $this->plugins[ $slug ]['version'];
1944
+ }
1945
+
1946
+ return false;
1947
+ }
1948
+
1949
+ $repo_updates = get_site_transient( 'update_plugins' );
1950
+
1951
+ if ( isset( $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->new_version ) ) {
1952
+ return $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->new_version;
1953
+ }
1954
+
1955
+ return false;
1956
+ }
1957
+
1958
+ /**
1959
+ * Retrieve potential upgrade notice for a plugin.
1960
+ *
1961
+ * @since 2.5.0
1962
+ *
1963
+ * @param string $slug Plugin slug.
1964
+ * @return string The upgrade notice or an empty string if no message was available or provided.
1965
+ */
1966
+ public function get_upgrade_notice( $slug ) {
1967
+ // We currently can't get reliable info on non-WP-repo plugins - issue #380.
1968
+ if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
1969
+ return '';
1970
+ }
1971
+
1972
+ $repo_updates = get_site_transient( 'update_plugins' );
1973
+
1974
+ if ( ! empty( $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->upgrade_notice ) ) {
1975
+ return $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->upgrade_notice;
1976
+ }
1977
+
1978
+ return '';
1979
+ }
1980
+
1981
+ /**
1982
+ * Wrapper around the core WP get_plugins function, making sure it's actually available.
1983
+ *
1984
+ * @since 2.5.0
1985
+ *
1986
+ * @param string $plugin_folder Optional. Relative path to single plugin folder.
1987
+ * @return array Array of installed plugins with plugin information.
1988
+ */
1989
+ public function get_plugins( $plugin_folder = '' ) {
1990
+ if ( ! function_exists( 'get_plugins' ) ) {
1991
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
1992
+ }
1993
+
1994
+ return get_plugins( $plugin_folder );
1995
+ }
1996
+
1997
+ /**
1998
+ * Delete dismissable nag option when theme is switched.
1999
+ *
2000
+ * This ensures that the user(s) is/are again reminded via nag of required
2001
+ * and/or recommended plugins if they re-activate the theme.
2002
+ *
2003
+ * @since 2.1.1
2004
+ */
2005
+ public function update_dismiss() {
2006
+ delete_metadata( 'user', null, 'tgmpa_dismissed_notice_' . $this->id, null, true );
2007
+ }
2008
+
2009
+ /**
2010
+ * Forces plugin activation if the parameter 'force_activation' is
2011
+ * set to true.
2012
+ *
2013
+ * This allows theme authors to specify certain plugins that must be
2014
+ * active at all times while using the current theme.
2015
+ *
2016
+ * Please take special care when using this parameter as it has the
2017
+ * potential to be harmful if not used correctly. Setting this parameter
2018
+ * to true will not allow the specified plugin to be deactivated unless
2019
+ * the user switches themes.
2020
+ *
2021
+ * @since 2.2.0
2022
+ */
2023
+ public function force_activation() {
2024
+ foreach ( $this->plugins as $slug => $plugin ) {
2025
+ if ( true === $plugin['force_activation'] ) {
2026
+ if ( ! $this->is_plugin_installed( $slug ) ) {
2027
+ // Oops, plugin isn't there so iterate to next condition.
2028
+ continue;
2029
+ } elseif ( $this->can_plugin_activate( $slug ) ) {
2030
+ // There we go, activate the plugin.
2031
+ activate_plugin( $plugin['file_path'] );
2032
+ }
2033
+ }
2034
+ }
2035
+ }
2036
+
2037
+ /**
2038
+ * Forces plugin deactivation if the parameter 'force_deactivation'
2039
+ * is set to true and adds the plugin to the 'recently active' plugins list.
2040
+ *
2041
+ * This allows theme authors to specify certain plugins that must be
2042
+ * deactivated upon switching from the current theme to another.
2043
+ *
2044
+ * Please take special care when using this parameter as it has the
2045
+ * potential to be harmful if not used correctly.
2046
+ *
2047
+ * @since 2.2.0
2048
+ */
2049
+ public function force_deactivation() {
2050
+ $deactivated = array();
2051
+
2052
+ foreach ( $this->plugins as $slug => $plugin ) {
2053
+ /*
2054
+ * Only proceed forward if the parameter is set to true and plugin is active
2055
+ * as a 'normal' (not must-use) plugin.
2056
+ */
2057
+ if ( true === $plugin['force_deactivation'] && is_plugin_active( $plugin['file_path'] ) ) {
2058
+ deactivate_plugins( $plugin['file_path'] );
2059
+ $deactivated[ $plugin['file_path'] ] = time();
2060
+ }
2061
+ }
2062
+
2063
+ if ( ! empty( $deactivated ) ) {
2064
+ update_option( 'recently_activated', $deactivated + (array) get_option( 'recently_activated' ) );
2065
+ }
2066
+ }
2067
+
2068
+ /**
2069
+ * Echo the current TGMPA version number to the page.
2070
+ *
2071
+ * @since 2.5.0
2072
+ */
2073
+ public function show_tgmpa_version() {
2074
+ echo '<p style="float: right; padding: 0em 1.5em 0.5em 0;"><strong><small>',
2075
+ esc_html(
2076
+ sprintf(
2077
+ /* translators: %s: version number */
2078
+ __( 'TGMPA v%s', 'tgmpa' ),
2079
+ self::TGMPA_VERSION
2080
+ )
2081
+ ),
2082
+ '</small></strong></p>';
2083
+ }
2084
+
2085
+ /**
2086
+ * Returns the singleton instance of the class.
2087
+ *
2088
+ * @since 2.4.0
2089
+ *
2090
+ * @return \TGM_Plugin_Activation The TGM_Plugin_Activation object.
2091
+ */
2092
+ public static function get_instance() {
2093
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof self ) ) {
2094
+ self::$instance = new self();
2095
+ }
2096
+
2097
+ return self::$instance;
2098
+ }
2099
+ }
2100
+
2101
+ if ( ! function_exists( 'load_tgm_plugin_activation' ) ) {
2102
+ /**
2103
+ * Ensure only one instance of the class is ever invoked.
2104
+ *
2105
+ * @since 2.5.0
2106
+ */
2107
+ function load_tgm_plugin_activation() {
2108
+ $GLOBALS['wp_mail_smtp_tgmpa'] = TGM_Plugin_Activation::get_instance();
2109
+ }
2110
+ }
2111
+
2112
+ if ( did_action( 'plugins_loaded' ) ) {
2113
+ load_tgm_plugin_activation();
2114
+ } else {
2115
+ add_action( 'plugins_loaded', 'WPMailSMTP\load_tgm_plugin_activation' );
2116
+ }
2117
+ }
2118
+
2119
+ if ( ! function_exists( 'tgmpa' ) ) {
2120
+ /**
2121
+ * Helper function to register a collection of required plugins.
2122
+ *
2123
+ * @since 2.0.0
2124
+ * @api
2125
+ *
2126
+ * @param array $plugins An array of plugin arrays.
2127
+ * @param array $config Optional. An array of configuration values.
2128
+ */
2129
+ function tgmpa( $plugins, $config = array() ) {
2130
+ $instance = call_user_func( array( get_class( $GLOBALS['wp_mail_smtp_tgmpa'] ), 'get_instance' ) );
2131
+
2132
+ foreach ( $plugins as $plugin ) {
2133
+ call_user_func( array( $instance, 'register' ), $plugin );
2134
+ }
2135
+
2136
+ if ( ! empty( $config ) && is_array( $config ) ) {
2137
+ // Send out notices for deprecated arguments passed.
2138
+ if ( isset( $config['notices'] ) ) {
2139
+ _deprecated_argument( __FUNCTION__, '2.2.0', 'The `notices` config parameter was renamed to `has_notices` in TGMPA 2.2.0. Please adjust your configuration.' );
2140
+ if ( ! isset( $config['has_notices'] ) ) {
2141
+ $config['has_notices'] = $config['notices'];
2142
+ }
2143
+ }
2144
+
2145
+ if ( isset( $config['parent_menu_slug'] ) ) {
2146
+ _deprecated_argument( __FUNCTION__, '2.4.0', 'The `parent_menu_slug` config parameter was removed in TGMPA 2.4.0. In TGMPA 2.5.0 an alternative was (re-)introduced. Please adjust your configuration. For more information visit the website: http://tgmpluginactivation.com/configuration/#h-configuration-options.' );
2147
+ }
2148
+ if ( isset( $config['parent_url_slug'] ) ) {
2149
+ _deprecated_argument( __FUNCTION__, '2.4.0', 'The `parent_url_slug` config parameter was removed in TGMPA 2.4.0. In TGMPA 2.5.0 an alternative was (re-)introduced. Please adjust your configuration. For more information visit the website: http://tgmpluginactivation.com/configuration/#h-configuration-options.' );
2150
+ }
2151
+
2152
+ call_user_func( array( $instance, 'config' ), $config );
2153
+ }
2154
+ }
2155
+ }
2156
+
2157
+ /**
2158
+ * WP_List_Table isn't always available. If it isn't available,
2159
+ * we load it here.
2160
+ *
2161
+ * @since 2.2.0
2162
+ */
2163
+ if ( ! class_exists( 'WP_List_Table' ) ) {
2164
+ require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
2165
+ }
2166
+
2167
+ if ( ! class_exists( 'TGMPA_List_Table' ) ) {
2168
+
2169
+ /**
2170
+ * List table class for handling plugins.
2171
+ *
2172
+ * Extends the WP_List_Table class to provide a future-compatible
2173
+ * way of listing out all required/recommended plugins.
2174
+ *
2175
+ * Gives users an interface similar to the Plugin Administration
2176
+ * area with similar (albeit stripped down) capabilities.
2177
+ *
2178
+ * This class also allows for the bulk install of plugins.
2179
+ *
2180
+ * @since 2.2.0
2181
+ *
2182
+ * @package TGM-Plugin-Activation
2183
+ * @author Thomas Griffin
2184
+ * @author Gary Jones
2185
+ */
2186
+ class TGMPA_List_Table extends \WP_List_Table {
2187
+ /**
2188
+ * TGMPA instance.
2189
+ *
2190
+ * @since 2.5.0
2191
+ *
2192
+ * @var object
2193
+ */
2194
+ protected $tgmpa;
2195
+
2196
+ /**
2197
+ * The currently chosen view.
2198
+ *
2199
+ * @since 2.5.0
2200
+ *
2201
+ * @var string One of: 'all', 'install', 'update', 'activate'
2202
+ */
2203
+ public $view_context = 'all';
2204
+
2205
+ /**
2206
+ * The plugin counts for the various views.
2207
+ *
2208
+ * @since 2.5.0
2209
+ *
2210
+ * @var array
2211
+ */
2212
+ protected $view_totals = array(
2213
+ 'all' => 0,
2214
+ 'install' => 0,
2215
+ 'update' => 0,
2216
+ 'activate' => 0,
2217
+ );
2218
+
2219
+ /**
2220
+ * References parent constructor and sets defaults for class.
2221
+ *
2222
+ * @since 2.2.0
2223
+ */
2224
+ public function __construct() {
2225
+ $this->tgmpa = call_user_func( array( get_class( $GLOBALS['wp_mail_smtp_tgmpa'] ), 'get_instance' ) );
2226
+
2227
+ parent::__construct(
2228
+ array(
2229
+ 'singular' => 'plugin',
2230
+ 'plural' => 'plugins',
2231
+ 'ajax' => false,
2232
+ )
2233
+ );
2234
+
2235
+ if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], array( 'install', 'update', 'activate' ), true ) ) {
2236
+ $this->view_context = sanitize_key( $_REQUEST['plugin_status'] );
2237
+ }
2238
+
2239
+ add_filter( 'tgmpa_table_data_items', array( $this, 'sort_table_items' ) );
2240
+ }
2241
+
2242
+ /**
2243
+ * Get a list of CSS classes for the <table> tag.
2244
+ *
2245
+ * Overruled to prevent the 'plural' argument from being added.
2246
+ *
2247
+ * @since 2.5.0
2248
+ *
2249
+ * @return array CSS classnames.
2250
+ */
2251
+ public function get_table_classes() {
2252
+ return array( 'widefat', 'fixed' );
2253
+ }
2254
+
2255
+ /**
2256
+ * Gathers and renames all of our plugin information to be used by WP_List_Table to create our table.
2257
+ *
2258
+ * @since 2.2.0
2259
+ *
2260
+ * @return array $table_data Information for use in table.
2261
+ */
2262
+ protected function _gather_plugin_data() {
2263
+ // Load thickbox for plugin links.
2264
+ $this->tgmpa->admin_init();
2265
+ $this->tgmpa->thickbox();
2266
+
2267
+ // Categorize the plugins which have open actions.
2268
+ $plugins = $this->categorize_plugins_to_views();
2269
+
2270
+ // Set the counts for the view links.
2271
+ $this->set_view_totals( $plugins );
2272
+
2273
+ // Prep variables for use and grab list of all installed plugins.
2274
+ $table_data = array();
2275
+ $i = 0;
2276
+
2277
+ // Redirect to the 'all' view if no plugins were found for the selected view context.
2278
+ if ( empty( $plugins[ $this->view_context ] ) ) {
2279
+ $this->view_context = 'all';
2280
+ }
2281
+
2282
+ foreach ( $plugins[ $this->view_context ] as $slug => $plugin ) {
2283
+ $table_data[ $i ]['sanitized_plugin'] = $plugin['name'];
2284
+ $table_data[ $i ]['slug'] = $slug;
2285
+ $table_data[ $i ]['plugin'] = '<strong>' . $this->tgmpa->get_info_link( $slug ) . '</strong>';
2286
+ $table_data[ $i ]['source'] = $this->get_plugin_source_type_text( $plugin['source_type'] );
2287
+ $table_data[ $i ]['type'] = $this->get_plugin_advise_type_text( $plugin['required'] );
2288
+ $table_data[ $i ]['status'] = $this->get_plugin_status_text( $slug );
2289
+ $table_data[ $i ]['installed_version'] = $this->tgmpa->get_installed_version( $slug );
2290
+ $table_data[ $i ]['minimum_version'] = $plugin['version'];
2291
+ $table_data[ $i ]['available_version'] = $this->tgmpa->does_plugin_have_update( $slug );
2292
+
2293
+ // Prep the upgrade notice info.
2294
+ $upgrade_notice = $this->tgmpa->get_upgrade_notice( $slug );
2295
+ if ( ! empty( $upgrade_notice ) ) {
2296
+ $table_data[ $i ]['upgrade_notice'] = $upgrade_notice;
2297
+
2298
+ add_action( "tgmpa_after_plugin_row_{$slug}", array( $this, 'wp_plugin_update_row' ), 10, 2 );
2299
+ }
2300
+
2301
+ $table_data[ $i ] = apply_filters( 'tgmpa_table_data_item', $table_data[ $i ], $plugin );
2302
+
2303
+ $i++;
2304
+ }
2305
+
2306
+ return $table_data;
2307
+ }
2308
+
2309
+ /**
2310
+ * Categorize the plugins which have open actions into views for the TGMPA page.
2311
+ *
2312
+ * @since 2.5.0
2313
+ */
2314
+ protected function categorize_plugins_to_views() {
2315
+ $plugins = array(
2316
+ 'all' => array(), // Meaning: all plugins which still have open actions.
2317
+ 'install' => array(),
2318
+ 'update' => array(),
2319
+ 'activate' => array(),
2320
+ );
2321
+
2322
+ foreach ( $this->tgmpa->plugins as $slug => $plugin ) {
2323
+ if ( $this->tgmpa->is_plugin_active( $slug ) && false === $this->tgmpa->does_plugin_have_update( $slug ) ) {
2324
+ // No need to display plugins if they are installed, up-to-date and active.
2325
+ continue;
2326
+ } else {
2327
+ $plugins['all'][ $slug ] = $plugin;
2328
+
2329
+ if ( ! $this->tgmpa->is_plugin_installed( $slug ) ) {
2330
+ $plugins['install'][ $slug ] = $plugin;
2331
+ } else {
2332
+ if ( false !== $this->tgmpa->does_plugin_have_update( $slug ) ) {
2333
+ $plugins['update'][ $slug ] = $plugin;
2334
+ }
2335
+
2336
+ if ( $this->tgmpa->can_plugin_activate( $slug ) ) {
2337
+ $plugins['activate'][ $slug ] = $plugin;
2338
+ }
2339
+ }
2340
+ }
2341
+ }
2342
+
2343
+ return $plugins;
2344
+ }
2345
+
2346
+ /**
2347
+ * Set the counts for the view links.
2348
+ *
2349
+ * @since 2.5.0
2350
+ *
2351
+ * @param array $plugins Plugins order by view.
2352
+ */
2353
+ protected function set_view_totals( $plugins ) {
2354
+ foreach ( $plugins as $type => $list ) {
2355
+ $this->view_totals[ $type ] = count( $list );
2356
+ }
2357
+ }
2358
+
2359
+ /**
2360
+ * Get the plugin required/recommended text string.
2361
+ *
2362
+ * @since 2.5.0
2363
+ *
2364
+ * @param string $required Plugin required setting.
2365
+ * @return string
2366
+ */
2367
+ protected function get_plugin_advise_type_text( $required ) {
2368
+ if ( true === $required ) {
2369
+ return __( 'Required', 'tgmpa' );
2370
+ }
2371
+
2372
+ return __( 'Recommended', 'tgmpa' );
2373
+ }
2374
+
2375
+ /**
2376
+ * Get the plugin source type text string.
2377
+ *
2378
+ * @since 2.5.0
2379
+ *
2380
+ * @param string $type Plugin type.
2381
+ * @return string
2382
+ */
2383
+ protected function get_plugin_source_type_text( $type ) {
2384
+ $string = '';
2385
+
2386
+ switch ( $type ) {
2387
+ case 'repo':
2388
+ $string = __( 'WordPress Repository', 'tgmpa' );
2389
+ break;
2390
+ case 'external':
2391
+ $string = __( 'External Source', 'tgmpa' );
2392
+ break;
2393
+ case 'bundled':
2394
+ $string = __( 'Pre-Packaged', 'tgmpa' );
2395
+ break;
2396
+ }
2397
+
2398
+ return $string;
2399
+ }
2400
+
2401
+ /**
2402
+ * Determine the plugin status message.
2403
+ *
2404
+ * @since 2.5.0
2405
+ *
2406
+ * @param string $slug Plugin slug.
2407
+ * @return string
2408
+ */
2409
+ protected function get_plugin_status_text( $slug ) {
2410
+ if ( ! $this->tgmpa->is_plugin_installed( $slug ) ) {
2411
+ return __( 'Not Installed', 'tgmpa' );
2412
+ }
2413
+
2414
+ if ( ! $this->tgmpa->is_plugin_active( $slug ) ) {
2415
+ $install_status = __( 'Installed But Not Activated', 'tgmpa' );
2416
+ } else {
2417
+ $install_status = __( 'Active', 'tgmpa' );
2418
+ }
2419
+
2420
+ $update_status = '';
2421
+
2422
+ if ( $this->tgmpa->does_plugin_require_update( $slug ) && false === $this->tgmpa->does_plugin_have_update( $slug ) ) {
2423
+ $update_status = __( 'Required Update not Available', 'tgmpa' );
2424
+
2425
+ } elseif ( $this->tgmpa->does_plugin_require_update( $slug ) ) {
2426
+ $update_status = __( 'Requires Update', 'tgmpa' );
2427
+
2428
+ } elseif ( false !== $this->tgmpa->does_plugin_have_update( $slug ) ) {
2429
+ $update_status = __( 'Update recommended', 'tgmpa' );
2430
+ }
2431
+
2432
+ if ( '' === $update_status ) {
2433
+ return $install_status;
2434
+ }
2435
+
2436
+ return sprintf(
2437
+ /* translators: 1: install status, 2: update status */
2438
+ _x( '%1$s, %2$s', 'Install/Update Status', 'tgmpa' ),
2439
+ $install_status,
2440
+ $update_status
2441
+ );
2442
+ }
2443
+
2444
+ /**
2445
+ * Sort plugins by Required/Recommended type and by alphabetical plugin name within each type.
2446
+ *
2447
+ * @since 2.5.0
2448
+ *
2449
+ * @param array $items Prepared table items.
2450
+ * @return array Sorted table items.
2451
+ */
2452
+ public function sort_table_items( $items ) {
2453
+ $type = array();
2454
+ $name = array();
2455
+
2456
+ foreach ( $items as $i => $plugin ) {
2457
+ $type[ $i ] = $plugin['type']; // Required / recommended.
2458
+ $name[ $i ] = $plugin['sanitized_plugin'];
2459
+ }
2460
+
2461
+ array_multisort( $type, SORT_DESC, $name, SORT_ASC, $items );
2462
+
2463
+ return $items;
2464
+ }
2465
+
2466
+ /**
2467
+ * Get an associative array ( id => link ) of the views available on this table.
2468
+ *
2469
+ * @since 2.5.0
2470
+ *
2471
+ * @return array
2472
+ */
2473
+ public function get_views() {
2474
+ $status_links = array();
2475
+
2476
+ foreach ( $this->view_totals as $type => $count ) {
2477
+ if ( $count < 1 ) {
2478
+ continue;
2479
+ }
2480
+
2481
+ switch ( $type ) {
2482
+ case 'all':
2483
+ /* translators: 1: number of plugins. */
2484
+ $text = _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $count, 'plugins', 'tgmpa' );
2485
+ break;
2486
+ case 'install':
2487
+ /* translators: 1: number of plugins. */
2488
+ $text = _n( 'To Install <span class="count">(%s)</span>', 'To Install <span class="count">(%s)</span>', $count, 'tgmpa' );
2489
+ break;
2490
+ case 'update':
2491
+ /* translators: 1: number of plugins. */
2492
+ $text = _n( 'Update Available <span class="count">(%s)</span>', 'Update Available <span class="count">(%s)</span>', $count, 'tgmpa' );
2493
+ break;
2494
+ case 'activate':
2495
+ /* translators: 1: number of plugins. */
2496
+ $text = _n( 'To Activate <span class="count">(%s)</span>', 'To Activate <span class="count">(%s)</span>', $count, 'tgmpa' );
2497
+ break;
2498
+ default:
2499
+ $text = '';
2500
+ break;
2501
+ }
2502
+
2503
+ if ( ! empty( $text ) ) {
2504
+
2505
+ $status_links[ $type ] = sprintf(
2506
+ '<a href="%s"%s>%s</a>',
2507
+ esc_url( $this->tgmpa->get_tgmpa_status_url( $type ) ),
2508
+ ( $type === $this->view_context ) ? ' class="current"' : '',
2509
+ sprintf( $text, number_format_i18n( $count ) )
2510
+ );
2511
+ }
2512
+ }
2513
+
2514
+ return $status_links;
2515
+ }
2516
+
2517
+ /**
2518
+ * Create default columns to display important plugin information
2519
+ * like type, action and status.
2520
+ *
2521
+ * @since 2.2.0
2522
+ *
2523
+ * @param array $item Array of item data.
2524
+ * @param string $column_name The name of the column.
2525
+ * @return string
2526
+ */
2527
+ public function column_default( $item, $column_name ) {
2528
+ return $item[ $column_name ];
2529
+ }
2530
+
2531
+ /**
2532
+ * Required for bulk installing.
2533
+ *
2534
+ * Adds a checkbox for each plugin.
2535
+ *
2536
+ * @since 2.2.0
2537
+ *
2538
+ * @param array $item Array of item data.
2539
+ * @return string The input checkbox with all necessary info.
2540
+ */
2541
+ public function column_cb( $item ) {
2542
+ return sprintf(
2543
+ '<input type="checkbox" name="%1$s[]" value="%2$s" id="%3$s" />',
2544
+ esc_attr( $this->_args['singular'] ),
2545
+ esc_attr( $item['slug'] ),
2546
+ esc_attr( $item['sanitized_plugin'] )
2547
+ );
2548
+ }
2549
+
2550
+ /**
2551
+ * Create default title column along with the action links.
2552
+ *
2553
+ * @since 2.2.0
2554
+ *
2555
+ * @param array $item Array of item data.
2556
+ * @return string The plugin name and action links.
2557
+ */
2558
+ public function column_plugin( $item ) {
2559
+ return sprintf(
2560
+ '%1$s %2$s',
2561
+ $item['plugin'],
2562
+ $this->row_actions( $this->get_row_actions( $item ), true )
2563
+ );
2564
+ }
2565
+
2566
+ /**
2567
+ * Create version information column.
2568
+ *
2569
+ * @since 2.5.0
2570
+ *
2571
+ * @param array $item Array of item data.
2572
+ * @return string HTML-formatted version information.
2573
+ */
2574
+ public function column_version( $item ) {
2575
+ $output = array();
2576
+
2577
+ if ( $this->tgmpa->is_plugin_installed( $item['slug'] ) ) {
2578
+ $installed = ! empty( $item['installed_version'] ) ? $item['installed_version'] : _x( 'unknown', 'as in: "version nr unknown"', 'tgmpa' );
2579
+
2580
+ $color = '';
2581
+ if ( ! empty( $item['minimum_version'] ) && $this->tgmpa->does_plugin_require_update( $item['slug'] ) ) {
2582
+ $color = ' color: #ff0000; font-weight: bold;';
2583
+ }
2584
+
2585
+ $output[] = sprintf(
2586
+ '<p><span style="min-width: 32px; text-align: right; float: right;%1$s">%2$s</span>' . __( 'Installed version:', 'tgmpa' ) . '</p>',
2587
+ $color,
2588
+ $installed
2589
+ );
2590
+ }
2591
+
2592
+ if ( ! empty( $item['minimum_version'] ) ) {
2593
+ $output[] = sprintf(
2594
+ '<p><span style="min-width: 32px; text-align: right; float: right;">%1$s</span>' . __( 'Minimum required version:', 'tgmpa' ) . '</p>',
2595
+ $item['minimum_version']
2596
+ );
2597
+ }
2598
+
2599
+ if ( ! empty( $item['available_version'] ) ) {
2600
+ $color = '';
2601
+ if ( ! empty( $item['minimum_version'] ) && version_compare( $item['available_version'], $item['minimum_version'], '>=' ) ) {
2602
+ $color = ' color: #71C671; font-weight: bold;';
2603
+ }
2604
+
2605
+ $output[] = sprintf(
2606
+ '<p><span style="min-width: 32px; text-align: right; float: right;%1$s">%2$s</span>' . __( 'Available version:', 'tgmpa' ) . '</p>',
2607
+ $color,
2608
+ $item['available_version']
2609
+ );
2610
+ }
2611
+
2612
+ if ( empty( $output ) ) {
2613
+ return '&nbsp;'; // Let's not break the table layout.
2614
+ } else {
2615
+ return implode( "\n", $output );
2616
+ }
2617
+ }
2618
+
2619
+ /**
2620
+ * Sets default message within the plugins table if no plugins
2621
+ * are left for interaction.
2622
+ *
2623
+ * Hides the menu item to prevent the user from clicking and
2624
+ * getting a permissions error.
2625
+ *
2626
+ * @since 2.2.0
2627
+ */
2628
+ public function no_items() {
2629
+ echo esc_html__( 'No plugins to install, update or activate.', 'tgmpa' ) . ' <a href="' . esc_url( self_admin_url() ) . '"> ' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '</a>';
2630
+ echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
2631
+ }
2632
+
2633
+ /**
2634
+ * Output all the column information within the table.
2635
+ *
2636
+ * @since 2.2.0
2637
+ *
2638
+ * @return array $columns The column names.
2639
+ */
2640
+ public function get_columns() {
2641
+ $columns = array(
2642
+ 'cb' => '<input type="checkbox" />',
2643
+ 'plugin' => __( 'Plugin', 'tgmpa' ),
2644
+ 'source' => __( 'Source', 'tgmpa' ),
2645
+ 'type' => __( 'Type', 'tgmpa' ),
2646
+ );
2647
+
2648
+ if ( 'all' === $this->view_context || 'update' === $this->view_context ) {
2649
+ $columns['version'] = __( 'Version', 'tgmpa' );
2650
+ $columns['status'] = __( 'Status', 'tgmpa' );
2651
+ }
2652
+
2653
+ return apply_filters( 'tgmpa_table_columns', $columns );
2654
+ }
2655
+
2656
+ /**
2657
+ * Get name of default primary column
2658
+ *
2659
+ * @since 2.5.0 / WP 4.3+ compatibility
2660
+ * @access protected
2661
+ *
2662
+ * @return string
2663
+ */
2664
+ protected function get_default_primary_column_name() {
2665
+ return 'plugin';
2666
+ }
2667
+
2668
+ /**
2669
+ * Get the name of the primary column.
2670
+ *
2671
+ * @since 2.5.0 / WP 4.3+ compatibility
2672
+ * @access protected
2673
+ *
2674
+ * @return string The name of the primary column.
2675
+ */
2676
+ protected function get_primary_column_name() {
2677
+ if ( method_exists( 'WP_List_Table', 'get_primary_column_name' ) ) {
2678
+ return parent::get_primary_column_name();
2679
+ } else {
2680
+ return $this->get_default_primary_column_name();
2681
+ }
2682
+ }
2683
+
2684
+ /**
2685
+ * Get the actions which are relevant for a specific plugin row.
2686
+ *
2687
+ * @since 2.5.0
2688
+ *
2689
+ * @param array $item Array of item data.
2690
+ * @return array Array with relevant action links.
2691
+ */
2692
+ protected function get_row_actions( $item ) {
2693
+ $actions = array();
2694
+ $action_links = array();
2695
+
2696
+ // Display the 'Install' action link if the plugin is not yet available.
2697
+ if ( ! $this->tgmpa->is_plugin_installed( $item['slug'] ) ) {
2698
+ /* translators: %2$s: plugin name in screen reader markup */
2699
+ $actions['install'] = __( 'Install %2$s', 'tgmpa' );
2700
+ } else {
2701
+ // Display the 'Update' action link if an update is available and WP complies with plugin minimum.
2702
+ if ( false !== $this->tgmpa->does_plugin_have_update( $item['slug'] ) && $this->tgmpa->can_plugin_update( $item['slug'] ) ) {
2703
+ /* translators: %2$s: plugin name in screen reader markup */
2704
+ $actions['update'] = __( 'Update %2$s', 'tgmpa' );
2705
+ }
2706
+
2707
+ // Display the 'Activate' action link, but only if the plugin meets the minimum version.
2708
+ if ( $this->tgmpa->can_plugin_activate( $item['slug'] ) ) {
2709
+ /* translators: %2$s: plugin name in screen reader markup */
2710
+ $actions['activate'] = __( 'Activate %2$s', 'tgmpa' );
2711
+ }
2712
+ }
2713
+
2714
+ // Create the actual links.
2715
+ foreach ( $actions as $action => $text ) {
2716
+ $nonce_url = wp_nonce_url(
2717
+ add_query_arg(
2718
+ array(
2719
+ 'plugin' => urlencode( $item['slug'] ),
2720
+ 'tgmpa-' . $action => $action . '-plugin',
2721
+ ),
2722
+ $this->tgmpa->get_tgmpa_url()
2723
+ ),
2724
+ 'tgmpa-' . $action,
2725
+ 'tgmpa-nonce'
2726
+ );
2727
+
2728
+ $action_links[ $action ] = sprintf(
2729
+ '<a href="%1$s">' . esc_html( $text ) . '</a>', // $text contains the second placeholder.
2730
+ esc_url( $nonce_url ),
2731
+ '<span class="screen-reader-text">' . esc_html( $item['sanitized_plugin'] ) . '</span>'
2732
+ );
2733
+ }
2734
+
2735
+ $prefix = ( defined( 'WP_NETWORK_ADMIN' ) && WP_NETWORK_ADMIN ) ? 'network_admin_' : '';
2736
+ return apply_filters( "tgmpa_{$prefix}plugin_action_links", array_filter( $action_links ), $item['slug'], $item, $this->view_context );
2737
+ }
2738
+
2739
+ /**
2740
+ * Generates content for a single row of the table.
2741
+ *
2742
+ * @since 2.5.0
2743
+ *
2744
+ * @param object $item The current item.
2745
+ */
2746
+ public function single_row( $item ) {
2747
+ parent::single_row( $item );
2748
+
2749
+ /**
2750
+ * Fires after each specific row in the TGMPA Plugins list table.
2751
+ *
2752
+ * The dynamic portion of the hook name, `$item['slug']`, refers to the slug
2753
+ * for the plugin.
2754
+ *
2755
+ * @since 2.5.0
2756
+ */
2757
+ do_action( "tgmpa_after_plugin_row_{$item['slug']}", $item['slug'], $item, $this->view_context );
2758
+ }
2759
+
2760
+ /**
2761
+ * Show the upgrade notice below a plugin row if there is one.
2762
+ *
2763
+ * @since 2.5.0
2764
+ *
2765
+ * @see /wp-admin/includes/update.php
2766
+ *
2767
+ * @param string $slug Plugin slug.
2768
+ * @param array $item The information available in this table row.
2769
+ * @return null Return early if upgrade notice is empty.
2770
+ */
2771
+ public function wp_plugin_update_row( $slug, $item ) {
2772
+ if ( empty( $item['upgrade_notice'] ) ) {
2773
+ return;
2774
+ }
2775
+
2776
+ echo '
2777
+ <tr class="plugin-update-tr">
2778
+ <td colspan="', absint( $this->get_column_count() ), '" class="plugin-update colspanchange">
2779
+ <div class="update-message">',
2780
+ esc_html__( 'Upgrade message from the plugin author:', 'tgmpa' ),
2781
+ ' <strong>', wp_kses_data( $item['upgrade_notice'] ), '</strong>
2782
+ </div>
2783
+ </td>
2784
+ </tr>';
2785
+ }
2786
+
2787
+ /**
2788
+ * Extra controls to be displayed between bulk actions and pagination.
2789
+ *
2790
+ * @since 2.5.0
2791
+ *
2792
+ * @param string $which 'top' or 'bottom' table navigation.
2793
+ */
2794
+ public function extra_tablenav( $which ) {
2795
+ if ( 'bottom' === $which ) {
2796
+ $this->tgmpa->show_tgmpa_version();
2797
+ }
2798
+ }
2799
+
2800
+ /**
2801
+ * Defines the bulk actions for handling registered plugins.
2802
+ *
2803
+ * @since 2.2.0
2804
+ *
2805
+ * @return array $actions The bulk actions for the plugin install table.
2806
+ */
2807
+ public function get_bulk_actions() {
2808
+
2809
+ $actions = array();
2810
+
2811
+ if ( 'update' !== $this->view_context && 'activate' !== $this->view_context ) {
2812
+ if ( current_user_can( 'install_plugins' ) ) {
2813
+ $actions['tgmpa-bulk-install'] = __( 'Install', 'tgmpa' );
2814
+ }
2815
+ }
2816
+
2817
+ if ( 'install' !== $this->view_context ) {
2818
+ if ( current_user_can( 'update_plugins' ) ) {
2819
+ $actions['tgmpa-bulk-update'] = __( 'Update', 'tgmpa' );
2820
+ }
2821
+ if ( current_user_can( 'activate_plugins' ) ) {
2822
+ $actions['tgmpa-bulk-activate'] = __( 'Activate', 'tgmpa' );
2823
+ }
2824
+ }
2825
+
2826
+ return $actions;
2827
+ }
2828
+
2829
+ /**
2830
+ * Processes bulk installation and activation actions.
2831
+ *
2832
+ * The bulk installation process looks for the $_POST information and passes that
2833
+ * through if a user has to use WP_Filesystem to enter their credentials.
2834
+ *
2835
+ * @since 2.2.0
2836
+ */
2837
+ public function process_bulk_actions() {
2838
+ // Bulk installation process.
2839
+ if ( 'tgmpa-bulk-install' === $this->current_action() || 'tgmpa-bulk-update' === $this->current_action() ) {
2840
+
2841
+ check_admin_referer( 'bulk-' . $this->_args['plural'] );
2842
+
2843
+ $install_type = 'install';
2844
+ if ( 'tgmpa-bulk-update' === $this->current_action() ) {
2845
+ $install_type = 'update';
2846
+ }
2847
+
2848
+ $plugins_to_install = array();
2849
+
2850
+ // Did user actually select any plugins to install/update ?
2851
+ if ( empty( $_POST['plugin'] ) ) {
2852
+ if ( 'install' === $install_type ) {
2853
+ $message = __( 'No plugins were selected to be installed. No action taken.', 'tgmpa' );
2854
+ } else {
2855
+ $message = __( 'No plugins were selected to be updated. No action taken.', 'tgmpa' );
2856
+ }
2857
+
2858
+ echo '<div id="message" class="error"><p>', esc_html( $message ), '</p></div>';
2859
+
2860
+ return false;
2861
+ }
2862
+
2863
+ if ( is_array( $_POST['plugin'] ) ) {
2864
+ $plugins_to_install = (array) $_POST['plugin'];
2865
+ } elseif ( is_string( $_POST['plugin'] ) ) {
2866
+ // Received via Filesystem page - un-flatten array (WP bug #19643).
2867
+ $plugins_to_install = explode( ',', $_POST['plugin'] );
2868
+ }
2869
+
2870
+ // Sanitize the received input.
2871
+ $plugins_to_install = array_map( 'urldecode', $plugins_to_install );
2872
+ $plugins_to_install = array_map( array( $this->tgmpa, 'sanitize_key' ), $plugins_to_install );
2873
+
2874
+ // Validate the received input.
2875
+ foreach ( $plugins_to_install as $key => $slug ) {
2876
+ // Check if the plugin was registered with TGMPA and remove if not.
2877
+ if ( ! isset( $this->tgmpa->plugins[ $slug ] ) ) {
2878
+ unset( $plugins_to_install[ $key ] );
2879
+ continue;
2880
+ }
2881
+
2882
+ // For install: make sure this is a plugin we *can* install and not one already installed.
2883
+ if ( 'install' === $install_type && true === $this->tgmpa->is_plugin_installed( $slug ) ) {
2884
+ unset( $plugins_to_install[ $key ] );
2885
+ }
2886
+
2887
+ // For updates: make sure this is a plugin we *can* update (update available and WP version ok).
2888
+ if ( 'update' === $install_type && false === $this->tgmpa->is_plugin_updatetable( $slug ) ) {
2889
+ unset( $plugins_to_install[ $key ] );
2890
+ }
2891
+ }
2892
+
2893
+ // No need to proceed further if we have no plugins to handle.
2894
+ if ( empty( $plugins_to_install ) ) {
2895
+ if ( 'install' === $install_type ) {
2896
+ $message = __( 'No plugins are available to be installed at this time.', 'tgmpa' );
2897
+ } else {
2898
+ $message = __( 'No plugins are available to be updated at this time.', 'tgmpa' );
2899
+ }
2900
+
2901
+ echo '<div id="message" class="error"><p>', esc_html( $message ), '</p></div>';
2902
+
2903
+ return false;
2904
+ }
2905
+
2906
+ // Pass all necessary information if WP_Filesystem is needed.
2907
+ $url = wp_nonce_url(
2908
+ $this->tgmpa->get_tgmpa_url(),
2909
+ 'bulk-' . $this->_args['plural']
2910
+ );
2911
+
2912
+ // Give validated data back to $_POST which is the only place the filesystem looks for extra fields.
2913
+ $_POST['plugin'] = implode( ',', $plugins_to_install ); // Work around for WP bug #19643.
2914
+
2915
+ $method = ''; // Leave blank so WP_Filesystem can populate it as necessary.
2916
+ $fields = array_keys( $_POST ); // Extra fields to pass to WP_Filesystem.
2917
+
2918
+ if ( false === ( $creds = request_filesystem_credentials( esc_url_raw( $url ), $method, false, false, $fields ) ) ) {
2919
+ return true; // Stop the normal page form from displaying, credential request form will be shown.
2920
+ }
2921
+
2922
+ // Now we have some credentials, setup WP_Filesystem.
2923
+ if ( ! WP_Filesystem( $creds ) ) {
2924
+ // Our credentials were no good, ask the user for them again.
2925
+ request_filesystem_credentials( esc_url_raw( $url ), $method, true, false, $fields );
2926
+
2927
+ return true;
2928
+ }
2929
+
2930
+ /* If we arrive here, we have the filesystem */
2931
+
2932
+ // Store all information in arrays since we are processing a bulk installation.
2933
+ $names = array();
2934
+ $sources = array(); // Needed for installs.
2935
+ $file_paths = array(); // Needed for upgrades.
2936
+ $to_inject = array(); // Information to inject into the update_plugins transient.
2937
+
2938
+ // Prepare the data for validated plugins for the install/upgrade.
2939
+ foreach ( $plugins_to_install as $slug ) {
2940
+ $name = $this->tgmpa->plugins[ $slug ]['name'];
2941
+ $source = $this->tgmpa->get_download_url( $slug );
2942
+
2943
+ if ( ! empty( $name ) && ! empty( $source ) ) {
2944
+ $names[] = $name;
2945
+
2946
+ switch ( $install_type ) {
2947
+
2948
+ case 'install':
2949
+ $sources[] = $source;
2950
+ break;
2951
+
2952
+ case 'update':
2953
+ $file_paths[] = $this->tgmpa->plugins[ $slug ]['file_path'];
2954
+ $to_inject[ $slug ] = $this->tgmpa->plugins[ $slug ];
2955
+ $to_inject[ $slug ]['source'] = $source;
2956
+ break;
2957
+ }
2958
+ }
2959
+ }
2960
+ unset( $slug, $name, $source );
2961
+
2962
+ // Create a new instance of TGMPA_Bulk_Installer.
2963
+ $installer = new TGMPA_Bulk_Installer(
2964
+ new TGMPA_Bulk_Installer_Skin(
2965
+ array(
2966
+ 'url' => esc_url_raw( $this->tgmpa->get_tgmpa_url() ),
2967
+ 'nonce' => 'bulk-' . $this->_args['plural'],
2968
+ 'names' => $names,
2969
+ 'install_type' => $install_type,
2970
+ )
2971
+ )
2972
+ );
2973
+
2974
+ // Wrap the install process with the appropriate HTML.
2975
+ echo '<div class="tgmpa">',
2976
+ '<h2 style="font-size: 23px; font-weight: 400; line-height: 29px; margin: 0; padding: 9px 15px 4px 0;">', esc_html( get_admin_page_title() ), '</h2>
2977
+ <div class="update-php" style="width: 100%; height: 98%; min-height: 850px; padding-top: 1px;">';
2978
+
2979
+ // Process the bulk installation submissions.
2980
+ add_filter( 'upgrader_source_selection', array( $this->tgmpa, 'maybe_adjust_source_dir' ), 1, 3 );
2981
+
2982
+ if ( 'tgmpa-bulk-update' === $this->current_action() ) {
2983
+ // Inject our info into the update transient.
2984
+ $this->tgmpa->inject_update_info( $to_inject );
2985
+
2986
+ $installer->bulk_upgrade( $file_paths );
2987
+ } else {
2988
+ $installer->bulk_install( $sources );
2989
+ }
2990
+
2991
+ remove_filter( 'upgrader_source_selection', array( $this->tgmpa, 'maybe_adjust_source_dir' ), 1 );
2992
+
2993
+ echo '</div></div>';
2994
+
2995
+ return true;
2996
+ }
2997
+
2998
+ // Bulk activation process.
2999
+ if ( 'tgmpa-bulk-activate' === $this->current_action() ) {
3000
+ check_admin_referer( 'bulk-' . $this->_args['plural'] );
3001
+
3002
+ // Did user actually select any plugins to activate ?
3003
+ if ( empty( $_POST['plugin'] ) ) {
3004
+ echo '<div id="message" class="error"><p>', esc_html__( 'No plugins were selected to be activated. No action taken.', 'tgmpa' ), '</p></div>';
3005
+
3006
+ return false;
3007
+ }
3008
+
3009
+ // Grab plugin data from $_POST.
3010
+ $plugins = array();
3011
+ if ( isset( $_POST['plugin'] ) ) {
3012
+ $plugins = array_map( 'urldecode', (array) $_POST['plugin'] );
3013
+ $plugins = array_map( array( $this->tgmpa, 'sanitize_key' ), $plugins );
3014
+ }
3015
+
3016
+ $plugins_to_activate = array();
3017
+ $plugin_names = array();
3018
+
3019
+ // Grab the file paths for the selected & inactive plugins from the registration array.
3020
+ foreach ( $plugins as $slug ) {
3021
+ if ( $this->tgmpa->can_plugin_activate( $slug ) ) {
3022
+ $plugins_to_activate[] = $this->tgmpa->plugins[ $slug ]['file_path'];
3023
+ $plugin_names[] = $this->tgmpa->plugins[ $slug ]['name'];
3024
+ }
3025
+ }
3026
+ unset( $slug );
3027
+
3028
+ // Return early if there are no plugins to activate.
3029
+ if ( empty( $plugins_to_activate ) ) {
3030
+ echo '<div id="message" class="error"><p>', esc_html__( 'No plugins are available to be activated at this time.', 'tgmpa' ), '</p></div>';
3031
+
3032
+ return false;
3033
+ }
3034
+
3035
+ // Now we are good to go - let's start activating plugins.
3036
+ $activate = activate_plugins( $plugins_to_activate );
3037
+
3038
+ if ( is_wp_error( $activate ) ) {
3039
+ echo '<div id="message" class="error"><p>', wp_kses_post( $activate->get_error_message() ), '</p></div>';
3040
+ } else {
3041
+ $count = count( $plugin_names ); // Count so we can use _n function.
3042
+ $plugin_names = array_map( array( 'TGMPA_Utils', 'wrap_in_strong' ), $plugin_names );
3043
+ $last_plugin = array_pop( $plugin_names ); // Pop off last name to prep for readability.
3044
+ $imploded = empty( $plugin_names ) ? $last_plugin : ( implode( ', ', $plugin_names ) . ' ' . esc_html_x( 'and', 'plugin A *and* plugin B', 'tgmpa' ) . ' ' . $last_plugin );
3045
+
3046
+ printf( // WPCS: xss ok.
3047
+ '<div id="message" class="updated"><p>%1$s %2$s.</p></div>',
3048
+ esc_html( _n( 'The following plugin was activated successfully:', 'The following plugins were activated successfully:', $count, 'tgmpa' ) ),
3049
+ $imploded
3050
+ );
3051
+
3052
+ // Update recently activated plugins option.
3053
+ $recent = (array) get_option( 'recently_activated' );
3054
+ foreach ( $plugins_to_activate as $plugin => $time ) {
3055
+ if ( isset( $recent[ $plugin ] ) ) {
3056
+ unset( $recent[ $plugin ] );
3057
+ }
3058
+ }
3059
+ update_option( 'recently_activated', $recent );
3060
+ }
3061
+
3062
+ unset( $_POST ); // Reset the $_POST variable in case user wants to perform one action after another.
3063
+
3064
+ return true;
3065
+ }
3066
+
3067
+ return false;
3068
+ }
3069
+
3070
+ /**
3071
+ * Prepares all of our information to be outputted into a usable table.
3072
+ *
3073
+ * @since 2.2.0
3074
+ */
3075
+ public function prepare_items() {
3076
+ $columns = $this->get_columns(); // Get all necessary column information.
3077
+ $hidden = array(); // No columns to hide, but we must set as an array.
3078
+ $sortable = array(); // No reason to make sortable columns.
3079
+ $primary = $this->get_primary_column_name(); // Column which has the row actions.
3080
+ $this->_column_headers = array( $columns, $hidden, $sortable, $primary ); // Get all necessary column headers.
3081
+
3082
+ // Process our bulk activations here.
3083
+ if ( 'tgmpa-bulk-activate' === $this->current_action() ) {
3084
+ $this->process_bulk_actions();
3085
+ }
3086
+
3087
+ // Store all of our plugin data into $items array so WP_List_Table can use it.
3088
+ $this->items = apply_filters( 'tgmpa_table_data_items', $this->_gather_plugin_data() );
3089
+ }
3090
+
3091
+ /* *********** DEPRECATED METHODS *********** */
3092
+
3093
+ /**
3094
+ * Retrieve plugin data, given the plugin name.
3095
+ *
3096
+ * @since 2.2.0
3097
+ * @deprecated 2.5.0 use {@see TGM_Plugin_Activation::_get_plugin_data_from_name()} instead.
3098
+ * @see TGM_Plugin_Activation::_get_plugin_data_from_name()
3099
+ *
3100
+ * @param string $name Name of the plugin, as it was registered.
3101
+ * @param string $data Optional. Array key of plugin data to return. Default is slug.
3102
+ * @return string|boolean Plugin slug if found, false otherwise.
3103
+ */
3104
+ protected function _get_plugin_data_from_name( $name, $data = 'slug' ) {
3105
+ _deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'TGM_Plugin_Activation::_get_plugin_data_from_name()' );
3106
+
3107
+ return $this->tgmpa->_get_plugin_data_from_name( $name, $data );
3108
+ }
3109
+ }
3110
+ }
3111
+
3112
+
3113
+ if ( ! class_exists( 'TGM_Bulk_Installer' ) ) {
3114
+
3115
+ /**
3116
+ * Hack: Prevent TGMPA v2.4.1- bulk installer class from being loaded if 2.4.1- is loaded after 2.5+.
3117
+ *
3118
+ * @since 2.5.2
3119
+ *
3120
+ * {@internal The TGMPA_Bulk_Installer class was originally called TGM_Bulk_Installer.
3121
+ * For more information, see that class.}}
3122
+ */
3123
+ class TGM_Bulk_Installer {
3124
+ }
3125
+ }
3126
+
3127
+ if ( ! class_exists( 'TGM_Bulk_Installer_Skin' ) ) {
3128
+
3129
+ /**
3130
+ * Hack: Prevent TGMPA v2.4.1- bulk installer skin class from being loaded if 2.4.1- is loaded after 2.5+.
3131
+ *
3132
+ * @since 2.5.2
3133
+ *
3134
+ * {@internal The TGMPA_Bulk_Installer_Skin class was originally called TGM_Bulk_Installer_Skin.
3135
+ * For more information, see that class.}}
3136
+ */
3137
+ class TGM_Bulk_Installer_Skin {
3138
+ }
3139
+ }
3140
+
3141
+ /**
3142
+ * The WP_Upgrader file isn't always available. If it isn't available,
3143
+ * we load it here.
3144
+ *
3145
+ * We check to make sure no action or activation keys are set so that WordPress
3146
+ * does not try to re-include the class when processing upgrades or installs outside
3147
+ * of the class.
3148
+ *
3149
+ * @since 2.2.0
3150
+ */
3151
+ add_action( 'admin_init', 'WPMailSMTP\tgmpa_load_bulk_installer' );
3152
+ if ( ! function_exists( 'tgmpa_load_bulk_installer' ) ) {
3153
+ /**
3154
+ * Load bulk installer
3155
+ */
3156
+ function tgmpa_load_bulk_installer() {
3157
+ // Silently fail if 2.5+ is loaded *after* an older version.
3158
+ if ( ! isset( $GLOBALS['wp_mail_smtp_tgmpa'] ) ) {
3159
+ return;
3160
+ }
3161
+
3162
+ // Get TGMPA class instance.
3163
+ $tgmpa_instance = call_user_func( array( get_class( $GLOBALS['wp_mail_smtp_tgmpa'] ), 'get_instance' ) );
3164
+
3165
+ if ( isset( $_GET['page'] ) && $tgmpa_instance->menu === $_GET['page'] ) {
3166
+ if ( ! class_exists( '\Plugin_Upgrader', false ) ) {
3167
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
3168
+ }
3169
+
3170
+ if ( ! class_exists( 'TGMPA_Bulk_Installer' ) ) {
3171
+
3172
+ /**
3173
+ * Installer class to handle bulk plugin installations.
3174
+ *
3175
+ * Extends WP_Upgrader and customizes to suit the installation of multiple
3176
+ * plugins.
3177
+ *
3178
+ * @since 2.2.0
3179
+ *
3180
+ * {@internal Since 2.5.0 the class is an extension of Plugin_Upgrader rather than WP_Upgrader.}}
3181
+ * {@internal Since 2.5.2 the class has been renamed from TGM_Bulk_Installer to TGMPA_Bulk_Installer.
3182
+ * This was done to prevent backward compatibility issues with v2.3.6.}}
3183
+ *
3184
+ * @package TGM-Plugin-Activation
3185
+ * @author Thomas Griffin
3186
+ * @author Gary Jones
3187
+ */
3188
+ class TGMPA_Bulk_Installer extends \Plugin_Upgrader {
3189
+ /**
3190
+ * Holds result of bulk plugin installation.
3191
+ *
3192
+ * @since 2.2.0
3193
+ *
3194
+ * @var string
3195
+ */
3196
+ public $result;
3197
+
3198
+ /**
3199
+ * Flag to check if bulk installation is occurring or not.
3200
+ *
3201
+ * @since 2.2.0
3202
+ *
3203
+ * @var boolean
3204
+ */
3205
+ public $bulk = false;
3206
+
3207
+ /**
3208
+ * TGMPA instance
3209
+ *
3210
+ * @since 2.5.0
3211
+ *
3212
+ * @var object
3213
+ */
3214
+ protected $tgmpa;
3215
+
3216
+ /**
3217
+ * Whether or not the destination directory needs to be cleared ( = on update).
3218
+ *
3219
+ * @since 2.5.0
3220
+ *
3221
+ * @var bool
3222
+ */
3223
+ protected $clear_destination = false;
3224
+
3225
+ /**
3226
+ * References parent constructor and sets defaults for class.
3227
+ *
3228
+ * @since 2.2.0
3229
+ *
3230
+ * @param \Bulk_Upgrader_Skin|null $skin Installer skin.
3231
+ */
3232
+ public function __construct( $skin = null ) {
3233
+ // Get TGMPA class instance.
3234
+ $this->tgmpa = call_user_func( array( get_class( $GLOBALS['wp_mail_smtp_tgmpa'] ), 'get_instance' ) );
3235
+
3236
+ parent::__construct( $skin );
3237
+
3238
+ if ( isset( $this->skin->options['install_type'] ) && 'update' === $this->skin->options['install_type'] ) {
3239
+ $this->clear_destination = true;
3240
+ }
3241
+
3242
+ if ( $this->tgmpa->is_automatic ) {
3243
+ $this->activate_strings();
3244
+ }
3245
+
3246
+ add_action( 'upgrader_process_complete', array( $this->tgmpa, 'populate_file_path' ) );
3247
+ }
3248
+
3249
+ /**
3250
+ * Sets the correct activation strings for the installer skin to use.
3251
+ *
3252
+ * @since 2.2.0
3253
+ */
3254
+ public function activate_strings() {
3255
+ $this->strings['activation_failed'] = __( 'Plugin activation failed.', 'tgmpa' );
3256
+ $this->strings['activation_success'] = __( 'Plugin activated successfully.', 'tgmpa' );
3257
+ }
3258
+
3259
+ /**
3260
+ * Performs the actual installation of each plugin.
3261
+ *
3262
+ * @since 2.2.0
3263
+ *
3264
+ * @see WP_Upgrader::run()
3265
+ *
3266
+ * @param array $options The installation config options.
3267
+ * @return null|array Return early if error, array of installation data on success.
3268
+ */
3269
+ public function run( $options ) {
3270
+ $result = parent::run( $options );
3271
+
3272
+ // Reset the strings in case we changed one during automatic activation.
3273
+ if ( $this->tgmpa->is_automatic ) {
3274
+ if ( 'update' === $this->skin->options['install_type'] ) {
3275
+ $this->upgrade_strings();
3276
+ } else {
3277
+ $this->install_strings();
3278
+ }
3279
+ }
3280
+
3281
+ return $result;
3282
+ }
3283
+
3284
+ /**
3285
+ * Processes the bulk installation of plugins.
3286
+ *
3287
+ * @since 2.2.0
3288
+ *
3289
+ * {@internal This is basically a near identical copy of the WP Core
3290
+ * Plugin_Upgrader::bulk_upgrade() method, with minor adjustments to deal with
3291
+ * new installs instead of upgrades.
3292
+ * For ease of future synchronizations, the adjustments are clearly commented, but no other
3293
+ * comments are added. Code style has been made to comply.}}
3294
+ *
3295
+ * @see Plugin_Upgrader::bulk_upgrade()
3296
+ * @see https://core.trac.wordpress.org/browser/tags/4.2.1/src/wp-admin/includes/class-wp-upgrader.php#L838
3297
+ * (@internal Last synced: Dec 31st 2015 against https://core.trac.wordpress.org/browser/trunk?rev=36134}}
3298
+ *
3299
+ * @param array $plugins The plugin sources needed for installation.
3300
+ * @param array $args Arbitrary passed extra arguments.
3301
+ * @return array|false Install confirmation messages on success, false on failure.
3302
+ */
3303
+ public function bulk_install( $plugins, $args = array() ) {
3304
+ // [TGMPA + ] Hook auto-activation in.
3305
+ add_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
3306
+
3307
+ $defaults = array(
3308
+ 'clear_update_cache' => true,
3309
+ );
3310
+ $parsed_args = wp_parse_args( $args, $defaults );
3311
+
3312
+ $this->init();
3313
+ $this->bulk = true;
3314
+
3315
+ $this->install_strings(); // [TGMPA + ] adjusted.
3316
+
3317
+ /* [TGMPA - ] $current = get_site_transient( 'update_plugins' ); */
3318
+
3319
+ /* [TGMPA - ] add_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'), 10, 4); */
3320
+
3321
+ $this->skin->header();
3322
+
3323
+ // Connect to the Filesystem first.
3324
+ $res = $this->fs_connect( array( WP_CONTENT_DIR, WP_PLUGIN_DIR ) );
3325
+ if ( ! $res ) {
3326
+ $this->skin->footer();
3327
+ return false;
3328
+ }
3329
+
3330
+ $this->skin->bulk_header();
3331
+
3332
+ /*
3333
+ * Only start maintenance mode if:
3334
+ * - running Multisite and there are one or more plugins specified, OR
3335
+ * - a plugin with an update available is currently active.
3336
+ * @TODO: For multisite, maintenance mode should only kick in for individual sites if at all possible.
3337
+ */
3338
+ $maintenance = ( is_multisite() && ! empty( $plugins ) );
3339
+
3340
+ /*
3341
+ [TGMPA - ]
3342
+ foreach ( $plugins as $plugin )
3343
+ $maintenance = $maintenance || ( is_plugin_active( $plugin ) && isset( $current->response[ $plugin] ) );
3344
+ */
3345
+ if ( $maintenance ) {
3346
+ $this->maintenance_mode( true );
3347
+ }
3348
+
3349
+ $results = array();
3350
+
3351
+ $this->update_count = count( $plugins );
3352
+ $this->update_current = 0;
3353
+ foreach ( $plugins as $plugin ) {
3354
+ $this->update_current++;
3355
+
3356
+ /*
3357
+ [TGMPA - ]
3358
+ $this->skin->plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true);
3359
+
3360
+ if ( !isset( $current->response[ $plugin ] ) ) {
3361
+ $this->skin->set_result('up_to_date');
3362
+ $this->skin->before();
3363
+ $this->skin->feedback('up_to_date');
3364
+ $this->skin->after();
3365
+ $results[$plugin] = true;
3366
+ continue;
3367
+ }
3368
+
3369
+ // Get the URL to the zip file.
3370
+ $r = $current->response[ $plugin ];
3371
+
3372
+ $this->skin->plugin_active = is_plugin_active($plugin);
3373
+ */
3374
+
3375
+ $result = $this->run(
3376
+ array(
3377
+ 'package' => $plugin, // [TGMPA + ] adjusted.
3378
+ 'destination' => WP_PLUGIN_DIR,
3379
+ 'clear_destination' => false, // [TGMPA + ] adjusted.
3380
+ 'clear_working' => true,
3381
+ 'is_multi' => true,
3382
+ 'hook_extra' => array(
3383
+ 'plugin' => $plugin,
3384
+ ),
3385
+ )
3386
+ );
3387
+
3388
+ $results[ $plugin ] = $this->result;
3389
+
3390
+ // Prevent credentials auth screen from displaying multiple times.
3391
+ if ( false === $result ) {
3392
+ break;
3393
+ }
3394
+ } //end foreach $plugins
3395
+
3396
+ $this->maintenance_mode( false );
3397
+
3398
+ /**
3399
+ * Fires when the bulk upgrader process is complete.
3400
+ *
3401
+ * @since WP 3.6.0 / TGMPA 2.5.0
3402
+ *
3403
+ * @param \Plugin_Upgrader $this Plugin_Upgrader instance. In other contexts, $this, might
3404
+ * be a Theme_Upgrader or Core_Upgrade instance.
3405
+ * @param array $data {
3406
+ * Array of bulk item update data.
3407
+ *
3408
+ * @type string $action Type of action. Default 'update'.
3409
+ * @type string $type Type of update process. Accepts 'plugin', 'theme', or 'core'.
3410
+ * @type bool $bulk Whether the update process is a bulk update. Default true.
3411
+ * @type array $packages Array of plugin, theme, or core packages to update.
3412
+ * }
3413
+ */
3414
+ do_action( 'upgrader_process_complete', $this, array(
3415
+ 'action' => 'install', // [TGMPA + ] adjusted.
3416
+ 'type' => 'plugin',
3417
+ 'bulk' => true,
3418
+ 'plugins' => $plugins,
3419
+ ) );
3420
+
3421
+ $this->skin->bulk_footer();
3422
+
3423
+ $this->skin->footer();
3424
+
3425
+ // Cleanup our hooks, in case something else does a upgrade on this connection.
3426
+ /* [TGMPA - ] remove_filter('upgrader_clear_destination', array($this, 'delete_old_plugin')); */
3427
+
3428
+ // [TGMPA + ] Remove our auto-activation hook.
3429
+ remove_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
3430
+
3431
+ // Force refresh of plugin update information.
3432
+ wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );
3433
+
3434
+ return $results;
3435
+ }
3436
+
3437
+ /**
3438
+ * Handle a bulk upgrade request.
3439
+ *
3440
+ * @since 2.5.0
3441
+ *
3442
+ * @see Plugin_Upgrader::bulk_upgrade()
3443
+ *
3444
+ * @param array $plugins The local WP file_path's of the plugins which should be upgraded.
3445
+ * @param array $args Arbitrary passed extra arguments.
3446
+ * @return string|bool Install confirmation messages on success, false on failure.
3447
+ */
3448
+ public function bulk_upgrade( $plugins, $args = array() ) {
3449
+
3450
+ add_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
3451
+
3452
+ $result = parent::bulk_upgrade( $plugins, $args );
3453
+
3454
+ remove_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
3455
+
3456
+ return $result;
3457
+ }
3458
+
3459
+ /**
3460
+ * Abuse a filter to auto-activate plugins after installation.
3461
+ *
3462
+ * Hooked into the 'upgrader_post_install' filter hook.
3463
+ *
3464
+ * @since 2.5.0
3465
+ *
3466
+ * @param bool $bool The value we need to give back (true).
3467
+ * @return bool
3468
+ */
3469
+ public function auto_activate( $bool ) {
3470
+ // Only process the activation of installed plugins if the automatic flag is set to true.
3471
+ if ( $this->tgmpa->is_automatic ) {
3472
+ // Flush plugins cache so the headers of the newly installed plugins will be read correctly.
3473
+ wp_clean_plugins_cache();
3474
+
3475
+ // Get the installed plugin file.
3476
+ $plugin_info = $this->plugin_info();
3477
+
3478
+ // Don't try to activate on upgrade of active plugin as WP will do this already.
3479
+ if ( ! is_plugin_active( $plugin_info ) ) {
3480
+ $activate = activate_plugin( $plugin_info );
3481
+
3482
+ // Adjust the success string based on the activation result.
3483
+ $this->strings['process_success'] = $this->strings['process_success'] . "<br />\n";
3484
+
3485
+ if ( is_wp_error( $activate ) ) {
3486
+ $this->skin->error( $activate );
3487
+ $this->strings['process_success'] .= $this->strings['activation_failed'];
3488
+ } else {
3489
+ $this->strings['process_success'] .= $this->strings['activation_success'];
3490
+ }
3491
+ }
3492
+ }
3493
+
3494
+ return $bool;
3495
+ }
3496
+ }
3497
+ }
3498
+
3499
+ if ( ! class_exists( 'TGMPA_Bulk_Installer_Skin' ) ) {
3500
+
3501
+ /**
3502
+ * Installer skin to set strings for the bulk plugin installations..
3503
+ *
3504
+ * Extends Bulk_Upgrader_Skin and customizes to suit the installation of multiple
3505
+ * plugins.
3506
+ *
3507
+ * @since 2.2.0
3508
+ *
3509
+ * {@internal Since 2.5.2 the class has been renamed from TGM_Bulk_Installer_Skin to
3510
+ * TGMPA_Bulk_Installer_Skin.
3511
+ * This was done to prevent backward compatibility issues with v2.3.6.}}
3512
+ *
3513
+ * @see https://core.trac.wordpress.org/browser/trunk/src/wp-admin/includes/class-wp-upgrader-skins.php
3514
+ *
3515
+ * @package TGM-Plugin-Activation
3516
+ * @author Thomas Griffin
3517
+ * @author Gary Jones
3518
+ */
3519
+ class TGMPA_Bulk_Installer_Skin extends \Bulk_Upgrader_Skin {
3520
+ /**
3521
+ * Holds plugin info for each individual plugin installation.
3522
+ *
3523
+ * @since 2.2.0
3524
+ *
3525
+ * @var array
3526
+ */
3527
+ public $plugin_info = array();
3528
+
3529
+ /**
3530
+ * Holds names of plugins that are undergoing bulk installations.
3531
+ *
3532
+ * @since 2.2.0
3533
+ *
3534
+ * @var array
3535
+ */
3536
+ public $plugin_names = array();
3537
+
3538
+ /**
3539
+ * Integer to use for iteration through each plugin installation.
3540
+ *
3541
+ * @since 2.2.0
3542
+ *
3543
+ * @var integer
3544
+ */
3545
+ public $i = 0;
3546
+
3547
+ /**
3548
+ * TGMPA instance
3549
+ *
3550
+ * @since 2.5.0
3551
+ *
3552
+ * @var object
3553
+ */
3554
+ protected $tgmpa;
3555
+
3556
+ /**
3557
+ * Constructor. Parses default args with new ones and extracts them for use.
3558
+ *
3559
+ * @since 2.2.0
3560
+ *
3561
+ * @param array $args Arguments to pass for use within the class.
3562
+ */
3563
+ public function __construct( $args = array() ) {
3564
+ // Get TGMPA class instance.
3565
+ $this->tgmpa = call_user_func( array( get_class( $GLOBALS['wp_mail_smtp_tgmpa'] ), 'get_instance' ) );
3566
+
3567
+ // Parse default and new args.
3568
+ $defaults = array(
3569
+ 'url' => '',
3570
+ 'nonce' => '',
3571
+ 'names' => array(),
3572
+ 'install_type' => 'install',
3573
+ );
3574
+ $args = wp_parse_args( $args, $defaults );
3575
+
3576
+ // Set plugin names to $this->plugin_names property.
3577
+ $this->plugin_names = $args['names'];
3578
+
3579
+ // Extract the new args.
3580
+ parent::__construct( $args );
3581
+ }
3582
+
3583
+ /**
3584
+ * Sets install skin strings for each individual plugin.
3585
+ *
3586
+ * Checks to see if the automatic activation flag is set and uses the
3587
+ * the proper strings accordingly.
3588
+ *
3589
+ * @since 2.2.0
3590
+ */
3591
+ public function add_strings() {
3592
+ if ( 'update' === $this->options['install_type'] ) {
3593
+ parent::add_strings();
3594
+ /* translators: 1: plugin name, 2: action number 3: total number of actions. */
3595
+ $this->upgrader->strings['skin_before_update_header'] = __( 'Updating Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
3596
+ } else {
3597
+ /* translators: 1: plugin name, 2: error message. */
3598
+ $this->upgrader->strings['skin_update_failed_error'] = __( 'An error occurred while installing %1$s: <strong>%2$s</strong>.', 'tgmpa' );
3599
+ /* translators: 1: plugin name. */
3600
+ $this->upgrader->strings['skin_update_failed'] = __( 'The installation of %1$s failed.', 'tgmpa' );
3601
+
3602
+ if ( $this->tgmpa->is_automatic ) {
3603
+ // Automatic activation strings.
3604
+ $this->upgrader->strings['skin_upgrade_start'] = __( 'The installation and activation process is starting. This process may take a while on some hosts, so please be patient.', 'tgmpa' );
3605
+ /* translators: 1: plugin name. */
3606
+ $this->upgrader->strings['skin_update_successful'] = __( '%1$s installed and activated successfully.', 'tgmpa' ) . ' <a href="#" class="hide-if-no-js" onclick="%2$s"><span>' . esc_html__( 'Show Details', 'tgmpa' ) . '</span><span class="hidden">' . esc_html__( 'Hide Details', 'tgmpa' ) . '</span>.</a>';
3607
+ $this->upgrader->strings['skin_upgrade_end'] = __( 'All installations and activations have been completed.', 'tgmpa' );
3608
+ /* translators: 1: plugin name, 2: action number 3: total number of actions. */
3609
+ $this->upgrader->strings['skin_before_update_header'] = __( 'Installing and Activating Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
3610
+ } else {
3611
+ // Default installation strings.
3612
+ $this->upgrader->strings['skin_upgrade_start'] = __( 'The installation process is starting. This process may take a while on some hosts, so please be patient.', 'tgmpa' );
3613
+ /* translators: 1: plugin name. */
3614
+ $this->upgrader->strings['skin_update_successful'] = esc_html__( '%1$s installed successfully.', 'tgmpa' ) . ' <a href="#" class="hide-if-no-js" onclick="%2$s"><span>' . esc_html__( 'Show Details', 'tgmpa' ) . '</span><span class="hidden">' . esc_html__( 'Hide Details', 'tgmpa' ) . '</span>.</a>';
3615
+ $this->upgrader->strings['skin_upgrade_end'] = __( 'All installations have been completed.', 'tgmpa' );
3616
+ /* translators: 1: plugin name, 2: action number 3: total number of actions. */
3617
+ $this->upgrader->strings['skin_before_update_header'] = __( 'Installing Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
3618
+ }
3619
+ }
3620
+ }
3621
+
3622
+ /**
3623
+ * Outputs the header strings and necessary JS before each plugin installation.
3624
+ *
3625
+ * @since 2.2.0
3626
+ *
3627
+ * @param string $title Unused in this implementation.
3628
+ */
3629
+ public function before( $title = '' ) {
3630
+ if ( empty( $title ) ) {
3631
+ $title = esc_html( $this->plugin_names[ $this->i ] );
3632
+ }
3633
+ parent::before( $title );
3634
+ }
3635
+
3636
+ /**
3637
+ * Outputs the footer strings and necessary JS after each plugin installation.
3638
+ *
3639
+ * Checks for any errors and outputs them if they exist, else output
3640
+ * success strings.
3641
+ *
3642
+ * @since 2.2.0
3643
+ *
3644
+ * @param string $title Unused in this implementation.
3645
+ */
3646
+ public function after( $title = '' ) {
3647
+ if ( empty( $title ) ) {
3648
+ $title = esc_html( $this->plugin_names[ $this->i ] );
3649
+ }
3650
+ parent::after( $title );
3651
+
3652
+ $this->i++;
3653
+ }
3654
+
3655
+ /**
3656
+ * Outputs links after bulk plugin installation is complete.
3657
+ *
3658
+ * @since 2.2.0
3659
+ */
3660
+ public function bulk_footer() {
3661
+ // Serve up the string to say installations (and possibly activations) are complete.
3662
+ parent::bulk_footer();
3663
+
3664
+ // Flush plugins cache so we can make sure that the installed plugins list is always up to date.
3665
+ wp_clean_plugins_cache();
3666
+
3667
+ $this->tgmpa->show_tgmpa_version();
3668
+
3669
+ // Display message based on if all plugins are now active or not.
3670
+ $update_actions = array();
3671
+
3672
+ if ( $this->tgmpa->is_tgmpa_complete() ) {
3673
+ // All plugins are active, so we display the complete string and hide the menu to protect users.
3674
+ echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
3675
+ $update_actions['dashboard'] = sprintf(
3676
+ esc_html( $this->tgmpa->strings['complete'] ),
3677
+ '<a href="' . esc_url( self_admin_url() ) . '">' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '</a>'
3678
+ );
3679
+ } else {
3680
+ $update_actions['tgmpa_page'] = '<a href="' . esc_url( $this->tgmpa->get_tgmpa_url() ) . '" target="_parent">' . esc_html( $this->tgmpa->strings['return'] ) . '</a>';
3681
+ }
3682
+
3683
+ /**
3684
+ * Filter the list of action links available following bulk plugin installs/updates.
3685
+ *
3686
+ * @since 2.5.0
3687
+ *
3688
+ * @param array $update_actions Array of plugin action links.
3689
+ * @param array $plugin_info Array of information for the last-handled plugin.
3690
+ */
3691
+ $update_actions = apply_filters( 'tgmpa_update_bulk_plugins_complete_actions', $update_actions, $this->plugin_info );
3692
+
3693
+ if ( ! empty( $update_actions ) ) {
3694
+ $this->feedback( implode( ' | ', (array) $update_actions ) );
3695
+ }
3696
+ }
3697
+
3698
+ /* *********** DEPRECATED METHODS *********** */
3699
+
3700
+ /**
3701
+ * Flush header output buffer.
3702
+ *
3703
+ * @since 2.2.0
3704
+ * @deprecated 2.5.0 use {@see Bulk_Upgrader_Skin::flush_output()} instead
3705
+ * @see Bulk_Upgrader_Skin::flush_output()
3706
+ */
3707
+ public function before_flush_output() {
3708
+ _deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'Bulk_Upgrader_Skin::flush_output()' );
3709
+ $this->flush_output();
3710
+ }
3711
+
3712
+ /**
3713
+ * Flush footer output buffer and iterate $this->i to make sure the
3714
+ * installation strings reference the correct plugin.
3715
+ *
3716
+ * @since 2.2.0
3717
+ * @deprecated 2.5.0 use {@see Bulk_Upgrader_Skin::flush_output()} instead
3718
+ * @see Bulk_Upgrader_Skin::flush_output()
3719
+ */
3720
+ public function after_flush_output() {
3721
+ _deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'Bulk_Upgrader_Skin::flush_output()' );
3722
+ $this->flush_output();
3723
+ $this->i++;
3724
+ }
3725
+ }
3726
+ }
3727
+ }
3728
+ }
3729
+ }
3730
+
3731
+ if ( ! class_exists( 'TGMPA_Utils' ) ) {
3732
+
3733
+ /**
3734
+ * Generic utilities for TGMPA.
3735
+ *
3736
+ * All methods are static, poor-dev name-spacing class wrapper.
3737
+ *
3738
+ * Class was called TGM_Utils in 2.5.0 but renamed TGMPA_Utils in 2.5.1 as this was conflicting with Soliloquy.
3739
+ *
3740
+ * @since 2.5.0
3741
+ *
3742
+ * @package TGM-Plugin-Activation
3743
+ * @author Juliette Reinders Folmer
3744
+ */
3745
+ class TGMPA_Utils {
3746
+ /**
3747
+ * Whether the PHP filter extension is enabled.
3748
+ *
3749
+ * @see http://php.net/book.filter
3750
+ *
3751
+ * @since 2.5.0
3752
+ *
3753
+ * @static
3754
+ *
3755
+ * @var bool $has_filters True is the extension is enabled.
3756
+ */
3757
+ public static $has_filters;
3758
+
3759
+ /**
3760
+ * Wrap an arbitrary string in <em> tags. Meant to be used in combination with array_map().
3761
+ *
3762
+ * @since 2.5.0
3763
+ *
3764
+ * @static
3765
+ *
3766
+ * @param string $string Text to be wrapped.
3767
+ * @return string
3768
+ */
3769
+ public static function wrap_in_em( $string ) {
3770
+ return '<em>' . wp_kses_post( $string ) . '</em>';
3771
+ }
3772
+
3773
+ /**
3774
+ * Wrap an arbitrary string in <strong> tags. Meant to be used in combination with array_map().
3775
+ *
3776
+ * @since 2.5.0
3777
+ *
3778
+ * @static
3779
+ *
3780
+ * @param string $string Text to be wrapped.
3781
+ * @return string
3782
+ */
3783
+ public static function wrap_in_strong( $string ) {
3784
+ return '<strong>' . wp_kses_post( $string ) . '</strong>';
3785
+ }
3786
+
3787
+ /**
3788
+ * Helper function: Validate a value as boolean
3789
+ *
3790
+ * @since 2.5.0
3791
+ *
3792
+ * @static
3793
+ *
3794
+ * @param mixed $value Arbitrary value.
3795
+ * @return bool
3796
+ */
3797
+ public static function validate_bool( $value ) {
3798
+ if ( ! isset( self::$has_filters ) ) {
3799
+ self::$has_filters = extension_loaded( 'filter' );
3800
+ }
3801
+
3802
+ if ( self::$has_filters ) {
3803
+ return filter_var( $value, FILTER_VALIDATE_BOOLEAN );
3804
+ } else {
3805
+ return self::emulate_filter_bool( $value );
3806
+ }
3807
+ }
3808
+
3809
+ /**
3810
+ * Helper function: Cast a value to bool
3811
+ *
3812
+ * @since 2.5.0
3813
+ *
3814
+ * @static
3815
+ *
3816
+ * @param mixed $value Value to cast.
3817
+ * @return bool
3818
+ */
3819
+ protected static function emulate_filter_bool( $value ) {
3820
+ // @codingStandardsIgnoreStart
3821
+ static $true = array(
3822
+ '1',
3823
+ 'true', 'True', 'TRUE',
3824
+ 'y', 'Y',
3825
+ 'yes', 'Yes', 'YES',
3826
+ 'on', 'On', 'ON',
3827
+ );
3828
+ static $false = array(
3829
+ '0',
3830
+ 'false', 'False', 'FALSE',
3831
+ 'n', 'N',
3832
+ 'no', 'No', 'NO',
3833
+ 'off', 'Off', 'OFF',
3834
+ );
3835
+ // @codingStandardsIgnoreEnd
3836
+
3837
+ if ( is_bool( $value ) ) {
3838
+ return $value;
3839
+ } elseif ( is_int( $value ) && ( 0 === $value || 1 === $value ) ) {
3840
+ return (bool) $value;
3841
+ } elseif ( ( is_float( $value ) && ! is_nan( $value ) ) && ( (float) 0 === $value || (float) 1 === $value ) ) {
3842
+ return (bool) $value;
3843
+ } elseif ( is_string( $value ) ) {
3844
+ $value = trim( $value );
3845
+ if ( in_array( $value, $true, true ) ) {
3846
+ return true;
3847
+ } elseif ( in_array( $value, $false, true ) ) {
3848
+ return false;
3849
+ } else {
3850
+ return false;
3851
+ }
3852
+ }
3853
+
3854
+ return false;
3855
+ }
3856
+ } // End of class TGMPA_Utils
3857
+ } // End of class_exists wrapper
uninstall.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Uninstalls WP Mail SMTP.
4
+ *
5
+ * @since 1.3.0
6
+ */
7
+
8
+ // Exit if accessed directly.
9
+ if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
10
+ exit;
11
+ }
12
+
13
+ // Confirm user has decided to remove all data, otherwise stop.
14
+ $settings = get_option( 'wp_mail_smtp', array() );
15
+ if ( empty( $settings['general']['uninstall'] ) ) {
16
+ return;
17
+ }
18
+
19
+ // Remove options.
20
+ $options = array(
21
+ 'wp_mail_smtp_initial_version',
22
+ 'wp_mail_smtp_version',
23
+ 'wp_mail_smtp',
24
+ '_amn_smtp_last_checked',
25
+ // Legacy options.
26
+ 'pepipost_ssl',
27
+ 'pepipost_port',
28
+ 'pepipost_pass',
29
+ 'pepipost_user',
30
+ 'smtp_pass',
31
+ 'smtp_user',
32
+ 'smtp_auth',
33
+ 'smtp_ssl',
34
+ 'smtp_port',
35
+ 'smtp_host',
36
+ 'mail_set_return_path',
37
+ 'mailer',
38
+ 'mail_from_name',
39
+ 'mail_from',
40
+ 'wp_mail_smtp_am_notifications_hidden',
41
+ );
42
+
43
+ foreach ( $options as $option ) {
44
+ delete_option( $option );
45
+ }
46
+
47
+ // Remove product annoucements.
48
+ $annoucements = get_posts( array(
49
+ 'post_type' => array( 'amn_smtp' ),
50
+ 'post_status' => 'any',
51
+ 'numberposts' => -1,
52
+ 'fields' => 'ids',
53
+ ) );
54
+ if ( ! empty( $annoucements ) ) {
55
+ foreach ( $annoucements as $annoucement ) {
56
+ wp_delete_post( $annoucement, true );
57
+ }
58
+ }
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInitbd625bfb904527ebcdc364a59295e538::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit84925637ca46a89b245a3fe4d9646ae4::getLoader();
vendor/composer/ClassLoader.php CHANGED
@@ -379,9 +379,9 @@ class ClassLoader
379
  $subPath = substr($subPath, 0, $lastPos);
380
  $search = $subPath.'\\';
381
  if (isset($this->prefixDirsPsr4[$search])) {
 
382
  foreach ($this->prefixDirsPsr4[$search] as $dir) {
383
- $length = $this->prefixLengthsPsr4[$first][$search];
384
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
385
  return $file;
386
  }
387
  }
379
  $subPath = substr($subPath, 0, $lastPos);
380
  $search = $subPath.'\\';
381
  if (isset($this->prefixDirsPsr4[$search])) {
382
+ $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383
  foreach ($this->prefixDirsPsr4[$search] as $dir) {
384
+ if (file_exists($file = $dir . $pathEnd)) {
 
385
  return $file;
386
  }
387
  }
vendor/composer/autoload_classmap.php CHANGED
@@ -6,234 +6,6 @@ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
- 'Google\\Auth\\ApplicationDefaultCredentials' => $vendorDir . '/google/auth/src/ApplicationDefaultCredentials.php',
10
- 'Google\\Auth\\CacheTrait' => $vendorDir . '/google/auth/src/CacheTrait.php',
11
- 'Google\\Auth\\Cache\\InvalidArgumentException' => $vendorDir . '/google/auth/src/Cache/InvalidArgumentException.php',
12
- 'Google\\Auth\\Cache\\Item' => $vendorDir . '/google/auth/src/Cache/Item.php',
13
- 'Google\\Auth\\Cache\\MemoryCacheItemPool' => $vendorDir . '/google/auth/src/Cache/MemoryCacheItemPool.php',
14
- 'Google\\Auth\\CredentialsLoader' => $vendorDir . '/google/auth/src/CredentialsLoader.php',
15
- 'Google\\Auth\\Credentials\\AppIdentityCredentials' => $vendorDir . '/google/auth/src/Credentials/AppIdentityCredentials.php',
16
- 'Google\\Auth\\Credentials\\GCECredentials' => $vendorDir . '/google/auth/src/Credentials/GCECredentials.php',
17
- 'Google\\Auth\\Credentials\\IAMCredentials' => $vendorDir . '/google/auth/src/Credentials/IAMCredentials.php',
18
- 'Google\\Auth\\Credentials\\ServiceAccountCredentials' => $vendorDir . '/google/auth/src/Credentials/ServiceAccountCredentials.php',
19
- 'Google\\Auth\\Credentials\\ServiceAccountJwtAccessCredentials' => $vendorDir . '/google/auth/src/Credentials/ServiceAccountJwtAccessCredentials.php',
20
- 'Google\\Auth\\Credentials\\UserRefreshCredentials' => $vendorDir . '/google/auth/src/Credentials/UserRefreshCredentials.php',
21
- 'Google\\Auth\\FetchAuthTokenCache' => $vendorDir . '/google/auth/src/FetchAuthTokenCache.php',
22
- 'Google\\Auth\\FetchAuthTokenInterface' => $vendorDir . '/google/auth/src/FetchAuthTokenInterface.php',
23
- 'Google\\Auth\\HttpHandler\\Guzzle5HttpHandler' => $vendorDir . '/google/auth/src/HttpHandler/Guzzle5HttpHandler.php',
24
- 'Google\\Auth\\HttpHandler\\Guzzle6HttpHandler' => $vendorDir . '/google/auth/src/HttpHandler/Guzzle6HttpHandler.php',
25
- 'Google\\Auth\\HttpHandler\\HttpHandlerFactory' => $vendorDir . '/google/auth/src/HttpHandler/HttpHandlerFactory.php',
26
- 'Google\\Auth\\Middleware\\AuthTokenMiddleware' => $vendorDir . '/google/auth/src/Middleware/AuthTokenMiddleware.php',
27
- 'Google\\Auth\\Middleware\\ScopedAccessTokenMiddleware' => $vendorDir . '/google/auth/src/Middleware/ScopedAccessTokenMiddleware.php',
28
- 'Google\\Auth\\Middleware\\SimpleMiddleware' => $vendorDir . '/google/auth/src/Middleware/SimpleMiddleware.php',
29
- 'Google\\Auth\\OAuth2' => $vendorDir . '/google/auth/src/OAuth2.php',
30
- 'Google\\Auth\\Subscriber\\AuthTokenSubscriber' => $vendorDir . '/google/auth/src/Subscriber/AuthTokenSubscriber.php',
31
- 'Google\\Auth\\Subscriber\\ScopedAccessTokenSubscriber' => $vendorDir . '/google/auth/src/Subscriber/ScopedAccessTokenSubscriber.php',
32
- 'Google\\Auth\\Subscriber\\SimpleSubscriber' => $vendorDir . '/google/auth/src/Subscriber/SimpleSubscriber.php',
33
- 'Google_AccessToken_Revoke' => $vendorDir . '/google/apiclient/src/Google/AccessToken/Revoke.php',
34
- 'Google_AccessToken_Verify' => $vendorDir . '/google/apiclient/src/Google/AccessToken/Verify.php',
35
- 'Google_AuthHandler_AuthHandlerFactory' => $vendorDir . '/google/apiclient/src/Google/AuthHandler/AuthHandlerFactory.php',
36
- 'Google_AuthHandler_Guzzle5AuthHandler' => $vendorDir . '/google/apiclient/src/Google/AuthHandler/Guzzle5AuthHandler.php',
37
- 'Google_AuthHandler_Guzzle6AuthHandler' => $vendorDir . '/google/apiclient/src/Google/AuthHandler/Guzzle6AuthHandler.php',
38
- 'Google_Client' => $vendorDir . '/google/apiclient/src/Google/Client.php',
39
- 'Google_Collection' => $vendorDir . '/google/apiclient/src/Google/Collection.php',
40
- 'Google_Exception' => $vendorDir . '/google/apiclient/src/Google/Exception.php',
41
- 'Google_Http_Batch' => $vendorDir . '/google/apiclient/src/Google/Http/Batch.php',
42
- 'Google_Http_MediaFileUpload' => $vendorDir . '/google/apiclient/src/Google/Http/MediaFileUpload.php',
43
- 'Google_Http_REST' => $vendorDir . '/google/apiclient/src/Google/Http/REST.php',
44
- 'Google_Model' => $vendorDir . '/google/apiclient/src/Google/Model.php',
45
- 'Google_Service' => $vendorDir . '/google/apiclient/src/Google/Service.php',
46
  'Google_Service_Exception' => $vendorDir . '/google/apiclient/src/Google/Service/Exception.php',
47
  'Google_Service_Resource' => $vendorDir . '/google/apiclient/src/Google/Service/Resource.php',
48
- 'Google_Task_Exception' => $vendorDir . '/google/apiclient/src/Google/Task/Exception.php',
49
- 'Google_Task_Retryable' => $vendorDir . '/google/apiclient/src/Google/Task/Retryable.php',
50
- 'Google_Task_Runner' => $vendorDir . '/google/apiclient/src/Google/Task/Runner.php',
51
- 'Google_Utils_UriTemplate' => $vendorDir . '/google/apiclient/src/Google/Utils/UriTemplate.php',
52
- 'GuzzleHttp\\Client' => $vendorDir . '/guzzlehttp/guzzle/src/Client.php',
53
- 'GuzzleHttp\\ClientInterface' => $vendorDir . '/guzzlehttp/guzzle/src/ClientInterface.php',
54
- 'GuzzleHttp\\Cookie\\CookieJar' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/CookieJar.php',
55
- 'GuzzleHttp\\Cookie\\CookieJarInterface' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php',
56
- 'GuzzleHttp\\Cookie\\FileCookieJar' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php',
57
- 'GuzzleHttp\\Cookie\\SessionCookieJar' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php',
58
- 'GuzzleHttp\\Cookie\\SetCookie' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/SetCookie.php',
59
- 'GuzzleHttp\\Exception\\BadResponseException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/BadResponseException.php',
60
- 'GuzzleHttp\\Exception\\ClientException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/ClientException.php',
61
- 'GuzzleHttp\\Exception\\ConnectException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/ConnectException.php',
62
- 'GuzzleHttp\\Exception\\GuzzleException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/GuzzleException.php',
63
- 'GuzzleHttp\\Exception\\RequestException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/RequestException.php',
64
- 'GuzzleHttp\\Exception\\SeekException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/SeekException.php',
65
- 'GuzzleHttp\\Exception\\ServerException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/ServerException.php',
66
- 'GuzzleHttp\\Exception\\TooManyRedirectsException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php',
67
- 'GuzzleHttp\\Exception\\TransferException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/TransferException.php',
68
- 'GuzzleHttp\\HandlerStack' => $vendorDir . '/guzzlehttp/guzzle/src/HandlerStack.php',
69
- 'GuzzleHttp\\Handler\\CurlFactory' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlFactory.php',
70
- 'GuzzleHttp\\Handler\\CurlFactoryInterface' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php',
71
- 'GuzzleHttp\\Handler\\CurlHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlHandler.php',
72
- 'GuzzleHttp\\Handler\\CurlMultiHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php',
73
- 'GuzzleHttp\\Handler\\EasyHandle' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/EasyHandle.php',
74
- 'GuzzleHttp\\Handler\\MockHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/MockHandler.php',
75
- 'GuzzleHttp\\Handler\\Proxy' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/Proxy.php',
76
- 'GuzzleHttp\\Handler\\StreamHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/StreamHandler.php',
77
- 'GuzzleHttp\\MessageFormatter' => $vendorDir . '/guzzlehttp/guzzle/src/MessageFormatter.php',
78
- 'GuzzleHttp\\Middleware' => $vendorDir . '/guzzlehttp/guzzle/src/Middleware.php',
79
- 'GuzzleHttp\\Pool' => $vendorDir . '/guzzlehttp/guzzle/src/Pool.php',
80
- 'GuzzleHttp\\PrepareBodyMiddleware' => $vendorDir . '/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php',
81
- 'GuzzleHttp\\Promise\\AggregateException' => $vendorDir . '/guzzlehttp/promises/src/AggregateException.php',
82
- 'GuzzleHttp\\Promise\\CancellationException' => $vendorDir . '/guzzlehttp/promises/src/CancellationException.php',
83
- 'GuzzleHttp\\Promise\\Coroutine' => $vendorDir . '/guzzlehttp/promises/src/Coroutine.php',
84
- 'GuzzleHttp\\Promise\\EachPromise' => $vendorDir . '/guzzlehttp/promises/src/EachPromise.php',
85
- 'GuzzleHttp\\Promise\\FulfilledPromise' => $vendorDir . '/guzzlehttp/promises/src/FulfilledPromise.php',
86
- 'GuzzleHttp\\Promise\\Promise' => $vendorDir . '/guzzlehttp/promises/src/Promise.php',
87
- 'GuzzleHttp\\Promise\\PromiseInterface' => $vendorDir . '/guzzlehttp/promises/src/PromiseInterface.php',
88
- 'GuzzleHttp\\Promise\\PromisorInterface' => $vendorDir . '/guzzlehttp/promises/src/PromisorInterface.php',
89
- 'GuzzleHttp\\Promise\\RejectedPromise' => $vendorDir . '/guzzlehttp/promises/src/RejectedPromise.php',
90
- 'GuzzleHttp\\Promise\\RejectionException' => $vendorDir . '/guzzlehttp/promises/src/RejectionException.php',
91
- 'GuzzleHttp\\Promise\\TaskQueue' => $vendorDir . '/guzzlehttp/promises/src/TaskQueue.php',
92
- 'GuzzleHttp\\Promise\\TaskQueueInterface' => $vendorDir . '/guzzlehttp/promises/src/TaskQueueInterface.php',
93
- 'GuzzleHttp\\Psr7\\AppendStream' => $vendorDir . '/guzzlehttp/psr7/src/AppendStream.php',
94
- 'GuzzleHttp\\Psr7\\BufferStream' => $vendorDir . '/guzzlehttp/psr7/src/BufferStream.php',
95
- 'GuzzleHttp\\Psr7\\CachingStream' => $vendorDir . '/guzzlehttp/psr7/src/CachingStream.php',
96
- 'GuzzleHttp\\Psr7\\DroppingStream' => $vendorDir . '/guzzlehttp/psr7/src/DroppingStream.php',
97
- 'GuzzleHttp\\Psr7\\FnStream' => $vendorDir . '/guzzlehttp/psr7/src/FnStream.php',
98
- 'GuzzleHttp\\Psr7\\InflateStream' => $vendorDir . '/guzzlehttp/psr7/src/InflateStream.php',
99
- 'GuzzleHttp\\Psr7\\LazyOpenStream' => $vendorDir . '/guzzlehttp/psr7/src/LazyOpenStream.php',
100
- 'GuzzleHttp\\Psr7\\LimitStream' => $vendorDir . '/guzzlehttp/psr7/src/LimitStream.php',
101
- 'GuzzleHttp\\Psr7\\MessageTrait' => $vendorDir . '/guzzlehttp/psr7/src/MessageTrait.php',
102
- 'GuzzleHttp\\Psr7\\MultipartStream' => $vendorDir . '/guzzlehttp/psr7/src/MultipartStream.php',
103
- 'GuzzleHttp\\Psr7\\NoSeekStream' => $vendorDir . '/guzzlehttp/psr7/src/NoSeekStream.php',
104
- 'GuzzleHttp\\Psr7\\PumpStream' => $vendorDir . '/guzzlehttp/psr7/src/PumpStream.php',
105
- 'GuzzleHttp\\Psr7\\Request' => $vendorDir . '/guzzlehttp/psr7/src/Request.php',
106
- 'GuzzleHttp\\Psr7\\Response' => $vendorDir . '/guzzlehttp/psr7/src/Response.php',
107
- 'GuzzleHttp\\Psr7\\ServerRequest' => $vendorDir . '/guzzlehttp/psr7/src/ServerRequest.php',
108
- 'GuzzleHttp\\Psr7\\Stream' => $vendorDir . '/guzzlehttp/psr7/src/Stream.php',
109
- 'GuzzleHttp\\Psr7\\StreamDecoratorTrait' => $vendorDir . '/guzzlehttp/psr7/src/StreamDecoratorTrait.php',
110
- 'GuzzleHttp\\Psr7\\StreamWrapper' => $vendorDir . '/guzzlehttp/psr7/src/StreamWrapper.php',
111
- 'GuzzleHttp\\Psr7\\UploadedFile' => $vendorDir . '/guzzlehttp/psr7/src/UploadedFile.php',
112
- 'GuzzleHttp\\Psr7\\Uri' => $vendorDir . '/guzzlehttp/psr7/src/Uri.php',
113
- 'GuzzleHttp\\Psr7\\UriNormalizer' => $vendorDir . '/guzzlehttp/psr7/src/UriNormalizer.php',
114
- 'GuzzleHttp\\Psr7\\UriResolver' => $vendorDir . '/guzzlehttp/psr7/src/UriResolver.php',
115
- 'GuzzleHttp\\RedirectMiddleware' => $vendorDir . '/guzzlehttp/guzzle/src/RedirectMiddleware.php',
116
- 'GuzzleHttp\\RequestOptions' => $vendorDir . '/guzzlehttp/guzzle/src/RequestOptions.php',
117
- 'GuzzleHttp\\RetryMiddleware' => $vendorDir . '/guzzlehttp/guzzle/src/RetryMiddleware.php',
118
- 'GuzzleHttp\\TransferStats' => $vendorDir . '/guzzlehttp/guzzle/src/TransferStats.php',
119
- 'GuzzleHttp\\UriTemplate' => $vendorDir . '/guzzlehttp/guzzle/src/UriTemplate.php',
120
- 'Monolog\\ErrorHandler' => $vendorDir . '/monolog/monolog/src/Monolog/ErrorHandler.php',
121
- 'Monolog\\Formatter\\ChromePHPFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php',
122
- 'Monolog\\Formatter\\ElasticaFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php',
123
- 'Monolog\\Formatter\\FlowdockFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php',
124
- 'Monolog\\Formatter\\FluentdFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php',
125
- 'Monolog\\Formatter\\FormatterInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php',
126
- 'Monolog\\Formatter\\GelfMessageFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php',
127
- 'Monolog\\Formatter\\HtmlFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php',
128
- 'Monolog\\Formatter\\JsonFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php',
129
- 'Monolog\\Formatter\\LineFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LineFormatter.php',
130
- 'Monolog\\Formatter\\LogglyFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php',
131
- 'Monolog\\Formatter\\LogstashFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php',
132
- 'Monolog\\Formatter\\MongoDBFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php',
133
- 'Monolog\\Formatter\\NormalizerFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php',
134
- 'Monolog\\Formatter\\ScalarFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php',
135
- 'Monolog\\Formatter\\WildfireFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php',
136
- 'Monolog\\Handler\\AbstractHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractHandler.php',
137
- 'Monolog\\Handler\\AbstractProcessingHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php',
138
- 'Monolog\\Handler\\AbstractSyslogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php',
139
- 'Monolog\\Handler\\AmqpHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AmqpHandler.php',
140
- 'Monolog\\Handler\\BrowserConsoleHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php',
141
- 'Monolog\\Handler\\BufferHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/BufferHandler.php',
142
- 'Monolog\\Handler\\ChromePHPHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php',
143
- 'Monolog\\Handler\\CouchDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php',
144
- 'Monolog\\Handler\\CubeHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/CubeHandler.php',
145
- 'Monolog\\Handler\\Curl\\Util' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/Curl/Util.php',
146
- 'Monolog\\Handler\\DeduplicationHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php',
147
- 'Monolog\\Handler\\DoctrineCouchDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php',
148
- 'Monolog\\Handler\\DynamoDbHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php',
149
- 'Monolog\\Handler\\ElasticSearchHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php',
150
- 'Monolog\\Handler\\ErrorLogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php',
151
- 'Monolog\\Handler\\FilterHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FilterHandler.php',
152
- 'Monolog\\Handler\\FingersCrossedHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php',
153
- 'Monolog\\Handler\\FingersCrossed\\ActivationStrategyInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php',
154
- 'Monolog\\Handler\\FingersCrossed\\ChannelLevelActivationStrategy' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php',
155
- 'Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php',
156
- 'Monolog\\Handler\\FirePHPHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php',
157
- 'Monolog\\Handler\\FleepHookHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php',
158
- 'Monolog\\Handler\\FlowdockHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php',
159
- 'Monolog\\Handler\\GelfHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/GelfHandler.php',
160
- 'Monolog\\Handler\\GroupHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/GroupHandler.php',
161
- 'Monolog\\Handler\\HandlerInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HandlerInterface.php',
162
- 'Monolog\\Handler\\HandlerWrapper' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php',
163
- 'Monolog\\Handler\\HipChatHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HipChatHandler.php',
164
- 'Monolog\\Handler\\IFTTTHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php',
165
- 'Monolog\\Handler\\LogEntriesHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php',
166
- 'Monolog\\Handler\\LogglyHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogglyHandler.php',
167
- 'Monolog\\Handler\\MailHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MailHandler.php',
168
- 'Monolog\\Handler\\MandrillHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MandrillHandler.php',
169
- 'Monolog\\Handler\\MissingExtensionException' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php',
170
- 'Monolog\\Handler\\MongoDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php',
171
- 'Monolog\\Handler\\NativeMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php',
172
- 'Monolog\\Handler\\NewRelicHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php',
173
- 'Monolog\\Handler\\NullHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NullHandler.php',
174
- 'Monolog\\Handler\\PHPConsoleHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php',
175
- 'Monolog\\Handler\\PsrHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PsrHandler.php',
176
- 'Monolog\\Handler\\PushoverHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PushoverHandler.php',
177
- 'Monolog\\Handler\\RavenHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RavenHandler.php',
178
- 'Monolog\\Handler\\RedisHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RedisHandler.php',
179
- 'Monolog\\Handler\\RollbarHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RollbarHandler.php',
180
- 'Monolog\\Handler\\RotatingFileHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php',
181
- 'Monolog\\Handler\\SamplingHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SamplingHandler.php',
182
- 'Monolog\\Handler\\SlackHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SlackHandler.php',
183
- 'Monolog\\Handler\\SlackWebhookHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php',
184
- 'Monolog\\Handler\\Slack\\SlackRecord' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php',
185
- 'Monolog\\Handler\\SlackbotHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SlackbotHandler.php',
186
- 'Monolog\\Handler\\SocketHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SocketHandler.php',
187
- 'Monolog\\Handler\\StreamHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/StreamHandler.php',
188
- 'Monolog\\Handler\\SwiftMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php',
189
- 'Monolog\\Handler\\SyslogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogHandler.php',
190
- 'Monolog\\Handler\\SyslogUdpHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php',
191
- 'Monolog\\Handler\\SyslogUdp\\UdpSocket' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php',
192
- 'Monolog\\Handler\\WhatFailureGroupHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php',
193
- 'Monolog\\Handler\\ZendMonitorHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php',
194
- 'Monolog\\Logger' => $vendorDir . '/monolog/monolog/src/Monolog/Logger.php',
195
- 'Monolog\\Processor\\GitProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/GitProcessor.php',
196
- 'Monolog\\Processor\\IntrospectionProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php',
197
- 'Monolog\\Processor\\MemoryPeakUsageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php',
198
- 'Monolog\\Processor\\MemoryProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php',
199
- 'Monolog\\Processor\\MemoryUsageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php',
200
- 'Monolog\\Processor\\MercurialProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php',
201
- 'Monolog\\Processor\\ProcessIdProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php',
202
- 'Monolog\\Processor\\PsrLogMessageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php',
203
- 'Monolog\\Processor\\TagProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/TagProcessor.php',
204
- 'Monolog\\Processor\\UidProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/UidProcessor.php',
205
- 'Monolog\\Processor\\WebProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/WebProcessor.php',
206
- 'Monolog\\Registry' => $vendorDir . '/monolog/monolog/src/Monolog/Registry.php',
207
- 'Psr\\Cache\\CacheException' => $vendorDir . '/psr/cache/src/CacheException.php',
208
- 'Psr\\Cache\\CacheItemInterface' => $vendorDir . '/psr/cache/src/CacheItemInterface.php',
209
- 'Psr\\Cache\\CacheItemPoolInterface' => $vendorDir . '/psr/cache/src/CacheItemPoolInterface.php',
210
- 'Psr\\Cache\\InvalidArgumentException' => $vendorDir . '/psr/cache/src/InvalidArgumentException.php',
211
- 'Psr\\Http\\Message\\MessageInterface' => $vendorDir . '/psr/http-message/src/MessageInterface.php',
212
- 'Psr\\Http\\Message\\RequestInterface' => $vendorDir . '/psr/http-message/src/RequestInterface.php',
213
- 'Psr\\Http\\Message\\ResponseInterface' => $vendorDir . '/psr/http-message/src/ResponseInterface.php',
214
- 'Psr\\Http\\Message\\ServerRequestInterface' => $vendorDir . '/psr/http-message/src/ServerRequestInterface.php',
215
- 'Psr\\Http\\Message\\StreamInterface' => $vendorDir . '/psr/http-message/src/StreamInterface.php',
216
- 'Psr\\Http\\Message\\UploadedFileInterface' => $vendorDir . '/psr/http-message/src/UploadedFileInterface.php',
217
- 'Psr\\Http\\Message\\UriInterface' => $vendorDir . '/psr/http-message/src/UriInterface.php',
218
- 'Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/Psr/Log/AbstractLogger.php',
219
- 'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/Psr/Log/InvalidArgumentException.php',
220
- 'Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/Psr/Log/LogLevel.php',
221
- 'Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareInterface.php',
222
- 'Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareTrait.php',
223
- 'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php',
224
- 'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php',
225
- 'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php',
226
- 'phpseclib\\Crypt\\AES' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/AES.php',
227
- 'phpseclib\\Crypt\\Base' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Base.php',
228
- 'phpseclib\\Crypt\\Blowfish' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php',
229
- 'phpseclib\\Crypt\\DES' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/DES.php',
230
- 'phpseclib\\Crypt\\Hash' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Hash.php',
231
- 'phpseclib\\Crypt\\RC2' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RC2.php',
232
- 'phpseclib\\Crypt\\RC4' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RC4.php',
233
- 'phpseclib\\Crypt\\RSA' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RSA.php',
234
- 'phpseclib\\Crypt\\Random' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Random.php',
235
- 'phpseclib\\Crypt\\Rijndael' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php',
236
- 'phpseclib\\Crypt\\TripleDES' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php',
237
- 'phpseclib\\Crypt\\Twofish' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php',
238
- 'phpseclib\\Math\\BigInteger' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Math/BigInteger.php',
239
  );
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  'Google_Service_Exception' => $vendorDir . '/google/apiclient/src/Google/Service/Exception.php',
10
  'Google_Service_Resource' => $vendorDir . '/google/apiclient/src/Google/Service/Resource.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  );
vendor/composer/autoload_files.php CHANGED
@@ -10,18 +10,4 @@ return array(
10
  'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
11
  '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
12
  'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
13
- '36d9695c51c127dacf01b83c468dbbdb' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail.php',
14
- 'd95a5932fb3c05855cde09b51efec1ac' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Message.php',
15
- '1a8cb0c91ca8ad9f9147193a084f80bd' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/Users.php',
16
- '5d5f545fa7a58b1185f901d0c1006a41' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersDrafts.php',
17
- '79c900432abc031cbad7036b9fce5523' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersHistory.php',
18
- '1a56422ddba9140c62183b59448a7227' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersLabels.php',
19
- 'f7d0eb6d1da014e7ff1b6038c3314921' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersMessages.php',
20
- 'ed22ed3db05c96f75d2885e41650be07' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersMessagesAttachments.php',
21
- '535c184b9a328f2295fc70c028f13aa7' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettings.php',
22
- 'fc9b994b4190b187884a1bb5b334c54d' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsFilters.php',
23
- '3a081d084d3ba366d67d7139e5d9fbcf' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsForwardingAddresses.php',
24
- '60d509e933e5ca336a897bb7b549f15b' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsSendAs.php',
25
- '39c11aa4169566f44661343f8929bbd0' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsSendAsSmimeInfo.php',
26
- 'cf7f0634ca5d41f748c82f89bd3e960b' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersThreads.php',
27
  );
10
  'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
11
  '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
12
  'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  );
vendor/composer/autoload_psr4.php CHANGED
@@ -7,6 +7,7 @@ $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
  'phpseclib\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
 
10
  'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
11
  'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
12
  'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
7
 
8
  return array(
9
  'phpseclib\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
10
+ 'WPMailSMTP\\' => array($baseDir . '/src'),
11
  'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
12
  'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
13
  'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInitbd625bfb904527ebcdc364a59295e538
6
  {
7
  private static $loader;
8
 
@@ -19,39 +19,48 @@ class ComposerAutoloaderInitbd625bfb904527ebcdc364a59295e538
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInitbd625bfb904527ebcdc364a59295e538', 'loadClassLoader'), true, false);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInitbd625bfb904527ebcdc364a59295e538', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInitbd625bfb904527ebcdc364a59295e538::getInitializer($loader));
31
  } else {
 
 
 
 
 
 
 
 
 
 
32
  $classMap = require __DIR__ . '/autoload_classmap.php';
33
  if ($classMap) {
34
  $loader->addClassMap($classMap);
35
  }
36
  }
37
 
38
- $loader->setClassMapAuthoritative(true);
39
- $loader->register(false);
40
 
41
  if ($useStaticLoader) {
42
- $includeFiles = Composer\Autoload\ComposerStaticInitbd625bfb904527ebcdc364a59295e538::$files;
43
  } else {
44
  $includeFiles = require __DIR__ . '/autoload_files.php';
45
  }
46
  foreach ($includeFiles as $fileIdentifier => $file) {
47
- composerRequirebd625bfb904527ebcdc364a59295e538($fileIdentifier, $file);
48
  }
49
 
50
  return $loader;
51
  }
52
  }
53
 
54
- function composerRequirebd625bfb904527ebcdc364a59295e538($fileIdentifier, $file)
55
  {
56
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
57
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit84925637ca46a89b245a3fe4d9646ae4
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit84925637ca46a89b245a3fe4d9646ae4', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit84925637ca46a89b245a3fe4d9646ae4', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit84925637ca46a89b245a3fe4d9646ae4::getInitializer($loader));
31
  } else {
32
+ $map = require __DIR__ . '/autoload_namespaces.php';
33
+ foreach ($map as $namespace => $path) {
34
+ $loader->set($namespace, $path);
35
+ }
36
+
37
+ $map = require __DIR__ . '/autoload_psr4.php';
38
+ foreach ($map as $namespace => $path) {
39
+ $loader->setPsr4($namespace, $path);
40
+ }
41
+
42
  $classMap = require __DIR__ . '/autoload_classmap.php';
43
  if ($classMap) {
44
  $loader->addClassMap($classMap);
45
  }
46
  }
47
 
48
+ $loader->register(true);
 
49
 
50
  if ($useStaticLoader) {
51
+ $includeFiles = Composer\Autoload\ComposerStaticInit84925637ca46a89b245a3fe4d9646ae4::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
+ composerRequire84925637ca46a89b245a3fe4d9646ae4($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
+ function composerRequire84925637ca46a89b245a3fe4d9646ae4($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
vendor/composer/autoload_static.php CHANGED
@@ -4,27 +4,13 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInitbd625bfb904527ebcdc364a59295e538
8
  {
9
  public static $files = array (
10
  'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
11
  'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
12
  '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
13
  'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
14
- '36d9695c51c127dacf01b83c468dbbdb' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail.php',
15
- 'd95a5932fb3c05855cde09b51efec1ac' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Message.php',
16
- '1a8cb0c91ca8ad9f9147193a084f80bd' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/Users.php',
17
- '5d5f545fa7a58b1185f901d0c1006a41' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersDrafts.php',
18
- '79c900432abc031cbad7036b9fce5523' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersHistory.php',
19
- '1a56422ddba9140c62183b59448a7227' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersLabels.php',
20
- 'f7d0eb6d1da014e7ff1b6038c3314921' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersMessages.php',
21
- 'ed22ed3db05c96f75d2885e41650be07' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersMessagesAttachments.php',
22
- '535c184b9a328f2295fc70c028f13aa7' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettings.php',
23
- 'fc9b994b4190b187884a1bb5b334c54d' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsFilters.php',
24
- '3a081d084d3ba366d67d7139e5d9fbcf' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsForwardingAddresses.php',
25
- '60d509e933e5ca336a897bb7b549f15b' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsSendAs.php',
26
- '39c11aa4169566f44661343f8929bbd0' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsSendAsSmimeInfo.php',
27
- 'cf7f0634ca5d41f748c82f89bd3e960b' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersThreads.php',
28
  );
29
 
30
  public static $prefixLengthsPsr4 = array (
@@ -32,6 +18,10 @@ class ComposerStaticInitbd625bfb904527ebcdc364a59295e538
32
  array (
33
  'phpseclib\\' => 10,
34
  ),
 
 
 
 
35
  'P' =>
36
  array (
37
  'Psr\\Log\\' => 8,
@@ -64,6 +54,10 @@ class ComposerStaticInitbd625bfb904527ebcdc364a59295e538
64
  array (
65
  0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
66
  ),
 
 
 
 
67
  'Psr\\Log\\' =>
68
  array (
69
  0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
@@ -121,245 +115,17 @@ class ComposerStaticInitbd625bfb904527ebcdc364a59295e538
121
  );
122
 
123
  public static $classMap = array (
124
- 'Google\\Auth\\ApplicationDefaultCredentials' => __DIR__ . '/..' . '/google/auth/src/ApplicationDefaultCredentials.php',
125
- 'Google\\Auth\\CacheTrait' => __DIR__ . '/..' . '/google/auth/src/CacheTrait.php',
126
- 'Google\\Auth\\Cache\\InvalidArgumentException' => __DIR__ . '/..' . '/google/auth/src/Cache/InvalidArgumentException.php',
127
- 'Google\\Auth\\Cache\\Item' => __DIR__ . '/..' . '/google/auth/src/Cache/Item.php',
128
- 'Google\\Auth\\Cache\\MemoryCacheItemPool' => __DIR__ . '/..' . '/google/auth/src/Cache/MemoryCacheItemPool.php',
129
- 'Google\\Auth\\CredentialsLoader' => __DIR__ . '/..' . '/google/auth/src/CredentialsLoader.php',
130
- 'Google\\Auth\\Credentials\\AppIdentityCredentials' => __DIR__ . '/..' . '/google/auth/src/Credentials/AppIdentityCredentials.php',
131
- 'Google\\Auth\\Credentials\\GCECredentials' => __DIR__ . '/..' . '/google/auth/src/Credentials/GCECredentials.php',
132
- 'Google\\Auth\\Credentials\\IAMCredentials' => __DIR__ . '/..' . '/google/auth/src/Credentials/IAMCredentials.php',
133
- 'Google\\Auth\\Credentials\\ServiceAccountCredentials' => __DIR__ . '/..' . '/google/auth/src/Credentials/ServiceAccountCredentials.php',
134
- 'Google\\Auth\\Credentials\\ServiceAccountJwtAccessCredentials' => __DIR__ . '/..' . '/google/auth/src/Credentials/ServiceAccountJwtAccessCredentials.php',
135
- 'Google\\Auth\\Credentials\\UserRefreshCredentials' => __DIR__ . '/..' . '/google/auth/src/Credentials/UserRefreshCredentials.php',
136
- 'Google\\Auth\\FetchAuthTokenCache' => __DIR__ . '/..' . '/google/auth/src/FetchAuthTokenCache.php',
137
- 'Google\\Auth\\FetchAuthTokenInterface' => __DIR__ . '/..' . '/google/auth/src/FetchAuthTokenInterface.php',
138
- 'Google\\Auth\\HttpHandler\\Guzzle5HttpHandler' => __DIR__ . '/..' . '/google/auth/src/HttpHandler/Guzzle5HttpHandler.php',
139
- 'Google\\Auth\\HttpHandler\\Guzzle6HttpHandler' => __DIR__ . '/..' . '/google/auth/src/HttpHandler/Guzzle6HttpHandler.php',
140
- 'Google\\Auth\\HttpHandler\\HttpHandlerFactory' => __DIR__ . '/..' . '/google/auth/src/HttpHandler/HttpHandlerFactory.php',
141
- 'Google\\Auth\\Middleware\\AuthTokenMiddleware' => __DIR__ . '/..' . '/google/auth/src/Middleware/AuthTokenMiddleware.php',
142
- 'Google\\Auth\\Middleware\\ScopedAccessTokenMiddleware' => __DIR__ . '/..' . '/google/auth/src/Middleware/ScopedAccessTokenMiddleware.php',
143
- 'Google\\Auth\\Middleware\\SimpleMiddleware' => __DIR__ . '/..' . '/google/auth/src/Middleware/SimpleMiddleware.php',
144
- 'Google\\Auth\\OAuth2' => __DIR__ . '/..' . '/google/auth/src/OAuth2.php',
145
- 'Google\\Auth\\Subscriber\\AuthTokenSubscriber' => __DIR__ . '/..' . '/google/auth/src/Subscriber/AuthTokenSubscriber.php',
146
- 'Google\\Auth\\Subscriber\\ScopedAccessTokenSubscriber' => __DIR__ . '/..' . '/google/auth/src/Subscriber/ScopedAccessTokenSubscriber.php',
147
- 'Google\\Auth\\Subscriber\\SimpleSubscriber' => __DIR__ . '/..' . '/google/auth/src/Subscriber/SimpleSubscriber.php',
148
- 'Google_AccessToken_Revoke' => __DIR__ . '/..' . '/google/apiclient/src/Google/AccessToken/Revoke.php',
149
- 'Google_AccessToken_Verify' => __DIR__ . '/..' . '/google/apiclient/src/Google/AccessToken/Verify.php',
150
- 'Google_AuthHandler_AuthHandlerFactory' => __DIR__ . '/..' . '/google/apiclient/src/Google/AuthHandler/AuthHandlerFactory.php',
151
- 'Google_AuthHandler_Guzzle5AuthHandler' => __DIR__ . '/..' . '/google/apiclient/src/Google/AuthHandler/Guzzle5AuthHandler.php',
152
- 'Google_AuthHandler_Guzzle6AuthHandler' => __DIR__ . '/..' . '/google/apiclient/src/Google/AuthHandler/Guzzle6AuthHandler.php',
153
- 'Google_Client' => __DIR__ . '/..' . '/google/apiclient/src/Google/Client.php',
154
- 'Google_Collection' => __DIR__ . '/..' . '/google/apiclient/src/Google/Collection.php',
155
- 'Google_Exception' => __DIR__ . '/..' . '/google/apiclient/src/Google/Exception.php',
156
- 'Google_Http_Batch' => __DIR__ . '/..' . '/google/apiclient/src/Google/Http/Batch.php',
157
- 'Google_Http_MediaFileUpload' => __DIR__ . '/..' . '/google/apiclient/src/Google/Http/MediaFileUpload.php',
158
- 'Google_Http_REST' => __DIR__ . '/..' . '/google/apiclient/src/Google/Http/REST.php',
159
- 'Google_Model' => __DIR__ . '/..' . '/google/apiclient/src/Google/Model.php',
160
- 'Google_Service' => __DIR__ . '/..' . '/google/apiclient/src/Google/Service.php',
161
  'Google_Service_Exception' => __DIR__ . '/..' . '/google/apiclient/src/Google/Service/Exception.php',
162
  'Google_Service_Resource' => __DIR__ . '/..' . '/google/apiclient/src/Google/Service/Resource.php',
163
- 'Google_Task_Exception' => __DIR__ . '/..' . '/google/apiclient/src/Google/Task/Exception.php',
164
- 'Google_Task_Retryable' => __DIR__ . '/..' . '/google/apiclient/src/Google/Task/Retryable.php',
165
- 'Google_Task_Runner' => __DIR__ . '/..' . '/google/apiclient/src/Google/Task/Runner.php',
166
- 'Google_Utils_UriTemplate' => __DIR__ . '/..' . '/google/apiclient/src/Google/Utils/UriTemplate.php',
167
- 'GuzzleHttp\\Client' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Client.php',
168
- 'GuzzleHttp\\ClientInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/ClientInterface.php',
169
- 'GuzzleHttp\\Cookie\\CookieJar' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/CookieJar.php',
170
- 'GuzzleHttp\\Cookie\\CookieJarInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php',
171
- 'GuzzleHttp\\Cookie\\FileCookieJar' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php',
172
- 'GuzzleHttp\\Cookie\\SessionCookieJar' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php',
173
- 'GuzzleHttp\\Cookie\\SetCookie' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/SetCookie.php',
174
- 'GuzzleHttp\\Exception\\BadResponseException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/BadResponseException.php',
175
- 'GuzzleHttp\\Exception\\ClientException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/ClientException.php',
176
- 'GuzzleHttp\\Exception\\ConnectException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/ConnectException.php',
177
- 'GuzzleHttp\\Exception\\GuzzleException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/GuzzleException.php',
178
- 'GuzzleHttp\\Exception\\RequestException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/RequestException.php',
179
- 'GuzzleHttp\\Exception\\SeekException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/SeekException.php',
180
- 'GuzzleHttp\\Exception\\ServerException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/ServerException.php',
181
- 'GuzzleHttp\\Exception\\TooManyRedirectsException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php',
182
- 'GuzzleHttp\\Exception\\TransferException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/TransferException.php',
183
- 'GuzzleHttp\\HandlerStack' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/HandlerStack.php',
184
- 'GuzzleHttp\\Handler\\CurlFactory' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlFactory.php',
185
- 'GuzzleHttp\\Handler\\CurlFactoryInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php',
186
- 'GuzzleHttp\\Handler\\CurlHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlHandler.php',
187
- 'GuzzleHttp\\Handler\\CurlMultiHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php',
188
- 'GuzzleHttp\\Handler\\EasyHandle' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/EasyHandle.php',
189
- 'GuzzleHttp\\Handler\\MockHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/MockHandler.php',
190
- 'GuzzleHttp\\Handler\\Proxy' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/Proxy.php',
191
- 'GuzzleHttp\\Handler\\StreamHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/StreamHandler.php',
192
- 'GuzzleHttp\\MessageFormatter' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/MessageFormatter.php',
193
- 'GuzzleHttp\\Middleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Middleware.php',
194
- 'GuzzleHttp\\Pool' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Pool.php',
195
- 'GuzzleHttp\\PrepareBodyMiddleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php',
196
- 'GuzzleHttp\\Promise\\AggregateException' => __DIR__ . '/..' . '/guzzlehttp/promises/src/AggregateException.php',
197
- 'GuzzleHttp\\Promise\\CancellationException' => __DIR__ . '/..' . '/guzzlehttp/promises/src/CancellationException.php',
198
- 'GuzzleHttp\\Promise\\Coroutine' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Coroutine.php',
199
- 'GuzzleHttp\\Promise\\EachPromise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/EachPromise.php',
200
- 'GuzzleHttp\\Promise\\FulfilledPromise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/FulfilledPromise.php',
201
- 'GuzzleHttp\\Promise\\Promise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Promise.php',
202
- 'GuzzleHttp\\Promise\\PromiseInterface' => __DIR__ . '/..' . '/guzzlehttp/promises/src/PromiseInterface.php',
203
- 'GuzzleHttp\\Promise\\PromisorInterface' => __DIR__ . '/..' . '/guzzlehttp/promises/src/PromisorInterface.php',
204
- 'GuzzleHttp\\Promise\\RejectedPromise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/RejectedPromise.php',
205
- 'GuzzleHttp\\Promise\\RejectionException' => __DIR__ . '/..' . '/guzzlehttp/promises/src/RejectionException.php',
206
- 'GuzzleHttp\\Promise\\TaskQueue' => __DIR__ . '/..' . '/guzzlehttp/promises/src/TaskQueue.php',
207
- 'GuzzleHttp\\Promise\\TaskQueueInterface' => __DIR__ . '/..' . '/guzzlehttp/promises/src/TaskQueueInterface.php',
208
- 'GuzzleHttp\\Psr7\\AppendStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/AppendStream.php',
209
- 'GuzzleHttp\\Psr7\\BufferStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/BufferStream.php',
210
- 'GuzzleHttp\\Psr7\\CachingStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/CachingStream.php',
211
- 'GuzzleHttp\\Psr7\\DroppingStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/DroppingStream.php',
212
- 'GuzzleHttp\\Psr7\\FnStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/FnStream.php',
213
- 'GuzzleHttp\\Psr7\\InflateStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/InflateStream.php',
214
- 'GuzzleHttp\\Psr7\\LazyOpenStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/LazyOpenStream.php',
215
- 'GuzzleHttp\\Psr7\\LimitStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/LimitStream.php',
216
- 'GuzzleHttp\\Psr7\\MessageTrait' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/MessageTrait.php',
217
- 'GuzzleHttp\\Psr7\\MultipartStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/MultipartStream.php',
218
- 'GuzzleHttp\\Psr7\\NoSeekStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/NoSeekStream.php',
219
- 'GuzzleHttp\\Psr7\\PumpStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/PumpStream.php',
220
- 'GuzzleHttp\\Psr7\\Request' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Request.php',
221
- 'GuzzleHttp\\Psr7\\Response' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Response.php',
222
- 'GuzzleHttp\\Psr7\\ServerRequest' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/ServerRequest.php',
223
- 'GuzzleHttp\\Psr7\\Stream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Stream.php',
224
- 'GuzzleHttp\\Psr7\\StreamDecoratorTrait' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/StreamDecoratorTrait.php',
225
- 'GuzzleHttp\\Psr7\\StreamWrapper' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/StreamWrapper.php',
226
- 'GuzzleHttp\\Psr7\\UploadedFile' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/UploadedFile.php',
227
- 'GuzzleHttp\\Psr7\\Uri' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Uri.php',
228
- 'GuzzleHttp\\Psr7\\UriNormalizer' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/UriNormalizer.php',
229
- 'GuzzleHttp\\Psr7\\UriResolver' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/UriResolver.php',
230
- 'GuzzleHttp\\RedirectMiddleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/RedirectMiddleware.php',
231
- 'GuzzleHttp\\RequestOptions' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/RequestOptions.php',
232
- 'GuzzleHttp\\RetryMiddleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/RetryMiddleware.php',
233
- 'GuzzleHttp\\TransferStats' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/TransferStats.php',
234
- 'GuzzleHttp\\UriTemplate' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/UriTemplate.php',
235
- 'Monolog\\ErrorHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/ErrorHandler.php',
236
- 'Monolog\\Formatter\\ChromePHPFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php',
237
- 'Monolog\\Formatter\\ElasticaFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php',
238
- 'Monolog\\Formatter\\FlowdockFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php',
239
- 'Monolog\\Formatter\\FluentdFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php',
240
- 'Monolog\\Formatter\\FormatterInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php',
241
- 'Monolog\\Formatter\\GelfMessageFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php',
242
- 'Monolog\\Formatter\\HtmlFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php',
243
- 'Monolog\\Formatter\\JsonFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php',
244
- 'Monolog\\Formatter\\LineFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/LineFormatter.php',
245
- 'Monolog\\Formatter\\LogglyFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php',
246
- 'Monolog\\Formatter\\LogstashFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php',
247
- 'Monolog\\Formatter\\MongoDBFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php',
248
- 'Monolog\\Formatter\\NormalizerFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php',
249
- 'Monolog\\Formatter\\ScalarFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php',
250
- 'Monolog\\Formatter\\WildfireFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php',
251
- 'Monolog\\Handler\\AbstractHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractHandler.php',
252
- 'Monolog\\Handler\\AbstractProcessingHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php',
253
- 'Monolog\\Handler\\AbstractSyslogHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php',
254
- 'Monolog\\Handler\\AmqpHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AmqpHandler.php',
255
- 'Monolog\\Handler\\BrowserConsoleHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php',
256
- 'Monolog\\Handler\\BufferHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/BufferHandler.php',
257
- 'Monolog\\Handler\\ChromePHPHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php',
258
- 'Monolog\\Handler\\CouchDBHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php',
259
- 'Monolog\\Handler\\CubeHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/CubeHandler.php',
260
- 'Monolog\\Handler\\Curl\\Util' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/Curl/Util.php',
261
- 'Monolog\\Handler\\DeduplicationHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php',
262
- 'Monolog\\Handler\\DoctrineCouchDBHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php',
263
- 'Monolog\\Handler\\DynamoDbHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php',
264
- 'Monolog\\Handler\\ElasticSearchHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php',
265
- 'Monolog\\Handler\\ErrorLogHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php',
266
- 'Monolog\\Handler\\FilterHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FilterHandler.php',
267
- 'Monolog\\Handler\\FingersCrossedHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php',
268
- 'Monolog\\Handler\\FingersCrossed\\ActivationStrategyInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php',
269
- 'Monolog\\Handler\\FingersCrossed\\ChannelLevelActivationStrategy' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php',
270
- 'Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php',
271
- 'Monolog\\Handler\\FirePHPHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php',
272
- 'Monolog\\Handler\\FleepHookHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php',
273
- 'Monolog\\Handler\\FlowdockHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php',
274
- 'Monolog\\Handler\\GelfHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/GelfHandler.php',
275
- 'Monolog\\Handler\\GroupHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/GroupHandler.php',
276
- 'Monolog\\Handler\\HandlerInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/HandlerInterface.php',
277
- 'Monolog\\Handler\\HandlerWrapper' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php',
278
- 'Monolog\\Handler\\HipChatHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/HipChatHandler.php',
279
- 'Monolog\\Handler\\IFTTTHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php',
280
- 'Monolog\\Handler\\LogEntriesHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php',
281
- 'Monolog\\Handler\\LogglyHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/LogglyHandler.php',
282
- 'Monolog\\Handler\\MailHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MailHandler.php',
283
- 'Monolog\\Handler\\MandrillHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MandrillHandler.php',
284
- 'Monolog\\Handler\\MissingExtensionException' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php',
285
- 'Monolog\\Handler\\MongoDBHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php',
286
- 'Monolog\\Handler\\NativeMailerHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php',
287
- 'Monolog\\Handler\\NewRelicHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php',
288
- 'Monolog\\Handler\\NullHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/NullHandler.php',
289
- 'Monolog\\Handler\\PHPConsoleHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php',
290
- 'Monolog\\Handler\\PsrHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/PsrHandler.php',
291
- 'Monolog\\Handler\\PushoverHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/PushoverHandler.php',
292
- 'Monolog\\Handler\\RavenHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RavenHandler.php',
293
- 'Monolog\\Handler\\RedisHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RedisHandler.php',
294
- 'Monolog\\Handler\\RollbarHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RollbarHandler.php',
295
- 'Monolog\\Handler\\RotatingFileHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php',
296
- 'Monolog\\Handler\\SamplingHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SamplingHandler.php',
297
- 'Monolog\\Handler\\SlackHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SlackHandler.php',
298
- 'Monolog\\Handler\\SlackWebhookHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php',
299
- 'Monolog\\Handler\\Slack\\SlackRecord' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php',
300
- 'Monolog\\Handler\\SlackbotHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SlackbotHandler.php',
301
- 'Monolog\\Handler\\SocketHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SocketHandler.php',
302
- 'Monolog\\Handler\\StreamHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/StreamHandler.php',
303
- 'Monolog\\Handler\\SwiftMailerHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php',
304
- 'Monolog\\Handler\\SyslogHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogHandler.php',
305
- 'Monolog\\Handler\\SyslogUdpHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php',
306
- 'Monolog\\Handler\\SyslogUdp\\UdpSocket' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php',
307
- 'Monolog\\Handler\\WhatFailureGroupHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php',
308
- 'Monolog\\Handler\\ZendMonitorHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php',
309
- 'Monolog\\Logger' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Logger.php',
310
- 'Monolog\\Processor\\GitProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/GitProcessor.php',
311
- 'Monolog\\Processor\\IntrospectionProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php',
312
- 'Monolog\\Processor\\MemoryPeakUsageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php',
313
- 'Monolog\\Processor\\MemoryProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php',
314
- 'Monolog\\Processor\\MemoryUsageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php',
315
- 'Monolog\\Processor\\MercurialProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php',
316
- 'Monolog\\Processor\\ProcessIdProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php',
317
- 'Monolog\\Processor\\PsrLogMessageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php',
318
- 'Monolog\\Processor\\TagProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/TagProcessor.php',
319
- 'Monolog\\Processor\\UidProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/UidProcessor.php',
320
- 'Monolog\\Processor\\WebProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/WebProcessor.php',
321
- 'Monolog\\Registry' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Registry.php',
322
- 'Psr\\Cache\\CacheException' => __DIR__ . '/..' . '/psr/cache/src/CacheException.php',
323
- 'Psr\\Cache\\CacheItemInterface' => __DIR__ . '/..' . '/psr/cache/src/CacheItemInterface.php',
324
- 'Psr\\Cache\\CacheItemPoolInterface' => __DIR__ . '/..' . '/psr/cache/src/CacheItemPoolInterface.php',
325
- 'Psr\\Cache\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/cache/src/InvalidArgumentException.php',
326
- 'Psr\\Http\\Message\\MessageInterface' => __DIR__ . '/..' . '/psr/http-message/src/MessageInterface.php',
327
- 'Psr\\Http\\Message\\RequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/RequestInterface.php',
328
- 'Psr\\Http\\Message\\ResponseInterface' => __DIR__ . '/..' . '/psr/http-message/src/ResponseInterface.php',
329
- 'Psr\\Http\\Message\\ServerRequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/ServerRequestInterface.php',
330
- 'Psr\\Http\\Message\\StreamInterface' => __DIR__ . '/..' . '/psr/http-message/src/StreamInterface.php',
331
- 'Psr\\Http\\Message\\UploadedFileInterface' => __DIR__ . '/..' . '/psr/http-message/src/UploadedFileInterface.php',
332
- 'Psr\\Http\\Message\\UriInterface' => __DIR__ . '/..' . '/psr/http-message/src/UriInterface.php',
333
- 'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/AbstractLogger.php',
334
- 'Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/Psr/Log/InvalidArgumentException.php',
335
- 'Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/Psr/Log/LogLevel.php',
336
- 'Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerAwareInterface.php',
337
- 'Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerAwareTrait.php',
338
- 'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerInterface.php',
339
- 'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerTrait.php',
340
- 'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/NullLogger.php',
341
- 'phpseclib\\Crypt\\AES' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/AES.php',
342
- 'phpseclib\\Crypt\\Base' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Base.php',
343
- 'phpseclib\\Crypt\\Blowfish' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php',
344
- 'phpseclib\\Crypt\\DES' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/DES.php',
345
- 'phpseclib\\Crypt\\Hash' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Hash.php',
346
- 'phpseclib\\Crypt\\RC2' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RC2.php',
347
- 'phpseclib\\Crypt\\RC4' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RC4.php',
348
- 'phpseclib\\Crypt\\RSA' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RSA.php',
349
- 'phpseclib\\Crypt\\Random' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Random.php',
350
- 'phpseclib\\Crypt\\Rijndael' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php',
351
- 'phpseclib\\Crypt\\TripleDES' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php',
352
- 'phpseclib\\Crypt\\Twofish' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php',
353
- 'phpseclib\\Math\\BigInteger' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Math/BigInteger.php',
354
  );
355
 
356
  public static function getInitializer(ClassLoader $loader)
357
  {
358
  return \Closure::bind(function () use ($loader) {
359
- $loader->prefixLengthsPsr4 = ComposerStaticInitbd625bfb904527ebcdc364a59295e538::$prefixLengthsPsr4;
360
- $loader->prefixDirsPsr4 = ComposerStaticInitbd625bfb904527ebcdc364a59295e538::$prefixDirsPsr4;
361
- $loader->prefixesPsr0 = ComposerStaticInitbd625bfb904527ebcdc364a59295e538::$prefixesPsr0;
362
- $loader->classMap = ComposerStaticInitbd625bfb904527ebcdc364a59295e538::$classMap;
363
 
364
  }, null, ClassLoader::class);
365
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit84925637ca46a89b245a3fe4d9646ae4
8
  {
9
  public static $files = array (
10
  'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
11
  'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
12
  '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
13
  'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  );
15
 
16
  public static $prefixLengthsPsr4 = array (
18
  array (
19
  'phpseclib\\' => 10,
20
  ),
21
+ 'W' =>
22
+ array (
23
+ 'WPMailSMTP\\' => 11,
24
+ ),
25
  'P' =>
26
  array (
27
  'Psr\\Log\\' => 8,
54
  array (
55
  0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
56
  ),
57
+ 'WPMailSMTP\\' =>
58
+ array (
59
+ 0 => __DIR__ . '/../..' . '/src',
60
+ ),
61
  'Psr\\Log\\' =>
62
  array (
63
  0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
115
  );
116
 
117
  public static $classMap = array (
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  'Google_Service_Exception' => __DIR__ . '/..' . '/google/apiclient/src/Google/Service/Exception.php',
119
  'Google_Service_Resource' => __DIR__ . '/..' . '/google/apiclient/src/Google/Service/Resource.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  );
121
 
122
  public static function getInitializer(ClassLoader $loader)
123
  {
124
  return \Closure::bind(function () use ($loader) {
125
+ $loader->prefixLengthsPsr4 = ComposerStaticInit84925637ca46a89b245a3fe4d9646ae4::$prefixLengthsPsr4;
126
+ $loader->prefixDirsPsr4 = ComposerStaticInit84925637ca46a89b245a3fe4d9646ae4::$prefixDirsPsr4;
127
+ $loader->prefixesPsr0 = ComposerStaticInit84925637ca46a89b245a3fe4d9646ae4::$prefixesPsr0;
128
+ $loader->classMap = ComposerStaticInit84925637ca46a89b245a3fe4d9646ae4::$classMap;
129
 
130
  }, null, ClassLoader::class);
131
  }
vendor/google/apiclient-services/src/Google/Service/Gmail/Label.php CHANGED
@@ -17,6 +17,8 @@
17
 
18
  class Google_Service_Gmail_Label extends Google_Model
19
  {
 
 
20
  public $id;
21
  public $labelListVisibility;
22
  public $messageListVisibility;
@@ -27,6 +29,20 @@ class Google_Service_Gmail_Label extends Google_Model
27
  public $threadsUnread;
28
  public $type;
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  public function setId($id)
31
  {
32
  $this->id = $id;
17
 
18
  class Google_Service_Gmail_Label extends Google_Model
19
  {
20
+ protected $colorType = 'Google_Service_Gmail_LabelColor';
21
+ protected $colorDataType = '';
22
  public $id;
23
  public $labelListVisibility;
24
  public $messageListVisibility;
29
  public $threadsUnread;
30
  public $type;
31
 
32
+ /**
33
+ * @param Google_Service_Gmail_LabelColor
34
+ */
35
+ public function setColor(Google_Service_Gmail_LabelColor $color)
36
+ {
37
+ $this->color = $color;
38
+ }
39
+ /**
40
+ * @return Google_Service_Gmail_LabelColor
41
+ */
42
+ public function getColor()
43
+ {
44
+ return $this->color;
45
+ }
46
  public function setId($id)
47
  {
48
  $this->id = $id;
vendor/google/apiclient-services/src/Google/Service/Gmail/LabelColor.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_LabelColor extends Google_Model
19
+ {
20
+ public $backgroundColor;
21
+ public $textColor;
22
+
23
+ public function setBackgroundColor($backgroundColor)
24
+ {
25
+ $this->backgroundColor = $backgroundColor;
26
+ }
27
+ public function getBackgroundColor()
28
+ {
29
+ return $this->backgroundColor;
30
+ }
31
+ public function setTextColor($textColor)
32
+ {
33
+ $this->textColor = $textColor;
34
+ }
35
+ public function getTextColor()
36
+ {
37
+ return $this->textColor;
38
+ }
39
+ }
vendor/google/apiclient/src/Google/AccessToken/Verify.php CHANGED
@@ -178,7 +178,7 @@ class Google_AccessToken_Verify
178
  {
179
  $certs = null;
180
  if ($cache = $this->getCache()) {
181
- $cacheItem = $cache->getItem('federated_signon_certs_v3', 3600);
182
  $certs = $cacheItem->get();
183
  }
184
 
@@ -189,6 +189,7 @@ class Google_AccessToken_Verify
189
  );
190
 
191
  if ($cache) {
 
192
  $cacheItem->set($certs);
193
  $cache->save($cacheItem);
194
  }
@@ -210,8 +211,8 @@ class Google_AccessToken_Verify
210
  $jwtClass = 'Firebase\JWT\JWT';
211
  }
212
 
213
- if (property_exists($jwtClass, 'leeway')) {
214
- // adds 1 second to JWT leeway
215
  // @see https://github.com/google/google-api-php-client/issues/827
216
  $jwtClass::$leeway = 1;
217
  }
178
  {
179
  $certs = null;
180
  if ($cache = $this->getCache()) {
181
+ $cacheItem = $cache->getItem('federated_signon_certs_v3');
182
  $certs = $cacheItem->get();
183
  }
184
 
189
  );
190
 
191
  if ($cache) {
192
+ $cacheItem->expiresAt(new DateTime('+1 hour'));
193
  $cacheItem->set($certs);
194
  $cache->save($cacheItem);
195
  }
211
  $jwtClass = 'Firebase\JWT\JWT';
212
  }
213
 
214
+ if (property_exists($jwtClass, 'leeway') && $jwtClass::$leeway < 1) {
215
+ // Ensures JWT leeway is at least 1
216
  // @see https://github.com/google/google-api-php-client/issues/827
217
  $jwtClass::$leeway = 1;
218
  }
vendor/google/apiclient/src/Google/Client.php CHANGED
@@ -25,7 +25,6 @@ use Google\Auth\Credentials\UserRefreshCredentials;
25
  use GuzzleHttp\Client;
26
  use GuzzleHttp\ClientInterface;
27
  use GuzzleHttp\Ring\Client\StreamHandler;
28
- use GuzzleHttp\Psr7;
29
  use Psr\Cache\CacheItemPoolInterface;
30
  use Psr\Http\Message\RequestInterface;
31
  use Psr\Log\LoggerInterface;
@@ -39,7 +38,7 @@ use Monolog\Handler\SyslogHandler as MonologSyslogHandler;
39
  */
40
  class Google_Client
41
  {
42
- const LIBVER = "2.2.1";
43
  const USER_AGENT_SUFFIX = "google-api-php-client/";
44
  const OAUTH2_REVOKE_URI = 'https://accounts.google.com/o/oauth2/revoke';
45
  const OAUTH2_TOKEN_URI = 'https://www.googleapis.com/oauth2/v4/token';
@@ -211,7 +210,7 @@ class Google_Client
211
 
212
  /**
213
  * Fetches a fresh access token with a given assertion token.
214
- * @param $assertionCredentials optional.
215
  * @return array access token
216
  */
217
  public function fetchAccessTokenWithAssertion(ClientInterface $authHttp = null)
@@ -441,11 +440,16 @@ class Google_Client
441
  return $this->token;
442
  }
443
 
 
 
 
444
  public function getRefreshToken()
445
  {
446
  if (isset($this->token['refresh_token'])) {
447
  return $this->token['refresh_token'];
448
  }
 
 
449
  }
450
 
451
  /**
@@ -480,6 +484,9 @@ class Google_Client
480
  return ($created + ($this->token['expires_in'] - 30)) < time();
481
  }
482
 
 
 
 
483
  public function getAuth()
484
  {
485
  throw new BadMethodCallException(
@@ -487,6 +494,9 @@ class Google_Client
487
  );
488
  }
489
 
 
 
 
490
  public function setAuth($auth)
491
  {
492
  throw new BadMethodCallException(
@@ -753,7 +763,7 @@ class Google_Client
753
  }
754
 
755
  /**
756
- * @return array
757
  * @visible For Testing
758
  */
759
  public function prepareScopes()
@@ -886,7 +896,7 @@ class Google_Client
886
  /**
887
  * Use when the service account has been delegated domain wide access.
888
  *
889
- * @param string subject an email address account to impersonate
890
  */
891
  public function setSubject($subject)
892
  {
@@ -968,7 +978,7 @@ class Google_Client
968
  }
969
 
970
  /**
971
- * @return Google\Auth\CacheInterface Cache implementation
972
  */
973
  public function setCacheConfig(array $cacheConfig)
974
  {
25
  use GuzzleHttp\Client;
26
  use GuzzleHttp\ClientInterface;
27
  use GuzzleHttp\Ring\Client\StreamHandler;
 
28
  use Psr\Cache\CacheItemPoolInterface;
29
  use Psr\Http\Message\RequestInterface;
30
  use Psr\Log\LoggerInterface;
38
  */
39
  class Google_Client
40
  {
41
+ const LIBVER = "2.2.2";
42
  const USER_AGENT_SUFFIX = "google-api-php-client/";
43
  const OAUTH2_REVOKE_URI = 'https://accounts.google.com/o/oauth2/revoke';
44
  const OAUTH2_TOKEN_URI = 'https://www.googleapis.com/oauth2/v4/token';
210
 
211
  /**
212
  * Fetches a fresh access token with a given assertion token.
213
+ * @param ClientInterface $authHttp optional.
214
  * @return array access token
215
  */
216
  public function fetchAccessTokenWithAssertion(ClientInterface $authHttp = null)
440
  return $this->token;
441
  }
442
 
443
+ /**
444
+ * @return string|null
445
+ */
446
  public function getRefreshToken()
447
  {
448
  if (isset($this->token['refresh_token'])) {
449
  return $this->token['refresh_token'];
450
  }
451
+
452
+ return null;
453
  }
454
 
455
  /**
484
  return ($created + ($this->token['expires_in'] - 30)) < time();
485
  }
486
 
487
+ /**
488
+ * @deprecated See UPGRADING.md for more information
489
+ */
490
  public function getAuth()
491
  {
492
  throw new BadMethodCallException(
494
  );
495
  }
496
 
497
+ /**
498
+ * @deprecated See UPGRADING.md for more information
499
+ */
500
  public function setAuth($auth)
501
  {
502
  throw new BadMethodCallException(
763
  }
764
 
765
  /**
766
+ * @return string|null
767
  * @visible For Testing
768
  */
769
  public function prepareScopes()
896
  /**
897
  * Use when the service account has been delegated domain wide access.
898
  *
899
+ * @param string $subject an email address account to impersonate
900
  */
901
  public function setSubject($subject)
902
  {
978
  }
979
 
980
  /**
981
+ * @param array $cacheConfig
982
  */
983
  public function setCacheConfig(array $cacheConfig)
984
  {
vendor/google/apiclient/src/Google/Service/Resource.php CHANGED
@@ -255,8 +255,14 @@ class Google_Service_Resource
255
  */
256
  public function createRequestUri($restPath, $params)
257
  {
 
 
 
 
 
 
 
258
  // code for leading slash
259
- $requestUrl = $this->servicePath . $restPath;
260
  if ($this->rootUrl) {
261
  if ('/' !== substr($this->rootUrl, -1) && '/' !== substr($requestUrl, 0, 1)) {
262
  $requestUrl = '/' . $requestUrl;
255
  */
256
  public function createRequestUri($restPath, $params)
257
  {
258
+ // Override the default servicePath address if the $restPath use a /
259
+ if ('/' == substr($restPath, 0, 1)) {
260
+ $requestUrl = substr($restPath, 1);
261
+ } else {
262
+ $requestUrl = $this->servicePath . $restPath;
263
+ }
264
+
265
  // code for leading slash
 
266
  if ($this->rootUrl) {
267
  if ('/' !== substr($this->rootUrl, -1) && '/' !== substr($requestUrl, 0, 1)) {
268
  $requestUrl = '/' . $requestUrl;
vendor/google/auth/src/ApplicationDefaultCredentials.php CHANGED
@@ -86,7 +86,7 @@ class ApplicationDefaultCredentials
86
  ) {
87
  $creds = self::getCredentials($scope, $httpHandler, $cacheConfig, $cache);
88
 
89
- return new AuthTokenSubscriber($creds, $cacheConfig);
90
  }
91
 
92
  /**
@@ -114,7 +114,7 @@ class ApplicationDefaultCredentials
114
  ) {
115
  $creds = self::getCredentials($scope, $httpHandler, $cacheConfig, $cache);
116
 
117
- return new AuthTokenMiddleware($creds, $cacheConfig);
118
  }
119
 
120
  /**
86
  ) {
87
  $creds = self::getCredentials($scope, $httpHandler, $cacheConfig, $cache);
88
 
89
+ return new AuthTokenSubscriber($creds, $httpHandler);
90
  }
91
 
92
  /**
114
  ) {
115
  $creds = self::getCredentials($scope, $httpHandler, $cacheConfig, $cache);
116
 
117
+ return new AuthTokenMiddleware($creds, $httpHandler);
118
  }
119
 
120
  /**
vendor/google/auth/src/Cache/Item.php CHANGED
@@ -134,7 +134,7 @@ final class Item implements CacheItemInterface
134
  } else {
135
  $message = 'Argument 1 passed to %s::expiresAfter() must be an ' .
136
  'instance of DateInterval or of the type integer, %s given';
137
- $error = sprintf($message, get_class($this), gettype($expiration));
138
 
139
  $this->handleError($error);
140
  }
134
  } else {
135
  $message = 'Argument 1 passed to %s::expiresAfter() must be an ' .
136
  'instance of DateInterval or of the type integer, %s given';
137
+ $error = sprintf($message, get_class($this), gettype($time));
138
 
139
  $this->handleError($error);
140
  }
vendor/google/auth/src/Cache/SysVCacheItemPool.php ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2018 Google Inc. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ namespace Google\Auth\Cache;
18
+
19
+ use Psr\Cache\CacheItemInterface;
20
+ use Psr\Cache\CacheItemPoolInterface;
21
+
22
+ /**
23
+ * SystemV shared memory based CacheItemPool implementation.
24
+ *
25
+ * This CacheItemPool implementation can be used among multiple processes, but
26
+ * it doesn't provide any locking mechanism. If multiple processes write to
27
+ * this ItemPool, you have to avoid race condition manually in your code.
28
+ */
29
+ class SysVCacheItemPool implements CacheItemPoolInterface
30
+ {
31
+ const VAR_KEY = 1;
32
+
33
+ const DEFAULT_PROJ = 'A';
34
+
35
+ const DEFAULT_MEMSIZE = 10000;
36
+
37
+ const DEFAULT_PERM = 0600;
38
+
39
+ /** @var int */
40
+ private $sysvKey;
41
+
42
+ /**
43
+ * @var CacheItemInterface[]
44
+ */
45
+ private $items;
46
+
47
+ /**
48
+ * @var CacheItemInterface[]
49
+ */
50
+ private $deferredItems;
51
+
52
+ /**
53
+ * @var array
54
+ */
55
+ private $options;
56
+
57
+ /**
58
+ * Save the current items.
59
+ *
60
+ * @return bool true when success, false upon failure
61
+ */
62
+ private function saveCurrentItems()
63
+ {
64
+ $shmid = shm_attach(
65
+ $this->sysvKey,
66
+ $this->options['memsize'],
67
+ $this->options['perm']
68
+ );
69
+ if ($shmid !== false) {
70
+ $ret = shm_put_var(
71
+ $shmid,
72
+ $this->options['variableKey'],
73
+ $this->items
74
+ );
75
+ shm_detach($shmid);
76
+ return $ret;
77
+ }
78
+ return false;
79
+ }
80
+
81
+ /**
82
+ * Load the items from the shared memory.
83
+ *
84
+ * @return bool true when success, false upon failure
85
+ */
86
+ private function loadItems()
87
+ {
88
+ $shmid = shm_attach(
89
+ $this->sysvKey,
90
+ $this->options['memsize'],
91
+ $this->options['perm']
92
+ );
93
+ if ($shmid !== false) {
94
+ $data = @shm_get_var($shmid, $this->options['variableKey']);
95
+ if (!empty($data)) {
96
+ $this->items = $data;
97
+ } else {
98
+ $this->items = [];
99
+ }
100
+ shm_detach($shmid);
101
+ return true;
102
+ }
103
+ return false;
104
+ }
105
+
106
+ /**
107
+ * Create a SystemV shared memory based CacheItemPool.
108
+ *
109
+ * @param array $options [optional] {
110
+ * Configuration options.
111
+ *
112
+ * @type int $variableKey The variable key for getting the data from
113
+ * the shared memory. **Defaults to** 1.
114
+ * @type string $proj The project identifier for ftok. This needs to
115
+ * be a one character string. **Defaults to** 'A'.
116
+ * @type int $memsize The memory size in bytes for shm_attach.
117
+ * **Defaults to** 10000.
118
+ * @type int $perm The permission for shm_attach. **Defaults to** 0600.
119
+ */
120
+ public function __construct($options = [])
121
+ {
122
+ if (! extension_loaded('sysvshm')) {
123
+ throw \RuntimeException(
124
+ 'sysvshm extension is required to use this ItemPool');
125
+ }
126
+ $this->options = $options + [
127
+ 'variableKey' => self::VAR_KEY,
128
+ 'proj' => self::DEFAULT_PROJ,
129
+ 'memsize' => self::DEFAULT_MEMSIZE,
130
+ 'perm' => self::DEFAULT_PERM
131
+ ];
132
+ $this->items = [];
133
+ $this->deferredItems = [];
134
+ $this->sysvKey = ftok(__FILE__, $this->options['proj']);
135
+ $this->loadItems();
136
+ }
137
+
138
+ /**
139
+ * {@inheritdoc}
140
+ */
141
+ public function getItem($key)
142
+ {
143
+ $this->loadItems();
144
+ return current($this->getItems([$key]));
145
+ }
146
+
147
+ /**
148
+ * {@inheritdoc}
149
+ */
150
+ public function getItems(array $keys = [])
151
+ {
152
+ $this->loadItems();
153
+ $items = [];
154
+ foreach ($keys as $key) {
155
+ $items[$key] = $this->hasItem($key) ?
156
+ clone $this->items[$key] :
157
+ new Item($key);
158
+ }
159
+ return $items;
160
+ }
161
+
162
+ /**
163
+ * {@inheritdoc}
164
+ */
165
+ public function hasItem($key)
166
+ {
167
+ $this->loadItems();
168
+ return isset($this->items[$key]) && $this->items[$key]->isHit();
169
+ }
170
+
171
+ /**
172
+ * {@inheritdoc}
173
+ */
174
+ public function clear()
175
+ {
176
+ $this->items = [];
177
+ $this->deferredItems = [];
178
+ return $this->saveCurrentItems();
179
+ }
180
+
181
+ /**
182
+ * {@inheritdoc}
183
+ */
184
+ public function deleteItem($key)
185
+ {
186
+ return $this->deleteItems([$key]);
187
+ }
188
+
189
+ /**
190
+ * {@inheritdoc}
191
+ */
192
+ public function deleteItems(array $keys)
193
+ {
194
+ foreach ($keys as $key) {
195
+ unset($this->items[$key]);
196
+ }
197
+ return $this->saveCurrentItems();
198
+ }
199
+
200
+ /**
201
+ * {@inheritdoc}
202
+ */
203
+ public function save(CacheItemInterface $item)
204
+ {
205
+ $this->items[$item->getKey()] = $item;
206
+ return $this->saveCurrentItems();
207
+ }
208
+
209
+ /**
210
+ * {@inheritdoc}
211
+ */
212
+ public function saveDeferred(CacheItemInterface $item)
213
+ {
214
+ $this->deferredItems[$item->getKey()] = $item;
215
+ return true;
216
+ }
217
+
218
+ /**
219
+ * {@inheritdoc}
220
+ */
221
+ public function commit()
222
+ {
223
+ foreach ($this->deferredItems as $item) {
224
+ if ($this->save($item) === false) {
225
+ return false;
226
+ }
227
+ }
228
+ $this->deferredItems = [];
229
+ return true;
230
+ }
231
+ }
vendor/google/auth/src/Credentials/GCECredentials.php CHANGED
@@ -102,13 +102,13 @@ class GCECredentials extends CredentialsLoader
102
 
103
  /**
104
  * Determines if this an App Engine Flexible instance, by accessing the
105
- * GAE_VM environment variable.
106
  *
107
  * @return true if this an App Engine Flexible Instance, false otherwise
108
  */
109
  public static function onAppEngineFlexible()
110
  {
111
- return isset($_SERVER['GAE_VM']) && 'true' === $_SERVER['GAE_VM'];
112
  }
113
 
114
  /**
102
 
103
  /**
104
  * Determines if this an App Engine Flexible instance, by accessing the
105
+ * GAE_INSTANCE environment variable.
106
  *
107
  * @return true if this an App Engine Flexible Instance, false otherwise
108
  */
109
  public static function onAppEngineFlexible()
110
  {
111
+ return substr(getenv('GAE_INSTANCE'), 0, 4) === 'aef-';
112
  }
113
 
114
  /**
vendor/google/auth/src/HttpHandler/Guzzle5HttpHandler.php CHANGED
@@ -16,7 +16,11 @@
16
  */
17
  namespace Google\Auth\HttpHandler;
18
 
 
19
  use GuzzleHttp\ClientInterface;
 
 
 
20
  use GuzzleHttp\Psr7\Response;
21
  use Psr\Http\Message\RequestInterface;
22
  use Psr\Http\Message\ResponseInterface;
@@ -46,17 +50,73 @@ class Guzzle5HttpHandler
46
  */
47
  public function __invoke(RequestInterface $request, array $options = [])
48
  {
49
- $request = $this->client->createRequest(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  $request->getMethod(),
51
  $request->getUri(),
52
- array_merge([
53
  'headers' => $request->getHeaders(),
54
  'body' => $request->getBody(),
55
  ], $options)
56
  );
 
57
 
58
- $response = $this->client->send($request);
59
-
60
  return new Response(
61
  $response->getStatusCode(),
62
  $response->getHeaders() ?: [],
16
  */
17
  namespace Google\Auth\HttpHandler;
18
 
19
+ use Exception;
20
  use GuzzleHttp\ClientInterface;
21
+ use GuzzleHttp\Message\ResponseInterface as Guzzle5ResponseInterface;
22
+ use GuzzleHttp\Promise\Promise;
23
+ use GuzzleHttp\Promise\RejectedPromise;
24
  use GuzzleHttp\Psr7\Response;
25
  use Psr\Http\Message\RequestInterface;
26
  use Psr\Http\Message\ResponseInterface;
50
  */
51
  public function __invoke(RequestInterface $request, array $options = [])
52
  {
53
+ $response = $this->client->send(
54
+ $this->createGuzzle5Request($request, $options)
55
+ );
56
+
57
+ return $this->createPsr7Response($response);
58
+ }
59
+
60
+ /**
61
+ * Accepts a PSR-7 request and an array of options and returns a PromiseInterface
62
+ *
63
+ * @param RequestInterface $request
64
+ * @param array $options
65
+ *
66
+ * @return Promise
67
+ */
68
+ public function async(RequestInterface $request, array $options = [])
69
+ {
70
+ if (!class_exists('GuzzleHttp\Promise\Promise')) {
71
+ throw new Exception('Install guzzlehttp/promises to use async with Guzzle 5');
72
+ }
73
+
74
+ $futureResponse = $this->client->send(
75
+ $this->createGuzzle5Request(
76
+ $request,
77
+ ['future' => true] + $options
78
+ )
79
+ );
80
+
81
+ $promise = new Promise(
82
+ function () use ($futureResponse) {
83
+ try {
84
+ $futureResponse->wait();
85
+ } catch (Exception $e) {
86
+ // The promise is already delivered when the exception is
87
+ // thrown, so don't rethrow it.
88
+ }
89
+ },
90
+ [$futureResponse, 'cancel']
91
+ );
92
+
93
+ $futureResponse->then([$promise, 'resolve'], [$promise, 'reject']);
94
+
95
+ return $promise->then(
96
+ function (Guzzle5ResponseInterface $response) {
97
+ // Adapt the Guzzle 5 Response to a PSR-7 Response.
98
+ return $this->createPsr7Response($response);
99
+ },
100
+ function (Exception $e) {
101
+ return new RejectedPromise($e);
102
+ }
103
+ );
104
+ }
105
+
106
+ private function createGuzzle5Request(RequestInterface $request, array $options)
107
+ {
108
+ return $this->client->createRequest(
109
  $request->getMethod(),
110
  $request->getUri(),
111
+ array_merge_recursive([
112
  'headers' => $request->getHeaders(),
113
  'body' => $request->getBody(),
114
  ], $options)
115
  );
116
+ }
117
 
118
+ private function createPsr7Response(Guzzle5ResponseInterface $response)
119
+ {
120
  return new Response(
121
  $response->getStatusCode(),
122
  $response->getHeaders() ?: [],
vendor/google/auth/src/HttpHandler/Guzzle6HttpHandler.php CHANGED
@@ -33,4 +33,17 @@ class Guzzle6HttpHandler
33
  {
34
  return $this->client->send($request, $options);
35
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  }
33
  {
34
  return $this->client->send($request, $options);
35
  }
36
+
37
+ /**
38
+ * Accepts a PSR-7 request and an array of options and returns a PromiseInterface
39
+ *
40
+ * @param RequestInterface $request
41
+ * @param array $options
42
+ *
43
+ * @return \GuzzleHttp\Promise\Promise
44
+ */
45
+ public function async(RequestInterface $request, array $options = [])
46
+ {
47
+ return $this->client->sendAsync($request, $options);
48
+ }
49
  }
vendor/guzzlehttp/guzzle/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011-2016 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
2
 
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
  of this software and associated documentation files (the "Software"), to deal
1
+ Copyright (c) 2011-2018 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
2
 
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
  of this software and associated documentation files (the "Software"), to deal
vendor/guzzlehttp/guzzle/src/Client.php CHANGED
@@ -290,7 +290,14 @@ class Client implements ClientInterface
290
  */
291
  private function applyOptions(RequestInterface $request, array &$options)
292
  {
293
- $modify = [];
 
 
 
 
 
 
 
294
 
295
  if (isset($options['form_params'])) {
296
  if (isset($options['multipart'])) {
@@ -302,6 +309,8 @@ class Client implements ClientInterface
302
  }
303
  $options['body'] = http_build_query($options['form_params'], '', '&');
304
  unset($options['form_params']);
 
 
305
  $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
306
  }
307
 
@@ -313,24 +322,19 @@ class Client implements ClientInterface
313
  if (isset($options['json'])) {
314
  $options['body'] = \GuzzleHttp\json_encode($options['json']);
315
  unset($options['json']);
 
 
316
  $options['_conditional']['Content-Type'] = 'application/json';
317
  }
318
 
319
  if (!empty($options['decode_content'])
320
  && $options['decode_content'] !== true
321
  ) {
 
 
322
  $modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
323
  }
324
 
325
- if (isset($options['headers'])) {
326
- if (isset($modify['set_headers'])) {
327
- $modify['set_headers'] = $options['headers'] + $modify['set_headers'];
328
- } else {
329
- $modify['set_headers'] = $options['headers'];
330
- }
331
- unset($options['headers']);
332
- }
333
-
334
  if (isset($options['body'])) {
335
  if (is_array($options['body'])) {
336
  $this->invalidBody();
@@ -344,6 +348,8 @@ class Client implements ClientInterface
344
  $type = isset($value[2]) ? strtolower($value[2]) : 'basic';
345
  switch ($type) {
346
  case 'basic':
 
 
347
  $modify['set_headers']['Authorization'] = 'Basic '
348
  . base64_encode("$value[0]:$value[1]");
349
  break;
@@ -382,6 +388,8 @@ class Client implements ClientInterface
382
  $request = Psr7\modify_request($request, $modify);
383
  if ($request->getBody() instanceof Psr7\MultipartStream) {
384
  // Use a multipart/form-data POST if a Content-Type is not set.
 
 
385
  $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
386
  . $request->getBody()->getBoundary();
387
  }
290
  */
291
  private function applyOptions(RequestInterface $request, array &$options)
292
  {
293
+ $modify = [
294
+ 'set_headers' => [],
295
+ ];
296
+
297
+ if (isset($options['headers'])) {
298
+ $modify['set_headers'] = $options['headers'];
299
+ unset($options['headers']);
300
+ }
301
 
302
  if (isset($options['form_params'])) {
303
  if (isset($options['multipart'])) {
309
  }
310
  $options['body'] = http_build_query($options['form_params'], '', '&');
311
  unset($options['form_params']);
312
+ // Ensure that we don't have the header in different case and set the new value.
313
+ $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
314
  $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
315
  }
316
 
322
  if (isset($options['json'])) {
323
  $options['body'] = \GuzzleHttp\json_encode($options['json']);
324
  unset($options['json']);
325
+ // Ensure that we don't have the header in different case and set the new value.
326
+ $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
327
  $options['_conditional']['Content-Type'] = 'application/json';
328
  }
329
 
330
  if (!empty($options['decode_content'])
331
  && $options['decode_content'] !== true
332
  ) {
333
+ // Ensure that we don't have the header in different case and set the new value.
334
+ $options['_conditional'] = Psr7\_caseless_remove(['Accept-Encoding'], $options['_conditional']);
335
  $modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
336
  }
337
 
 
 
 
 
 
 
 
 
 
338
  if (isset($options['body'])) {
339
  if (is_array($options['body'])) {
340
  $this->invalidBody();
348
  $type = isset($value[2]) ? strtolower($value[2]) : 'basic';
349
  switch ($type) {
350
  case 'basic':
351
+ // Ensure that we don't have the header in different case and set the new value.
352
+ $modify['set_headers'] = Psr7\_caseless_remove(['Authorization'], $modify['set_headers']);
353
  $modify['set_headers']['Authorization'] = 'Basic '
354
  . base64_encode("$value[0]:$value[1]");
355
  break;
388
  $request = Psr7\modify_request($request, $modify);
389
  if ($request->getBody() instanceof Psr7\MultipartStream) {
390
  // Use a multipart/form-data POST if a Content-Type is not set.
391
+ // Ensure that we don't have the header in different case and set the new value.
392
+ $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
393
  $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
394
  . $request->getBody()->getBoundary();
395
  }
vendor/guzzlehttp/guzzle/src/ClientInterface.php CHANGED
@@ -12,7 +12,7 @@ use Psr\Http\Message\UriInterface;
12
  */
13
  interface ClientInterface
14
  {
15
- const VERSION = '6.2.1';
16
 
17
  /**
18
  * Send an HTTP request.
12
  */
13
  interface ClientInterface
14
  {
15
+ const VERSION = '6.3.3';
16
 
17
  /**
18
  * Send an HTTP request.
vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php CHANGED
@@ -95,11 +95,11 @@ class CookieJar implements CookieJarInterface
95
  public function getCookieByName($name)
96
  {
97
  // don't allow a null name
98
- if($name === null) {
99
  return null;
100
  }
101
- foreach($this->cookies as $cookie) {
102
- if($cookie->getName() !== null && strcasecmp($cookie->getName(), $name) === 0) {
103
  return $cookie;
104
  }
105
  }
95
  public function getCookieByName($name)
96
  {
97
  // don't allow a null name
98
+ if ($name === null) {
99
  return null;
100
  }
101
+ foreach ($this->cookies as $cookie) {
102
+ if ($cookie->getName() !== null && strcasecmp($cookie->getName(), $name) === 0) {
103
  return $cookie;
104
  }
105
  }
vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php CHANGED
@@ -15,7 +15,7 @@ class SessionCookieJar extends CookieJar
15
  /**
16
  * Create a new SessionCookieJar object
17
  *
18
- * @param string $sessionKey Session key name to store the cookie
19
  * data in session
20
  * @param bool $storeSessionCookies Set to true to store session cookies
21
  * in the cookie jar.
15
  /**
16
  * Create a new SessionCookieJar object
17
  *
18
+ * @param string $sessionKey Session key name to store the cookie
19
  * data in session
20
  * @param bool $storeSessionCookies Set to true to store session cookies
21
  * in the cookie jar.
vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php CHANGED
@@ -35,14 +35,13 @@ class SetCookie
35
  $data = self::$defaults;
36
  // Explode the cookie string using a series of semicolons
37
  $pieces = array_filter(array_map('trim', explode(';', $cookie)));
38
- // The name of the cookie (first kvp) must include an equal sign.
39
- if (empty($pieces) || !strpos($pieces[0], '=')) {
40
  return new self($data);
41
  }
42
 
43
  // Add the cookie pieces into the parsed data array
44
  foreach ($pieces as $part) {
45
-
46
  $cookieParts = explode('=', $part, 2);
47
  $key = trim($cookieParts[0]);
48
  $value = isset($cookieParts[1])
@@ -349,7 +348,7 @@ class SetCookie
349
  return false;
350
  }
351
 
352
- return (bool) preg_match('/\.' . preg_quote($cookieDomain) . '$/', $domain);
353
  }
354
 
355
  /**
@@ -359,7 +358,7 @@ class SetCookie
359
  */
360
  public function isExpired()
361
  {
362
- return $this->getExpires() && time() > $this->getExpires();
363
  }
364
 
365
  /**
@@ -378,8 +377,8 @@ class SetCookie
378
  // Check if any of the invalid characters are present in the cookie name
379
  if (preg_match(
380
  '/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/',
381
- $name)
382
- ) {
383
  return 'Cookie name must not contain invalid characters: ASCII '
384
  . 'Control characters (0-31;127), space, tab and the '
385
  . 'following characters: ()<>@,;:\"/?={}';
35
  $data = self::$defaults;
36
  // Explode the cookie string using a series of semicolons
37
  $pieces = array_filter(array_map('trim', explode(';', $cookie)));
38
+ // The name of the cookie (first kvp) must exist and include an equal sign.
39
+ if (empty($pieces[0]) || !strpos($pieces[0], '=')) {
40
  return new self($data);
41
  }
42
 
43
  // Add the cookie pieces into the parsed data array
44
  foreach ($pieces as $part) {
 
45
  $cookieParts = explode('=', $part, 2);
46
  $key = trim($cookieParts[0]);
47
  $value = isset($cookieParts[1])
348
  return false;
349
  }
350
 
351
+ return (bool) preg_match('/\.' . preg_quote($cookieDomain, '/') . '$/', $domain);
352
  }
353
 
354
  /**
358
  */
359
  public function isExpired()
360
  {
361
+ return $this->getExpires() !== null && time() > $this->getExpires();
362
  }
363
 
364
  /**
377
  // Check if any of the invalid characters are present in the cookie name
378
  if (preg_match(
379
  '/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/',
380
+ $name
381
+ )) {
382
  return 'Cookie name must not contain invalid characters: ASCII '
383
  . 'Control characters (0-31;127), space, tab and the '
384
  . 'following characters: ()<>@,;:\"/?={}';
vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php CHANGED
@@ -1,4 +1,13 @@
1
  <?php
2
  namespace GuzzleHttp\Exception;
3
 
 
 
 
 
 
 
 
 
 
4
  interface GuzzleException {}
1
  <?php
2
  namespace GuzzleHttp\Exception;
3
 
4
+ /**
5
+ * @method string getMessage()
6
+ * @method \Throwable|null getPrevious()
7
+ * @method mixed getCode()
8
+ * @method string getFile()
9
+ * @method int getLine()
10
+ * @method array getTrace()
11
+ * @method string getTraceAsString()
12
+ */
13
  interface GuzzleException {}
vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php CHANGED
@@ -4,7 +4,6 @@ namespace GuzzleHttp\Handler;
4
  use GuzzleHttp\Exception\RequestException;
5
  use GuzzleHttp\Exception\ConnectException;
6
  use GuzzleHttp\Promise\FulfilledPromise;
7
- use GuzzleHttp\Promise\RejectedPromise;
8
  use GuzzleHttp\Psr7;
9
  use GuzzleHttp\Psr7\LazyOpenStream;
10
  use GuzzleHttp\TransferStats;
@@ -288,7 +287,14 @@ class CurlFactory implements CurlFactoryInterface
288
  {
289
  foreach ($conf['_headers'] as $name => $values) {
290
  foreach ($values as $value) {
291
- $conf[CURLOPT_HTTPHEADER][] = "$name: $value";
 
 
 
 
 
 
 
292
  }
293
  }
294
 
@@ -388,7 +394,7 @@ class CurlFactory implements CurlFactoryInterface
388
  if (isset($options['force_ip_resolve'])) {
389
  if ('v4' === $options['force_ip_resolve']) {
390
  $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
391
- } else if ('v6' === $options['force_ip_resolve']) {
392
  $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V6;
393
  }
394
  }
4
  use GuzzleHttp\Exception\RequestException;
5
  use GuzzleHttp\Exception\ConnectException;
6
  use GuzzleHttp\Promise\FulfilledPromise;
 
7
  use GuzzleHttp\Psr7;
8
  use GuzzleHttp\Psr7\LazyOpenStream;
9
  use GuzzleHttp\TransferStats;
287
  {
288
  foreach ($conf['_headers'] as $name => $values) {
289
  foreach ($values as $value) {
290
+ $value = (string) $value;
291
+ if ($value === '') {
292
+ // cURL requires a special format for empty headers.
293
+ // See https://github.com/guzzle/guzzle/issues/1882 for more details.
294
+ $conf[CURLOPT_HTTPHEADER][] = "$name;";
295
+ } else {
296
+ $conf[CURLOPT_HTTPHEADER][] = "$name: $value";
297
+ }
298
  }
299
  }
300
 
394
  if (isset($options['force_ip_resolve'])) {
395
  if ('v4' === $options['force_ip_resolve']) {
396
  $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
397
+ } elseif ('v6' === $options['force_ip_resolve']) {
398
  $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V6;
399
  }
400
  }
vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php CHANGED
@@ -65,7 +65,9 @@ class CurlMultiHandler
65
 
66
  $promise = new Promise(
67
  [$this, 'execute'],
68
- function () use ($id) { return $this->cancel($id); }
 
 
69
  );
70
 
71
  $this->addRequest(['easy' => $easy, 'deferred' => $promise]);
65
 
66
  $promise = new Promise(
67
  [$this, 'execute'],
68
+ function () use ($id) {
69
+ return $this->cancel($id);
70
+ }
71
  );
72
 
73
  $this->addRequest(['easy' => $easy, 'deferred' => $promise]);
vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php CHANGED
@@ -4,7 +4,6 @@ namespace GuzzleHttp\Handler;
4
  use GuzzleHttp\Exception\RequestException;
5
  use GuzzleHttp\Exception\ConnectException;
6
  use GuzzleHttp\Promise\FulfilledPromise;
7
- use GuzzleHttp\Promise\RejectedPromise;
8
  use GuzzleHttp\Promise\PromiseInterface;
9
  use GuzzleHttp\Psr7;
10
  use GuzzleHttp\TransferStats;
@@ -61,6 +60,7 @@ class StreamHandler
61
  if (strpos($message, 'getaddrinfo') // DNS lookup failed
62
  || strpos($message, 'Connection refused')
63
  || strpos($message, "couldn't connect to host") // error on HHVM
 
64
  ) {
65
  $e = new ConnectException($e->getMessage(), $request, $e);
66
  }
@@ -103,7 +103,7 @@ class StreamHandler
103
  $status = $parts[1];
104
  $reason = isset($parts[2]) ? $parts[2] : null;
105
  $headers = \GuzzleHttp\headers_from_lines($hdrs);
106
- list ($stream, $headers) = $this->checkDecode($options, $headers, $stream);
107
  $stream = Psr7\stream_for($stream);
108
  $sink = $stream;
109
 
@@ -276,7 +276,7 @@ class StreamHandler
276
  }
277
 
278
  $params = [];
279
- $context = $this->getDefaultContext($request, $options);
280
 
281
  if (isset($options['on_headers']) && !is_callable($options['on_headers'])) {
282
  throw new \InvalidArgumentException('on_headers must be callable');
@@ -307,7 +307,6 @@ class StreamHandler
307
  && isset($options['auth'][2])
308
  && 'ntlm' == $options['auth'][2]
309
  ) {
310
-
311
  throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
312
  }
313
 
4
  use GuzzleHttp\Exception\RequestException;
5
  use GuzzleHttp\Exception\ConnectException;
6
  use GuzzleHttp\Promise\FulfilledPromise;
 
7
  use GuzzleHttp\Promise\PromiseInterface;
8
  use GuzzleHttp\Psr7;
9
  use GuzzleHttp\TransferStats;
60
  if (strpos($message, 'getaddrinfo') // DNS lookup failed
61
  || strpos($message, 'Connection refused')
62
  || strpos($message, "couldn't connect to host") // error on HHVM
63
+ || strpos($message, "connection attempt failed")
64
  ) {
65
  $e = new ConnectException($e->getMessage(), $request, $e);
66
  }
103
  $status = $parts[1];
104
  $reason = isset($parts[2]) ? $parts[2] : null;
105
  $headers = \GuzzleHttp\headers_from_lines($hdrs);
106
+ list($stream, $headers) = $this->checkDecode($options, $headers, $stream);
107
  $stream = Psr7\stream_for($stream);
108
  $sink = $stream;
109
 
276
  }
277
 
278
  $params = [];
279
+ $context = $this->getDefaultContext($request);
280
 
281
  if (isset($options['on_headers']) && !is_callable($options['on_headers'])) {
282
  throw new \InvalidArgumentException('on_headers must be callable');
307
  && isset($options['auth'][2])
308
  && 'ntlm' == $options['auth'][2]
309
  ) {
 
310
  throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
311
  }
312
 
vendor/guzzlehttp/guzzle/src/HandlerStack.php CHANGED
@@ -22,7 +22,7 @@ class HandlerStack
22
  * Creates a default handler stack that can be used by clients.
23
  *
24
  * The returned handler will wrap the provided handler or use the most
25
- * appropriate default handler for you system. The returned HandlerStack has
26
  * support for cookies, redirects, HTTP error exceptions, and preparing a body
27
  * before sending.
28
  *
22
  * Creates a default handler stack that can be used by clients.
23
  *
24
  * The returned handler will wrap the provided handler or use the most
25
+ * appropriate default handler for your system. The returned HandlerStack has
26
  * support for cookies, redirects, HTTP error exceptions, and preparing a body
27
  * before sending.
28
  *
vendor/guzzlehttp/guzzle/src/MessageFormatter.php CHANGED
@@ -19,7 +19,6 @@ use Psr\Http\Message\ResponseInterface;
19
  * - {host}: Host of the request
20
  * - {method}: Method of the request
21
  * - {uri}: URI of the request
22
- * - {host}: Host of the request
23
  * - {version}: Protocol version
24
  * - {target}: Request target of the request (path + query + fragment)
25
  * - {hostname}: Hostname of the machine that sent the request
@@ -74,7 +73,6 @@ class MessageFormatter
74
  return preg_replace_callback(
75
  '/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
76
  function (array $matches) use ($request, $response, $error, &$cache) {
77
-
78
  if (isset($cache[$matches[1]])) {
79
  return $cache[$matches[1]];
80
  }
19
  * - {host}: Host of the request
20
  * - {method}: Method of the request
21
  * - {uri}: URI of the request
 
22
  * - {version}: Protocol version
23
  * - {target}: Request target of the request (path + query + fragment)
24
  * - {hostname}: Hostname of the machine that sent the request
73
  return preg_replace_callback(
74
  '/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
75
  function (array $matches) use ($request, $response, $error, &$cache) {
 
76
  if (isset($cache[$matches[1]])) {
77
  return $cache[$matches[1]];
78
  }
vendor/guzzlehttp/guzzle/src/Middleware.php CHANGED
@@ -34,10 +34,11 @@ final class Middleware
34
  $cookieJar = $options['cookies'];
35
  $request = $cookieJar->withCookieHeader($request);
36
  return $handler($request, $options)
37
- ->then(function ($response) use ($cookieJar, $request) {
38
- $cookieJar->extractCookies($request, $response);
39
- return $response;
40
- }
 
41
  );
42
  };
43
  };
@@ -72,7 +73,7 @@ final class Middleware
72
  /**
73
  * Middleware that pushes history data to an ArrayAccess container.
74
  *
75
- * @param array $container Container to hold the history (by reference).
76
  *
77
  * @return callable Returns a function that accepts the next handler.
78
  * @throws \InvalidArgumentException if container is not an array or ArrayAccess.
34
  $cookieJar = $options['cookies'];
35
  $request = $cookieJar->withCookieHeader($request);
36
  return $handler($request, $options)
37
+ ->then(
38
+ function ($response) use ($cookieJar, $request) {
39
+ $cookieJar->extractCookies($request, $response);
40
+ return $response;
41
+ }
42
  );
43
  };
44
  };
73
  /**
74
  * Middleware that pushes history data to an ArrayAccess container.
75
  *
76
+ * @param array|\ArrayAccess $container Container to hold the history (by reference).
77
  *
78
  * @return callable Returns a function that accepts the next handler.
79
  * @throws \InvalidArgumentException if container is not an array or ArrayAccess.
vendor/guzzlehttp/guzzle/src/UriTemplate.php CHANGED
@@ -107,7 +107,6 @@ class UriTemplate
107
  $useQuery = self::$operatorHash[$parsed['operator']]['query'];
108
 
109
  foreach ($parsed['values'] as $value) {
110
-
111
  if (!isset($this->variables[$value['value']])) {
112
  continue;
113
  }
@@ -117,11 +116,9 @@ class UriTemplate
117
  $expanded = '';
118
 
119
  if (is_array($variable)) {
120
-
121
  $isAssoc = $this->isAssoc($variable);
122
  $kvp = [];
123
  foreach ($variable as $key => $var) {
124
-
125
  if ($isAssoc) {
126
  $key = rawurlencode($key);
127
  $isNestedArray = is_array($var);
@@ -179,7 +176,6 @@ class UriTemplate
179
  }
180
  $expanded = implode(',', $kvp);
181
  }
182
-
183
  } else {
184
  if ($value['modifier'] === ':') {
185
  $variable = substr($variable, 0, $value['position']);
107
  $useQuery = self::$operatorHash[$parsed['operator']]['query'];
108
 
109
  foreach ($parsed['values'] as $value) {
 
110
  if (!isset($this->variables[$value['value']])) {
111
  continue;
112
  }
116
  $expanded = '';
117
 
118
  if (is_array($variable)) {
 
119
  $isAssoc = $this->isAssoc($variable);
120
  $kvp = [];
121
  foreach ($variable as $key => $var) {
 
122
  if ($isAssoc) {
123
  $key = rawurlencode($key);
124
  $isNestedArray = is_array($var);
176
  }
177
  $expanded = implode(',', $kvp);
178
  }
 
179
  } else {
180
  if ($value['modifier'] === ':') {
181
  $variable = substr($variable, 0, $value['position']);
vendor/guzzlehttp/guzzle/src/functions.php CHANGED
@@ -302,7 +302,8 @@ function json_decode($json, $assoc = false, $depth = 512, $options = 0)
302
  $data = \json_decode($json, $assoc, $depth, $options);
303
  if (JSON_ERROR_NONE !== json_last_error()) {
304
  throw new \InvalidArgumentException(
305
- 'json_decode error: ' . json_last_error_msg());
 
306
  }
307
 
308
  return $data;
@@ -324,7 +325,8 @@ function json_encode($value, $options = 0, $depth = 512)
324
  $json = \json_encode($value, $options, $depth);
325
  if (JSON_ERROR_NONE !== json_last_error()) {
326
  throw new \InvalidArgumentException(
327
- 'json_encode error: ' . json_last_error_msg());
 
328
  }
329
 
330
  return $json;
302
  $data = \json_decode($json, $assoc, $depth, $options);
303
  if (JSON_ERROR_NONE !== json_last_error()) {
304
  throw new \InvalidArgumentException(
305
+ 'json_decode error: ' . json_last_error_msg()
306
+ );
307
  }
308
 
309
  return $data;
325
  $json = \json_encode($value, $options, $depth);
326
  if (JSON_ERROR_NONE !== json_last_error()) {
327
  throw new \InvalidArgumentException(
328
+ 'json_encode error: ' . json_last_error_msg()
329
+ );
330
  }
331
 
332
  return $json;
vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php CHANGED
@@ -468,23 +468,27 @@ class RSA
468
  break;
469
  case extension_loaded('openssl') && file_exists($this->configFile):
470
  // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
471
- ob_start();
472
- @phpinfo();
473
- $content = ob_get_contents();
474
- ob_end_clean();
475
-
476
- preg_match_all('#OpenSSL (Header|Library) Version(.*)#im', $content, $matches);
477
-
478
  $versions = array();
479
- if (!empty($matches[1])) {
480
- for ($i = 0; $i < count($matches[1]); $i++) {
481
- $fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
482
-
483
- // Remove letter part in OpenSSL version
484
- if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) {
485
- $versions[$matches[1][$i]] = $fullVersion;
486
- } else {
487
- $versions[$matches[1][$i]] = $m[0];
 
 
 
 
 
 
 
 
 
 
 
488
  }
489
  }
490
  }
468
  break;
469
  case extension_loaded('openssl') && file_exists($this->configFile):
470
  // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
 
 
 
 
 
 
 
471
  $versions = array();
472
+
473
+ // avoid generating errors (even with suppression) when phpinfo() is disabled (common in production systems)
474
+ if (strpos(ini_get('disable_functions'), 'phpinfo') === false) {
475
+ ob_start();
476
+ @phpinfo();
477
+ $content = ob_get_contents();
478
+ ob_end_clean();
479
+
480
+ preg_match_all('#OpenSSL (Header|Library) Version(.*)#im', $content, $matches);
481
+
482
+ if (!empty($matches[1])) {
483
+ for ($i = 0; $i < count($matches[1]); $i++) {
484
+ $fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
485
+
486
+ // Remove letter part in OpenSSL version
487
+ if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) {
488
+ $versions[$matches[1][$i]] = $fullVersion;
489
+ } else {
490
+ $versions[$matches[1][$i]] = $m[0];
491
+ }
492
  }
493
  }
494
  }
vendor/phpseclib/phpseclib/phpseclib/Crypt/Random.php CHANGED
@@ -45,6 +45,10 @@ class Random
45
  */
46
  static function string($length)
47
  {
 
 
 
 
48
  if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
49
  try {
50
  return \random_bytes($length);
45
  */
46
  static function string($length)
47
  {
48
+ if (!$length) {
49
+ return '';
50
+ }
51
+
52
  if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
53
  try {
54
  return \random_bytes($length);
vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php CHANGED
@@ -266,23 +266,27 @@ class BigInteger
266
 
267
  if (extension_loaded('openssl') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
268
  // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
269
- ob_start();
270
- @phpinfo();
271
- $content = ob_get_contents();
272
- ob_end_clean();
273
 
274
- preg_match_all('#OpenSSL (Header|Library) Version(.*)#im', $content, $matches);
 
 
 
 
 
275
 
276
- $versions = array();
277
- if (!empty($matches[1])) {
278
- for ($i = 0; $i < count($matches[1]); $i++) {
279
- $fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
280
-
281
- // Remove letter part in OpenSSL version
282
- if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) {
283
- $versions[$matches[1][$i]] = $fullVersion;
284
- } else {
285
- $versions[$matches[1][$i]] = $m[0];
 
 
286
  }
287
  }
288
  }
@@ -535,7 +539,7 @@ class BigInteger
535
  $temp = $comparison < 0 ? $this->add(new static(1)) : $this->copy();
536
  $bytes = $temp->toBytes();
537
 
538
- if (empty($bytes)) { // eg. if the number we're trying to convert is -1
539
  $bytes = chr(0);
540
  }
541
 
@@ -2868,8 +2872,7 @@ class BigInteger
2868
  switch (MATH_BIGINTEGER_MODE) {
2869
  case self::MODE_GMP:
2870
  $temp = new static();
2871
- $temp->value = gmp_xor($this->value, $x->value);
2872
-
2873
  return $this->_normalize($temp);
2874
  case self::MODE_BCMATH:
2875
  $left = $this->toBytes();
@@ -2885,6 +2888,7 @@ class BigInteger
2885
 
2886
  $length = max(count($this->value), count($x->value));
2887
  $result = $this->copy();
 
2888
  $result->value = array_pad($result->value, $length, 0);
2889
  $x->value = array_pad($x->value, $length, 0);
2890
 
266
 
267
  if (extension_loaded('openssl') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
268
  // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
269
+ $versions = array();
 
 
 
270
 
271
+ // avoid generating errors (even with suppression) when phpinfo() is disabled (common in production systems)
272
+ if (strpos(ini_get('disable_functions'), 'phpinfo') === false) {
273
+ ob_start();
274
+ @phpinfo();
275
+ $content = ob_get_contents();
276
+ ob_end_clean();
277
 
278
+ preg_match_all('#OpenSSL (Header|Library) Version(.*)#im', $content, $matches);
279
+
280
+ if (!empty($matches[1])) {
281
+ for ($i = 0; $i < count($matches[1]); $i++) {
282
+ $fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
283
+
284
+ // Remove letter part in OpenSSL version
285
+ if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) {
286
+ $versions[$matches[1][$i]] = $fullVersion;
287
+ } else {
288
+ $versions[$matches[1][$i]] = $m[0];
289
+ }
290
  }
291
  }
292
  }
539
  $temp = $comparison < 0 ? $this->add(new static(1)) : $this->copy();
540
  $bytes = $temp->toBytes();
541
 
542
+ if (!strlen($bytes)) { // eg. if the number we're trying to convert is -1
543
  $bytes = chr(0);
544
  }
545
 
2872
  switch (MATH_BIGINTEGER_MODE) {
2873
  case self::MODE_GMP:
2874
  $temp = new static();
2875
+ $temp->value = gmp_xor(gmp_abs($this->value), gmp_abs($x->value));
 
2876
  return $this->_normalize($temp);
2877
  case self::MODE_BCMATH:
2878
  $left = $this->toBytes();
2888
 
2889
  $length = max(count($this->value), count($x->value));
2890
  $result = $this->copy();
2891
+ $result->is_negative = false;
2892
  $result->value = array_pad($result->value, $length, 0);
2893
  $x->value = array_pad($x->value, $length, 0);
2894
 
wp-mail-smtp.php CHANGED
@@ -4,58 +4,7 @@ if ( ! defined( 'ABSPATH' ) ) {
4
  exit; // Exit if accessed directly.
5
  }
6
 
7
- /**
8
- * Autoloader. Inspired by PSR-4 examples:
9
- *
10
- * @link https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md
11
- *
12
- * @since 1.0.0
13
- *
14
- * @param string $class The fully-qualified class name.
15
- */
16
- spl_autoload_register( function ( $class ) {
17
-
18
- list( $plugin_space ) = explode( '\\', $class );
19
- if ( $plugin_space !== 'WPMailSMTP' ) {
20
- return;
21
- }
22
-
23
- $plugin_folder = 'wp-mail-smtp';
24
-
25
- // Default directory for all code is plugin's /src/.
26
- $base_dir = WP_PLUGIN_DIR . '/' . $plugin_folder . '/src/';
27
-
28
- // Get the relative class name.
29
- $relative_class = substr( $class, strlen( $plugin_space ) + 1 );
30
-
31
- /**
32
- * Normalize a filesystem path.
33
- * Copy of the `wp_normalize_path()` from WordPress 3.9.
34
- *
35
- * @since 1.2.0
36
- *
37
- * @param string $path
38
- *
39
- * @return string
40
- */
41
- $normalize = function( $path ) {
42
- $path = str_replace( '\\', '/', $path );
43
- $path = preg_replace( '|(?<=.)/+|', '/', $path );
44
- if ( ':' === substr( $path, 1, 1 ) ) {
45
- $path = ucfirst( $path );
46
- }
47
- return $path;
48
- };
49
-
50
- // Prepare a path to a file.
51
- $file = $normalize( $base_dir . $relative_class . '.php' );
52
-
53
- // If the file exists, require it.
54
- if ( is_readable( $file ) ) {
55
- /** @noinspection PhpIncludeInspection */
56
- require_once $file;
57
- }
58
- } );
59
 
60
  /**
61
  * Global function-holder. Works similar to a singleton's instance().
4
  exit; // Exit if accessed directly.
5
  }
6
 
7
+ require_once __DIR__ . '/vendor/autoload.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  /**
10
  * Global function-holder. Works similar to a singleton's instance().
wp_mail_smtp.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /**
3
  * Plugin Name: WP Mail SMTP
4
- * Version: 1.2.5
5
  * Plugin URI: https://wpforms.com/
6
  * Description: Reconfigures the wp_mail() function to use SMTP instead of mail() and creates an options page to manage the settings.
7
  * Author: WPForms
@@ -12,12 +12,12 @@
12
 
13
  /**
14
  * @author WPForms
15
- * @copyright WPForms, 2007-17, All Rights Reserved
16
  * This code is released under the GPL licence version 3 or later, available here
17
  * http://www.gnu.org/licenses/gpl.txt
18
  */
19
 
20
- define( 'WPMS_PLUGIN_VER', '1.2.5' );
21
  define( 'WPMS_PHP_VER', '5.3' );
22
 
23
  /**
1
  <?php
2
  /**
3
  * Plugin Name: WP Mail SMTP
4
+ * Version: 1.3.0
5
  * Plugin URI: https://wpforms.com/
6
  * Description: Reconfigures the wp_mail() function to use SMTP instead of mail() and creates an options page to manage the settings.
7
  * Author: WPForms
12
 
13
  /**
14
  * @author WPForms
15
+ * @copyright WPForms, 2007-18, All Rights Reserved
16
  * This code is released under the GPL licence version 3 or later, available here
17
  * http://www.gnu.org/licenses/gpl.txt
18
  */
19
 
20
+ define( 'WPMS_PLUGIN_VER', '1.3.0' );
21
  define( 'WPMS_PHP_VER', '5.3' );
22
 
23
  /**