Version Description
- 2019-12-12 =
- Added: New recommended mailer: Pepipost.
- Added: "Suggest a Mailer" link in a list of mailers to send us your ideas about new ones.
- Fixed: Sendgrid: Content ID for attachments missing.
- Changed: Timeout to HTTP requests (pepipost, sendgrid, mailgun), same as max_execution_time, to prevent fails when sending emails with big attachments.
Download this release
Release Info
Developer | slaFFik |
Plugin | WP Mail SMTP by WPForms |
Version | 1.8.0 |
Comparing to | |
See all releases |
Code changes from version 1.7.1 to 1.8.0
- assets/css/smtp-admin.min.css +1 -1
- assets/images/providers/pepipost-smtp.png +0 -0
- assets/images/providers/pepipost.png +0 -0
- assets/js/smtp-about.js +190 -190
- assets/languages/wp-mail-smtp.pot +67 -37
- readme.txt +395 -377
- src/Admin/Area.php +889 -889
- src/Admin/Pages/About.php +702 -702
- src/Admin/Pages/SettingsTab.php +546 -537
- src/Admin/PluginsInstallSkin.php +55 -55
- src/Options.php +38 -13
- src/Processor.php +232 -232
- src/Providers/Loader.php +205 -204
- src/Providers/MailerAbstract.php +24 -4
- src/Providers/Pepipost/Options.php +2 -2
- src/Providers/PepipostAPI/Mailer.php +440 -0
- src/Providers/PepipostAPI/Options.php +119 -0
- src/Providers/Sendgrid/Mailer.php +1 -0
- src/Providers/Sendinblue/Options.php +119 -119
- vendor/guzzlehttp/guzzle/phpstan-baseline.neon +1412 -0
- vendor/guzzlehttp/guzzle/src/Client.php +531 -422
- vendor/guzzlehttp/guzzle/src/ClientInterface.php +87 -84
- vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php +316 -314
- vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php +84 -84
- vendor/guzzlehttp/guzzle/src/Exception/RequestException.php +192 -217
- vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php +585 -580
- vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php +219 -205
- vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php +195 -190
- vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php +544 -544
- vendor/guzzlehttp/guzzle/src/HandlerStack.php +277 -273
- vendor/guzzlehttp/guzzle/src/MessageFormatter.php +185 -180
- vendor/guzzlehttp/guzzle/src/Pool.php +132 -123
- vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php +111 -106
- vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php +249 -237
- vendor/guzzlehttp/guzzle/src/RequestOptions.php +263 -255
- vendor/guzzlehttp/guzzle/src/RetryMiddleware.php +128 -115
- vendor/guzzlehttp/guzzle/src/TransferStats.php +126 -126
- vendor/guzzlehttp/guzzle/src/functions.php +346 -346
- vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php +3 -1
- vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php +3 -2
- vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php +2 -2
- vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php +1 -1
- vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php +1 -1
- vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php +4 -125
- vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php +5 -4
- vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php +19 -0
- vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php +3 -2
- vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php +3 -2
- vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php +41 -11
- vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php +44 -14
- vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php +2 -1
- vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php +2 -1
- vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php +2 -1
- vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php +2 -1
- vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php +42 -11
- vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php +7 -2
- vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php +2 -1
- vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php +2 -1
- vendor/monolog/monolog/src/Monolog/Utils.php +134 -0
- wp_mail_smtp.php +167 -166
assets/css/smtp-admin.min.css
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
-
#wpcontent{padding-left:0 !important;position:relative}@media (max-width: 600px){#wpcontent{padding-top:46px}}@media (max-width: 600px){#wpbody{padding-top:0}}body.toplevel_page_wp-mail-smtp div.jconfirm *,body.toplevel_page_wp-mail-smtp div.jconfirm *::before,body.toplevel_page_wp-mail-smtp div.jconfirm *::after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box-container div.jconfirm-box{border-radius:0;box-shadow:0 2px 6px rgba(0,0,0,0.2)}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box-container div.jconfirm-box div.jconfirm-closeIcon{color:rgba(0,0,0,0.4);top:8px;right:8px}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box-container div.jconfirm-box div.jconfirm-closeIcon:hover{color:rgba(0,0,0,0.8)}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-title-c{margin:0 0 26px 0 !important;padding:0 !important}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-title-c .jconfirm-icon-c{margin:0 !important;color:#c4c4c4 !important;-webkit-transition:none !important;transition:none !important;-webkit-transform:none !important;-ms-transform:none !important;transform:none !important;font-size:45px !important}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-title-c .jconfirm-icon-c i:empty{display:none}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-title-c .jconfirm-icon-c svg{height:35px}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-title-c .jconfirm-title{display:block;color:#333}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-title-c .jconfirm-icon-c+span.jconfirm-title{margin-top:20px !important}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content-pane{margin-bottom:0;display:block}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content-pane .jconfirm-content{overflow:inherit}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content{font-size:16px;color:#555;line-height:1.4}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content.lite-upgrade p{font-size:18px;padding:0 20px}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content p{margin:0 0 16px;font-size:18px;line-height:1.5}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content p:last-of-type{margin:0}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content p.large{font-size:18px}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content p.small{font-size:14px}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content .already-purchased{font-size:12px;color:#ccc;text-decoration:none}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content .already-purchased:hover{text-decoration:underline}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-buttons .already-purchased{display:block;font-size:12px;color:#aaa;text-decoration:none;padding-top:20px}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-buttons .already-purchased:hover{color:#999;text-decoration:underline}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box .discount-note{text-align:center;margin:30px 0 0}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box .discount-note p{background-color:#faffac;margin:0 -30px;padding:24px 60px 20px;font-size:15px;color:#4d4d4d;position:relative}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box .discount-note p:after{content:'\f058';display:inline-block;font:normal normal normal 14px/1 FontAwesome;background-color:#fff;font-size:26px;border-radius:50%;padding:5px 6px;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;top:-20px;right:50%;margin-right:-18px;color:#3abc01}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box .discount-note span{font-weight:700;color:#3abc01}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box .discount-note a{color:#aaa;display:block;margin-top:12px}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box input[type=text]{display:block;width:99%;border:1px solid #d6d6d6;padding:10px;box-shadow:none;margin:20px auto 0 auto}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box button.btn-confirm{background-color:#FF982D;color:#fff;outline:none}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box button.btn-confirm:hover{background-color:#f97f00;border-color:#f97f00}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box button,body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box button.btn-default{color:#666}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box button.btn-block{display:block;text-align:center;width:100%;margin:0 0 10px 0 !important}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box button.btn-normal-case{text-transform:none !important}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box .error{display:none;color:red}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box .wpforms-error{border:1px solid #ebccd1 !important}#wp-mail-smtp-header{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-hide{display:none}#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.tab{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.tab.active{border-bottom:2px solid #FF982D}#wp-mail-smtp .wp-mail-smtp-page-title a.tab:hover{border-color:#999}#wp-mail-smtp .wp-mail-smtp-page-title a.action{padding:5px;border:0;min-height:auto;color:#fff;margin:-10px 0 0 20px}#wp-mail-smtp .wp-mail-smtp-page-title .page-title{background-color:#fff;display:inline-block;font-size:23px;margin:0;padding:15px 20px 15px 0}#wp-mail-smtp .wp-mail-smtp-page-content{padding:0 20px}#wp-mail-smtp .wp-mail-smtp-page-content *,#wp-mail-smtp .wp-mail-smtp-page-content *::before,#wp-mail-smtp .wp-mail-smtp-page-content *::after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-clear:before{content:" ";display:table}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-clear:after{clear:both;content:" ";display:table}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .wp-mail-smtp-setting-row:first-of-type{padding-top:10px !important}@media (max-width: 781px){#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row{padding:20px 0}}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.inactive{display:none}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row .wp-mail-smtp-setting-mid-row-sep{background:#e4e4e4;height:1px;border:0;margin:15px 0}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.section-heading{padding:20px 0}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.section-heading.no-desc h2,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.section-heading.no-desc h4{margin:0}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.section-heading .wp-mail-smtp-setting-field{margin:0;max-width:1005px}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .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-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox .desc{margin:0 0 0 30px}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-text .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-password .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-number .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page-content .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-content .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-content .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-content .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-content .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-content .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-content .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-content .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:#46B450}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:disabled+.wp-mail-smtp-setting-toggle-switch{background-color:#69c471;cursor:default}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .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-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:disabled+.wp-mail-smtp-setting-toggle-switch+.wp-mail-smtp-setting-toggle-checked-label,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:disabled+.wp-mail-smtp-setting-toggle-switch+.wp-mail-smtp-setting-toggle-unchecked-label{color:#aaa}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .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:400;color:#777;font-size:13px}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .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-content .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-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer{padding-bottom:20px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailers{width:680px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer{display:inline-block;width:150px;margin-right:15px;margin-bottom:15px;position:relative}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer .wp-mail-smtp-mailer-recommended{position:absolute;right:-1px;width:99px;top:2px;z-index:1}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .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;cursor:pointer;height:76px;position:relative;margin-bottom:10px;-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-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer .wp-mail-smtp-mailer-image.is-recommended{background-image:url(../images/recommended.svg);background-repeat:no-repeat;background-size:60%;background-position:top right -2px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer .wp-mail-smtp-mailer-image img{max-width:90%;max-height:40px;display:block;position:relative;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-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer.wp-mail-smtp-mailer-smtp .wp-mail-smtp-mailer-image img{max-height:30px}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .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-content .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-content .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-content .wp-mail-smtp-setting-row h2,#wp-mail-smtp .wp-mail-smtp-page-content .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-content .wp-mail-smtp-setting-row h2{margin-bottom:15px}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .wp-mail-smtp-setting-row p{margin:12px 0 0;font-size:14px;line-height:1.5em}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p:first-of-type{margin:8px 0 0}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p.desc{font-style:italic;color:#777}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p.buttonned{margin-top:30px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p.inline-notice{margin:5px 0 15px;box-sizing:border-box;background:#fff;border-left:4px solid transparent;box-shadow:0 1px 1px 0 rgba(0,0,0,0.1)}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p.inline-notice.inline-error{border-color:#dc3232;margin-bottom:5px;padding:10px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p.inline-notice.inline-edu-notice{border-color:#809EB0;line-height:1.5em;padding:10px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p.inline-notice a.wp-mail-smtp-mailer-notice-dismiss{float:right;color:#999DA1;margin:0 0 10px 10px;text-decoration:none}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p.inline-notice a.wp-mail-smtp-mailer-notice-dismiss:hover{color:#666a6e}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row ul{margin:8px 0 0}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row ul.list li{margin-left:20px;list-style-type:disc}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list th{padding:5px 5px 5px 0;text-align:left}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td.email{padding-right:2em}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td.status{width:100px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td.actions a{border-bottom:1px solid;display:inline-block;margin-right:5px;text-decoration:none}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td.actions a[class*=delete]{color:#a00}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td.actions a[class*=delete]:hover,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td.actions a[class*=delete]:active,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td.actions a[class*=delete]:focus{color:#400}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=text],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=email],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=number],#wp-mail-smtp .wp-mail-smtp-page-content .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-content .wp-mail-smtp-setting-row input[type=text],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=email],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=number],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=password]{width:300px}}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=text][readonly],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=email][readonly],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=number][readonly],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=password][readonly]{background-color:#f9f9f9}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=text].small-text,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=email].small-text,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=number].small-text,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=password].small-text{width:75px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=text]:focus,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=email]:focus,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=number]:focus,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=password]:focus{border-color:#bbb}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=text]:disabled,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=email]:disabled,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=number]:disabled,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=password]:disabled{opacity:0.6}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-label{display:block;float:left;width:205px;padding:0 20px 0 0}@media (max-width: 781px){#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-label{float:none;width:100%;padding-bottom:15px}}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-label label{display:block;font-weight:600;font-size:1.1em}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-field{display:block;margin:0 0 0 205px;max-width:800px}@media (max-width: 781px){#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-field{margin:0}}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-submit{margin:0;padding:25px 0}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-submit .help-text{margin-left:10px;vertical-align:middle}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .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;width:1005px}#wp-mail-smtp .wp-mail-smtp-page-content.wp-mail-smtp-page-general p{margin:0}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .notice-inline.notice-success{border-left-color:#46b450}#wp-mail-smtp .wp-mail-smtp-page-content .notice-inline.notice-warning{border-left-color:#ffb900}#wp-mail-smtp .wp-mail-smtp-page-content .notice-inline.notice-error{border-left-color:#dc3232}#wp-mail-smtp .wp-mail-smtp-page-content .notice-inline.notice-info{border-left-color:#00a0d2}#wp-mail-smtp .wp-mail-smtp-page-content .notice p,#wp-mail-smtp .wp-mail-smtp-page-content .notice-inline p{margin:0.5em 0;padding:2px}#wp-mail-smtp .wp-mail-smtp-page-content pre{white-space:pre-line}#wp-mail-smtp .wp-mail-smtp-page-content.active{display:block}#wp-mail-smtp .wp-mail-smtp-page-content .connected-as{margin-left:30px}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug{background-color:#fff;padding:25px 20px 1px 25px}#wp-mail-smtp .wp-mail-smtp-page-content #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-content #wp-mail-smtp-debug p{font-size:14px;color:#555;margin-bottom:1.1em}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ul,#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ol{font-size:14px;color:#555;margin:0 0 1.1em 1.8em}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ul li,#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ol li{margin:0 0 8px 0;line-height:1.5}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ul li:last-of-type,#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ol li:last-of-type{margin:0}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ul li ul,#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ol li ul{list-style-type:disc}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug a{color:#FF982D}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug a:hover{color:#f97f00}#wp-mail-smtp .wp-mail-smtp-page-content #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-content #wp-mail-smtp-debug .price-off{color:green;font-weight:bold}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug .error-log-toggle{text-decoration:none;color:#444}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug .error-log-toggle:hover{color:#FF982D}#wp-mail-smtp .wp-mail-smtp-page-content #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-content #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-content #wp-mail-smtp-debug .error-log pre{margin:0}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug .error-log-note{display:none}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner{background-color:#fff;padding:25px 20px;border:1px solid #dadada;margin:10px 0 0 0;position:relative}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .wp-mail-smtp-pro-banner-dismiss{position:absolute;right:10px;top:10px}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .wp-mail-smtp-pro-banner-dismiss button{background:none;border:none;color:#a9a9a9;cursor:pointer;margin:0;padding:0}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner h2{color:#444;margin-top:0;font-size:16px;font-weight:700}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner p{font-size:14px;color:#555;margin-bottom:1.1em}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner p:last-of-type{margin:0}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .benefits{margin:0 0 16px 0;overflow:auto;max-width:1000px}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .benefits ul{margin:0;padding:0;width:50%;float:left}@media (max-width: 600px){#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .benefits ul{width:100%;float:none}}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .benefits ul li{margin:0;padding:0 0 2px 16px;color:#555;font-size:14px;position:relative}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .benefits ul li:before{content:'+';position:absolute;top:-1px;left:0}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .benefits ul li.arrow-right:before{content:'→'}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner a{color:#FF982D}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner a:hover,#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner a:active,#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner a:focus{color:#f97f00}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .stars{text-decoration:none}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .stars .dashicons{width:16px;height:16px;font-size:16px;vertical-align:text-top}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .price-off{color:green;font-weight:bold}#wp-mail-smtp .wp-mail-smtp-admin-columns>div[class*="-column-"]{float:left}#wp-mail-smtp .wp-mail-smtp-admin-columns .wp-mail-smtp-admin-column-20{width:20%}#wp-mail-smtp .wp-mail-smtp-admin-columns .wp-mail-smtp-admin-column-33{width:33.33333%}#wp-mail-smtp .wp-mail-smtp-admin-columns .wp-mail-smtp-admin-column-40{width:40%}#wp-mail-smtp .wp-mail-smtp-admin-columns .wp-mail-smtp-admin-column-50{width:50%}#wp-mail-smtp .wp-mail-smtp-admin-columns .wp-mail-smtp-admin-column-60{width:60%}#wp-mail-smtp .wp-mail-smtp-admin-columns .wp-mail-smtp-admin-column-80{width:80%}#wp-mail-smtp .wp-mail-smtp-admin-columns .wp-mail-smtp-admin-column-last{float:right !important}#wp-mail-smtp .wp-mail-smtp-admin-columns:after{content:"";display:table;clear:both}#wp-mail-smtp .wp-mail-smtp-page-upsell{display:flex;align-items:center;justify-content:center;height:auto;flex-direction:column}#wp-mail-smtp .wp-mail-smtp-page-upsell>*{width:800px}#wp-mail-smtp .wp-mail-smtp-page-upsell *,#wp-mail-smtp .wp-mail-smtp-page-upsell *::before,#wp-mail-smtp .wp-mail-smtp-page-upsell *::after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#wp-mail-smtp .wp-mail-smtp-page-upsell h2{font-size:24px;color:#444444;text-align:center}#wp-mail-smtp .wp-mail-smtp-page-upsell h3{font-size:16px;font-weight:normal;color:#72777C;line-height:1.5em;margin-top:0;margin-bottom:25px;text-align:center}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features{margin-bottom:40px;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:stretch;align-content:flex-start}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature{display:flex;flex-direction:row;width:360px;align-items:flex-start;align-content:flex-start;margin-right:60px;margin-top:40px}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature:nth-of-type(1){margin-top:20px}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature:nth-of-type(2){margin-top:20px}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature:nth-of-type(even){margin-right:0}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature .wp-mail-smtp-page-upsell-feature-image{width:65px;text-align:center}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature .wp-mail-smtp-page-upsell-feature-image img{display:block;margin:5px auto 0}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature .wp-mail-smtp-page-upsell-feature-content{margin-left:20px}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature .wp-mail-smtp-page-upsell-feature-content h4{font-size:15px;margin:0 0 0.5em}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature .wp-mail-smtp-page-upsell-feature-content p{color:#72777C;margin:0}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-images{margin-bottom:20px;text-align:center}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-images img{width:380px;height:auto;margin-right:20px;border:5px solid #fff;border-radius:5px;box-shadow:0 0 10px 5px rgba(0,0,0,0.15)}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-images img:last-child{margin-right:0}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-button{text-align:center}.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-btn .dashicons{font-size:16px;width:16px;height:16px}.wp-mail-smtp-btn:disabled{opacity:0.5;cursor:not-allowed}.wp-mail-smtp-btn.wp-mail-smtp-btn-md{font-size:13px;font-weight:600;padding:8px 12px;min-height:35px}.wp-mail-smtp-btn.wp-mail-smtp-btn-lg{font-size:16px;font-weight:600;padding:16px 28px}.wp-mail-smtp-btn.wp-mail-smtp-btn-orange{background-color:#FF982D;border-color:#FF982D;color:#fff}.wp-mail-smtp-btn.wp-mail-smtp-btn-orange:hover,.wp-mail-smtp-btn.wp-mail-smtp-btn-orange:active,.wp-mail-smtp-btn.wp-mail-smtp-btn-orange:focus{background-color:#f97f00;border-color:#f97f00}.wp-mail-smtp-btn.wp-mail-smtp-btn-red{background-color:#DC3232;border-color:#DC3232;color:#fff}.wp-mail-smtp-btn.wp-mail-smtp-btn-red:hover,.wp-mail-smtp-btn.wp-mail-smtp-btn-red:active,.wp-mail-smtp-btn.wp-mail-smtp-btn-red:focus{background-color:darkred;border-color:darkred}.wp-mail-smtp-btn.wp-mail-smtp-btn-grey{background-color:#f5f5f5;border:1px solid #ccc;color:#666}.wp-mail-smtp-btn.wp-mail-smtp-btn-grey:hover,.wp-mail-smtp-btn.wp-mail-smtp-btn-grey:active,.wp-mail-smtp-btn.wp-mail-smtp-btn-grey:focus{background-color:#d7d7d7;border-color:#ccc;color:#444}.wp-mail-smtp-btn.wp-mail-smtp-btn-light-grey{background-color:#f5f5f5;border:1px solid #ccc;color:#666}.wp-mail-smtp-btn.wp-mail-smtp-btn-light-grey:hover,.wp-mail-smtp-btn.wp-mail-smtp-btn-light-grey:active,.wp-mail-smtp-btn.wp-mail-smtp-btn-light-grey:focus{background-color:#eee;color:#444}.wp-mail-smtp-btn.wp-mail-smtp-btn-blueish{background-color:#738e9e;border:1px solid #738e9e;color:#fff}.wp-mail-smtp-btn.wp-mail-smtp-btn-blueish:hover,.wp-mail-smtp-btn.wp-mail-smtp-btn-blueish:active,.wp-mail-smtp-btn.wp-mail-smtp-btn-blueish:focus{background-color:#395360;border-color:#395360;color:#fff}
|
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}}body.toplevel_page_wp-mail-smtp div.jconfirm *,body.toplevel_page_wp-mail-smtp div.jconfirm *::before,body.toplevel_page_wp-mail-smtp div.jconfirm *::after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box-container div.jconfirm-box{border-radius:0;box-shadow:0 2px 6px rgba(0,0,0,0.2)}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box-container div.jconfirm-box div.jconfirm-closeIcon{color:rgba(0,0,0,0.4);top:8px;right:8px}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box-container div.jconfirm-box div.jconfirm-closeIcon:hover{color:rgba(0,0,0,0.8)}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-title-c{margin:0 0 26px 0 !important;padding:0 !important}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-title-c .jconfirm-icon-c{margin:0 !important;color:#c4c4c4 !important;-webkit-transition:none !important;transition:none !important;-webkit-transform:none !important;-ms-transform:none !important;transform:none !important;font-size:45px !important}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-title-c .jconfirm-icon-c i:empty{display:none}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-title-c .jconfirm-icon-c svg{height:35px}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-title-c .jconfirm-title{display:block;color:#333}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-title-c .jconfirm-icon-c+span.jconfirm-title{margin-top:20px !important}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content-pane{margin-bottom:0;display:block}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content-pane .jconfirm-content{overflow:inherit}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content{font-size:16px;color:#555;line-height:1.4}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content.lite-upgrade p{font-size:18px;padding:0 20px}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content p{margin:0 0 16px;font-size:18px;line-height:1.5}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content p:last-of-type{margin:0}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content p.large{font-size:18px}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content p.small{font-size:14px}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content .already-purchased{font-size:12px;color:#ccc;text-decoration:none}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-content .already-purchased:hover{text-decoration:underline}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-buttons .already-purchased{display:block;font-size:12px;color:#aaa;text-decoration:none;padding-top:20px}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box div.jconfirm-buttons .already-purchased:hover{color:#999;text-decoration:underline}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box .discount-note{text-align:center;margin:30px 0 0}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box .discount-note p{background-color:#faffac;margin:0 -30px;padding:24px 60px 20px;font-size:15px;color:#4d4d4d;position:relative}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box .discount-note p:after{content:'\f058';display:inline-block;font:normal normal normal 14px/1 FontAwesome;background-color:#fff;font-size:26px;border-radius:50%;padding:5px 6px;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;top:-20px;right:50%;margin-right:-18px;color:#3abc01}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box .discount-note span{font-weight:700;color:#3abc01}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box .discount-note a{color:#aaa;display:block;margin-top:12px}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box input[type=text]{display:block;width:99%;border:1px solid #d6d6d6;padding:10px;box-shadow:none;margin:20px auto 0 auto}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box button.btn-confirm{background-color:#FF982D;color:#fff;outline:none}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box button.btn-confirm:hover{background-color:#f97f00;border-color:#f97f00}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box button,body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box button.btn-default{color:#666}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box button.btn-block{display:block;text-align:center;width:100%;margin:0 0 10px 0 !important}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box button.btn-normal-case{text-transform:none !important}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box .error{display:none;color:red}body.toplevel_page_wp-mail-smtp div.jconfirm div.jconfirm-box .wpforms-error{border:1px solid #ebccd1 !important}#wp-mail-smtp-header{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-hide{display:none}#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.tab{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.tab.active{border-bottom:2px solid #FF982D}#wp-mail-smtp .wp-mail-smtp-page-title a.tab:hover{border-color:#999}#wp-mail-smtp .wp-mail-smtp-page-title a.action{padding:5px;border:0;min-height:auto;color:#fff;margin:-10px 0 0 20px}#wp-mail-smtp .wp-mail-smtp-page-title .page-title{background-color:#fff;display:inline-block;font-size:23px;margin:0;padding:15px 20px 15px 0}#wp-mail-smtp .wp-mail-smtp-page-content{padding:0 20px}#wp-mail-smtp .wp-mail-smtp-page-content *,#wp-mail-smtp .wp-mail-smtp-page-content *::before,#wp-mail-smtp .wp-mail-smtp-page-content *::after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-clear:before{content:" ";display:table}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-clear:after{clear:both;content:" ";display:table}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .wp-mail-smtp-setting-row:first-of-type{padding-top:10px !important}@media (max-width: 781px){#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row{padding:20px 0}}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.inactive{display:none}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row .wp-mail-smtp-setting-mid-row-sep{background:#e4e4e4;height:1px;border:0;margin:15px 0}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.section-heading{padding:20px 0}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.section-heading.no-desc h2,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.section-heading.no-desc h4{margin:0}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.section-heading .wp-mail-smtp-setting-field{margin:0;max-width:1005px}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .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-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox .desc{margin:0 0 0 30px}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-text .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-password .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-number .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page-content .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-content .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-content .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-content .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-content .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-content .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-content .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-content .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:#46B450}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:disabled+.wp-mail-smtp-setting-toggle-switch{background-color:#69c471;cursor:default}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .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-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:disabled+.wp-mail-smtp-setting-toggle-switch+.wp-mail-smtp-setting-toggle-checked-label,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:disabled+.wp-mail-smtp-setting-toggle-switch+.wp-mail-smtp-setting-toggle-unchecked-label{color:#aaa}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .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:400;color:#777;font-size:13px}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .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-content .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-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer{padding-bottom:20px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailers .wp-mail-smtp-mailer{display:inline-block;width:140px;margin-right:12px;margin-bottom:12px;position:relative}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailers .wp-mail-smtp-mailer .wp-mail-smtp-mailer-image{background:#fff;text-align:center;border:2px solid #E5E5E5;border-radius:4px;cursor:pointer;height:76px;position:relative;margin-bottom:10px;-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-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailers .wp-mail-smtp-mailer .wp-mail-smtp-mailer-image.is-recommended{background-image:url(../images/recommended.svg);background-repeat:no-repeat;background-size:60%;background-position:top right -2px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailers .wp-mail-smtp-mailer .wp-mail-smtp-mailer-image img{max-width:90%;max-height:40px;display:block;position:relative;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-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailers .wp-mail-smtp-mailer.wp-mail-smtp-mailer-smtp .wp-mail-smtp-mailer-image img{max-height:30px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailers .wp-mail-smtp-mailer.suggest-new a.wp-mail-smtp-mailer-image{min-width:140px;display:table-cell;color:#777777;text-decoration:underline;vertical-align:middle;bottom:10px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailers .wp-mail-smtp-mailer.suggest-new .wp-mail-smtp-mailer-text{visibility:hidden}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailers .wp-mail-smtp-mailer.active .wp-mail-smtp-mailer-image{border-color:#FF982D}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailers .wp-mail-smtp-mailer.active .wp-mail-smtp-mailer-image img{opacity:1}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailers .wp-mail-smtp-mailer:hover .wp-mail-smtp-mailer-image{border-color:#ccc}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailers .wp-mail-smtp-mailer:hover .wp-mail-smtp-mailer-image img{opacity:1}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row h2,#wp-mail-smtp .wp-mail-smtp-page-content .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-content .wp-mail-smtp-setting-row h2{margin-bottom:15px}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .wp-mail-smtp-setting-row p{margin:12px 0 0;font-size:14px;line-height:1.5em}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p:first-of-type{margin:8px 0 0}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p.desc{font-style:italic;color:#777}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p.buttonned{margin-top:30px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p.inline-notice{margin:5px 0 15px;box-sizing:border-box;background:#fff;border-left:4px solid transparent;box-shadow:0 1px 1px 0 rgba(0,0,0,0.1)}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p.inline-notice.inline-error{border-color:#dc3232;margin-bottom:5px;padding:10px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p.inline-notice.inline-edu-notice{border-color:#809EB0;line-height:1.5em;padding:10px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p.inline-notice a.wp-mail-smtp-mailer-notice-dismiss{float:right;color:#999DA1;margin:0 0 10px 10px;text-decoration:none}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row p.inline-notice a.wp-mail-smtp-mailer-notice-dismiss:hover{color:#666a6e}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row ul{margin:8px 0 0}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row ul.list li{margin-left:20px;list-style-type:disc}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list th{padding:5px 5px 5px 0;text-align:left}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td.email{padding-right:2em}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td.status{width:100px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td.actions a{border-bottom:1px solid;display:inline-block;margin-right:5px;text-decoration:none}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td.actions a[class*=delete]{color:#a00}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td.actions a[class*=delete]:hover,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td.actions a[class*=delete]:active,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row table.actions-list td.actions a[class*=delete]:focus{color:#400}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=text],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=email],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=number],#wp-mail-smtp .wp-mail-smtp-page-content .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;line-height:1.3}@media (max-width: 959px){#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=text],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=email],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=number],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=password]{width:300px}}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=text][readonly],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=email][readonly],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=number][readonly],#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=password][readonly]{background-color:#f9f9f9}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=text].small-text,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=email].small-text,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=number].small-text,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=password].small-text{width:75px}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=text]:focus,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=email]:focus,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=number]:focus,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=password]:focus{border-color:#bbb}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=text]:disabled,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=email]:disabled,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=number]:disabled,#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-row input[type=password]:disabled{opacity:0.6}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-label{display:block;float:left;width:205px;padding:0 20px 0 0}@media (max-width: 781px){#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-label{float:none;width:100%;padding-bottom:15px}}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-label label{display:block;font-weight:600;font-size:1.1em}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-field{display:block;margin:0 0 0 205px;max-width:800px}@media (max-width: 781px){#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-setting-field{margin:0}}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-submit{margin:0;padding:25px 0}#wp-mail-smtp .wp-mail-smtp-page-content .wp-mail-smtp-submit .help-text{margin-left:10px;vertical-align:middle}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .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;width:1005px}#wp-mail-smtp .wp-mail-smtp-page-content.wp-mail-smtp-page-general p{margin:0}#wp-mail-smtp .wp-mail-smtp-page-content .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-content .notice-inline.notice-success{border-left-color:#46b450}#wp-mail-smtp .wp-mail-smtp-page-content .notice-inline.notice-warning{border-left-color:#ffb900}#wp-mail-smtp .wp-mail-smtp-page-content .notice-inline.notice-error{border-left-color:#dc3232}#wp-mail-smtp .wp-mail-smtp-page-content .notice-inline.notice-info{border-left-color:#00a0d2}#wp-mail-smtp .wp-mail-smtp-page-content .notice p,#wp-mail-smtp .wp-mail-smtp-page-content .notice-inline p{margin:0.5em 0;padding:2px}#wp-mail-smtp .wp-mail-smtp-page-content pre{white-space:pre-line}#wp-mail-smtp .wp-mail-smtp-page-content.active{display:block}#wp-mail-smtp .wp-mail-smtp-page-content .connected-as{margin-left:30px}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug{background-color:#fff;padding:25px 20px 1px 25px}#wp-mail-smtp .wp-mail-smtp-page-content #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-content #wp-mail-smtp-debug p{font-size:14px;color:#555;margin-bottom:1.1em}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ul,#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ol{font-size:14px;color:#555;margin:0 0 1.1em 1.8em}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ul li,#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ol li{margin:0 0 8px 0;line-height:1.5}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ul li:last-of-type,#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ol li:last-of-type{margin:0}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ul li ul,#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug ol li ul{list-style-type:disc}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug a{color:#FF982D}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug a:hover{color:#f97f00}#wp-mail-smtp .wp-mail-smtp-page-content #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-content #wp-mail-smtp-debug .price-off{color:green;font-weight:bold}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug .error-log-toggle{text-decoration:none;color:#444}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug .error-log-toggle:hover{color:#FF982D}#wp-mail-smtp .wp-mail-smtp-page-content #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-content #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-content #wp-mail-smtp-debug .error-log pre{margin:0}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-debug .error-log-note{display:none}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner{background-color:#fff;padding:25px 20px;border:1px solid #dadada;margin:10px 0 0 0;position:relative}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .wp-mail-smtp-pro-banner-dismiss{position:absolute;right:10px;top:10px}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .wp-mail-smtp-pro-banner-dismiss button{background:none;border:none;color:#a9a9a9;cursor:pointer;margin:0;padding:0}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner h2{color:#444;margin-top:0;font-size:16px;font-weight:700}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner p{font-size:14px;color:#555;margin-bottom:1.1em}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner p:last-of-type{margin:0}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .benefits{margin:0 0 16px 0;overflow:auto;max-width:1000px}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .benefits ul{margin:0;padding:0;width:50%;float:left}@media (max-width: 600px){#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .benefits ul{width:100%;float:none}}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .benefits ul li{margin:0;padding:0 0 2px 16px;color:#555;font-size:14px;position:relative}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .benefits ul li:before{content:'+';position:absolute;top:-1px;left:0}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .benefits ul li.arrow-right:before{content:'→'}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner a{color:#FF982D}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner a:hover,#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner a:active,#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner a:focus{color:#f97f00}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .stars{text-decoration:none}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .stars .dashicons{width:16px;height:16px;font-size:16px;vertical-align:text-top}#wp-mail-smtp .wp-mail-smtp-page-content #wp-mail-smtp-pro-banner .price-off{color:green;font-weight:bold}#wp-mail-smtp .wp-mail-smtp-admin-columns>div[class*="-column-"]{float:left}#wp-mail-smtp .wp-mail-smtp-admin-columns .wp-mail-smtp-admin-column-20{width:20%}#wp-mail-smtp .wp-mail-smtp-admin-columns .wp-mail-smtp-admin-column-33{width:33.33333%}#wp-mail-smtp .wp-mail-smtp-admin-columns .wp-mail-smtp-admin-column-40{width:40%}#wp-mail-smtp .wp-mail-smtp-admin-columns .wp-mail-smtp-admin-column-50{width:50%}#wp-mail-smtp .wp-mail-smtp-admin-columns .wp-mail-smtp-admin-column-60{width:60%}#wp-mail-smtp .wp-mail-smtp-admin-columns .wp-mail-smtp-admin-column-80{width:80%}#wp-mail-smtp .wp-mail-smtp-admin-columns .wp-mail-smtp-admin-column-last{float:right !important}#wp-mail-smtp .wp-mail-smtp-admin-columns:after{content:"";display:table;clear:both}#wp-mail-smtp .wp-mail-smtp-page-upsell{display:flex;align-items:center;justify-content:center;height:auto;flex-direction:column}#wp-mail-smtp .wp-mail-smtp-page-upsell>*{width:800px}#wp-mail-smtp .wp-mail-smtp-page-upsell *,#wp-mail-smtp .wp-mail-smtp-page-upsell *::before,#wp-mail-smtp .wp-mail-smtp-page-upsell *::after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#wp-mail-smtp .wp-mail-smtp-page-upsell h2{font-size:24px;color:#444444;text-align:center}#wp-mail-smtp .wp-mail-smtp-page-upsell h3{font-size:16px;font-weight:normal;color:#72777C;line-height:1.5em;margin-top:0;margin-bottom:25px;text-align:center}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features{margin-bottom:40px;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:stretch;align-content:flex-start}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature{display:flex;flex-direction:row;width:360px;align-items:flex-start;align-content:flex-start;margin-right:60px;margin-top:40px}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature:nth-of-type(1){margin-top:20px}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature:nth-of-type(2){margin-top:20px}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature:nth-of-type(even){margin-right:0}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature .wp-mail-smtp-page-upsell-feature-image{width:65px;text-align:center}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature .wp-mail-smtp-page-upsell-feature-image img{display:block;margin:5px auto 0}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature .wp-mail-smtp-page-upsell-feature-content{margin-left:20px}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature .wp-mail-smtp-page-upsell-feature-content h4{font-size:15px;margin:0 0 0.5em}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-content .wp-mail-smtp-page-upsell-features .wp-mail-smtp-page-upsell-feature .wp-mail-smtp-page-upsell-feature-content p{color:#72777C;margin:0}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-images{margin-bottom:20px;text-align:center}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-images img{width:380px;height:auto;margin-right:20px;border:5px solid #fff;border-radius:5px;box-shadow:0 0 10px 5px rgba(0,0,0,0.15)}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-images img:last-child{margin-right:0}#wp-mail-smtp .wp-mail-smtp-page-upsell .wp-mail-smtp-page-upsell-button{text-align:center}.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-btn .dashicons{font-size:16px;width:16px;height:16px}.wp-mail-smtp-btn:disabled{opacity:0.5;cursor:not-allowed}.wp-mail-smtp-btn.wp-mail-smtp-btn-md{font-size:13px;font-weight:600;padding:8px 12px;min-height:35px}.wp-mail-smtp-btn.wp-mail-smtp-btn-lg{font-size:16px;font-weight:600;padding:16px 28px}.wp-mail-smtp-btn.wp-mail-smtp-btn-orange{background-color:#FF982D;border-color:#FF982D;color:#fff}.wp-mail-smtp-btn.wp-mail-smtp-btn-orange:hover,.wp-mail-smtp-btn.wp-mail-smtp-btn-orange:active,.wp-mail-smtp-btn.wp-mail-smtp-btn-orange:focus{background-color:#f97f00;border-color:#f97f00}.wp-mail-smtp-btn.wp-mail-smtp-btn-red{background-color:#DC3232;border-color:#DC3232;color:#fff}.wp-mail-smtp-btn.wp-mail-smtp-btn-red:hover,.wp-mail-smtp-btn.wp-mail-smtp-btn-red:active,.wp-mail-smtp-btn.wp-mail-smtp-btn-red:focus{background-color:darkred;border-color:darkred}.wp-mail-smtp-btn.wp-mail-smtp-btn-grey{background-color:#f5f5f5;border:1px solid #ccc;color:#666}.wp-mail-smtp-btn.wp-mail-smtp-btn-grey:hover,.wp-mail-smtp-btn.wp-mail-smtp-btn-grey:active,.wp-mail-smtp-btn.wp-mail-smtp-btn-grey:focus{background-color:#d7d7d7;border-color:#ccc;color:#444}.wp-mail-smtp-btn.wp-mail-smtp-btn-light-grey{background-color:#f5f5f5;border:1px solid #ccc;color:#666}.wp-mail-smtp-btn.wp-mail-smtp-btn-light-grey:hover,.wp-mail-smtp-btn.wp-mail-smtp-btn-light-grey:active,.wp-mail-smtp-btn.wp-mail-smtp-btn-light-grey:focus{background-color:#eee;color:#444}.wp-mail-smtp-btn.wp-mail-smtp-btn-blueish{background-color:#738e9e;border:1px solid #738e9e;color:#fff}.wp-mail-smtp-btn.wp-mail-smtp-btn-blueish:hover,.wp-mail-smtp-btn.wp-mail-smtp-btn-blueish:active,.wp-mail-smtp-btn.wp-mail-smtp-btn-blueish:focus{background-color:#395360;border-color:#395360;color:#fff}
|
2 |
|
3 |
/*# sourceMappingURL=smtp-admin.min.css.map */
|
assets/images/providers/pepipost-smtp.png
ADDED
Binary file
|
assets/images/providers/pepipost.png
CHANGED
Binary file
|
assets/js/smtp-about.js
CHANGED
@@ -1,190 +1,190 @@
|
|
1 |
-
/* global WPMailSMTP, jQuery, wp_mail_smtp_about */
|
2 |
-
|
3 |
-
var WPMailSMTP = window.WPMailSMTP || {};
|
4 |
-
WPMailSMTP.Admin = WPMailSMTP.Admin || {};
|
5 |
-
|
6 |
-
/**
|
7 |
-
* WP Mail SMTP Admin area About module.
|
8 |
-
*
|
9 |
-
* @since 1.5.0
|
10 |
-
*/
|
11 |
-
WPMailSMTP.Admin.About = WPMailSMTP.Admin.About || (function ( document, window, $ ) {
|
12 |
-
|
13 |
-
'use strict';
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Private functions and properties.
|
17 |
-
*
|
18 |
-
* @since 1.5.0
|
19 |
-
*
|
20 |
-
* @type {Object}
|
21 |
-
*/
|
22 |
-
var __private = {};
|
23 |
-
|
24 |
-
/**
|
25 |
-
* Public functions and properties.
|
26 |
-
*
|
27 |
-
* @since 1.5.0
|
28 |
-
*
|
29 |
-
* @type {Object}
|
30 |
-
*/
|
31 |
-
var app = {
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Start the engine. DOM is not ready yet, use only to init something.
|
35 |
-
*
|
36 |
-
* @since 1.5.0
|
37 |
-
*/
|
38 |
-
init: function () {
|
39 |
-
|
40 |
-
// Do that when DOM is ready.
|
41 |
-
$( document ).ready( app.ready );
|
42 |
-
},
|
43 |
-
|
44 |
-
/**
|
45 |
-
* DOM is fully loaded.
|
46 |
-
*
|
47 |
-
* @since 1.5.0
|
48 |
-
*/
|
49 |
-
ready: function () {
|
50 |
-
|
51 |
-
app.pageHolder = $( '.wp-mail-smtp-page-about' );
|
52 |
-
|
53 |
-
app.bindActions();
|
54 |
-
|
55 |
-
$( '.wp-mail-smtp-page' ).trigger( 'WPMailSMTP.Admin.About.ready' );
|
56 |
-
},
|
57 |
-
|
58 |
-
/**
|
59 |
-
* Process all generic actions/events, mostly custom that were fired by our API.
|
60 |
-
*
|
61 |
-
* @since 1.5.0
|
62 |
-
*/
|
63 |
-
bindActions: function () {
|
64 |
-
|
65 |
-
/*
|
66 |
-
* Make plugins description the same height.
|
67 |
-
*/
|
68 |
-
jQuery('.wp-mail-smtp-admin-about-plugins .plugin-item .details').matchHeight();
|
69 |
-
|
70 |
-
/*
|
71 |
-
* Install/Active the plugins.
|
72 |
-
*/
|
73 |
-
$( document ).on( 'click', '.wp-mail-smtp-admin-about-plugins .plugin-item .action-button .button', function( e ) {
|
74 |
-
e.preventDefault();
|
75 |
-
|
76 |
-
var $btn = $( this );
|
77 |
-
|
78 |
-
if ( $btn.hasClass( 'disabled' ) || $btn.hasClass( 'loading' ) ) {
|
79 |
-
return false;
|
80 |
-
}
|
81 |
-
|
82 |
-
var $plugin = $btn.closest( '.plugin-item' ),
|
83 |
-
plugin = $btn.attr( 'data-plugin' ),
|
84 |
-
task,
|
85 |
-
cssClass,
|
86 |
-
statusText,
|
87 |
-
buttonText,
|
88 |
-
errorText,
|
89 |
-
successText;
|
90 |
-
|
91 |
-
$btn.prop( 'disabled', true ).addClass( 'loading' );
|
92 |
-
$btn.text( wp_mail_smtp_about.plugin_processing );
|
93 |
-
|
94 |
-
if ( $btn.hasClass( 'status-inactive' ) ) {
|
95 |
-
// Activate.
|
96 |
-
task = 'about_plugin_activate';
|
97 |
-
cssClass = 'status-active button button-secondary disabled';
|
98 |
-
statusText = wp_mail_smtp_about.plugin_active;
|
99 |
-
buttonText = wp_mail_smtp_about.plugin_activated;
|
100 |
-
errorText = wp_mail_smtp_about.plugin_activate;
|
101 |
-
|
102 |
-
} else if ( $btn.hasClass( 'status-download' ) ) {
|
103 |
-
// Install & Activate.
|
104 |
-
task = 'about_plugin_install';
|
105 |
-
cssClass = 'status-active button disabled';
|
106 |
-
statusText = wp_mail_smtp_about.plugin_active;
|
107 |
-
buttonText = wp_mail_smtp_about.plugin_activated;
|
108 |
-
errorText = wp_mail_smtp_about.plugin_activate;
|
109 |
-
|
110 |
-
} else {
|
111 |
-
return;
|
112 |
-
}
|
113 |
-
|
114 |
-
// Setup ajax POST data.
|
115 |
-
var data = {
|
116 |
-
action: 'wp_mail_smtp_ajax',
|
117 |
-
task: task,
|
118 |
-
nonce : wp_mail_smtp_about.nonce,
|
119 |
-
plugin: plugin
|
120 |
-
};
|
121 |
-
|
122 |
-
$.post( wp_mail_smtp_about.ajax_url, data, function( res ) {
|
123 |
-
var is_install_successful;
|
124 |
-
|
125 |
-
if ( res.success ) {
|
126 |
-
is_install_successful = true;
|
127 |
-
if ( 'about_plugin_install' === task ) {
|
128 |
-
$btn.attr( 'data-plugin', res.data.basename );
|
129 |
-
successText = res.data.msg;
|
130 |
-
if ( ! res.data.is_activated ) {
|
131 |
-
cssClass = 'button';
|
132 |
-
statusText = wp_mail_smtp_about.plugin_inactive;
|
133 |
-
buttonText = wp_mail_smtp_about.plugin_activate;
|
134 |
-
}
|
135 |
-
} else {
|
136 |
-
successText = res.data;
|
137 |
-
}
|
138 |
-
$plugin.find( '.actions' ).append( '<div class="msg success">'+successText+'</div>' );
|
139 |
-
$plugin.find( 'span.status-label' )
|
140 |
-
.removeClass( 'status-active status-inactive status-download' )
|
141 |
-
.addClass( cssClass )
|
142 |
-
.removeClass( 'button button-primary button-secondary disabled' )
|
143 |
-
.text( statusText );
|
144 |
-
$btn
|
145 |
-
.removeClass( 'status-active status-inactive status-download' )
|
146 |
-
.removeClass( 'button button-primary button-secondary disabled' )
|
147 |
-
.addClass( cssClass ).html( buttonText );
|
148 |
-
} else {
|
149 |
-
is_install_successful = false;
|
150 |
-
|
151 |
-
if (
|
152 |
-
res.hasOwnProperty( 'data' ) &&
|
153 |
-
res.data.hasOwnProperty( 0 ) &&
|
154 |
-
res.data[ 0 ].hasOwnProperty( 'code' ) &&
|
155 |
-
res.data[ 0 ].code === 'download_failed'
|
156 |
-
) {
|
157 |
-
// Specific server-returned error.
|
158 |
-
$plugin.find( '.actions' ).append( '<div class="msg error">' + wp_mail_smtp_about.plugin_install_error + '</div>' );
|
159 |
-
}
|
160 |
-
else {
|
161 |
-
// Generic error.
|
162 |
-
$plugin.find( '.actions' ).append( '<div class="msg error">' + res.data + '</div>' );
|
163 |
-
}
|
164 |
-
|
165 |
-
$btn.html( wp_mail_smtp_about.plugin_download_btn );
|
166 |
-
}
|
167 |
-
|
168 |
-
if ( is_install_successful ) {
|
169 |
-
$btn.prop( 'disabled', false );
|
170 |
-
}
|
171 |
-
$btn.removeClass( 'loading' );
|
172 |
-
|
173 |
-
// Automatically clear plugin messages after 3 seconds.
|
174 |
-
setTimeout( function () {
|
175 |
-
$( '.plugin-item .msg' ).remove();
|
176 |
-
}, 3000 );
|
177 |
-
|
178 |
-
}).fail( function( xhr ) {
|
179 |
-
console.log( xhr.responseText );
|
180 |
-
});
|
181 |
-
});
|
182 |
-
}
|
183 |
-
};
|
184 |
-
|
185 |
-
// Provide access to public functions/properties.
|
186 |
-
return app;
|
187 |
-
})( document, window, jQuery );
|
188 |
-
|
189 |
-
// Initialize.
|
190 |
-
WPMailSMTP.Admin.About.init();
|
1 |
+
/* global WPMailSMTP, jQuery, wp_mail_smtp_about */
|
2 |
+
|
3 |
+
var WPMailSMTP = window.WPMailSMTP || {};
|
4 |
+
WPMailSMTP.Admin = WPMailSMTP.Admin || {};
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WP Mail SMTP Admin area About module.
|
8 |
+
*
|
9 |
+
* @since 1.5.0
|
10 |
+
*/
|
11 |
+
WPMailSMTP.Admin.About = WPMailSMTP.Admin.About || (function ( document, window, $ ) {
|
12 |
+
|
13 |
+
'use strict';
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Private functions and properties.
|
17 |
+
*
|
18 |
+
* @since 1.5.0
|
19 |
+
*
|
20 |
+
* @type {Object}
|
21 |
+
*/
|
22 |
+
var __private = {};
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Public functions and properties.
|
26 |
+
*
|
27 |
+
* @since 1.5.0
|
28 |
+
*
|
29 |
+
* @type {Object}
|
30 |
+
*/
|
31 |
+
var app = {
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Start the engine. DOM is not ready yet, use only to init something.
|
35 |
+
*
|
36 |
+
* @since 1.5.0
|
37 |
+
*/
|
38 |
+
init: function () {
|
39 |
+
|
40 |
+
// Do that when DOM is ready.
|
41 |
+
$( document ).ready( app.ready );
|
42 |
+
},
|
43 |
+
|
44 |
+
/**
|
45 |
+
* DOM is fully loaded.
|
46 |
+
*
|
47 |
+
* @since 1.5.0
|
48 |
+
*/
|
49 |
+
ready: function () {
|
50 |
+
|
51 |
+
app.pageHolder = $( '.wp-mail-smtp-page-about' );
|
52 |
+
|
53 |
+
app.bindActions();
|
54 |
+
|
55 |
+
$( '.wp-mail-smtp-page' ).trigger( 'WPMailSMTP.Admin.About.ready' );
|
56 |
+
},
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Process all generic actions/events, mostly custom that were fired by our API.
|
60 |
+
*
|
61 |
+
* @since 1.5.0
|
62 |
+
*/
|
63 |
+
bindActions: function () {
|
64 |
+
|
65 |
+
/*
|
66 |
+
* Make plugins description the same height.
|
67 |
+
*/
|
68 |
+
jQuery('.wp-mail-smtp-admin-about-plugins .plugin-item .details').matchHeight();
|
69 |
+
|
70 |
+
/*
|
71 |
+
* Install/Active the plugins.
|
72 |
+
*/
|
73 |
+
$( document ).on( 'click', '.wp-mail-smtp-admin-about-plugins .plugin-item .action-button .button', function( e ) {
|
74 |
+
e.preventDefault();
|
75 |
+
|
76 |
+
var $btn = $( this );
|
77 |
+
|
78 |
+
if ( $btn.hasClass( 'disabled' ) || $btn.hasClass( 'loading' ) ) {
|
79 |
+
return false;
|
80 |
+
}
|
81 |
+
|
82 |
+
var $plugin = $btn.closest( '.plugin-item' ),
|
83 |
+
plugin = $btn.attr( 'data-plugin' ),
|
84 |
+
task,
|
85 |
+
cssClass,
|
86 |
+
statusText,
|
87 |
+
buttonText,
|
88 |
+
errorText,
|
89 |
+
successText;
|
90 |
+
|
91 |
+
$btn.prop( 'disabled', true ).addClass( 'loading' );
|
92 |
+
$btn.text( wp_mail_smtp_about.plugin_processing );
|
93 |
+
|
94 |
+
if ( $btn.hasClass( 'status-inactive' ) ) {
|
95 |
+
// Activate.
|
96 |
+
task = 'about_plugin_activate';
|
97 |
+
cssClass = 'status-active button button-secondary disabled';
|
98 |
+
statusText = wp_mail_smtp_about.plugin_active;
|
99 |
+
buttonText = wp_mail_smtp_about.plugin_activated;
|
100 |
+
errorText = wp_mail_smtp_about.plugin_activate;
|
101 |
+
|
102 |
+
} else if ( $btn.hasClass( 'status-download' ) ) {
|
103 |
+
// Install & Activate.
|
104 |
+
task = 'about_plugin_install';
|
105 |
+
cssClass = 'status-active button disabled';
|
106 |
+
statusText = wp_mail_smtp_about.plugin_active;
|
107 |
+
buttonText = wp_mail_smtp_about.plugin_activated;
|
108 |
+
errorText = wp_mail_smtp_about.plugin_activate;
|
109 |
+
|
110 |
+
} else {
|
111 |
+
return;
|
112 |
+
}
|
113 |
+
|
114 |
+
// Setup ajax POST data.
|
115 |
+
var data = {
|
116 |
+
action: 'wp_mail_smtp_ajax',
|
117 |
+
task: task,
|
118 |
+
nonce : wp_mail_smtp_about.nonce,
|
119 |
+
plugin: plugin
|
120 |
+
};
|
121 |
+
|
122 |
+
$.post( wp_mail_smtp_about.ajax_url, data, function( res ) {
|
123 |
+
var is_install_successful;
|
124 |
+
|
125 |
+
if ( res.success ) {
|
126 |
+
is_install_successful = true;
|
127 |
+
if ( 'about_plugin_install' === task ) {
|
128 |
+
$btn.attr( 'data-plugin', res.data.basename );
|
129 |
+
successText = res.data.msg;
|
130 |
+
if ( ! res.data.is_activated ) {
|
131 |
+
cssClass = 'button';
|
132 |
+
statusText = wp_mail_smtp_about.plugin_inactive;
|
133 |
+
buttonText = wp_mail_smtp_about.plugin_activate;
|
134 |
+
}
|
135 |
+
} else {
|
136 |
+
successText = res.data;
|
137 |
+
}
|
138 |
+
$plugin.find( '.actions' ).append( '<div class="msg success">'+successText+'</div>' );
|
139 |
+
$plugin.find( 'span.status-label' )
|
140 |
+
.removeClass( 'status-active status-inactive status-download' )
|
141 |
+
.addClass( cssClass )
|
142 |
+
.removeClass( 'button button-primary button-secondary disabled' )
|
143 |
+
.text( statusText );
|
144 |
+
$btn
|
145 |
+
.removeClass( 'status-active status-inactive status-download' )
|
146 |
+
.removeClass( 'button button-primary button-secondary disabled' )
|
147 |
+
.addClass( cssClass ).html( buttonText );
|
148 |
+
} else {
|
149 |
+
is_install_successful = false;
|
150 |
+
|
151 |
+
if (
|
152 |
+
res.hasOwnProperty( 'data' ) &&
|
153 |
+
res.data.hasOwnProperty( 0 ) &&
|
154 |
+
res.data[ 0 ].hasOwnProperty( 'code' ) &&
|
155 |
+
res.data[ 0 ].code === 'download_failed'
|
156 |
+
) {
|
157 |
+
// Specific server-returned error.
|
158 |
+
$plugin.find( '.actions' ).append( '<div class="msg error">' + wp_mail_smtp_about.plugin_install_error + '</div>' );
|
159 |
+
}
|
160 |
+
else {
|
161 |
+
// Generic error.
|
162 |
+
$plugin.find( '.actions' ).append( '<div class="msg error">' + res.data + '</div>' );
|
163 |
+
}
|
164 |
+
|
165 |
+
$btn.html( wp_mail_smtp_about.plugin_download_btn );
|
166 |
+
}
|
167 |
+
|
168 |
+
if ( is_install_successful ) {
|
169 |
+
$btn.prop( 'disabled', false );
|
170 |
+
}
|
171 |
+
$btn.removeClass( 'loading' );
|
172 |
+
|
173 |
+
// Automatically clear plugin messages after 3 seconds.
|
174 |
+
setTimeout( function () {
|
175 |
+
$( '.plugin-item .msg' ).remove();
|
176 |
+
}, 3000 );
|
177 |
+
|
178 |
+
}).fail( function( xhr ) {
|
179 |
+
console.log( xhr.responseText );
|
180 |
+
});
|
181 |
+
});
|
182 |
+
}
|
183 |
+
};
|
184 |
+
|
185 |
+
// Provide access to public functions/properties.
|
186 |
+
return app;
|
187 |
+
})( document, window, jQuery );
|
188 |
+
|
189 |
+
// Initialize.
|
190 |
+
WPMailSMTP.Admin.About.init();
|
assets/languages/wp-mail-smtp.pot
CHANGED
@@ -1,13 +1,13 @@
|
|
1 |
msgid ""
|
2 |
msgstr ""
|
3 |
-
"Project-Id-Version: WP Mail SMTP 1.
|
4 |
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wp-mail-smtp\n"
|
5 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
6 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
7 |
"MIME-Version: 1.0\n"
|
8 |
"Content-Type: text/plain; charset=UTF-8\n"
|
9 |
"Content-Transfer-Encoding: 8bit\n"
|
10 |
-
"POT-Creation-Date: 2019-
|
11 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
12 |
"X-Generator: WP-CLI 2.2.0\n"
|
13 |
"X-Domain: wp-mail-smtp\n"
|
@@ -478,7 +478,7 @@ msgid "Check this if you would like to remove ALL WP Mail SMTP data upon plugin
|
|
478 |
msgstr ""
|
479 |
|
480 |
#: src/Admin/Pages/MiscTab.php:215
|
481 |
-
#: src/Admin/Pages/SettingsTab.php:
|
482 |
msgid "Settings were successfully saved."
|
483 |
msgstr ""
|
484 |
|
@@ -578,93 +578,98 @@ msgstr ""
|
|
578 |
msgid "Mailer"
|
579 |
msgstr ""
|
580 |
|
581 |
-
#: src/Admin/Pages/SettingsTab.php:
|
|
|
|
|
|
|
|
|
|
|
582 |
msgid "Dismiss this notice"
|
583 |
msgstr ""
|
584 |
|
585 |
-
#: src/Admin/Pages/SettingsTab.php:
|
586 |
msgid "You're using WP Mail SMTP Lite - no license needed. Enjoy!"
|
587 |
msgstr ""
|
588 |
|
589 |
#. translators: %s - WPMailSMTP.com upgrade URL.
|
590 |
-
#: src/Admin/Pages/SettingsTab.php:
|
591 |
msgid "To unlock more features consider <strong><a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"wp-mail-smtp-upgrade-modal\">upgrading to PRO</a></strong>."
|
592 |
msgstr ""
|
593 |
|
594 |
-
#: src/Admin/Pages/SettingsTab.php:
|
595 |
msgid "As a valued WP Mail SMTP Lite user you receive <strong>20% off</strong>, automatically applied at checkout!"
|
596 |
msgstr ""
|
597 |
|
598 |
-
#: src/Admin/Pages/SettingsTab.php:
|
599 |
msgid "Get WP Mail SMTP Pro and Unlock all the Powerful Features"
|
600 |
msgstr ""
|
601 |
|
602 |
-
#: src/Admin/Pages/SettingsTab.php:
|
603 |
msgid "Thanks for being a loyal WP Mail SMTP user. Upgrade to WP Mail SMTP Pro to unlock more awesome features and experience why WP Mail SMTP is the most popular SMTP plugin."
|
604 |
msgstr ""
|
605 |
|
606 |
-
#: src/Admin/Pages/SettingsTab.php:
|
607 |
msgid "We know that you will truly love WP Mail SMTP. It's used by over 1,000,000 websites."
|
608 |
msgstr ""
|
609 |
|
610 |
-
#: src/Admin/Pages/SettingsTab.php:
|
611 |
msgid "Pro Features:"
|
612 |
msgstr ""
|
613 |
|
614 |
-
#: src/Admin/Pages/SettingsTab.php:
|
615 |
msgid "Manage Notifications - control which emails your site sends"
|
616 |
msgstr ""
|
617 |
|
618 |
-
#: src/Admin/Pages/SettingsTab.php:
|
619 |
msgid "Email Logging - keep track of every email sent from your site"
|
620 |
msgstr ""
|
621 |
|
622 |
-
#: src/Admin/Pages/SettingsTab.php:
|
623 |
msgid "Office 365 - send emails using your Office 365 account"
|
624 |
msgstr ""
|
625 |
|
626 |
-
#: src/Admin/Pages/SettingsTab.php:
|
627 |
msgid "Amazon SES - harness the power of AWS"
|
628 |
msgstr ""
|
629 |
|
630 |
-
#: src/Admin/Pages/SettingsTab.php:
|
631 |
msgid "Outlook.com - send emails using your Outlook.com account"
|
632 |
msgstr ""
|
633 |
|
634 |
-
#: src/Admin/Pages/SettingsTab.php:
|
635 |
msgid "Access to our world class support team"
|
636 |
msgstr ""
|
637 |
|
638 |
-
#: src/Admin/Pages/SettingsTab.php:
|
639 |
msgid "White Glove Setup - sit back and relax while we handle everything for you"
|
640 |
msgstr ""
|
641 |
|
642 |
-
#: src/Admin/Pages/SettingsTab.php:
|
643 |
msgid "Install WP Mail SMTP Pro plugin"
|
644 |
msgstr ""
|
645 |
|
646 |
-
#: src/Admin/Pages/SettingsTab.php:
|
647 |
msgid "Set up domain name verification (DNS)"
|
648 |
msgstr ""
|
649 |
|
650 |
-
#: src/Admin/Pages/SettingsTab.php:
|
651 |
msgid "Configure Mailgun service"
|
652 |
msgstr ""
|
653 |
|
654 |
-
#: src/Admin/Pages/SettingsTab.php:
|
655 |
msgid "Set up WP Mail SMTP Pro plugin"
|
656 |
msgstr ""
|
657 |
|
658 |
-
#: src/Admin/Pages/SettingsTab.php:
|
659 |
msgid "Test and verify email delivery"
|
660 |
msgstr ""
|
661 |
|
662 |
#. translators: %s - WPMailSMTP.com URL.
|
663 |
-
#: src/Admin/Pages/SettingsTab.php:
|
664 |
msgid "<a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer\">Get WP Mail SMTP Pro Today and Unlock all the Powerful Features »</a>"
|
665 |
msgstr ""
|
666 |
|
667 |
-
#: src/Admin/Pages/SettingsTab.php:
|
668 |
msgid "<strong>Bonus:</strong> WP Mail SMTP users get <span class=\"price-off\">20% off regular price</span>, automatically applied at checkout."
|
669 |
msgstr ""
|
670 |
|
@@ -1445,9 +1450,44 @@ msgid "We're sorry, the Microsoft Outlook mailer is not available on your plan.
|
|
1445 |
msgstr ""
|
1446 |
|
1447 |
#: src/Providers/Pepipost/Options.php:25
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1448 |
msgid "Pepipost"
|
1449 |
msgstr ""
|
1450 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1451 |
#: src/Providers/Sendgrid/Options.php:25
|
1452 |
msgid "SendGrid"
|
1453 |
msgstr ""
|
@@ -1457,11 +1497,6 @@ msgstr ""
|
|
1457 |
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 day.<br><br>Read our %3$sSendGrid documentation%4$s to learn how to set up SendGrid and improve your email deliverability."
|
1458 |
msgstr ""
|
1459 |
|
1460 |
-
#: src/Providers/Sendgrid/Options.php:57
|
1461 |
-
#: src/Providers/Sendinblue/Options.php:88
|
1462 |
-
msgid "API Key"
|
1463 |
-
msgstr ""
|
1464 |
-
|
1465 |
#. translators: %s - API key link.
|
1466 |
#: src/Providers/Sendgrid/Options.php:76
|
1467 |
msgid "Follow this link to get an API Key from SendGrid: %s."
|
@@ -1478,7 +1513,7 @@ msgstr ""
|
|
1478 |
|
1479 |
#. translators: %1$s - URL to sendinblue.com site.
|
1480 |
#: src/Providers/Sendinblue/Options.php:31
|
1481 |
-
msgid "<strong><a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">Sendinblue</a> is
|
1482 |
msgstr ""
|
1483 |
|
1484 |
#. translators: %2$s - URL to wpmailsmtp.com doc.
|
@@ -1494,11 +1529,6 @@ msgstr ""
|
|
1494 |
msgid "Sendinblue"
|
1495 |
msgstr ""
|
1496 |
|
1497 |
-
#. translators: %s - sendinblue.com link to get an API Key.
|
1498 |
-
#: src/Providers/Sendinblue/Options.php:107
|
1499 |
-
msgid "Follow this link to get an API Key: %s."
|
1500 |
-
msgstr ""
|
1501 |
-
|
1502 |
#: src/Providers/Sendinblue/Options.php:109
|
1503 |
msgid "Get v3 API Key"
|
1504 |
msgstr ""
|
@@ -1662,6 +1692,6 @@ msgstr ""
|
|
1662 |
msgid "Your site is running an outdated version of PHP that is no longer supported and may cause issues with %1$s. %2$sRead more%3$s for additional information."
|
1663 |
msgstr ""
|
1664 |
|
1665 |
-
#: wp_mail_smtp.php:
|
1666 |
msgid "Please deactivate the free version of the WP Mail SMTP plugin before activating WP Mail SMTP Pro."
|
1667 |
msgstr ""
|
1 |
msgid ""
|
2 |
msgstr ""
|
3 |
+
"Project-Id-Version: WP Mail SMTP 1.8.0\n"
|
4 |
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wp-mail-smtp\n"
|
5 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
6 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
7 |
"MIME-Version: 1.0\n"
|
8 |
"Content-Type: text/plain; charset=UTF-8\n"
|
9 |
"Content-Transfer-Encoding: 8bit\n"
|
10 |
+
"POT-Creation-Date: 2019-12-12T16:09:57+02:00\n"
|
11 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
12 |
"X-Generator: WP-CLI 2.2.0\n"
|
13 |
"X-Domain: wp-mail-smtp\n"
|
478 |
msgstr ""
|
479 |
|
480 |
#: src/Admin/Pages/MiscTab.php:215
|
481 |
+
#: src/Admin/Pages/SettingsTab.php:542
|
482 |
msgid "Settings were successfully saved."
|
483 |
msgstr ""
|
484 |
|
578 |
msgid "Mailer"
|
579 |
msgstr ""
|
580 |
|
581 |
+
#: src/Admin/Pages/SettingsTab.php:241
|
582 |
+
#: src/Admin/Pages/SettingsTab.php:245
|
583 |
+
msgid "Suggest a Mailer"
|
584 |
+
msgstr ""
|
585 |
+
|
586 |
+
#: src/Admin/Pages/SettingsTab.php:274
|
587 |
msgid "Dismiss this notice"
|
588 |
msgstr ""
|
589 |
|
590 |
+
#: src/Admin/Pages/SettingsTab.php:316
|
591 |
msgid "You're using WP Mail SMTP Lite - no license needed. Enjoy!"
|
592 |
msgstr ""
|
593 |
|
594 |
#. translators: %s - WPMailSMTP.com upgrade URL.
|
595 |
+
#: src/Admin/Pages/SettingsTab.php:322
|
596 |
msgid "To unlock more features consider <strong><a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"wp-mail-smtp-upgrade-modal\">upgrading to PRO</a></strong>."
|
597 |
msgstr ""
|
598 |
|
599 |
+
#: src/Admin/Pages/SettingsTab.php:341
|
600 |
msgid "As a valued WP Mail SMTP Lite user you receive <strong>20% off</strong>, automatically applied at checkout!"
|
601 |
msgstr ""
|
602 |
|
603 |
+
#: src/Admin/Pages/SettingsTab.php:402
|
604 |
msgid "Get WP Mail SMTP Pro and Unlock all the Powerful Features"
|
605 |
msgstr ""
|
606 |
|
607 |
+
#: src/Admin/Pages/SettingsTab.php:406
|
608 |
msgid "Thanks for being a loyal WP Mail SMTP user. Upgrade to WP Mail SMTP Pro to unlock more awesome features and experience why WP Mail SMTP is the most popular SMTP plugin."
|
609 |
msgstr ""
|
610 |
|
611 |
+
#: src/Admin/Pages/SettingsTab.php:410
|
612 |
msgid "We know that you will truly love WP Mail SMTP. It's used by over 1,000,000 websites."
|
613 |
msgstr ""
|
614 |
|
615 |
+
#: src/Admin/Pages/SettingsTab.php:413
|
616 |
msgid "Pro Features:"
|
617 |
msgstr ""
|
618 |
|
619 |
+
#: src/Admin/Pages/SettingsTab.php:417
|
620 |
msgid "Manage Notifications - control which emails your site sends"
|
621 |
msgstr ""
|
622 |
|
623 |
+
#: src/Admin/Pages/SettingsTab.php:418
|
624 |
msgid "Email Logging - keep track of every email sent from your site"
|
625 |
msgstr ""
|
626 |
|
627 |
+
#: src/Admin/Pages/SettingsTab.php:419
|
628 |
msgid "Office 365 - send emails using your Office 365 account"
|
629 |
msgstr ""
|
630 |
|
631 |
+
#: src/Admin/Pages/SettingsTab.php:420
|
632 |
msgid "Amazon SES - harness the power of AWS"
|
633 |
msgstr ""
|
634 |
|
635 |
+
#: src/Admin/Pages/SettingsTab.php:421
|
636 |
msgid "Outlook.com - send emails using your Outlook.com account"
|
637 |
msgstr ""
|
638 |
|
639 |
+
#: src/Admin/Pages/SettingsTab.php:422
|
640 |
msgid "Access to our world class support team"
|
641 |
msgstr ""
|
642 |
|
643 |
+
#: src/Admin/Pages/SettingsTab.php:425
|
644 |
msgid "White Glove Setup - sit back and relax while we handle everything for you"
|
645 |
msgstr ""
|
646 |
|
647 |
+
#: src/Admin/Pages/SettingsTab.php:426
|
648 |
msgid "Install WP Mail SMTP Pro plugin"
|
649 |
msgstr ""
|
650 |
|
651 |
+
#: src/Admin/Pages/SettingsTab.php:427
|
652 |
msgid "Set up domain name verification (DNS)"
|
653 |
msgstr ""
|
654 |
|
655 |
+
#: src/Admin/Pages/SettingsTab.php:428
|
656 |
msgid "Configure Mailgun service"
|
657 |
msgstr ""
|
658 |
|
659 |
+
#: src/Admin/Pages/SettingsTab.php:429
|
660 |
msgid "Set up WP Mail SMTP Pro plugin"
|
661 |
msgstr ""
|
662 |
|
663 |
+
#: src/Admin/Pages/SettingsTab.php:430
|
664 |
msgid "Test and verify email delivery"
|
665 |
msgstr ""
|
666 |
|
667 |
#. translators: %s - WPMailSMTP.com URL.
|
668 |
+
#: src/Admin/Pages/SettingsTab.php:438
|
669 |
msgid "<a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer\">Get WP Mail SMTP Pro Today and Unlock all the Powerful Features »</a>"
|
670 |
msgstr ""
|
671 |
|
672 |
+
#: src/Admin/Pages/SettingsTab.php:456
|
673 |
msgid "<strong>Bonus:</strong> WP Mail SMTP users get <span class=\"price-off\">20% off regular price</span>, automatically applied at checkout."
|
674 |
msgstr ""
|
675 |
|
1450 |
msgstr ""
|
1451 |
|
1452 |
#: src/Providers/Pepipost/Options.php:25
|
1453 |
+
msgid "Pepipost SMTP"
|
1454 |
+
msgstr ""
|
1455 |
+
|
1456 |
+
#. translators: %1$s - URL to pepipost.com site.
|
1457 |
+
#: src/Providers/PepipostAPI/Options.php:31
|
1458 |
+
msgid "<strong><a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">Pepipost</a> is a recommended transactional email service.</strong> Every month Pepipost delivers over 8 billion emails from 20,000+ customers. Their mission is to reliably send emails in the most efficient way and at the most disruptive pricing ever. Pepipost provides users 30,000 free emails the first 30 days, then 100 emails per day."
|
1459 |
+
msgstr ""
|
1460 |
+
|
1461 |
+
#. translators: %1$s - URL to wpmailsmtp.com doc.
|
1462 |
+
#: src/Providers/PepipostAPI/Options.php:34
|
1463 |
+
msgid "Read our <a href=\"%2$s\" target=\"_blank\" rel=\"noopener noreferrer\">Pepipost documentation</a> to learn how to configure Pepipost and improve your email deliverability."
|
1464 |
+
msgstr ""
|
1465 |
+
|
1466 |
+
#: src/Providers/PepipostAPI/Options.php:53
|
1467 |
+
msgid "Get Pepipost Now (Free)"
|
1468 |
+
msgstr ""
|
1469 |
+
|
1470 |
+
#: src/Providers/PepipostAPI/Options.php:61
|
1471 |
msgid "Pepipost"
|
1472 |
msgstr ""
|
1473 |
|
1474 |
+
#: src/Providers/PepipostAPI/Options.php:88
|
1475 |
+
#: src/Providers/Sendgrid/Options.php:57
|
1476 |
+
#: src/Providers/Sendinblue/Options.php:88
|
1477 |
+
msgid "API Key"
|
1478 |
+
msgstr ""
|
1479 |
+
|
1480 |
+
#. translators: %s - pepipost.com link to get an API Key.
|
1481 |
+
#. translators: %s - sendinblue.com link to get an API Key.
|
1482 |
+
#: src/Providers/PepipostAPI/Options.php:107
|
1483 |
+
#: src/Providers/Sendinblue/Options.php:107
|
1484 |
+
msgid "Follow this link to get an API Key: %s."
|
1485 |
+
msgstr ""
|
1486 |
+
|
1487 |
+
#: src/Providers/PepipostAPI/Options.php:109
|
1488 |
+
msgid "Get the API Key"
|
1489 |
+
msgstr ""
|
1490 |
+
|
1491 |
#: src/Providers/Sendgrid/Options.php:25
|
1492 |
msgid "SendGrid"
|
1493 |
msgstr ""
|
1497 |
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 day.<br><br>Read our %3$sSendGrid documentation%4$s to learn how to set up SendGrid and improve your email deliverability."
|
1498 |
msgstr ""
|
1499 |
|
|
|
|
|
|
|
|
|
|
|
1500 |
#. translators: %s - API key link.
|
1501 |
#: src/Providers/Sendgrid/Options.php:76
|
1502 |
msgid "Follow this link to get an API Key from SendGrid: %s."
|
1513 |
|
1514 |
#. translators: %1$s - URL to sendinblue.com site.
|
1515 |
#: src/Providers/Sendinblue/Options.php:31
|
1516 |
+
msgid "<strong><a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">Sendinblue</a> is a recommended transactional email service.</strong> Founded in 2012, they serve 80,000+ growing companies around the world and send over 30 million emails each day. They understand that transactional emails are the heart of your customer relationships. Their email deliverability experts are constantly at work optimizing the reliability and speed of their SMTP infrastructure. Sendinblue provides users 300 free emails per day."
|
1517 |
msgstr ""
|
1518 |
|
1519 |
#. translators: %2$s - URL to wpmailsmtp.com doc.
|
1529 |
msgid "Sendinblue"
|
1530 |
msgstr ""
|
1531 |
|
|
|
|
|
|
|
|
|
|
|
1532 |
#: src/Providers/Sendinblue/Options.php:109
|
1533 |
msgid "Get v3 API Key"
|
1534 |
msgstr ""
|
1692 |
msgid "Your site is running an outdated version of PHP that is no longer supported and may cause issues with %1$s. %2$sRead more%3$s for additional information."
|
1693 |
msgstr ""
|
1694 |
|
1695 |
+
#: wp_mail_smtp.php:131
|
1696 |
msgid "Please deactivate the free version of the WP Mail SMTP plugin before activating WP Mail SMTP Pro."
|
1697 |
msgstr ""
|
readme.txt
CHANGED
@@ -1,377 +1,395 @@
|
|
1 |
-
=== WP Mail SMTP by WPForms ===
|
2 |
-
Contributors: wpforms, jaredatch, smub, slaFFik
|
3 |
-
Tags: smtp, wp mail smtp, wordpress smtp, gmail smtp, sendgrid smtp, mailgun smtp, mail, mailer, phpmailer, wp_mail, email, mailgun, sengrid, gmail, wp smtp
|
4 |
-
Requires at least: 4.9
|
5 |
-
Tested up to: 5.3
|
6 |
-
Stable tag: 1.
|
7 |
-
Requires PHP: 5.3
|
8 |
-
|
9 |
-
The most popular WordPress SMTP and PHP Mailer plugin. Trusted by over 1 million 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 1 million websites use WP Mail SMTP to send their emails reliably.
|
16 |
-
|
17 |
-
Our goal is to make email deliverability easy and reliable. We want to ensure your emails reach the inbox.
|
18 |
-
|
19 |
-
WP Mail SMTP fixes your email deliverability by reconfiguring WordPress to use a proper SMTP provider when sending emails.
|
20 |
-
|
21 |
-
= What is SMTP? =
|
22 |
-
|
23 |
-
SMTP (Simple Mail Transfer Protocol) is an industry standard for sending emails. Proper SMTP configuration helps increase email deliverability by using authentication.
|
24 |
-
|
25 |
-
Popular email clients like Gmail, Yahoo, and Office 365 are in a constant battle with email spammers. One of the things they look at is if an email is originating from the location it claims to be originating from.
|
26 |
-
|
27 |
-
If the proper authentication isn't there, then emails either go in the SPAM folder or worst, don't get delivered at all.
|
28 |
-
|
29 |
-
This is a problem for a lot of WordPress sites because by default, WordPress uses the PHP mail function to send emails generated by WordPress or any contact form plugin like <a href="https://wpforms.com/" rel="friend">WPForms</a>.
|
30 |
-
|
31 |
-
The issue is that most <a href"http://www.wpbeginner.com/wordpress-hosting/" rel="friend">WordPress hosting companies</a> don't have their servers properly configured for sending PHP emails.
|
32 |
-
|
33 |
-
The combination of two causes your WordPress emails to not get delivered.
|
34 |
-
|
35 |
-
= How does WP Mail SMTP work? =
|
36 |
-
|
37 |
-
WP Mail SMTP plugin easily resolves email delivery problems by improving and changing how your WordPress site sends email. We reconfigure the `wp_mail()` function to either use proper SMTP host credentials or leverage a built-in SMTP mail provider.
|
38 |
-
|
39 |
-
When using one of our built-in SMTP mail provider integrations (recommended), emails are sent using the provider's direct API. This means even if your web host is blocking SMTP ports, your emails still send successfully.
|
40 |
-
|
41 |
-
This helps you fix all WordPress not sending email issues.
|
42 |
-
|
43 |
-
WP Mail SMTP plugin includes many different SMTP setup options:
|
44 |
-
|
45 |
-
1.
|
46 |
-
2.
|
47 |
-
3.
|
48 |
-
4.
|
49 |
-
5.
|
50 |
-
6.
|
51 |
-
7.
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
=
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
=
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
=
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
WP Mail SMTP plugin
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
=
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
<a href="
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
=
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
* Added:
|
226 |
-
*
|
227 |
-
*
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
*
|
235 |
-
|
236 |
-
|
237 |
-
* Fixed:
|
238 |
-
|
239 |
-
= 1.
|
240 |
-
*
|
241 |
-
|
242 |
-
|
243 |
-
* Added:
|
244 |
-
*
|
245 |
-
*
|
246 |
-
* Changed:
|
247 |
-
* Changed:
|
248 |
-
|
249 |
-
|
250 |
-
*
|
251 |
-
*
|
252 |
-
*
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
*
|
261 |
-
*
|
262 |
-
|
263 |
-
|
264 |
-
*
|
265 |
-
*
|
266 |
-
*
|
267 |
-
*
|
268 |
-
*
|
269 |
-
* Fixed:
|
270 |
-
* Fixed:
|
271 |
-
* Fixed:
|
272 |
-
|
273 |
-
|
274 |
-
* Changed:
|
275 |
-
* Changed:
|
276 |
-
|
277 |
-
|
278 |
-
*
|
279 |
-
* Changed:
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
*
|
284 |
-
*
|
285 |
-
|
286 |
-
|
287 |
-
*
|
288 |
-
|
289 |
-
|
290 |
-
*
|
291 |
-
*
|
292 |
-
|
293 |
-
|
294 |
-
*
|
295 |
-
*
|
296 |
-
*
|
297 |
-
*
|
298 |
-
*
|
299 |
-
|
300 |
-
|
301 |
-
*
|
302 |
-
*
|
303 |
-
|
304 |
-
|
305 |
-
*
|
306 |
-
|
307 |
-
|
308 |
-
* Fixed: SMTP Debug
|
309 |
-
* Fixed:
|
310 |
-
|
311 |
-
|
312 |
-
*
|
313 |
-
*
|
314 |
-
*
|
315 |
-
*
|
316 |
-
|
317 |
-
|
318 |
-
*
|
319 |
-
*
|
320 |
-
*
|
321 |
-
*
|
322 |
-
*
|
323 |
-
* Fixed:
|
324 |
-
* Fixed:
|
325 |
-
* Fixed:
|
326 |
-
* Fixed:
|
327 |
-
* Fixed:
|
328 |
-
* Fixed:
|
329 |
-
* Changed:
|
330 |
-
* Changed:
|
331 |
-
|
332 |
-
|
333 |
-
*
|
334 |
-
|
335 |
-
= 1.2.
|
336 |
-
* Fixed:
|
337 |
-
* Fixed:
|
338 |
-
|
339 |
-
|
340 |
-
* Fixed:
|
341 |
-
* Fixed:
|
342 |
-
*
|
343 |
-
|
344 |
-
|
345 |
-
* Fixed:
|
346 |
-
|
347 |
-
|
348 |
-
*
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
*
|
355 |
-
*
|
356 |
-
|
357 |
-
|
358 |
-
* Fixed:
|
359 |
-
* Fixed:
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
* Added:
|
371 |
-
*
|
372 |
-
*
|
373 |
-
* Changed:
|
374 |
-
* Changed:
|
375 |
-
*
|
376 |
-
*
|
377 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== WP Mail SMTP by WPForms ===
|
2 |
+
Contributors: wpforms, jaredatch, smub, slaFFik
|
3 |
+
Tags: smtp, wp mail smtp, wordpress smtp, gmail smtp, sendgrid smtp, mailgun smtp, mail, mailer, phpmailer, wp_mail, email, mailgun, sengrid, gmail, wp smtp
|
4 |
+
Requires at least: 4.9
|
5 |
+
Tested up to: 5.3
|
6 |
+
Stable tag: 1.8.0
|
7 |
+
Requires PHP: 5.3
|
8 |
+
|
9 |
+
The most popular WordPress SMTP and PHP Mailer plugin. Trusted by over 1 million 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 1 million websites use WP Mail SMTP to send their emails reliably.
|
16 |
+
|
17 |
+
Our goal is to make email deliverability easy and reliable. We want to ensure your emails reach the inbox.
|
18 |
+
|
19 |
+
WP Mail SMTP fixes your email deliverability by reconfiguring WordPress to use a proper SMTP provider when sending emails.
|
20 |
+
|
21 |
+
= What is SMTP? =
|
22 |
+
|
23 |
+
SMTP (Simple Mail Transfer Protocol) is an industry standard for sending emails. Proper SMTP configuration helps increase email deliverability by using authentication.
|
24 |
+
|
25 |
+
Popular email clients like Gmail, Yahoo, and Office 365 are in a constant battle with email spammers. One of the things they look at is if an email is originating from the location it claims to be originating from.
|
26 |
+
|
27 |
+
If the proper authentication isn't there, then emails either go in the SPAM folder or worst, don't get delivered at all.
|
28 |
+
|
29 |
+
This is a problem for a lot of WordPress sites because by default, WordPress uses the PHP mail function to send emails generated by WordPress or any contact form plugin like <a href="https://wpforms.com/" rel="friend">WPForms</a>.
|
30 |
+
|
31 |
+
The issue is that most <a href"http://www.wpbeginner.com/wordpress-hosting/" rel="friend">WordPress hosting companies</a> don't have their servers properly configured for sending PHP emails.
|
32 |
+
|
33 |
+
The combination of two causes your WordPress emails to not get delivered.
|
34 |
+
|
35 |
+
= How does WP Mail SMTP work? =
|
36 |
+
|
37 |
+
WP Mail SMTP plugin easily resolves email delivery problems by improving and changing how your WordPress site sends email. We reconfigure the `wp_mail()` function to either use proper SMTP host credentials or leverage a built-in SMTP mail provider.
|
38 |
+
|
39 |
+
When using one of our built-in SMTP mail provider integrations (recommended), emails are sent using the provider's direct API. This means even if your web host is blocking SMTP ports, your emails still send successfully.
|
40 |
+
|
41 |
+
This helps you fix all WordPress not sending email issues.
|
42 |
+
|
43 |
+
WP Mail SMTP plugin includes many different SMTP setup options:
|
44 |
+
|
45 |
+
1. Pepipost SMTP <strong>(Recommended)</strong>
|
46 |
+
2. Sendinblue SMTP <strong>(Recommended)</strong>
|
47 |
+
3. Mailgun SMTP
|
48 |
+
4. SendGrid SMTP
|
49 |
+
5. Gmail SMTP
|
50 |
+
6. Microsoft SMTP (Outlook.com and Office 365) <a href="https://wpmailsmtp.com/?utm_source=wprepo&utm_medium=link&utm_campaign=liteversion&utm_content=readme" rel="friend">[Pro]</a>
|
51 |
+
7. Amazon SES SMTP <a href="https://wpmailsmtp.com/?utm_source=wprepo&utm_medium=link&utm_campaign=liteversion&utm_content=readme" rel="friend">[Pro]</a>
|
52 |
+
8. All Other SMTP
|
53 |
+
|
54 |
+
For all options, you can specify the "from name" and "email address" for outgoing emails.
|
55 |
+
|
56 |
+
Instead of having users use different SMTP plugins and workflows for different SMTP providers, we decided to bring it all in one. This is what makes WP Mail SMTP, the best SMTP solution for WordPress.
|
57 |
+
|
58 |
+
= Pepipost SMTP =
|
59 |
+
|
60 |
+
Pepipost is a recommended transactional email service.
|
61 |
+
|
62 |
+
Every month they delivers over 8 billion emails from 20,000+ customers.
|
63 |
+
|
64 |
+
Their mission is to reliably send emails in the most efficient way and at the most disruptive pricing ever.
|
65 |
+
Pepipost provides users 30,000 emails the first 30 days, then 100 emails per day.
|
66 |
+
|
67 |
+
Read our <a href="https://wpmailsmtp.com/docs/how-to-set-up-the-pepipost-mailer-in-wp-mail-smtp/" rel="friend">Pepipost documentation</a> for more details.
|
68 |
+
|
69 |
+
= Sendinblue SMTP =
|
70 |
+
|
71 |
+
Sendinblue is a recommended transactional email service.
|
72 |
+
|
73 |
+
They serve 80,000+ growing companies around the world and send over 30 million emails each day.
|
74 |
+
|
75 |
+
Their email deliverability experts are constantly at work optimizing the reliability and speed of their SMTP infrastructure. Sendinblue provides users 300 free emails per day.
|
76 |
+
|
77 |
+
Read our <a href="https://wpmailsmtp.com/docs/how-to-set-up-the-sendinblue-mailer-in-wp-mail-smtp/" rel="friend">Sendinblue documentation</a> for more details.
|
78 |
+
|
79 |
+
= Mailgun SMTP =
|
80 |
+
|
81 |
+
Mailgun SMTP is a popular SMTP service provider that allows you to send large quantities of emails. They allow you to send your first 10,000 emails for free every month.
|
82 |
+
|
83 |
+
WP Mail SMTP plugin offers a native integration with MailGun. All you have to do is connect your Mailgun account, and you will improve your email deliverability.
|
84 |
+
|
85 |
+
Read our <a href="https://wpmailsmtp.com/docs/how-to-set-up-the-mailgun-mailer-in-wp-mail-smtp/" rel="friend">Mailgun documentation</a> for more details.
|
86 |
+
|
87 |
+
= SendGrid SMTP =
|
88 |
+
|
89 |
+
SendGrid has a free SMTP plan that you can use to send up to 100 emails per day. With our native SendGrid SMTP integration, you can easily and securely set up SendGrid SMTP on your WordPress site.
|
90 |
+
|
91 |
+
Read our <a href="https://wpmailsmtp.com/docs/how-to-set-up-the-sendgrid-mailer-in-wp-mail-smtp/" rel="friend">SendGrid documentation</a> for more details.
|
92 |
+
|
93 |
+
= Gmail SMTP =
|
94 |
+
|
95 |
+
Often bloggers and small business owners don't want to use third-party SMTP services. Well you can use your Gmail or G Suite account for SMTP emails.
|
96 |
+
|
97 |
+
This allows you to use your <a href="http://www.wpbeginner.com/beginners-guide/how-to-setup-a-professional-email-address-with-gmail-and-google-apps/" rel="friend">professional email address</a> and improve email deliverability.
|
98 |
+
|
99 |
+
Unlike other Gmail SMTP plugins, our Gmail SMTP option uses OAuth to authenticate your Google account, keeping your login information 100% secure.
|
100 |
+
|
101 |
+
Read our <a href="https://wpmailsmtp.com/docs/how-to-set-up-the-gmail-mailer-in-wp-mail-smtp/" rel="friend">Gmail documentation</a> for more details.
|
102 |
+
|
103 |
+
= Microsoft SMTP (Outlook.com and Office 365) =
|
104 |
+
|
105 |
+
Many business use Outlook.com or Office 365 to their to power their email. For those users, the Microsoft mailer can be a great option. This integration allows you to use your existing Outlook.com or Office 365 account to send your emails reliably.
|
106 |
+
|
107 |
+
= Amazon SES SMTP =
|
108 |
+
|
109 |
+
Advanced or technical users can harness the power of Amazon AWS (Amazon Web Services) with the Amazon SES mailer. With this integration, you can send a high volume of emails at a very reasonable rate.
|
110 |
+
|
111 |
+
Read our <a href="https://wpmailsmtp.com/docs/how-to-set-up-the-amazon-ses-mailer-in-wp-mail-smtp/" rel="friend">Amazon SES documentation</a> for more details.
|
112 |
+
|
113 |
+
= Other SMTP =
|
114 |
+
|
115 |
+
WP Mail SMTP plugin also works with all major email services such as Gmail, Yahoo, Outlook, Microsoft Live, and any other email sending service that offers SMTP.
|
116 |
+
|
117 |
+
You can set the following options:
|
118 |
+
|
119 |
+
* Specify an SMTP host.
|
120 |
+
* Specify an SMTP port.
|
121 |
+
* Choose SSL / TLS encryption.
|
122 |
+
* Choose to use SMTP authentication or not.
|
123 |
+
* Specify an SMTP username and password.
|
124 |
+
|
125 |
+
To see recommended settings for the popular services as well as troubleshooting tips, check out our <a href="https://wpmailsmtp.com/docs/how-to-set-up-the-other-smtp-mailer-in-wp-mail-smtp/" rel="friend">SMTP documentation</a>.
|
126 |
+
|
127 |
+
We hope that you find WP Mail SMTP plugin helpful!
|
128 |
+
|
129 |
+
### WP Mail SMTP PRO
|
130 |
+
|
131 |
+
In addition to native Microsoft and Amazon SES integrations, WP Mail SMTP Pro provides access to many other powerful features and services.
|
132 |
+
|
133 |
+
<a href="https://wpmailsmtp.com/?utm_source=wprepo&utm_medium=link&utm_campaign=liteversion&utm_content=readme" rel="friend">Click here to purchase WP Mail SMTP Pro now!</a>
|
134 |
+
|
135 |
+
= Email Log =
|
136 |
+
|
137 |
+
Email Logging lets you log and view all emails sent from your site. Email logs are helpful for storing emails for your records, auditing outgoing emails, and debugging during site development.
|
138 |
+
|
139 |
+
= Manage WordPress Emails and Notifications =
|
140 |
+
|
141 |
+
The Manage Notification feature gives you full control over which email notifications WordPress sends. This means you can disable different WordPress notification emails. Don't want to receive emails when new users are created? No problem, turn it off.
|
142 |
+
|
143 |
+
= Expert Support =
|
144 |
+
|
145 |
+
We provide <a href="https://wordpress.org/support/topic/wp-mail-smtp-support-policy/">limited support</a> for the WP Mail SMTP plugin on the WordPress.org forums. Access to our world class one-on-one email support is available to <a href="https://wpmailsmtp.com/?utm_source=wprepo&utm_medium=link&utm_campaign=liteversion&utm_content=readme" rel="friend">WP Mail SMTP Pro</a> users.
|
146 |
+
|
147 |
+
= White Glove Setup =
|
148 |
+
|
149 |
+
Our White Glove Setup service is a great option that anyone can benefit from. Whether you don't have the time or maybe you feel a bit in over your head - we've got you covered.
|
150 |
+
|
151 |
+
You can sit back and relax while we set up everything for you. White glove setup includes WP Mail SMTP plugin installation and setup, configuration adjustments to your DNS for proper email domain name verification, Mailgun setup, and final testing to confirm everything is passing with flying colors.
|
152 |
+
|
153 |
+
### Security
|
154 |
+
|
155 |
+
The WP Mail SMTP team takes security very seriously. Not only does the plugin follow all security best practices, but we have several options available to ensure your site is safe and secure.
|
156 |
+
|
157 |
+
- Direct SMTP mailer integrations (recommended), such as Google and Mailgun, use the official provider APIs. This means you never enter your username or password in the plugin settings and these credentials are not stored in the database. Instead, we use tokens or API keys which are much more secure.
|
158 |
+
|
159 |
+
- When using Other SMTP mailer, we provide the option to insert your password in your `wp-config.php` file, so it's not visible in your WordPress settings or saved in the database.
|
160 |
+
|
161 |
+
### Credits
|
162 |
+
|
163 |
+
WP Mail SMTP plugin was originally created by Callum Macdonald. It is now owned and maintained by the team behind <a href="https://wpforms.com/" rel="friend">WPForms</a> - the best drag & drop form builder for WordPress.
|
164 |
+
|
165 |
+
You can try the <a href="https://wordpress.org/plugins/wpforms-lite/" rel="friend">free version of WPForms plugin</a> to see why it's the best in the market.
|
166 |
+
|
167 |
+
### What's Next
|
168 |
+
|
169 |
+
If you like this plugin, then consider checking out our other projects:
|
170 |
+
|
171 |
+
* <a href="https://optinmonster.com/" rel="friend" title="OptinMonster">OptinMonster</a> - Get More Email Subscribers with the most popular conversion optimization plugin for WordPress.
|
172 |
+
* <a href="https://www.monsterinsights.com/" rel="friend" title="MonsterInsights">MonsterInsights</a> - See the Stats that Matter and Grow Your Business with Confidence. Best Google Analytics Plugin for WordPress.
|
173 |
+
* <a href="https://www.seedprod.com/" rel="friend" title="SeedProd">SeedProd</a> - Jumpstart your website with the #1 Coming Soon & Maintenance Mode Plugin for WordPress.
|
174 |
+
|
175 |
+
Visit <a href="http://www.wpbeginner.com/" rel="friend" title="WPBeginner">WPBeginner</a> to learn from our <a href="http://www.wpbeginner.com/category/wp-tutorials/" rel="friend" title="WordPress Tutorials">WordPress Tutorials</a> and find out about other <a href="http://www.wpbeginner.com/category/plugins/" rel="friend" title="Best WordPress Plugins">best WordPress plugins</a>.
|
176 |
+
|
177 |
+
== Installation ==
|
178 |
+
|
179 |
+
1. Install WP Mail SMTP by WPForms either via the WordPress.org plugin repository or by uploading the files to your server. (See instructions on <a href="http://www.wpbeginner.com/beginners-guide/step-by-step-guide-to-install-a-wordpress-plugin-for-beginners/" rel="friend">how to install a WordPress plugin</a>)
|
180 |
+
2. Activate WP Mail SMTP by WPForms.
|
181 |
+
3. Navigate to the Settings area of WP Mail SMTP in the WordPress admin.
|
182 |
+
4. Choose your SMTP option (Mailgun SMTP, SendGrid SMTP, Gmail SMTP, or Other SMTP) and follow the instructions to set it up.
|
183 |
+
5. Need more help? Get support with <a href="https://wpmailsmtp.com/?utm_source=wprepo&utm_medium=link&utm_campaign=liteversion&utm_content=readme" rel="friend" title="WPForms">WP Mail SMTP PRO</a>.
|
184 |
+
|
185 |
+
== Frequently Asked Questions ==
|
186 |
+
|
187 |
+
= Can I use this plugin to send email via Gmail, G Suite, Outlook.com, Office 365, Hotmail, Yahoo, or AOL SMTP? =
|
188 |
+
|
189 |
+
Yes! We have extensive documentation that covers setting up SMTP most popular email services.
|
190 |
+
|
191 |
+
<a href="https://wpforms.com/docs/how-to-set-up-smtp-using-the-wp-mail-smtp-plugin/" rel="friend">Read our docs</a> to see the correct SMTP settings for each service.
|
192 |
+
|
193 |
+
= Help! I need support or have an issue. =
|
194 |
+
|
195 |
+
Please read <a href="https://wordpress.org/support/topic/wp-mail-smtp-support-policy/">our support policy</a> for more information.
|
196 |
+
|
197 |
+
Limited support is available for WP Mail SMTP users via WordPress.org support forums.
|
198 |
+
|
199 |
+
Email support and set up assistance is available to WP Mail SMTP Pro users.
|
200 |
+
|
201 |
+
= I found a bug, now what? =
|
202 |
+
|
203 |
+
If you've stumbled upon a bug, the best place to report it is in the <a href="https://github.com/awesomemotive/wp-mail-smtp">WP Mail SMTP GitHub repository</a>. GitHub is where the plugin is actively developed, and posting there will get your issue quickly seen by our developers (myself and Slava). Once posted, we'll review your bug report and triage the bug. When creating an issue, the more details you can add to your report, the faster the bug can be solved.
|
204 |
+
|
205 |
+
= Can you add feature x, y or z to the plugin? =
|
206 |
+
|
207 |
+
Short answer: maybe.
|
208 |
+
|
209 |
+
By all means please contact us to discuss features or options you'd like to see added to the plugin. We can't guarantee to add all of them, but we will consider all sensible requests. We can be contacted here:
|
210 |
+
<a href="https://wpmailsmtp.com/contact/" rel="friend">https://wpmailsmtp.com/contact/</a>
|
211 |
+
|
212 |
+
== Screenshots ==
|
213 |
+
|
214 |
+
1. WP Mail SMTP Settings page
|
215 |
+
2. Gmail / G Suite settings
|
216 |
+
3. Mailgun settings
|
217 |
+
4. SendGrid settings
|
218 |
+
5. SMTP settings
|
219 |
+
6. Send a Test Email
|
220 |
+
|
221 |
+
== Changelog ==
|
222 |
+
|
223 |
+
= 1.8.0 - 2019-12-12 =
|
224 |
+
* Added: New recommended mailer: Pepipost.
|
225 |
+
* Added: "Suggest a Mailer" link in a list of mailers to send us your ideas about new ones.
|
226 |
+
* Fixed: Sendgrid: Content ID for attachments missing.
|
227 |
+
* Changed: Timeout to HTTP requests (pepipost, sendgrid, mailgun), same as max_execution_time, to prevent fails when sending emails with big attachments.
|
228 |
+
|
229 |
+
= 1.7.1 - 2019-11-11 =
|
230 |
+
* Fixed: Compatibility with WordPress 5.3.
|
231 |
+
* Fixed: `Processor::get_default_email()` always returns empty value when server incorrectly configured.
|
232 |
+
|
233 |
+
= 1.7.0 - 2019-10-24 =
|
234 |
+
* Added: Add a new constant `WPMS_DO_NOT_SEND` to block email sending.
|
235 |
+
* Fixed: Default email (wordpress@example.com) rewriting in CLI mode.
|
236 |
+
* Fixed: Incorrect conflicts detection with certain plugins.
|
237 |
+
* Fixed: various typos in plugin settings.
|
238 |
+
|
239 |
+
= 1.6.2 - 2019-09-02 =
|
240 |
+
* Fixed: Race condition when loading with certain plugins, that send emails very early. Makes email delivery more reliable.
|
241 |
+
|
242 |
+
= 1.6.0 - 2019-08-21 =
|
243 |
+
* Added: New transactional mailer: Sendinblue.
|
244 |
+
* Added: Educate users to use transactional mailers for better deliverability.
|
245 |
+
* Added: New option and filter to disable admin area delivery error notices.
|
246 |
+
* Changed: Hide private API key saved in the DB for API based mailers using `input[type=password]`.
|
247 |
+
* Changed: Update links to various docs, pointing now to https://wpmailsmtp.com.
|
248 |
+
|
249 |
+
= 1.5.2 - 2019-07-18 =
|
250 |
+
* Fixed: "Redirect URI mismatch" error for "Gmail" mailer when trying to re-authorize an account that was initially created with version < v1.5.0.
|
251 |
+
* Changed: Make "Authentication" setting in "Other SMTP" mailer ON by default for new users.
|
252 |
+
* Changed: Mailers docs links now point to wpmailsmtp.com own site.
|
253 |
+
|
254 |
+
= 1.5.1 - 2019-07-12 =
|
255 |
+
* Fixed: Duplicated emails sent to the first recipient in a loop (and others not receiving their emails).
|
256 |
+
|
257 |
+
= 1.5.0 - 2019-07-09 =
|
258 |
+
* Added: Loсo plugin support.
|
259 |
+
* Added: "About us" admin area page.
|
260 |
+
* Added: Display in debug output a possible conflicting plugin existence.
|
261 |
+
* Added: Lots of actions and filters to improve flexibility of the plugin.
|
262 |
+
* Changed: Plugin menu is now top level.
|
263 |
+
* Changed: Hide secrets/API keys in page DOM in plugin admin area.
|
264 |
+
* Changed: Do not save constant values into the database when plugin settings are saved.
|
265 |
+
* Changed: Lots of i18n improvements to support translation for both free and paid version of the plugin.
|
266 |
+
* Changed: Gmail mailer - allow to change From Name email header.
|
267 |
+
* Changed: Gmail mailer - display email used to create a connection.
|
268 |
+
* Changed: WordPress 4.9 is the minimum WordPress version we support.
|
269 |
+
* Fixed: X-Mailer header should be present in all emails.
|
270 |
+
* Fixed: PHP notices when migrating under certain circumstances from 0.x version of the plugin.
|
271 |
+
* Fixed: Options::get_group() now supports values set via constants.
|
272 |
+
|
273 |
+
= 1.4.2 - 2019-03-23 =
|
274 |
+
* Changed: Tested up to WordPress 5.1.x.
|
275 |
+
* Changed: Removed TGMPA library.
|
276 |
+
|
277 |
+
= 1.4.1 - 2018-12-03 =
|
278 |
+
* Fixed: correctly process backslashes in SMTP passwords defined via constants.
|
279 |
+
* Changed: allow to send a Test Email when Default (none) mailer is selected in plugin settings.
|
280 |
+
|
281 |
+
= 1.4.0 - 2018-11-29 =
|
282 |
+
* Added: New option: Do Not Send - block emails from being sent.
|
283 |
+
* Added: New option: Send HTML or plain text emails when doing an Email Test.
|
284 |
+
* Added: New option: Mailgun region selection - US and EU (US is default to preserve compatibility).
|
285 |
+
* Fixed: Compatibility with WordPress 3.6+.
|
286 |
+
* Fixed: Compatibility with WordPress 5.0.
|
287 |
+
* Fixed: Constants usage is much more reliable now, works correctly on Multisite. Constants are global accross the whole network.
|
288 |
+
* Fixed: Preserve multipart emails when using Sendgrid/Mailgun mailers (were converted to HTML-only).
|
289 |
+
* Fixed: Security hardening.
|
290 |
+
* Changed: Prefill Email Test page From field with currently logged in user email.
|
291 |
+
* Changed: Update libraries: google/apiclient-services, google/auth, phpseclib/phpseclib and their dependecies.
|
292 |
+
* Changed: Display in debug output cURL version if Gmail mailing failed.
|
293 |
+
* Changed: Display in debug output OpenSSL version if it exists if Gmail/SMTP mailing failed.
|
294 |
+
* Changed: Display plugin version in dashboard error notice when emailing failed.
|
295 |
+
* Changed: Do not allow to send Test Email if mailer not configured properly.
|
296 |
+
* Changed: Notify in plugin admin area that Gmail doesn't allow to redefine From Name/Email etc.
|
297 |
+
* Changed: List all constants with descriptions in plugin main file: wp_mail_smtp.php.
|
298 |
+
* Changed: TGMPA: change descriptions from "Required" to "Recommended" (labels were incorrect).
|
299 |
+
|
300 |
+
= 1.3.3 - 2018-07-05 =
|
301 |
+
* Fixed: Compatibility with other plugins, that are using Google Service or Google Client classes.
|
302 |
+
* Changed: Optimize code loading.
|
303 |
+
|
304 |
+
= 1.3.2 - 2018-06-29 =
|
305 |
+
* Make sure that other plugins/themes are not conflicting with our TGMPA library.
|
306 |
+
|
307 |
+
= 1.3.1 - 2018-06-29 =
|
308 |
+
* Fixed: Other SMTP: Clear new Debug messages about failed email delivery on next successful email sending.
|
309 |
+
* Fixed: Introduce conditional autoloader to workaround Gmail PHP 5.5 requirement and its library compatibility issues vs PHP 5.3+ minimum viable plugin version.
|
310 |
+
|
311 |
+
= 1.3.0 - 2018-06-28 =
|
312 |
+
* Added: New option: force From Email rewrite regardless of the current value.
|
313 |
+
* Added: New option: force From Name rewrite regardless of the current value.
|
314 |
+
* Added: New option: remove all plugin data on plugin uninstall (when user deletes it).
|
315 |
+
* Added: Notify site admins in wp-admin area with a notice about last failed email delivery. Cleans up on successful delivery.
|
316 |
+
* Added: Notify site admins in wp-admin area with a notice about possible compatibility issues with other SMTP and email delivery plugins.
|
317 |
+
* Added: Improve User Debug Experience when doing Email Test - display helpful description and steps to fix the issue.
|
318 |
+
* Added: New users: provide default SMTP Port value for new users based on Encryption selection.
|
319 |
+
* Added: New users: notify about not configured plugin settings.
|
320 |
+
* Added: New users: Recommend free WPForms Lite plugin for those who don't have it.
|
321 |
+
* Added: SendGrid/Mailgun: provide support for multipart/alternative types of emails.
|
322 |
+
* Added: Gmail: new button to remove connection and to connect a new Google account.
|
323 |
+
* Fixed: Support plugin installation into /mu-plugins/ directory.
|
324 |
+
* Fixed: SendGrid: required text/plain part of email being the first one - fixes plain text emails not having links.
|
325 |
+
* Fixed: SendGrid and Mailgun: improperly sending plain text emails in html format.
|
326 |
+
* Fixed: SMTP Debug output was empty in some cases.
|
327 |
+
* Fixed: Compatibility with lots of other plugins that use Google Analytics library of different versions.
|
328 |
+
* Fixed: "client_id is empty" is no more a problem, should be fixed.
|
329 |
+
* Changed: For SendGrid and Mailgun allow using custom defined attachments names if present. Fallback to file name.
|
330 |
+
* Changed: Gmail: switch to a wider scope to prevent possible issues in certain circumstances.
|
331 |
+
* Changed: Remove whitespaces start/end of keys, secrets etc.
|
332 |
+
* Changed: Improved helpful description tests of various options.
|
333 |
+
* Changed: Improved plugin autoloading functionality.
|
334 |
+
|
335 |
+
= 1.2.5 - 2017-02-05 =
|
336 |
+
* Fixed: `Return path` can't be turned off.
|
337 |
+
* Fixed: `Authentication` sometimes can't be turned off.
|
338 |
+
* Fixed: `Auto TLS` sometimes can't be turned off.
|
339 |
+
* Fixed: BCC support for Gmail was broken.
|
340 |
+
* Fixed: Debug output improved to handle SELinux and grsecurity.
|
341 |
+
* Fixed: Strip slashes from plugin settings (useful for `From Name` option).
|
342 |
+
* Fixed: Change the way sanitization is done to prevent accidental removal of useful data.
|
343 |
+
* Fixed: Plugin activation will not overwrite settings back to defaults.
|
344 |
+
* Fixed: Properly set `Auto TLS` option on plugin activation.
|
345 |
+
* Fixed: Providers autoloading improved for certain Windows-based installs.
|
346 |
+
* Fixed: Use the proper path to load translations from plugin's `/languages` directory.
|
347 |
+
* Changed: Do not autoload on each page request plugin settings from WordPress options table.
|
348 |
+
* Changed: Do not autoload Pepipost classes unless it's saved as active mailer in settings.
|
349 |
+
|
350 |
+
= 1.2.4 - 2017-01-28 =
|
351 |
+
* Fixed: Improved escaping in debug reporting.
|
352 |
+
|
353 |
+
= 1.2.3 - 2017-01-22 =
|
354 |
+
* Fixed: Gmail tokens were reset after clicking Save Settings.
|
355 |
+
* Fixed: Slight typo in Gmail success message.
|
356 |
+
|
357 |
+
= 1.2.2 - 2017-12-27 =
|
358 |
+
* Fixed: Correctly handle Mailgun debug message for an incorrect api key.
|
359 |
+
* Fixed: Fatal error for Gmail and SMTP mailers with Nginx web-server (without Apache at all).
|
360 |
+
* Changed: Update X-Mailer emails header to show the real sender with a mailer and plugin version.
|
361 |
+
|
362 |
+
= 1.2.1 - 2017-12-21 =
|
363 |
+
* Fixed: Failed SMTP connections generate fatal errors.
|
364 |
+
|
365 |
+
= 1.2.0 - 2017-12-21 =
|
366 |
+
* Fixed: Decrease the factual minimum WordPress version from 3.9 to 3.6.
|
367 |
+
* Changed: Improve debug output for all mail providers.
|
368 |
+
|
369 |
+
= 1.1.0 - 2017-12-18 =
|
370 |
+
* Added: New option "Auto TLS" for SMTP mailer. Default is enabled. Migration routine for all sites.
|
371 |
+
* Changed: Improve debug output - clear styles and context-aware content.
|
372 |
+
* Changed: Better exceptions handling for Google authentication process.
|
373 |
+
* Changed: Do not sanitize passwords, api keys etc - as they may contain special characters in certain order and sanitization will break those values.
|
374 |
+
* Changed: Improve wording of some helpful texts inside plugin admin area.
|
375 |
+
* Fixed: Do not include certain files in dependency libraries that are not used by Google mailer. This should stop flagging plugin by Wordfence and VaultPress.
|
376 |
+
* Fixed: Constants usage is working now, to define the SMTP password, for example.
|
377 |
+
* Fixed: Notice for default mailer.
|
378 |
+
|
379 |
+
= 1.0.2 - 2017-12-12 =
|
380 |
+
* Fixed: PHPMailer using incorrect SMTPSecure value.
|
381 |
+
|
382 |
+
= 1.0.1 - 2017-12-12 =
|
383 |
+
* Fixed: Global POST processing conflict.
|
384 |
+
|
385 |
+
= 1.0.0 - 2017-12-12 =
|
386 |
+
* Added: Automatic migration tool to move options from older storage format to a new one.
|
387 |
+
* Added: Added Gmail & G Suite email provider integration - without your email and password.
|
388 |
+
* Added: Added SendGrid email provider integration - using the API key only.
|
389 |
+
* Added: Added Mailgun email provider integration - using the API key and configured domain only.
|
390 |
+
* Added: New compatibility mode - for PHP 5.2 old plugin will be loaded, for PHP 5.3 and higher - new version of admin area and new functionality.
|
391 |
+
* Changed: The new look of the admin area.
|
392 |
+
* Changed: SMTP password field now has "password" type.
|
393 |
+
* Changed: SMTP password field does not display real password at all when using constants in `wp-config.php` to define it.
|
394 |
+
* Changed: Escape properly all translations.
|
395 |
+
* Changed: More helpful test email content (with a mailer name).
|
src/Admin/Area.php
CHANGED
@@ -1,889 +1,889 @@
|
|
1 |
-
<?php
|
2 |
-
|
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.
|
10 |
-
*
|
11 |
-
* @since 1.0.0
|
12 |
-
*/
|
13 |
-
class Area {
|
14 |
-
|
15 |
-
/**
|
16 |
-
* @since 1.0.0
|
17 |
-
*
|
18 |
-
* @var string Slug of the admin area page.
|
19 |
-
*/
|
20 |
-
const SLUG = 'wp-mail-smtp';
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @since 1.0.0
|
24 |
-
*
|
25 |
-
* @var string Admin page unique hook.
|
26 |
-
*/
|
27 |
-
public $hook;
|
28 |
-
|
29 |
-
/**
|
30 |
-
* @since 1.0.0
|
31 |
-
*
|
32 |
-
* @var PageAbstract[]
|
33 |
-
*/
|
34 |
-
private $pages;
|
35 |
-
|
36 |
-
/**
|
37 |
-
* @since 1.5.0
|
38 |
-
*
|
39 |
-
* @var array List of official registered pages.
|
40 |
-
*/
|
41 |
-
public static $pages_registered = array( 'general', 'logs', 'about' );
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Area constructor.
|
45 |
-
*
|
46 |
-
* @since 1.0.0
|
47 |
-
*/
|
48 |
-
public function __construct() {
|
49 |
-
$this->hooks();
|
50 |
-
}
|
51 |
-
|
52 |
-
/**
|
53 |
-
* Assign all hooks to proper places.
|
54 |
-
*
|
55 |
-
* @since 1.0.0
|
56 |
-
*/
|
57 |
-
protected function hooks() {
|
58 |
-
|
59 |
-
// Add the Settings link to a plugin on Plugins page.
|
60 |
-
add_filter( 'plugin_action_links', array( $this, 'add_plugin_action_link' ), 10, 2 );
|
61 |
-
|
62 |
-
// Add the options page.
|
63 |
-
add_action( 'admin_menu', array( $this, 'add_admin_options_page' ) );
|
64 |
-
|
65 |
-
// Admin footer text.
|
66 |
-
add_filter( 'admin_footer_text', array( $this, 'get_admin_footer' ), 1, 2 );
|
67 |
-
|
68 |
-
// Enqueue admin area scripts and styles.
|
69 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
70 |
-
|
71 |
-
// Process the admin page forms actions.
|
72 |
-
add_action( 'admin_init', array( $this, 'process_actions' ) );
|
73 |
-
|
74 |
-
// Display custom notices based on the error/success codes.
|
75 |
-
add_action( 'admin_init', array( $this, 'display_custom_auth_notices' ) );
|
76 |
-
|
77 |
-
// Display notice instructing the user to complete plugin setup.
|
78 |
-
add_action( 'admin_init', array( $this, 'display_setup_notice' ) );
|
79 |
-
|
80 |
-
// Outputs the plugin admin header.
|
81 |
-
add_action( 'in_admin_header', array( $this, 'display_admin_header' ), 100 );
|
82 |
-
|
83 |
-
// Hide all unrelated to the plugin notices on the plugin admin pages.
|
84 |
-
add_action( 'admin_print_scripts', array( $this, 'hide_unrelated_notices' ) );
|
85 |
-
|
86 |
-
// Process all AJAX requests.
|
87 |
-
add_action( 'wp_ajax_wp_mail_smtp_ajax', array( $this, 'process_ajax' ) );
|
88 |
-
}
|
89 |
-
|
90 |
-
/**
|
91 |
-
* Display custom notices based on the error/success codes.
|
92 |
-
*
|
93 |
-
* @since 1.0.0
|
94 |
-
*/
|
95 |
-
public function display_custom_auth_notices() {
|
96 |
-
|
97 |
-
$error = isset( $_GET['error'] ) ? sanitize_key( $_GET['error'] ) : ''; // phpcs:ignore
|
98 |
-
$success = isset( $_GET['success'] ) ? sanitize_key( $_GET['success'] ) : ''; // phpcs:ignore
|
99 |
-
|
100 |
-
if ( empty( $error ) && empty( $success ) ) {
|
101 |
-
return;
|
102 |
-
}
|
103 |
-
|
104 |
-
if ( ! current_user_can( 'manage_options' ) ) {
|
105 |
-
return;
|
106 |
-
}
|
107 |
-
|
108 |
-
switch ( $error ) {
|
109 |
-
case 'google_access_denied':
|
110 |
-
WP::add_admin_notice(
|
111 |
-
/* translators: %s - error code, returned by Google API. */
|
112 |
-
sprintf( esc_html__( 'There was an error while processing the authentication request: %s. Please try again.', 'wp-mail-smtp' ), '<code>' . $error . '</code>' ),
|
113 |
-
WP::ADMIN_NOTICE_ERROR
|
114 |
-
);
|
115 |
-
break;
|
116 |
-
|
117 |
-
case 'google_no_code_scope':
|
118 |
-
case 'microsoft_no_code':
|
119 |
-
WP::add_admin_notice(
|
120 |
-
esc_html__( 'There was an error while processing the authentication request. Please try again.', 'wp-mail-smtp' ),
|
121 |
-
WP::ADMIN_NOTICE_ERROR
|
122 |
-
);
|
123 |
-
break;
|
124 |
-
|
125 |
-
case 'google_no_clients':
|
126 |
-
WP::add_admin_notice(
|
127 |
-
esc_html__( 'There was an error while processing the authentication request. Please make sure that you have Client ID and Client Secret both valid and saved.', 'wp-mail-smtp' ),
|
128 |
-
WP::ADMIN_NOTICE_ERROR
|
129 |
-
);
|
130 |
-
break;
|
131 |
-
}
|
132 |
-
|
133 |
-
switch ( $success ) {
|
134 |
-
case 'google_site_linked':
|
135 |
-
WP::add_admin_notice(
|
136 |
-
esc_html__( 'You have successfully linked the current site with your Google API project. Now you can start sending emails through Gmail.', 'wp-mail-smtp' ),
|
137 |
-
WP::ADMIN_NOTICE_SUCCESS
|
138 |
-
);
|
139 |
-
break;
|
140 |
-
case 'microsoft_site_linked':
|
141 |
-
WP::add_admin_notice(
|
142 |
-
esc_html__( 'You have successfully linked the current site with your Microsoft API project. Now you can start sending emails through Outlook.', 'wp-mail-smtp' ),
|
143 |
-
WP::ADMIN_NOTICE_SUCCESS
|
144 |
-
);
|
145 |
-
break;
|
146 |
-
}
|
147 |
-
}
|
148 |
-
|
149 |
-
/**
|
150 |
-
* Display notice instructing the user to complete plugin setup.
|
151 |
-
*
|
152 |
-
* @since 1.3.0
|
153 |
-
*/
|
154 |
-
public function display_setup_notice() {
|
155 |
-
|
156 |
-
// Bail if we're not on a plugin page.
|
157 |
-
if ( ! $this->is_admin_page( 'general' ) ) {
|
158 |
-
return;
|
159 |
-
}
|
160 |
-
|
161 |
-
$default_options = wp_json_encode( Options::get_defaults() );
|
162 |
-
$current_options = wp_json_encode( Options::init()->get_all() );
|
163 |
-
|
164 |
-
// Check if the current settings are the same as the default settings.
|
165 |
-
if ( $current_options !== $default_options ) {
|
166 |
-
return;
|
167 |
-
}
|
168 |
-
|
169 |
-
// Display notice informing user further action is needed.
|
170 |
-
WP::add_admin_notice(
|
171 |
-
sprintf(
|
172 |
-
wp_kses(
|
173 |
-
/* translators: %s - Mailer anchor link. */
|
174 |
-
__( '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' ),
|
175 |
-
array(
|
176 |
-
'a' => array(
|
177 |
-
'href' => array(),
|
178 |
-
),
|
179 |
-
'strong' => array(),
|
180 |
-
)
|
181 |
-
),
|
182 |
-
wp_mail_smtp()->get_admin()->get_admin_page_url( self::SLUG . '#wp-mail-smtp-setting-row-mailer' )
|
183 |
-
),
|
184 |
-
WP::ADMIN_NOTICE_INFO
|
185 |
-
);
|
186 |
-
}
|
187 |
-
|
188 |
-
/**
|
189 |
-
* Add admin area menu item.
|
190 |
-
*
|
191 |
-
* @since 1.0.0
|
192 |
-
* @since 1.5.0 Moved the menu to the top level. Added several more pages.
|
193 |
-
*/
|
194 |
-
public function add_admin_options_page() {
|
195 |
-
|
196 |
-
$this->hook = \add_menu_page(
|
197 |
-
\esc_html__( 'WP Mail SMTP', 'wp-mail-smtp' ),
|
198 |
-
\esc_html__( 'WP Mail SMTP', 'wp-mail-smtp' ),
|
199 |
-
'manage_options',
|
200 |
-
self::SLUG,
|
201 |
-
array( $this, 'display' ),
|
202 |
-
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiM5ZWEzYTgiIHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgdmlld0JveD0iMCAwIDQzIDM0Ij48cGF0aCBkPSJNMC4wMDcsMy41ODVWMjAuNDIxcTAsMy41ODYsMy43NTEsMy41ODVMMjAsMjRWMTlIMzBWMTQuMDE0bDAuOTkxLTFMMzQsMTNWMy41ODVRMzQsMCwzMC4yNDksMEgzLjc1OFEwLjAwNywwLC4wMDcsMy41ODVoMFpNMy41MjQsNi4xNTdhMS40OSwxLjQ5LDAsMCwxLS41MDgtMC45MzUsMS41ODEsMS41ODEsMCwwLDEsLjI3NC0xLjIwOCwxLjQ0OSwxLjQ0OSwwLDAsMSwxLjA5NC0uNjYzLDEuNzU2LDEuNzU2LDAsMCwxLDEuMjUuMzEybDExLjQwOSw3LjcxNkwyOC4zNzQsMy42NjNhMS45NiwxLjk2LDAsMCwxLDEuMjg5LS4zMTIsMS41NDYsMS41NDYsMCwwLDEsMS4wOTQuNjYzLDEuNCwxLjQsMCwwLDEsLjI3MywxLjIwOCwxLjY3LDEuNjcsMCwwLDEtLjU0Ny45MzVMMTcuMDQzLDE3LjIyNVoiLz48cGF0aCBkPSJNMjIsMjhIMzJsLTAuMDA5LDQuNjI0YTEuMTI2LDEuMTI2LDAsMCwwLDEuOTIyLjhsOC4yNS04LjIzNmExLjEyNiwxLjEyNiwwLDAsMCwwLTEuNTk0bC04LjI1LTguMjQxYTEuMTI2LDEuMTI2LDAsMCwwLTEuOTIyLjh2NC44NjZMMjIsMjF2N1oiLz48L3N2Zz4=',
|
203 |
-
98
|
204 |
-
);
|
205 |
-
|
206 |
-
\add_submenu_page(
|
207 |
-
self::SLUG,
|
208 |
-
$this->get_current_tab_title() . ' ‹ ' . \esc_html__( 'Settings', 'wp-mail-smtp' ),
|
209 |
-
\esc_html__( 'Settings', 'wp-mail-smtp' ),
|
210 |
-
'manage_options',
|
211 |
-
self::SLUG,
|
212 |
-
array( $this, 'display' )
|
213 |
-
);
|
214 |
-
\add_submenu_page(
|
215 |
-
self::SLUG,
|
216 |
-
\esc_html__( 'Email Log', 'wp-mail-smtp' ),
|
217 |
-
\esc_html__( 'Email Log', 'wp-mail-smtp' ),
|
218 |
-
'manage_options',
|
219 |
-
self::SLUG . '-logs',
|
220 |
-
array( $this, 'display' )
|
221 |
-
);
|
222 |
-
\add_submenu_page(
|
223 |
-
self::SLUG,
|
224 |
-
\esc_html__( 'About Us', 'wp-mail-smtp' ),
|
225 |
-
\esc_html__( 'About Us', 'wp-mail-smtp' ),
|
226 |
-
'manage_options',
|
227 |
-
self::SLUG . '-about',
|
228 |
-
array( $this, 'display' )
|
229 |
-
);
|
230 |
-
}
|
231 |
-
|
232 |
-
/**
|
233 |
-
* Enqueue admin area scripts and styles.
|
234 |
-
*
|
235 |
-
* @since 1.0.0
|
236 |
-
* @since 1.5.0 Added new assets for new pages.
|
237 |
-
* @since 1.7.0 Added jQuery Confirm library css/js files.
|
238 |
-
*
|
239 |
-
* @param string $hook
|
240 |
-
*/
|
241 |
-
public function enqueue_assets( $hook ) {
|
242 |
-
|
243 |
-
if ( strpos( $hook, self::SLUG ) === false ) {
|
244 |
-
return;
|
245 |
-
}
|
246 |
-
|
247 |
-
// General styles and js.
|
248 |
-
\wp_enqueue_style(
|
249 |
-
'wp-mail-smtp-admin',
|
250 |
-
\wp_mail_smtp()->assets_url . '/css/smtp-admin.min.css',
|
251 |
-
false,
|
252 |
-
WPMS_PLUGIN_VER
|
253 |
-
);
|
254 |
-
|
255 |
-
\wp_enqueue_script(
|
256 |
-
'wp-mail-smtp-admin',
|
257 |
-
\wp_mail_smtp()->assets_url . '/js/smtp-admin' . WP::asset_min() . '.js',
|
258 |
-
array( 'jquery' ),
|
259 |
-
WPMS_PLUGIN_VER,
|
260 |
-
false
|
261 |
-
);
|
262 |
-
|
263 |
-
\wp_localize_script(
|
264 |
-
'wp-mail-smtp-admin',
|
265 |
-
'wp_mail_smtp',
|
266 |
-
array(
|
267 |
-
'text_provider_remove' => esc_html__( 'Are you sure you want to reset the current provider connection? You will need to immediately create a new one to be able to send emails.', 'wp-mail-smtp' ),
|
268 |
-
'education' => array(
|
269 |
-
'upgrade_icon_lock' => '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="lock" class="svg-inline--fa fa-lock fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M400 224h-24v-72C376 68.2 307.8 0 224 0S72 68.2 72 152v72H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48zm-104 0H152v-72c0-39.7 32.3-72 72-72s72 32.3 72 72v72z"></path></svg>',
|
270 |
-
'upgrade_title' => esc_html__( '%name% is a PRO Feature', 'wp-mail-smtp' ),
|
271 |
-
'upgrade_button' => esc_html__( 'Upgrade to Pro', 'wp-mail-smtp' ),
|
272 |
-
'upgrade_url' => 'https://wpmailsmtp.com/lite-upgrade/?discount=SMTPLITEUPGRADE&utm_source=WordPress&utm_medium=plugin-settings&utm_campaign=liteplugin',
|
273 |
-
'upgrade_bonus' => '<p>' .
|
274 |
-
wp_kses(
|
275 |
-
__( '<strong>Bonus:</strong> WP Mail SMTP users get <span>20% off</span> regular price,<br>applied at checkout.', 'wp-mail-smtp' ),
|
276 |
-
array(
|
277 |
-
'strong' => true,
|
278 |
-
'span' => true,
|
279 |
-
'br' => true,
|
280 |
-
)
|
281 |
-
)
|
282 |
-
. '</p>',
|
283 |
-
'upgrade_doc' => '<a href="https://wpmailsmtp.com/docs/how-to-upgrade-wp-mail-smtp-to-pro-version/?utm_source=WordPress&utm_medium=link&utm_campaign=liteplugin" target="_blank" rel="noopener noreferrer" class="already-purchased">
|
284 |
-
' . esc_html__( 'Already purchased?', 'wp-mail-smtp' ) . '
|
285 |
-
</a>',
|
286 |
-
),
|
287 |
-
)
|
288 |
-
);
|
289 |
-
|
290 |
-
/*
|
291 |
-
* jQuery Confirm library v3.3.4.
|
292 |
-
*/
|
293 |
-
\wp_enqueue_style(
|
294 |
-
'wp-mail-smtp-admin-jconfirm',
|
295 |
-
\wp_mail_smtp()->assets_url . '/libs/jquery-confirm.min.css',
|
296 |
-
array( 'wp-mail-smtp-admin' ),
|
297 |
-
'3.3.4'
|
298 |
-
);
|
299 |
-
\wp_enqueue_script(
|
300 |
-
'wp-mail-smtp-admin-jconfirm',
|
301 |
-
\wp_mail_smtp()->assets_url . '/libs/jquery-confirm.min.js',
|
302 |
-
array( 'wp-mail-smtp-admin' ),
|
303 |
-
'3.3.4',
|
304 |
-
false
|
305 |
-
);
|
306 |
-
|
307 |
-
/*
|
308 |
-
* Logs page.
|
309 |
-
*/
|
310 |
-
if ( $this->is_admin_page( 'logs' ) ) {
|
311 |
-
\wp_enqueue_style(
|
312 |
-
'wp-mail-smtp-admin-logs',
|
313 |
-
apply_filters( 'wp_mail_smtp_admin_enqueue_assets_logs_css', '' ),
|
314 |
-
array( 'wp-mail-smtp-admin' ),
|
315 |
-
WPMS_PLUGIN_VER
|
316 |
-
);
|
317 |
-
|
318 |
-
\wp_enqueue_script(
|
319 |
-
'wp-mail-smtp-admin-logs',
|
320 |
-
apply_filters( 'wp_mail_smtp_admin_enqueue_assets_logs_js', '' ),
|
321 |
-
array( 'wp-mail-smtp-admin' ),
|
322 |
-
WPMS_PLUGIN_VER,
|
323 |
-
false
|
324 |
-
);
|
325 |
-
}
|
326 |
-
|
327 |
-
/*
|
328 |
-
* About page.
|
329 |
-
*/
|
330 |
-
if ( $this->is_admin_page( 'about' ) ) {
|
331 |
-
|
332 |
-
\wp_enqueue_style(
|
333 |
-
'wp-mail-smtp-admin-about',
|
334 |
-
\wp_mail_smtp()->assets_url . '/css/smtp-about.min.css',
|
335 |
-
array( 'wp-mail-smtp-admin' ),
|
336 |
-
WPMS_PLUGIN_VER
|
337 |
-
);
|
338 |
-
|
339 |
-
\wp_enqueue_script(
|
340 |
-
'wp-mail-smtp-admin-about',
|
341 |
-
\wp_mail_smtp()->assets_url . '/js/smtp-about' . WP::asset_min() . '.js',
|
342 |
-
array( 'wp-mail-smtp-admin' ),
|
343 |
-
'0.7.2',
|
344 |
-
false
|
345 |
-
);
|
346 |
-
|
347 |
-
$settings = array(
|
348 |
-
'ajax_url' => \admin_url( 'admin-ajax.php' ),
|
349 |
-
'nonce' => \wp_create_nonce( 'wp-mail-smtp-about' ),
|
350 |
-
// Strings.
|
351 |
-
'plugin_activate' => \esc_html__( 'Activate', 'wp-mail-smtp' ),
|
352 |
-
'plugin_activated' => \esc_html__( 'Activated', 'wp-mail-smtp' ),
|
353 |
-
'plugin_active' => \esc_html__( 'Active', 'wp-mail-smtp' ),
|
354 |
-
'plugin_inactive' => \esc_html__( 'Inactive', 'wp-mail-smtp' ),
|
355 |
-
'plugin_processing' => \esc_html__( 'Processing...', 'wp-mail-smtp' ),
|
356 |
-
'plugin_install_error' => \esc_html__( 'Could not install a plugin. Please download from WordPress.org and install manually.', 'wp-mail-smtp' ),
|
357 |
-
'plugin_install_activate_btn' => \esc_html__( 'Install and Activate', 'wp-mail-smtp' ),
|
358 |
-
'plugin_activate_btn' => \esc_html__( 'Activate', 'wp-mail-smtp' ),
|
359 |
-
'plugin_download_btn' => \esc_html__( 'Download', 'wp-mail-smtp' ),
|
360 |
-
);
|
361 |
-
|
362 |
-
\wp_localize_script(
|
363 |
-
'wp-mail-smtp-admin-about',
|
364 |
-
'wp_mail_smtp_about',
|
365 |
-
$settings
|
366 |
-
);
|
367 |
-
|
368 |
-
\wp_enqueue_script(
|
369 |
-
'wp-mail-smtp-admin-about-matchheight',
|
370 |
-
\wp_mail_smtp()->assets_url . '/js/jquery.matchHeight.min.js',
|
371 |
-
array( 'wp-mail-smtp-admin' ),
|
372 |
-
'0.7.2',
|
373 |
-
false
|
374 |
-
);
|
375 |
-
}
|
376 |
-
|
377 |
-
do_action( 'wp_mail_smtp_admin_area_enqueue_assets', $hook );
|
378 |
-
}
|
379 |
-
|
380 |
-
/**
|
381 |
-
* Outputs the plugin admin header.
|
382 |
-
*
|
383 |
-
* @since 1.0.0
|
384 |
-
*/
|
385 |
-
public function display_admin_header() {
|
386 |
-
|
387 |
-
// Bail if we're not on a plugin page.
|
388 |
-
if ( ! $this->is_admin_page() ) {
|
389 |
-
return;
|
390 |
-
}
|
391 |
-
?>
|
392 |
-
|
393 |
-
<div id="wp-mail-smtp-header">
|
394 |
-
<!--suppress HtmlUnknownTarget -->
|
395 |
-
<img class="wp-mail-smtp-header-logo" src="<?php echo esc_url( wp_mail_smtp()->assets_url ); ?>/images/logo.svg" alt="WP Mail SMTP"/>
|
396 |
-
</div>
|
397 |
-
|
398 |
-
<?php
|
399 |
-
}
|
400 |
-
|
401 |
-
/**
|
402 |
-
* Display a text to ask users to review the plugin on WP.org.
|
403 |
-
*
|
404 |
-
* @since 1.0.0
|
405 |
-
*
|
406 |
-
* @param string $text
|
407 |
-
*
|
408 |
-
* @return string
|
409 |
-
*/
|
410 |
-
public function get_admin_footer( $text ) {
|
411 |
-
|
412 |
-
if ( $this->is_admin_page() ) {
|
413 |
-
$url = 'https://wordpress.org/support/plugin/wp-mail-smtp/reviews/?filter=5#new-post';
|
414 |
-
|
415 |
-
$text = sprintf(
|
416 |
-
wp_kses(
|
417 |
-
/* translators: %1$s - WP.org link; %2$s - same WP.org link. */
|
418 |
-
__( 'Please rate <strong>WP Mail SMTP</strong> <a href="%1$s" target="_blank" rel="noopener noreferrer">★★★★★</a> on <a href="%2$s" target="_blank" rel="noopener noreferrer">WordPress.org</a> to help us spread the word. Thank you from the WP Mail SMTP team!', 'wp-mail-smtp' ),
|
419 |
-
array(
|
420 |
-
'strong' => array(),
|
421 |
-
'a' => array(
|
422 |
-
'href' => array(),
|
423 |
-
'target' => array(),
|
424 |
-
'rel' => array(),
|
425 |
-
),
|
426 |
-
)
|
427 |
-
),
|
428 |
-
$url,
|
429 |
-
$url
|
430 |
-
);
|
431 |
-
}
|
432 |
-
|
433 |
-
return $text;
|
434 |
-
}
|
435 |
-
|
436 |
-
/**
|
437 |
-
* Display content of the admin area page.
|
438 |
-
*
|
439 |
-
* @since 1.0.0
|
440 |
-
* @since 1.5.0 Rewrite to distinguish between General tabs and separate pages.
|
441 |
-
*/
|
442 |
-
public function display() {
|
443 |
-
|
444 |
-
// Bail if we're not on a plugin page.
|
445 |
-
if ( ! $this->is_admin_page() ) {
|
446 |
-
return;
|
447 |
-
}
|
448 |
-
|
449 |
-
$page = ! empty( $_GET['page'] ) ? \sanitize_key( $_GET['page'] ) : ''; // phpcs:ignore
|
450 |
-
?>
|
451 |
-
|
452 |
-
<div class="wrap" id="wp-mail-smtp">
|
453 |
-
|
454 |
-
<?php
|
455 |
-
switch ( $page ) {
|
456 |
-
case self::SLUG:
|
457 |
-
?>
|
458 |
-
|
459 |
-
<div class="wp-mail-smtp-page wp-mail-smtp-page-general wp-mail-smtp-tab-<?php echo esc_attr( $this->get_current_tab() ); ?>">
|
460 |
-
<?php $this->display_tabs(); ?>
|
461 |
-
</div>
|
462 |
-
|
463 |
-
<?php
|
464 |
-
break;
|
465 |
-
|
466 |
-
case self::SLUG . '-logs':
|
467 |
-
$logs_class = apply_filters( 'wp_mail_smtp_admin_display_get_logs_fqcn', '\WPMailSMTP\Admin\Pages\Logs' );
|
468 |
-
/** @var \WPMailSMTP\Admin\PageAbstract $logs */
|
469 |
-
$logs = new $logs_class();
|
470 |
-
|
471 |
-
$is_archive = wp_mail_smtp()->is_pro() && wp_mail_smtp()->pro->get_logs()->is_archive();
|
472 |
-
?>
|
473 |
-
|
474 |
-
<div class="wp-mail-smtp-page wp-mail-smtp-page-logs <?php echo $is_archive ? 'wp-mail-smtp-page-logs-archive' : 'wp-mail-smtp-page-logs-single'; ?>">
|
475 |
-
<?php $logs->display(); ?>
|
476 |
-
</div>
|
477 |
-
|
478 |
-
<?php
|
479 |
-
break;
|
480 |
-
|
481 |
-
case self::SLUG . '-about':
|
482 |
-
$about = new Pages\About();
|
483 |
-
?>
|
484 |
-
|
485 |
-
<div class="wp-mail-smtp-page wp-mail-smtp-page-about wp-mail-smtp-tab-about-<?php echo \esc_attr( $about->get_current_tab() ); ?>">
|
486 |
-
<?php $about->display(); ?>
|
487 |
-
</div>
|
488 |
-
|
489 |
-
<?php
|
490 |
-
break;
|
491 |
-
}
|
492 |
-
?>
|
493 |
-
</div>
|
494 |
-
|
495 |
-
<?php
|
496 |
-
}
|
497 |
-
|
498 |
-
/**
|
499 |
-
* Display General page tabs.
|
500 |
-
*
|
501 |
-
* @since 1.5.0
|
502 |
-
*/
|
503 |
-
protected function display_tabs() {
|
504 |
-
?>
|
505 |
-
|
506 |
-
<div class="wp-mail-smtp-page-title">
|
507 |
-
<?php
|
508 |
-
foreach ( $this->get_pages() as $page_slug => $page ) :
|
509 |
-
$label = $page->get_label();
|
510 |
-
if ( empty( $label ) ) {
|
511 |
-
continue;
|
512 |
-
}
|
513 |
-
$class = $page_slug === $this->get_current_tab() ? 'active' : '';
|
514 |
-
?>
|
515 |
-
|
516 |
-
<a href="<?php echo esc_url( $page->get_link() ); ?>" class="tab <?php echo esc_attr( $class ); ?>">
|
517 |
-
<?php echo esc_html( $label ); ?>
|
518 |
-
</a>
|
519 |
-
|
520 |
-
<?php endforeach; ?>
|
521 |
-
</div>
|
522 |
-
|
523 |
-
<div class="wp-mail-smtp-page-content">
|
524 |
-
<h1 class="screen-reader-text">
|
525 |
-
<?php echo esc_html( $this->get_current_tab_title() ); ?>
|
526 |
-
</h1>
|
527 |
-
|
528 |
-
<?php $this->display_current_tab_content(); ?>
|
529 |
-
</div>
|
530 |
-
|
531 |
-
<?php
|
532 |
-
}
|
533 |
-
|
534 |
-
/**
|
535 |
-
* Get the current tab content.
|
536 |
-
*
|
537 |
-
* @since 1.0.0
|
538 |
-
*/
|
539 |
-
public function display_current_tab_content() {
|
540 |
-
|
541 |
-
$pages = $this->get_pages();
|
542 |
-
|
543 |
-
if ( ! array_key_exists( $this->get_current_tab(), $pages ) ) {
|
544 |
-
return;
|
545 |
-
}
|
546 |
-
|
547 |
-
$pages[ $this->get_current_tab() ]->display();
|
548 |
-
}
|
549 |
-
|
550 |
-
/**
|
551 |
-
* Get the current admin area tab.
|
552 |
-
*
|
553 |
-
* @since 1.0.0
|
554 |
-
*
|
555 |
-
* @return string
|
556 |
-
*/
|
557 |
-
protected function get_current_tab() {
|
558 |
-
|
559 |
-
$current = '';
|
560 |
-
|
561 |
-
if ( $this->is_admin_page( 'general' ) ) {
|
562 |
-
$current = ! empty( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'settings'; // phpcs:ignore
|
563 |
-
}
|
564 |
-
|
565 |
-
return $current;
|
566 |
-
}
|
567 |
-
|
568 |
-
/**
|
569 |
-
* Get the array of default registered tabs for General page admin area.
|
570 |
-
*
|
571 |
-
* @since 1.0.0
|
572 |
-
*
|
573 |
-
* @return \WPMailSMTP\Admin\PageAbstract[]
|
574 |
-
*/
|
575 |
-
public function get_pages() {
|
576 |
-
|
577 |
-
if ( empty( $this->pages ) ) {
|
578 |
-
$this->pages = array(
|
579 |
-
'settings' => new Pages\SettingsTab(),
|
580 |
-
'test' => new Pages\TestTab(),
|
581 |
-
'logs' => new Pages\LogsTab(),
|
582 |
-
'control' => new Pages\ControlTab(),
|
583 |
-
'misc' => new Pages\MiscTab(),
|
584 |
-
'auth' => new Pages\AuthTab(),
|
585 |
-
);
|
586 |
-
}
|
587 |
-
|
588 |
-
return apply_filters( 'wp_mail_smtp_admin_get_pages', $this->pages );
|
589 |
-
}
|
590 |
-
|
591 |
-
/**
|
592 |
-
* Get the current tab title.
|
593 |
-
*
|
594 |
-
* @since 1.0.0
|
595 |
-
*
|
596 |
-
* @return string
|
597 |
-
*/
|
598 |
-
public function get_current_tab_title() {
|
599 |
-
|
600 |
-
$pages = $this->get_pages();
|
601 |
-
|
602 |
-
if ( ! array_key_exists( $this->get_current_tab(), $pages ) ) {
|
603 |
-
return '';
|
604 |
-
}
|
605 |
-
|
606 |
-
return $pages[ $this->get_current_tab() ]->get_title();
|
607 |
-
}
|
608 |
-
|
609 |
-
/**
|
610 |
-
* Check whether we are on an admin page.
|
611 |
-
*
|
612 |
-
* @since 1.0.0
|
613 |
-
* @since 1.5.0 Added support for new pages.
|
614 |
-
*
|
615 |
-
* @param array|string $slug ID(s) of a plugin page. Possible values: 'general', 'logs', 'about' or array of them.
|
616 |
-
*
|
617 |
-
* @return bool
|
618 |
-
*/
|
619 |
-
public function is_admin_page( $slug = array() ) {
|
620 |
-
|
621 |
-
$cur_page = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : ''; // phpcs:ignore
|
622 |
-
$check = self::SLUG;
|
623 |
-
$pages_equal = false;
|
624 |
-
|
625 |
-
if ( is_string( $slug ) ) {
|
626 |
-
$slug = sanitize_key( $slug );
|
627 |
-
|
628 |
-
if (
|
629 |
-
in_array( $slug, self::$pages_registered, true ) &&
|
630 |
-
$slug !== 'general'
|
631 |
-
) {
|
632 |
-
$check = self::SLUG . '-' . $slug;
|
633 |
-
}
|
634 |
-
|
635 |
-
$pages_equal = $cur_page === $check;
|
636 |
-
} elseif ( is_array( $slug ) ) {
|
637 |
-
if ( empty( $slug ) ) {
|
638 |
-
$slug = array_map( function ( $v ) {
|
639 |
-
if ( $v === 'general' ) {
|
640 |
-
return Area::SLUG;
|
641 |
-
}
|
642 |
-
return Area::SLUG . '-' . $v;
|
643 |
-
}, self::$pages_registered );
|
644 |
-
} else {
|
645 |
-
$slug = array_map( function ( $v ) {
|
646 |
-
if ( $v === 'general' ) {
|
647 |
-
return Area::SLUG;
|
648 |
-
}
|
649 |
-
return Area::SLUG . '-' . sanitize_key( $v );
|
650 |
-
}, $slug );
|
651 |
-
}
|
652 |
-
|
653 |
-
$pages_equal = in_array( $cur_page, $slug, true );
|
654 |
-
}
|
655 |
-
|
656 |
-
return is_admin() && $pages_equal;
|
657 |
-
}
|
658 |
-
|
659 |
-
/**
|
660 |
-
* Give ability to use either admin area option or a filter to hide error notices about failed email delivery.
|
661 |
-
* Filter has higher priority and overrides an option.
|
662 |
-
*
|
663 |
-
* @since 1.6.0
|
664 |
-
*
|
665 |
-
* @return bool
|
666 |
-
*/
|
667 |
-
public function is_error_delivery_notice_enabled() {
|
668 |
-
|
669 |
-
$is_hard_enabled = (bool) apply_filters( 'wp_mail_smtp_admin_is_error_delivery_notice_enabled', true );
|
670 |
-
|
671 |
-
// If someone changed the value to false using a filter - disable completely.
|
672 |
-
if ( ! $is_hard_enabled ) {
|
673 |
-
return false;
|
674 |
-
}
|
675 |
-
|
676 |
-
return ! (bool) Options::init()->get( 'general', 'email_delivery_errors_hidden' );
|
677 |
-
}
|
678 |
-
|
679 |
-
/**
|
680 |
-
* All possible plugin forms manipulation will be done here.
|
681 |
-
*
|
682 |
-
* @since 1.0.0
|
683 |
-
*/
|
684 |
-
public function process_actions() {
|
685 |
-
|
686 |
-
// Bail if we're not on a plugin General page.
|
687 |
-
if ( ! $this->is_admin_page( 'general' ) ) {
|
688 |
-
return;
|
689 |
-
}
|
690 |
-
|
691 |
-
$pages = $this->get_pages();
|
692 |
-
|
693 |
-
// Allow to process only own tabs.
|
694 |
-
if ( ! array_key_exists( $this->get_current_tab(), $pages ) ) {
|
695 |
-
return;
|
696 |
-
}
|
697 |
-
|
698 |
-
// Process POST only if it exists.
|
699 |
-
if ( ! empty( $_POST ) ) {
|
700 |
-
if ( ! empty( $_POST['wp-mail-smtp'] ) ) {
|
701 |
-
$post = $_POST['wp-mail-smtp'];
|
702 |
-
} else {
|
703 |
-
$post = array();
|
704 |
-
}
|
705 |
-
|
706 |
-
$pages[ $this->get_current_tab() ]->process_post( $post );
|
707 |
-
}
|
708 |
-
|
709 |
-
// This won't do anything for most pages.
|
710 |
-
// Works for plugin page only, when GET params are allowed.
|
711 |
-
$pages[ $this->get_current_tab() ]->process_auth();
|
712 |
-
}
|
713 |
-
|
714 |
-
/**
|
715 |
-
* Process all AJAX requests.
|
716 |
-
*
|
717 |
-
* @since 1.3.0
|
718 |
-
* @since 1.5.0 Added tasks to process plugins management.
|
719 |
-
*/
|
720 |
-
public function process_ajax() {
|
721 |
-
|
722 |
-
$data = array();
|
723 |
-
|
724 |
-
// Only admins can fire these ajax requests.
|
725 |
-
if ( ! current_user_can( 'manage_options' ) ) {
|
726 |
-
wp_send_json_error( $data );
|
727 |
-
}
|
728 |
-
|
729 |
-
if ( empty( $_POST['task'] ) ) { // phpcs:ignore
|
730 |
-
wp_send_json_error( $data );
|
731 |
-
}
|
732 |
-
|
733 |
-
$task = sanitize_key( $_POST['task'] ); // phpcs:ignore
|
734 |
-
|
735 |
-
switch ( $task ) {
|
736 |
-
case 'pro_banner_dismiss':
|
737 |
-
update_user_meta( get_current_user_id(), 'wp_mail_smtp_pro_banner_dismissed', true );
|
738 |
-
$data['message'] = esc_html__( 'WP Mail SMTP Pro related message was successfully dismissed.', 'wp-mail-smtp' );
|
739 |
-
break;
|
740 |
-
|
741 |
-
case 'about_plugin_install':
|
742 |
-
Pages\About::ajax_plugin_install();
|
743 |
-
break;
|
744 |
-
|
745 |
-
case 'about_plugin_activate':
|
746 |
-
Pages\About::ajax_plugin_activate();
|
747 |
-
break;
|
748 |
-
|
749 |
-
case 'notice_dismiss':
|
750 |
-
$notice = sanitize_key( $_POST['notice'] ); // phpcs:ignore
|
751 |
-
$mailer = sanitize_key( $_POST['mailer'] ); // phpcs:ignore
|
752 |
-
if ( empty( $notice ) || empty( $mailer ) ) {
|
753 |
-
break;
|
754 |
-
}
|
755 |
-
|
756 |
-
update_user_meta( get_current_user_id(), "wp_mail_smtp_notice_{$notice}_for_{$mailer}_dismissed", true );
|
757 |
-
$data['message'] = esc_html__( 'Educational notice for this mailer was successfully dismissed.', 'wp-mail-smtp' );
|
758 |
-
break;
|
759 |
-
|
760 |
-
default:
|
761 |
-
// Allow custom tasks data processing being added here.
|
762 |
-
$data = apply_filters( 'wp_mail_smtp_admin_process_ajax_' . $task . '_data', $data );
|
763 |
-
}
|
764 |
-
|
765 |
-
// Final ability to rewrite all the data, just in case.
|
766 |
-
$data = (array) apply_filters( 'wp_mail_smtp_admin_process_ajax_data', $data, $task );
|
767 |
-
|
768 |
-
if ( empty( $data ) ) {
|
769 |
-
wp_send_json_error( $data );
|
770 |
-
}
|
771 |
-
|
772 |
-
wp_send_json_success( $data );
|
773 |
-
}
|
774 |
-
|
775 |
-
/**
|
776 |
-
* Add a link to Settings page of a plugin on Plugins page.
|
777 |
-
*
|
778 |
-
* @since 1.0.0
|
779 |
-
* @since 1.5.0 Added a link to Email Log.
|
780 |
-
*
|
781 |
-
* @param array $links
|
782 |
-
* @param string $file
|
783 |
-
*
|
784 |
-
* @return mixed
|
785 |
-
*/
|
786 |
-
public function add_plugin_action_link( $links, $file ) {
|
787 |
-
|
788 |
-
// Will target both pro and lite version of a plugin.
|
789 |
-
if ( strpos( $file, 'wp-mail-smtp' ) === false ) {
|
790 |
-
return $links;
|
791 |
-
}
|
792 |
-
|
793 |
-
$settings_link = '<a href="' . esc_url( $this->get_admin_page_url() ) . '">' . esc_html__( 'Settings', 'wp-mail-smtp' ) . '</a>';
|
794 |
-
$logs_link = '<a href="' . esc_url( $this->get_admin_page_url( self::SLUG . '-logs' ) ) . '">' . esc_html__( 'Email Log', 'wp-mail-smtp' ) . '</a>';
|
795 |
-
|
796 |
-
array_unshift( $links, $settings_link, $logs_link );
|
797 |
-
|
798 |
-
return $links;
|
799 |
-
}
|
800 |
-
|
801 |
-
/**
|
802 |
-
* Get plugin admin area page URL.
|
803 |
-
*
|
804 |
-
* @since 1.0.0
|
805 |
-
* @since 1.5.0 URL is changed to support the top level position of the plugin admin area.
|
806 |
-
*
|
807 |
-
* @param string $page
|
808 |
-
*
|
809 |
-
* @return string
|
810 |
-
*/
|
811 |
-
public function get_admin_page_url( $page = '' ) {
|
812 |
-
|
813 |
-
if ( empty( $page ) ) {
|
814 |
-
$page = self::SLUG;
|
815 |
-
}
|
816 |
-
|
817 |
-
return add_query_arg(
|
818 |
-
'page',
|
819 |
-
$page,
|
820 |
-
admin_url( 'admin.php' )
|
821 |
-
);
|
822 |
-
}
|
823 |
-
|
824 |
-
/**
|
825 |
-
* Remove all non-WP Mail SMTP plugin notices from plugin pages.
|
826 |
-
*
|
827 |
-
* @since 1.0.0
|
828 |
-
*/
|
829 |
-
public function hide_unrelated_notices() {
|
830 |
-
|
831 |
-
// Bail if we're not on our screen or page.
|
832 |
-
if ( empty( $_REQUEST['page'] ) || strpos( $_REQUEST['page'], self::SLUG ) === false ) {
|
833 |
-
return;
|
834 |
-
}
|
835 |
-
|
836 |
-
global $wp_filter;
|
837 |
-
|
838 |
-
if ( ! empty( $wp_filter['user_admin_notices']->callbacks ) && is_array( $wp_filter['user_admin_notices']->callbacks ) ) {
|
839 |
-
foreach ( $wp_filter['user_admin_notices']->callbacks as $priority => $hooks ) {
|
840 |
-
foreach ( $hooks as $name => $arr ) {
|
841 |
-
if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
|
842 |
-
unset( $wp_filter['user_admin_notices']->callbacks[ $priority ][ $name ] );
|
843 |
-
continue;
|
844 |
-
}
|
845 |
-
if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
|
846 |
-
continue;
|
847 |
-
}
|
848 |
-
if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
|
849 |
-
unset( $wp_filter['user_admin_notices']->callbacks[ $priority ][ $name ] );
|
850 |
-
}
|
851 |
-
}
|
852 |
-
}
|
853 |
-
}
|
854 |
-
|
855 |
-
if ( ! empty( $wp_filter['admin_notices']->callbacks ) && is_array( $wp_filter['admin_notices']->callbacks ) ) {
|
856 |
-
foreach ( $wp_filter['admin_notices']->callbacks as $priority => $hooks ) {
|
857 |
-
foreach ( $hooks as $name => $arr ) {
|
858 |
-
if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
|
859 |
-
unset( $wp_filter['admin_notices']->callbacks[ $priority ][ $name ] );
|
860 |
-
continue;
|
861 |
-
}
|
862 |
-
if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
|
863 |
-
continue;
|
864 |
-
}
|
865 |
-
if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
|
866 |
-
unset( $wp_filter['admin_notices']->callbacks[ $priority ][ $name ] );
|
867 |
-
}
|
868 |
-
}
|
869 |
-
}
|
870 |
-
}
|
871 |
-
|
872 |
-
if ( ! empty( $wp_filter['all_admin_notices']->callbacks ) && is_array( $wp_filter['all_admin_notices']->callbacks ) ) {
|
873 |
-
foreach ( $wp_filter['all_admin_notices']->callbacks as $priority => $hooks ) {
|
874 |
-
foreach ( $hooks as $name => $arr ) {
|
875 |
-
if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
|
876 |
-
unset( $wp_filter['all_admin_notices']->callbacks[ $priority ][ $name ] );
|
877 |
-
continue;
|
878 |
-
}
|
879 |
-
if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
|
880 |
-
continue;
|
881 |
-
}
|
882 |
-
if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
|
883 |
-
unset( $wp_filter['all_admin_notices']->callbacks[ $priority ][ $name ] );
|
884 |
-
}
|
885 |
-
}
|
886 |
-
}
|
887 |
-
}
|
888 |
-
}
|
889 |
-
}
|
1 |
+
<?php
|
2 |
+
|
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.
|
10 |
+
*
|
11 |
+
* @since 1.0.0
|
12 |
+
*/
|
13 |
+
class Area {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @since 1.0.0
|
17 |
+
*
|
18 |
+
* @var string Slug of the admin area page.
|
19 |
+
*/
|
20 |
+
const SLUG = 'wp-mail-smtp';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @since 1.0.0
|
24 |
+
*
|
25 |
+
* @var string Admin page unique hook.
|
26 |
+
*/
|
27 |
+
public $hook;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @since 1.0.0
|
31 |
+
*
|
32 |
+
* @var PageAbstract[]
|
33 |
+
*/
|
34 |
+
private $pages;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @since 1.5.0
|
38 |
+
*
|
39 |
+
* @var array List of official registered pages.
|
40 |
+
*/
|
41 |
+
public static $pages_registered = array( 'general', 'logs', 'about' );
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Area constructor.
|
45 |
+
*
|
46 |
+
* @since 1.0.0
|
47 |
+
*/
|
48 |
+
public function __construct() {
|
49 |
+
$this->hooks();
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Assign all hooks to proper places.
|
54 |
+
*
|
55 |
+
* @since 1.0.0
|
56 |
+
*/
|
57 |
+
protected function hooks() {
|
58 |
+
|
59 |
+
// Add the Settings link to a plugin on Plugins page.
|
60 |
+
add_filter( 'plugin_action_links', array( $this, 'add_plugin_action_link' ), 10, 2 );
|
61 |
+
|
62 |
+
// Add the options page.
|
63 |
+
add_action( 'admin_menu', array( $this, 'add_admin_options_page' ) );
|
64 |
+
|
65 |
+
// Admin footer text.
|
66 |
+
add_filter( 'admin_footer_text', array( $this, 'get_admin_footer' ), 1, 2 );
|
67 |
+
|
68 |
+
// Enqueue admin area scripts and styles.
|
69 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
70 |
+
|
71 |
+
// Process the admin page forms actions.
|
72 |
+
add_action( 'admin_init', array( $this, 'process_actions' ) );
|
73 |
+
|
74 |
+
// Display custom notices based on the error/success codes.
|
75 |
+
add_action( 'admin_init', array( $this, 'display_custom_auth_notices' ) );
|
76 |
+
|
77 |
+
// Display notice instructing the user to complete plugin setup.
|
78 |
+
add_action( 'admin_init', array( $this, 'display_setup_notice' ) );
|
79 |
+
|
80 |
+
// Outputs the plugin admin header.
|
81 |
+
add_action( 'in_admin_header', array( $this, 'display_admin_header' ), 100 );
|
82 |
+
|
83 |
+
// Hide all unrelated to the plugin notices on the plugin admin pages.
|
84 |
+
add_action( 'admin_print_scripts', array( $this, 'hide_unrelated_notices' ) );
|
85 |
+
|
86 |
+
// Process all AJAX requests.
|
87 |
+
add_action( 'wp_ajax_wp_mail_smtp_ajax', array( $this, 'process_ajax' ) );
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Display custom notices based on the error/success codes.
|
92 |
+
*
|
93 |
+
* @since 1.0.0
|
94 |
+
*/
|
95 |
+
public function display_custom_auth_notices() {
|
96 |
+
|
97 |
+
$error = isset( $_GET['error'] ) ? sanitize_key( $_GET['error'] ) : ''; // phpcs:ignore
|
98 |
+
$success = isset( $_GET['success'] ) ? sanitize_key( $_GET['success'] ) : ''; // phpcs:ignore
|
99 |
+
|
100 |
+
if ( empty( $error ) && empty( $success ) ) {
|
101 |
+
return;
|
102 |
+
}
|
103 |
+
|
104 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
105 |
+
return;
|
106 |
+
}
|
107 |
+
|
108 |
+
switch ( $error ) {
|
109 |
+
case 'google_access_denied':
|
110 |
+
WP::add_admin_notice(
|
111 |
+
/* translators: %s - error code, returned by Google API. */
|
112 |
+
sprintf( esc_html__( 'There was an error while processing the authentication request: %s. Please try again.', 'wp-mail-smtp' ), '<code>' . $error . '</code>' ),
|
113 |
+
WP::ADMIN_NOTICE_ERROR
|
114 |
+
);
|
115 |
+
break;
|
116 |
+
|
117 |
+
case 'google_no_code_scope':
|
118 |
+
case 'microsoft_no_code':
|
119 |
+
WP::add_admin_notice(
|
120 |
+
esc_html__( 'There was an error while processing the authentication request. Please try again.', 'wp-mail-smtp' ),
|
121 |
+
WP::ADMIN_NOTICE_ERROR
|
122 |
+
);
|
123 |
+
break;
|
124 |
+
|
125 |
+
case 'google_no_clients':
|
126 |
+
WP::add_admin_notice(
|
127 |
+
esc_html__( 'There was an error while processing the authentication request. Please make sure that you have Client ID and Client Secret both valid and saved.', 'wp-mail-smtp' ),
|
128 |
+
WP::ADMIN_NOTICE_ERROR
|
129 |
+
);
|
130 |
+
break;
|
131 |
+
}
|
132 |
+
|
133 |
+
switch ( $success ) {
|
134 |
+
case 'google_site_linked':
|
135 |
+
WP::add_admin_notice(
|
136 |
+
esc_html__( 'You have successfully linked the current site with your Google API project. Now you can start sending emails through Gmail.', 'wp-mail-smtp' ),
|
137 |
+
WP::ADMIN_NOTICE_SUCCESS
|
138 |
+
);
|
139 |
+
break;
|
140 |
+
case 'microsoft_site_linked':
|
141 |
+
WP::add_admin_notice(
|
142 |
+
esc_html__( 'You have successfully linked the current site with your Microsoft API project. Now you can start sending emails through Outlook.', 'wp-mail-smtp' ),
|
143 |
+
WP::ADMIN_NOTICE_SUCCESS
|
144 |
+
);
|
145 |
+
break;
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Display notice instructing the user to complete plugin setup.
|
151 |
+
*
|
152 |
+
* @since 1.3.0
|
153 |
+
*/
|
154 |
+
public function display_setup_notice() {
|
155 |
+
|
156 |
+
// Bail if we're not on a plugin page.
|
157 |
+
if ( ! $this->is_admin_page( 'general' ) ) {
|
158 |
+
return;
|
159 |
+
}
|
160 |
+
|
161 |
+
$default_options = wp_json_encode( Options::get_defaults() );
|
162 |
+
$current_options = wp_json_encode( Options::init()->get_all() );
|
163 |
+
|
164 |
+
// Check if the current settings are the same as the default settings.
|
165 |
+
if ( $current_options !== $default_options ) {
|
166 |
+
return;
|
167 |
+
}
|
168 |
+
|
169 |
+
// Display notice informing user further action is needed.
|
170 |
+
WP::add_admin_notice(
|
171 |
+
sprintf(
|
172 |
+
wp_kses(
|
173 |
+
/* translators: %s - Mailer anchor link. */
|
174 |
+
__( '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' ),
|
175 |
+
array(
|
176 |
+
'a' => array(
|
177 |
+
'href' => array(),
|
178 |
+
),
|
179 |
+
'strong' => array(),
|
180 |
+
)
|
181 |
+
),
|
182 |
+
wp_mail_smtp()->get_admin()->get_admin_page_url( self::SLUG . '#wp-mail-smtp-setting-row-mailer' )
|
183 |
+
),
|
184 |
+
WP::ADMIN_NOTICE_INFO
|
185 |
+
);
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* Add admin area menu item.
|
190 |
+
*
|
191 |
+
* @since 1.0.0
|
192 |
+
* @since 1.5.0 Moved the menu to the top level. Added several more pages.
|
193 |
+
*/
|
194 |
+
public function add_admin_options_page() {
|
195 |
+
|
196 |
+
$this->hook = \add_menu_page(
|
197 |
+
\esc_html__( 'WP Mail SMTP', 'wp-mail-smtp' ),
|
198 |
+
\esc_html__( 'WP Mail SMTP', 'wp-mail-smtp' ),
|
199 |
+
'manage_options',
|
200 |
+
self::SLUG,
|
201 |
+
array( $this, 'display' ),
|
202 |
+
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiM5ZWEzYTgiIHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgdmlld0JveD0iMCAwIDQzIDM0Ij48cGF0aCBkPSJNMC4wMDcsMy41ODVWMjAuNDIxcTAsMy41ODYsMy43NTEsMy41ODVMMjAsMjRWMTlIMzBWMTQuMDE0bDAuOTkxLTFMMzQsMTNWMy41ODVRMzQsMCwzMC4yNDksMEgzLjc1OFEwLjAwNywwLC4wMDcsMy41ODVoMFpNMy41MjQsNi4xNTdhMS40OSwxLjQ5LDAsMCwxLS41MDgtMC45MzUsMS41ODEsMS41ODEsMCwwLDEsLjI3NC0xLjIwOCwxLjQ0OSwxLjQ0OSwwLDAsMSwxLjA5NC0uNjYzLDEuNzU2LDEuNzU2LDAsMCwxLDEuMjUuMzEybDExLjQwOSw3LjcxNkwyOC4zNzQsMy42NjNhMS45NiwxLjk2LDAsMCwxLDEuMjg5LS4zMTIsMS41NDYsMS41NDYsMCwwLDEsMS4wOTQuNjYzLDEuNCwxLjQsMCwwLDEsLjI3MywxLjIwOCwxLjY3LDEuNjcsMCwwLDEtLjU0Ny45MzVMMTcuMDQzLDE3LjIyNVoiLz48cGF0aCBkPSJNMjIsMjhIMzJsLTAuMDA5LDQuNjI0YTEuMTI2LDEuMTI2LDAsMCwwLDEuOTIyLjhsOC4yNS04LjIzNmExLjEyNiwxLjEyNiwwLDAsMCwwLTEuNTk0bC04LjI1LTguMjQxYTEuMTI2LDEuMTI2LDAsMCwwLTEuOTIyLjh2NC44NjZMMjIsMjF2N1oiLz48L3N2Zz4=',
|
203 |
+
98
|
204 |
+
);
|
205 |
+
|
206 |
+
\add_submenu_page(
|
207 |
+
self::SLUG,
|
208 |
+
$this->get_current_tab_title() . ' ‹ ' . \esc_html__( 'Settings', 'wp-mail-smtp' ),
|
209 |
+
\esc_html__( 'Settings', 'wp-mail-smtp' ),
|
210 |
+
'manage_options',
|
211 |
+
self::SLUG,
|
212 |
+
array( $this, 'display' )
|
213 |
+
);
|
214 |
+
\add_submenu_page(
|
215 |
+
self::SLUG,
|
216 |
+
\esc_html__( 'Email Log', 'wp-mail-smtp' ),
|
217 |
+
\esc_html__( 'Email Log', 'wp-mail-smtp' ),
|
218 |
+
'manage_options',
|
219 |
+
self::SLUG . '-logs',
|
220 |
+
array( $this, 'display' )
|
221 |
+
);
|
222 |
+
\add_submenu_page(
|
223 |
+
self::SLUG,
|
224 |
+
\esc_html__( 'About Us', 'wp-mail-smtp' ),
|
225 |
+
\esc_html__( 'About Us', 'wp-mail-smtp' ),
|
226 |
+
'manage_options',
|
227 |
+
self::SLUG . '-about',
|
228 |
+
array( $this, 'display' )
|
229 |
+
);
|
230 |
+
}
|
231 |
+
|
232 |
+
/**
|
233 |
+
* Enqueue admin area scripts and styles.
|
234 |
+
*
|
235 |
+
* @since 1.0.0
|
236 |
+
* @since 1.5.0 Added new assets for new pages.
|
237 |
+
* @since 1.7.0 Added jQuery Confirm library css/js files.
|
238 |
+
*
|
239 |
+
* @param string $hook
|
240 |
+
*/
|
241 |
+
public function enqueue_assets( $hook ) {
|
242 |
+
|
243 |
+
if ( strpos( $hook, self::SLUG ) === false ) {
|
244 |
+
return;
|
245 |
+
}
|
246 |
+
|
247 |
+
// General styles and js.
|
248 |
+
\wp_enqueue_style(
|
249 |
+
'wp-mail-smtp-admin',
|
250 |
+
\wp_mail_smtp()->assets_url . '/css/smtp-admin.min.css',
|
251 |
+
false,
|
252 |
+
WPMS_PLUGIN_VER
|
253 |
+
);
|
254 |
+
|
255 |
+
\wp_enqueue_script(
|
256 |
+
'wp-mail-smtp-admin',
|
257 |
+
\wp_mail_smtp()->assets_url . '/js/smtp-admin' . WP::asset_min() . '.js',
|
258 |
+
array( 'jquery' ),
|
259 |
+
WPMS_PLUGIN_VER,
|
260 |
+
false
|
261 |
+
);
|
262 |
+
|
263 |
+
\wp_localize_script(
|
264 |
+
'wp-mail-smtp-admin',
|
265 |
+
'wp_mail_smtp',
|
266 |
+
array(
|
267 |
+
'text_provider_remove' => esc_html__( 'Are you sure you want to reset the current provider connection? You will need to immediately create a new one to be able to send emails.', 'wp-mail-smtp' ),
|
268 |
+
'education' => array(
|
269 |
+
'upgrade_icon_lock' => '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="lock" class="svg-inline--fa fa-lock fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M400 224h-24v-72C376 68.2 307.8 0 224 0S72 68.2 72 152v72H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48zm-104 0H152v-72c0-39.7 32.3-72 72-72s72 32.3 72 72v72z"></path></svg>',
|
270 |
+
'upgrade_title' => esc_html__( '%name% is a PRO Feature', 'wp-mail-smtp' ),
|
271 |
+
'upgrade_button' => esc_html__( 'Upgrade to Pro', 'wp-mail-smtp' ),
|
272 |
+
'upgrade_url' => 'https://wpmailsmtp.com/lite-upgrade/?discount=SMTPLITEUPGRADE&utm_source=WordPress&utm_medium=plugin-settings&utm_campaign=liteplugin',
|
273 |
+
'upgrade_bonus' => '<p>' .
|
274 |
+
wp_kses(
|
275 |
+
__( '<strong>Bonus:</strong> WP Mail SMTP users get <span>20% off</span> regular price,<br>applied at checkout.', 'wp-mail-smtp' ),
|
276 |
+
array(
|
277 |
+
'strong' => true,
|
278 |
+
'span' => true,
|
279 |
+
'br' => true,
|
280 |
+
)
|
281 |
+
)
|
282 |
+
. '</p>',
|
283 |
+
'upgrade_doc' => '<a href="https://wpmailsmtp.com/docs/how-to-upgrade-wp-mail-smtp-to-pro-version/?utm_source=WordPress&utm_medium=link&utm_campaign=liteplugin" target="_blank" rel="noopener noreferrer" class="already-purchased">
|
284 |
+
' . esc_html__( 'Already purchased?', 'wp-mail-smtp' ) . '
|
285 |
+
</a>',
|
286 |
+
),
|
287 |
+
)
|
288 |
+
);
|
289 |
+
|
290 |
+
/*
|
291 |
+
* jQuery Confirm library v3.3.4.
|
292 |
+
*/
|
293 |
+
\wp_enqueue_style(
|
294 |
+
'wp-mail-smtp-admin-jconfirm',
|
295 |
+
\wp_mail_smtp()->assets_url . '/libs/jquery-confirm.min.css',
|
296 |
+
array( 'wp-mail-smtp-admin' ),
|
297 |
+
'3.3.4'
|
298 |
+
);
|
299 |
+
\wp_enqueue_script(
|
300 |
+
'wp-mail-smtp-admin-jconfirm',
|
301 |
+
\wp_mail_smtp()->assets_url . '/libs/jquery-confirm.min.js',
|
302 |
+
array( 'wp-mail-smtp-admin' ),
|
303 |
+
'3.3.4',
|
304 |
+
false
|
305 |
+
);
|
306 |
+
|
307 |
+
/*
|
308 |
+
* Logs page.
|
309 |
+
*/
|
310 |
+
if ( $this->is_admin_page( 'logs' ) ) {
|
311 |
+
\wp_enqueue_style(
|
312 |
+
'wp-mail-smtp-admin-logs',
|
313 |
+
apply_filters( 'wp_mail_smtp_admin_enqueue_assets_logs_css', '' ),
|
314 |
+
array( 'wp-mail-smtp-admin' ),
|
315 |
+
WPMS_PLUGIN_VER
|
316 |
+
);
|
317 |
+
|
318 |
+
\wp_enqueue_script(
|
319 |
+
'wp-mail-smtp-admin-logs',
|
320 |
+
apply_filters( 'wp_mail_smtp_admin_enqueue_assets_logs_js', '' ),
|
321 |
+
array( 'wp-mail-smtp-admin' ),
|
322 |
+
WPMS_PLUGIN_VER,
|
323 |
+
false
|
324 |
+
);
|
325 |
+
}
|
326 |
+
|
327 |
+
/*
|
328 |
+
* About page.
|
329 |
+
*/
|
330 |
+
if ( $this->is_admin_page( 'about' ) ) {
|
331 |
+
|
332 |
+
\wp_enqueue_style(
|
333 |
+
'wp-mail-smtp-admin-about',
|
334 |
+
\wp_mail_smtp()->assets_url . '/css/smtp-about.min.css',
|
335 |
+
array( 'wp-mail-smtp-admin' ),
|
336 |
+
WPMS_PLUGIN_VER
|
337 |
+
);
|
338 |
+
|
339 |
+
\wp_enqueue_script(
|
340 |
+
'wp-mail-smtp-admin-about',
|
341 |
+
\wp_mail_smtp()->assets_url . '/js/smtp-about' . WP::asset_min() . '.js',
|
342 |
+
array( 'wp-mail-smtp-admin' ),
|
343 |
+
'0.7.2',
|
344 |
+
false
|
345 |
+
);
|
346 |
+
|
347 |
+
$settings = array(
|
348 |
+
'ajax_url' => \admin_url( 'admin-ajax.php' ),
|
349 |
+
'nonce' => \wp_create_nonce( 'wp-mail-smtp-about' ),
|
350 |
+
// Strings.
|
351 |
+
'plugin_activate' => \esc_html__( 'Activate', 'wp-mail-smtp' ),
|
352 |
+
'plugin_activated' => \esc_html__( 'Activated', 'wp-mail-smtp' ),
|
353 |
+
'plugin_active' => \esc_html__( 'Active', 'wp-mail-smtp' ),
|
354 |
+
'plugin_inactive' => \esc_html__( 'Inactive', 'wp-mail-smtp' ),
|
355 |
+
'plugin_processing' => \esc_html__( 'Processing...', 'wp-mail-smtp' ),
|
356 |
+
'plugin_install_error' => \esc_html__( 'Could not install a plugin. Please download from WordPress.org and install manually.', 'wp-mail-smtp' ),
|
357 |
+
'plugin_install_activate_btn' => \esc_html__( 'Install and Activate', 'wp-mail-smtp' ),
|
358 |
+
'plugin_activate_btn' => \esc_html__( 'Activate', 'wp-mail-smtp' ),
|
359 |
+
'plugin_download_btn' => \esc_html__( 'Download', 'wp-mail-smtp' ),
|
360 |
+
);
|
361 |
+
|
362 |
+
\wp_localize_script(
|
363 |
+
'wp-mail-smtp-admin-about',
|
364 |
+
'wp_mail_smtp_about',
|
365 |
+
$settings
|
366 |
+
);
|
367 |
+
|
368 |
+
\wp_enqueue_script(
|
369 |
+
'wp-mail-smtp-admin-about-matchheight',
|
370 |
+
\wp_mail_smtp()->assets_url . '/js/jquery.matchHeight.min.js',
|
371 |
+
array( 'wp-mail-smtp-admin' ),
|
372 |
+
'0.7.2',
|
373 |
+
false
|
374 |
+
);
|
375 |
+
}
|
376 |
+
|
377 |
+
do_action( 'wp_mail_smtp_admin_area_enqueue_assets', $hook );
|
378 |
+
}
|
379 |
+
|
380 |
+
/**
|
381 |
+
* Outputs the plugin admin header.
|
382 |
+
*
|
383 |
+
* @since 1.0.0
|
384 |
+
*/
|
385 |
+
public function display_admin_header() {
|
386 |
+
|
387 |
+
// Bail if we're not on a plugin page.
|
388 |
+
if ( ! $this->is_admin_page() ) {
|
389 |
+
return;
|
390 |
+
}
|
391 |
+
?>
|
392 |
+
|
393 |
+
<div id="wp-mail-smtp-header">
|
394 |
+
<!--suppress HtmlUnknownTarget -->
|
395 |
+
<img class="wp-mail-smtp-header-logo" src="<?php echo esc_url( wp_mail_smtp()->assets_url ); ?>/images/logo.svg" alt="WP Mail SMTP"/>
|
396 |
+
</div>
|
397 |
+
|
398 |
+
<?php
|
399 |
+
}
|
400 |
+
|
401 |
+
/**
|
402 |
+
* Display a text to ask users to review the plugin on WP.org.
|
403 |
+
*
|
404 |
+
* @since 1.0.0
|
405 |
+
*
|
406 |
+
* @param string $text
|
407 |
+
*
|
408 |
+
* @return string
|
409 |
+
*/
|
410 |
+
public function get_admin_footer( $text ) {
|
411 |
+
|
412 |
+
if ( $this->is_admin_page() ) {
|
413 |
+
$url = 'https://wordpress.org/support/plugin/wp-mail-smtp/reviews/?filter=5#new-post';
|
414 |
+
|
415 |
+
$text = sprintf(
|
416 |
+
wp_kses(
|
417 |
+
/* translators: %1$s - WP.org link; %2$s - same WP.org link. */
|
418 |
+
__( 'Please rate <strong>WP Mail SMTP</strong> <a href="%1$s" target="_blank" rel="noopener noreferrer">★★★★★</a> on <a href="%2$s" target="_blank" rel="noopener noreferrer">WordPress.org</a> to help us spread the word. Thank you from the WP Mail SMTP team!', 'wp-mail-smtp' ),
|
419 |
+
array(
|
420 |
+
'strong' => array(),
|
421 |
+
'a' => array(
|
422 |
+
'href' => array(),
|
423 |
+
'target' => array(),
|
424 |
+
'rel' => array(),
|
425 |
+
),
|
426 |
+
)
|
427 |
+
),
|
428 |
+
$url,
|
429 |
+
$url
|
430 |
+
);
|
431 |
+
}
|
432 |
+
|
433 |
+
return $text;
|
434 |
+
}
|
435 |
+
|
436 |
+
/**
|
437 |
+
* Display content of the admin area page.
|
438 |
+
*
|
439 |
+
* @since 1.0.0
|
440 |
+
* @since 1.5.0 Rewrite to distinguish between General tabs and separate pages.
|
441 |
+
*/
|
442 |
+
public function display() {
|
443 |
+
|
444 |
+
// Bail if we're not on a plugin page.
|
445 |
+
if ( ! $this->is_admin_page() ) {
|
446 |
+
return;
|
447 |
+
}
|
448 |
+
|
449 |
+
$page = ! empty( $_GET['page'] ) ? \sanitize_key( $_GET['page'] ) : ''; // phpcs:ignore
|
450 |
+
?>
|
451 |
+
|
452 |
+
<div class="wrap" id="wp-mail-smtp">
|
453 |
+
|
454 |
+
<?php
|
455 |
+
switch ( $page ) {
|
456 |
+
case self::SLUG:
|
457 |
+
?>
|
458 |
+
|
459 |
+
<div class="wp-mail-smtp-page wp-mail-smtp-page-general wp-mail-smtp-tab-<?php echo esc_attr( $this->get_current_tab() ); ?>">
|
460 |
+
<?php $this->display_tabs(); ?>
|
461 |
+
</div>
|
462 |
+
|
463 |
+
<?php
|
464 |
+
break;
|
465 |
+
|
466 |
+
case self::SLUG . '-logs':
|
467 |
+
$logs_class = apply_filters( 'wp_mail_smtp_admin_display_get_logs_fqcn', '\WPMailSMTP\Admin\Pages\Logs' );
|
468 |
+
/** @var \WPMailSMTP\Admin\PageAbstract $logs */
|
469 |
+
$logs = new $logs_class();
|
470 |
+
|
471 |
+
$is_archive = wp_mail_smtp()->is_pro() && wp_mail_smtp()->pro->get_logs()->is_archive();
|
472 |
+
?>
|
473 |
+
|
474 |
+
<div class="wp-mail-smtp-page wp-mail-smtp-page-logs <?php echo $is_archive ? 'wp-mail-smtp-page-logs-archive' : 'wp-mail-smtp-page-logs-single'; ?>">
|
475 |
+
<?php $logs->display(); ?>
|
476 |
+
</div>
|
477 |
+
|
478 |
+
<?php
|
479 |
+
break;
|
480 |
+
|
481 |
+
case self::SLUG . '-about':
|
482 |
+
$about = new Pages\About();
|
483 |
+
?>
|
484 |
+
|
485 |
+
<div class="wp-mail-smtp-page wp-mail-smtp-page-about wp-mail-smtp-tab-about-<?php echo \esc_attr( $about->get_current_tab() ); ?>">
|
486 |
+
<?php $about->display(); ?>
|
487 |
+
</div>
|
488 |
+
|
489 |
+
<?php
|
490 |
+
break;
|
491 |
+
}
|
492 |
+
?>
|
493 |
+
</div>
|
494 |
+
|
495 |
+
<?php
|
496 |
+
}
|
497 |
+
|
498 |
+
/**
|
499 |
+
* Display General page tabs.
|
500 |
+
*
|
501 |
+
* @since 1.5.0
|
502 |
+
*/
|
503 |
+
protected function display_tabs() {
|
504 |
+
?>
|
505 |
+
|
506 |
+
<div class="wp-mail-smtp-page-title">
|
507 |
+
<?php
|
508 |
+
foreach ( $this->get_pages() as $page_slug => $page ) :
|
509 |
+
$label = $page->get_label();
|
510 |
+
if ( empty( $label ) ) {
|
511 |
+
continue;
|
512 |
+
}
|
513 |
+
$class = $page_slug === $this->get_current_tab() ? 'active' : '';
|
514 |
+
?>
|
515 |
+
|
516 |
+
<a href="<?php echo esc_url( $page->get_link() ); ?>" class="tab <?php echo esc_attr( $class ); ?>">
|
517 |
+
<?php echo esc_html( $label ); ?>
|
518 |
+
</a>
|
519 |
+
|
520 |
+
<?php endforeach; ?>
|
521 |
+
</div>
|
522 |
+
|
523 |
+
<div class="wp-mail-smtp-page-content">
|
524 |
+
<h1 class="screen-reader-text">
|
525 |
+
<?php echo esc_html( $this->get_current_tab_title() ); ?>
|
526 |
+
</h1>
|
527 |
+
|
528 |
+
<?php $this->display_current_tab_content(); ?>
|
529 |
+
</div>
|
530 |
+
|
531 |
+
<?php
|
532 |
+
}
|
533 |
+
|
534 |
+
/**
|
535 |
+
* Get the current tab content.
|
536 |
+
*
|
537 |
+
* @since 1.0.0
|
538 |
+
*/
|
539 |
+
public function display_current_tab_content() {
|
540 |
+
|
541 |
+
$pages = $this->get_pages();
|
542 |
+
|
543 |
+
if ( ! array_key_exists( $this->get_current_tab(), $pages ) ) {
|
544 |
+
return;
|
545 |
+
}
|
546 |
+
|
547 |
+
$pages[ $this->get_current_tab() ]->display();
|
548 |
+
}
|
549 |
+
|
550 |
+
/**
|
551 |
+
* Get the current admin area tab.
|
552 |
+
*
|
553 |
+
* @since 1.0.0
|
554 |
+
*
|
555 |
+
* @return string
|
556 |
+
*/
|
557 |
+
protected function get_current_tab() {
|
558 |
+
|
559 |
+
$current = '';
|
560 |
+
|
561 |
+
if ( $this->is_admin_page( 'general' ) ) {
|
562 |
+
$current = ! empty( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'settings'; // phpcs:ignore
|
563 |
+
}
|
564 |
+
|
565 |
+
return $current;
|
566 |
+
}
|
567 |
+
|
568 |
+
/**
|
569 |
+
* Get the array of default registered tabs for General page admin area.
|
570 |
+
*
|
571 |
+
* @since 1.0.0
|
572 |
+
*
|
573 |
+
* @return \WPMailSMTP\Admin\PageAbstract[]
|
574 |
+
*/
|
575 |
+
public function get_pages() {
|
576 |
+
|
577 |
+
if ( empty( $this->pages ) ) {
|
578 |
+
$this->pages = array(
|
579 |
+
'settings' => new Pages\SettingsTab(),
|
580 |
+
'test' => new Pages\TestTab(),
|
581 |
+
'logs' => new Pages\LogsTab(),
|
582 |
+
'control' => new Pages\ControlTab(),
|
583 |
+
'misc' => new Pages\MiscTab(),
|
584 |
+
'auth' => new Pages\AuthTab(),
|
585 |
+
);
|
586 |
+
}
|
587 |
+
|
588 |
+
return apply_filters( 'wp_mail_smtp_admin_get_pages', $this->pages );
|
589 |
+
}
|
590 |
+
|
591 |
+
/**
|
592 |
+
* Get the current tab title.
|
593 |
+
*
|
594 |
+
* @since 1.0.0
|
595 |
+
*
|
596 |
+
* @return string
|
597 |
+
*/
|
598 |
+
public function get_current_tab_title() {
|
599 |
+
|
600 |
+
$pages = $this->get_pages();
|
601 |
+
|
602 |
+
if ( ! array_key_exists( $this->get_current_tab(), $pages ) ) {
|
603 |
+
return '';
|
604 |
+
}
|
605 |
+
|
606 |
+
return $pages[ $this->get_current_tab() ]->get_title();
|
607 |
+
}
|
608 |
+
|
609 |
+
/**
|
610 |
+
* Check whether we are on an admin page.
|
611 |
+
*
|
612 |
+
* @since 1.0.0
|
613 |
+
* @since 1.5.0 Added support for new pages.
|
614 |
+
*
|
615 |
+
* @param array|string $slug ID(s) of a plugin page. Possible values: 'general', 'logs', 'about' or array of them.
|
616 |
+
*
|
617 |
+
* @return bool
|
618 |
+
*/
|
619 |
+
public function is_admin_page( $slug = array() ) {
|
620 |
+
|
621 |
+
$cur_page = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : ''; // phpcs:ignore
|
622 |
+
$check = self::SLUG;
|
623 |
+
$pages_equal = false;
|
624 |
+
|
625 |
+
if ( is_string( $slug ) ) {
|
626 |
+
$slug = sanitize_key( $slug );
|
627 |
+
|
628 |
+
if (
|
629 |
+
in_array( $slug, self::$pages_registered, true ) &&
|
630 |
+
$slug !== 'general'
|
631 |
+
) {
|
632 |
+
$check = self::SLUG . '-' . $slug;
|
633 |
+
}
|
634 |
+
|
635 |
+
$pages_equal = $cur_page === $check;
|
636 |
+
} elseif ( is_array( $slug ) ) {
|
637 |
+
if ( empty( $slug ) ) {
|
638 |
+
$slug = array_map( function ( $v ) {
|
639 |
+
if ( $v === 'general' ) {
|
640 |
+
return Area::SLUG;
|
641 |
+
}
|
642 |
+
return Area::SLUG . '-' . $v;
|
643 |
+
}, self::$pages_registered );
|
644 |
+
} else {
|
645 |
+
$slug = array_map( function ( $v ) {
|
646 |
+
if ( $v === 'general' ) {
|
647 |
+
return Area::SLUG;
|
648 |
+
}
|
649 |
+
return Area::SLUG . '-' . sanitize_key( $v );
|
650 |
+
}, $slug );
|
651 |
+
}
|
652 |
+
|
653 |
+
$pages_equal = in_array( $cur_page, $slug, true );
|
654 |
+
}
|
655 |
+
|
656 |
+
return is_admin() && $pages_equal;
|
657 |
+
}
|
658 |
+
|
659 |
+
/**
|
660 |
+
* Give ability to use either admin area option or a filter to hide error notices about failed email delivery.
|
661 |
+
* Filter has higher priority and overrides an option.
|
662 |
+
*
|
663 |
+
* @since 1.6.0
|
664 |
+
*
|
665 |
+
* @return bool
|
666 |
+
*/
|
667 |
+
public function is_error_delivery_notice_enabled() {
|
668 |
+
|
669 |
+
$is_hard_enabled = (bool) apply_filters( 'wp_mail_smtp_admin_is_error_delivery_notice_enabled', true );
|
670 |
+
|
671 |
+
// If someone changed the value to false using a filter - disable completely.
|
672 |
+
if ( ! $is_hard_enabled ) {
|
673 |
+
return false;
|
674 |
+
}
|
675 |
+
|
676 |
+
return ! (bool) Options::init()->get( 'general', 'email_delivery_errors_hidden' );
|
677 |
+
}
|
678 |
+
|
679 |
+
/**
|
680 |
+
* All possible plugin forms manipulation will be done here.
|
681 |
+
*
|
682 |
+
* @since 1.0.0
|
683 |
+
*/
|
684 |
+
public function process_actions() {
|
685 |
+
|
686 |
+
// Bail if we're not on a plugin General page.
|
687 |
+
if ( ! $this->is_admin_page( 'general' ) ) {
|
688 |
+
return;
|
689 |
+
}
|
690 |
+
|
691 |
+
$pages = $this->get_pages();
|
692 |
+
|
693 |
+
// Allow to process only own tabs.
|
694 |
+
if ( ! array_key_exists( $this->get_current_tab(), $pages ) ) {
|
695 |
+
return;
|
696 |
+
}
|
697 |
+
|
698 |
+
// Process POST only if it exists.
|
699 |
+
if ( ! empty( $_POST ) ) {
|
700 |
+
if ( ! empty( $_POST['wp-mail-smtp'] ) ) {
|
701 |
+
$post = $_POST['wp-mail-smtp'];
|
702 |
+
} else {
|
703 |
+
$post = array();
|
704 |
+
}
|
705 |
+
|
706 |
+
$pages[ $this->get_current_tab() ]->process_post( $post );
|
707 |
+
}
|
708 |
+
|
709 |
+
// This won't do anything for most pages.
|
710 |
+
// Works for plugin page only, when GET params are allowed.
|
711 |
+
$pages[ $this->get_current_tab() ]->process_auth();
|
712 |
+
}
|
713 |
+
|
714 |
+
/**
|
715 |
+
* Process all AJAX requests.
|
716 |
+
*
|
717 |
+
* @since 1.3.0
|
718 |
+
* @since 1.5.0 Added tasks to process plugins management.
|
719 |
+
*/
|
720 |
+
public function process_ajax() {
|
721 |
+
|
722 |
+
$data = array();
|
723 |
+
|
724 |
+
// Only admins can fire these ajax requests.
|
725 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
726 |
+
wp_send_json_error( $data );
|
727 |
+
}
|
728 |
+
|
729 |
+
if ( empty( $_POST['task'] ) ) { // phpcs:ignore
|
730 |
+
wp_send_json_error( $data );
|
731 |
+
}
|
732 |
+
|
733 |
+
$task = sanitize_key( $_POST['task'] ); // phpcs:ignore
|
734 |
+
|
735 |
+
switch ( $task ) {
|
736 |
+
case 'pro_banner_dismiss':
|
737 |
+
update_user_meta( get_current_user_id(), 'wp_mail_smtp_pro_banner_dismissed', true );
|
738 |
+
$data['message'] = esc_html__( 'WP Mail SMTP Pro related message was successfully dismissed.', 'wp-mail-smtp' );
|
739 |
+
break;
|
740 |
+
|
741 |
+
case 'about_plugin_install':
|
742 |
+
Pages\About::ajax_plugin_install();
|
743 |
+
break;
|
744 |
+
|
745 |
+
case 'about_plugin_activate':
|
746 |
+
Pages\About::ajax_plugin_activate();
|
747 |
+
break;
|
748 |
+
|
749 |
+
case 'notice_dismiss':
|
750 |
+
$notice = sanitize_key( $_POST['notice'] ); // phpcs:ignore
|
751 |
+
$mailer = sanitize_key( $_POST['mailer'] ); // phpcs:ignore
|
752 |
+
if ( empty( $notice ) || empty( $mailer ) ) {
|
753 |
+
break;
|
754 |
+
}
|
755 |
+
|
756 |
+
update_user_meta( get_current_user_id(), "wp_mail_smtp_notice_{$notice}_for_{$mailer}_dismissed", true );
|
757 |
+
$data['message'] = esc_html__( 'Educational notice for this mailer was successfully dismissed.', 'wp-mail-smtp' );
|
758 |
+
break;
|
759 |
+
|
760 |
+
default:
|
761 |
+
// Allow custom tasks data processing being added here.
|
762 |
+
$data = apply_filters( 'wp_mail_smtp_admin_process_ajax_' . $task . '_data', $data );
|
763 |
+
}
|
764 |
+
|
765 |
+
// Final ability to rewrite all the data, just in case.
|
766 |
+
$data = (array) apply_filters( 'wp_mail_smtp_admin_process_ajax_data', $data, $task );
|
767 |
+
|
768 |
+
if ( empty( $data ) ) {
|
769 |
+
wp_send_json_error( $data );
|
770 |
+
}
|
771 |
+
|
772 |
+
wp_send_json_success( $data );
|
773 |
+
}
|
774 |
+
|
775 |
+
/**
|
776 |
+
* Add a link to Settings page of a plugin on Plugins page.
|
777 |
+
*
|
778 |
+
* @since 1.0.0
|
779 |
+
* @since 1.5.0 Added a link to Email Log.
|
780 |
+
*
|
781 |
+
* @param array $links
|
782 |
+
* @param string $file
|
783 |
+
*
|
784 |
+
* @return mixed
|
785 |
+
*/
|
786 |
+
public function add_plugin_action_link( $links, $file ) {
|
787 |
+
|
788 |
+
// Will target both pro and lite version of a plugin.
|
789 |
+
if ( strpos( $file, 'wp-mail-smtp' ) === false ) {
|
790 |
+
return $links;
|
791 |
+
}
|
792 |
+
|
793 |
+
$settings_link = '<a href="' . esc_url( $this->get_admin_page_url() ) . '">' . esc_html__( 'Settings', 'wp-mail-smtp' ) . '</a>';
|
794 |
+
$logs_link = '<a href="' . esc_url( $this->get_admin_page_url( self::SLUG . '-logs' ) ) . '">' . esc_html__( 'Email Log', 'wp-mail-smtp' ) . '</a>';
|
795 |
+
|
796 |
+
array_unshift( $links, $settings_link, $logs_link );
|
797 |
+
|
798 |
+
return $links;
|
799 |
+
}
|
800 |
+
|
801 |
+
/**
|
802 |
+
* Get plugin admin area page URL.
|
803 |
+
*
|
804 |
+
* @since 1.0.0
|
805 |
+
* @since 1.5.0 URL is changed to support the top level position of the plugin admin area.
|
806 |
+
*
|
807 |
+
* @param string $page
|
808 |
+
*
|
809 |
+
* @return string
|
810 |
+
*/
|
811 |
+
public function get_admin_page_url( $page = '' ) {
|
812 |
+
|
813 |
+
if ( empty( $page ) ) {
|
814 |
+
$page = self::SLUG;
|
815 |
+
}
|
816 |
+
|
817 |
+
return add_query_arg(
|
818 |
+
'page',
|
819 |
+
$page,
|
820 |
+
admin_url( 'admin.php' )
|
821 |
+
);
|
822 |
+
}
|
823 |
+
|
824 |
+
/**
|
825 |
+
* Remove all non-WP Mail SMTP plugin notices from plugin pages.
|
826 |
+
*
|
827 |
+
* @since 1.0.0
|
828 |
+
*/
|
829 |
+
public function hide_unrelated_notices() {
|
830 |
+
|
831 |
+
// Bail if we're not on our screen or page.
|
832 |
+
if ( empty( $_REQUEST['page'] ) || strpos( $_REQUEST['page'], self::SLUG ) === false ) {
|
833 |
+
return;
|
834 |
+
}
|
835 |
+
|
836 |
+
global $wp_filter;
|
837 |
+
|
838 |
+
if ( ! empty( $wp_filter['user_admin_notices']->callbacks ) && is_array( $wp_filter['user_admin_notices']->callbacks ) ) {
|
839 |
+
foreach ( $wp_filter['user_admin_notices']->callbacks as $priority => $hooks ) {
|
840 |
+
foreach ( $hooks as $name => $arr ) {
|
841 |
+
if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
|
842 |
+
unset( $wp_filter['user_admin_notices']->callbacks[ $priority ][ $name ] );
|
843 |
+
continue;
|
844 |
+
}
|
845 |
+
if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
|
846 |
+
continue;
|
847 |
+
}
|
848 |
+
if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
|
849 |
+
unset( $wp_filter['user_admin_notices']->callbacks[ $priority ][ $name ] );
|
850 |
+
}
|
851 |
+
}
|
852 |
+
}
|
853 |
+
}
|
854 |
+
|
855 |
+
if ( ! empty( $wp_filter['admin_notices']->callbacks ) && is_array( $wp_filter['admin_notices']->callbacks ) ) {
|
856 |
+
foreach ( $wp_filter['admin_notices']->callbacks as $priority => $hooks ) {
|
857 |
+
foreach ( $hooks as $name => $arr ) {
|
858 |
+
if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
|
859 |
+
unset( $wp_filter['admin_notices']->callbacks[ $priority ][ $name ] );
|
860 |
+
continue;
|
861 |
+
}
|
862 |
+
if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
|
863 |
+
continue;
|
864 |
+
}
|
865 |
+
if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
|
866 |
+
unset( $wp_filter['admin_notices']->callbacks[ $priority ][ $name ] );
|
867 |
+
}
|
868 |
+
}
|
869 |
+
}
|
870 |
+
}
|
871 |
+
|
872 |
+
if ( ! empty( $wp_filter['all_admin_notices']->callbacks ) && is_array( $wp_filter['all_admin_notices']->callbacks ) ) {
|
873 |
+
foreach ( $wp_filter['all_admin_notices']->callbacks as $priority => $hooks ) {
|
874 |
+
foreach ( $hooks as $name => $arr ) {
|
875 |
+
if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
|
876 |
+
unset( $wp_filter['all_admin_notices']->callbacks[ $priority ][ $name ] );
|
877 |
+
continue;
|
878 |
+
}
|
879 |
+
if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
|
880 |
+
continue;
|
881 |
+
}
|
882 |
+
if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
|
883 |
+
unset( $wp_filter['all_admin_notices']->callbacks[ $priority ][ $name ] );
|
884 |
+
}
|
885 |
+
}
|
886 |
+
}
|
887 |
+
}
|
888 |
+
}
|
889 |
+
}
|
src/Admin/Pages/About.php
CHANGED
@@ -1,702 +1,702 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Admin\Pages;
|
4 |
-
|
5 |
-
use WPMailSMTP\Admin\Area;
|
6 |
-
use WPMailSMTP\Admin\PageAbstract;
|
7 |
-
use WPMailSMTP\Admin\PluginsInstallSkin;
|
8 |
-
use WPMailSMTP\Admin\PluginsInstallUpgrader;
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Class About to display a page with About Us and Versus content.
|
12 |
-
*
|
13 |
-
* @since 1.5.0
|
14 |
-
*/
|
15 |
-
class About extends PageAbstract {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* @since 1.5.0
|
19 |
-
*
|
20 |
-
* @var string Slug of a page.
|
21 |
-
*/
|
22 |
-
protected $slug = 'about';
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @since 1.5.0
|
26 |
-
*
|
27 |
-
* @var array List of supported tabs.
|
28 |
-
*/
|
29 |
-
protected $tabs = array( 'about', 'versus' );
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Get the page/tab link.
|
33 |
-
*
|
34 |
-
* @since 1.5.0
|
35 |
-
*
|
36 |
-
* @param string $tab Tab to generate a link to.
|
37 |
-
*
|
38 |
-
* @return string
|
39 |
-
*/
|
40 |
-
public function get_link( $tab = '' ) {
|
41 |
-
|
42 |
-
return add_query_arg(
|
43 |
-
'tab',
|
44 |
-
$this->get_defined_tab( $tab ),
|
45 |
-
admin_url( 'admin.php?page=' . Area::SLUG . '-' . $this->slug )
|
46 |
-
);
|
47 |
-
}
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Get the current tab.
|
51 |
-
*
|
52 |
-
* @since 1.5.0
|
53 |
-
*
|
54 |
-
* @return string Current tab.
|
55 |
-
*/
|
56 |
-
public function get_current_tab() {
|
57 |
-
|
58 |
-
if ( empty( $_GET['tab'] ) ) { // phpcs:ignore
|
59 |
-
return $this->slug;
|
60 |
-
}
|
61 |
-
|
62 |
-
return $this->get_defined_tab( $_GET['tab'] ); // phpcs:ignore
|
63 |
-
}
|
64 |
-
|
65 |
-
/**
|
66 |
-
* Get the defined or default tab.
|
67 |
-
*
|
68 |
-
* @since 1.5.0
|
69 |
-
*
|
70 |
-
* @param string $tab Tab to check.
|
71 |
-
*
|
72 |
-
* @return string Defined tab. Fallback to default one if it doesn't exist.
|
73 |
-
*/
|
74 |
-
protected function get_defined_tab( $tab ) {
|
75 |
-
|
76 |
-
$tab = \sanitize_key( $tab );
|
77 |
-
|
78 |
-
return \in_array( $tab, $this->tabs, true ) ? $tab : $this->slug;
|
79 |
-
}
|
80 |
-
|
81 |
-
/**
|
82 |
-
* Get label for a tab.
|
83 |
-
* Process only those that exists.
|
84 |
-
* Defaults to "About Us".
|
85 |
-
*
|
86 |
-
* @since 1.5.0
|
87 |
-
*
|
88 |
-
* @param string $tab Tab to get label for.
|
89 |
-
*
|
90 |
-
* @return string
|
91 |
-
*/
|
92 |
-
public function get_label( $tab = '' ) {
|
93 |
-
|
94 |
-
switch ( $this->get_defined_tab( $tab ) ) {
|
95 |
-
case 'versus':
|
96 |
-
$label = \sprintf(
|
97 |
-
/* translators: %s - plugin current license type. */
|
98 |
-
\esc_html__( '%s vs Pro', 'wp-mail-smtp' ),
|
99 |
-
\ucfirst( \wp_mail_smtp()->get_license_type() )
|
100 |
-
);
|
101 |
-
break;
|
102 |
-
|
103 |
-
case 'about':
|
104 |
-
default:
|
105 |
-
$label = \esc_html__( 'About Us', 'wp-mail-smtp' );
|
106 |
-
break;
|
107 |
-
}
|
108 |
-
|
109 |
-
return $label;
|
110 |
-
}
|
111 |
-
|
112 |
-
/**
|
113 |
-
* @inheritdoc
|
114 |
-
*/
|
115 |
-
public function get_title() {
|
116 |
-
return $this->get_label( $this->get_current_tab() );
|
117 |
-
}
|
118 |
-
|
119 |
-
/**
|
120 |
-
* Display About page content based on the current tab.
|
121 |
-
*
|
122 |
-
* @since 1.5.0
|
123 |
-
*/
|
124 |
-
public function display() {
|
125 |
-
?>
|
126 |
-
|
127 |
-
<div class="wp-mail-smtp-page-title">
|
128 |
-
<a href="<?php echo \esc_url( $this->get_link() ); ?>" class="tab <?php echo $this->get_current_tab() === 'about' ? 'active' : ''; ?>">
|
129 |
-
<?php echo \esc_html( $this->get_label( 'about' ) ); ?>
|
130 |
-
</a>
|
131 |
-
|
132 |
-
<?php if ( \wp_mail_smtp()->get_license_type() === 'lite' ) : ?>
|
133 |
-
<a href="<?php echo \esc_url( $this->get_link( 'versus' ) ); ?>" class="tab <?php echo $this->get_current_tab() === 'versus' ? 'active' : ''; ?>">
|
134 |
-
<?php echo \esc_html( $this->get_label( 'versus' ) ); ?>
|
135 |
-
</a>
|
136 |
-
<?php endif; ?>
|
137 |
-
</div>
|
138 |
-
|
139 |
-
<div class="wp-mail-smtp-page-content">
|
140 |
-
<h1 class="screen-reader-text">
|
141 |
-
<?php echo \esc_html( $this->get_label( $this->get_current_tab() ) ); ?>
|
142 |
-
</h1>
|
143 |
-
|
144 |
-
<?php
|
145 |
-
$callback = 'display_' . $this->get_current_tab();
|
146 |
-
|
147 |
-
if ( \method_exists( $this, $callback ) ) {
|
148 |
-
$this->{$callback}();
|
149 |
-
} else {
|
150 |
-
$this->display_about();
|
151 |
-
}
|
152 |
-
?>
|
153 |
-
</div>
|
154 |
-
|
155 |
-
<?php
|
156 |
-
}
|
157 |
-
|
158 |
-
/**
|
159 |
-
* Display an "About Us" tab content.
|
160 |
-
*
|
161 |
-
* @since 1.5.0
|
162 |
-
*/
|
163 |
-
protected function display_about() {
|
164 |
-
?>
|
165 |
-
|
166 |
-
<div class="wp-mail-smtp-admin-about-section wp-mail-smtp-admin-columns">
|
167 |
-
|
168 |
-
<div class="wp-mail-smtp-admin-column-60">
|
169 |
-
<h3>
|
170 |
-
<?php esc_html_e( 'Hello and welcome to WP Mail SMTP, the easiest and most popular WordPress SMTP plugin. We build software that helps your site reliably deliver emails every time.', 'wp-mail-smtp' ); ?>
|
171 |
-
</h3>
|
172 |
-
|
173 |
-
<p>
|
174 |
-
<?php esc_html_e( 'Email deliverability has been a well-documented problem for all WordPress websites. However as WPForms grew, we became more aware of this painful issue that affects our users and the larger WordPress community. So we decided to solve this problem and make a solution that\'s beginner friendly.', 'wp-mail-smtp' ); ?>
|
175 |
-
</p>
|
176 |
-
<p>
|
177 |
-
<?php esc_html_e( 'Our goal is to make reliable email deliverability easy for WordPress.', 'wp-mail-smtp' ); ?>
|
178 |
-
</p>
|
179 |
-
<p>
|
180 |
-
<?php
|
181 |
-
printf(
|
182 |
-
wp_kses(
|
183 |
-
/* translators: %1$s - WPBeginner URL, %2$s - OptinMonster URL, %3$s - MonsterInsights URL. */
|
184 |
-
__( 'WP Mail SMTP is brought to you by the same team that\'s behind the most user friendly WordPress forms, <a href="%1$s" target="_blank" rel="noopener noreferrer">WPForms</a>, the largest WordPress resource site, <a href="%2$s" target="_blank" rel="noopener noreferrer">WPBeginner</a>, the most popular lead-generation software, <a href="%3$s" target="_blank" rel="noopener noreferrer">OptinMonster</a>, and the best WordPress analytics plugin, <a href="%4$s" target="_blank" rel="noopener noreferrer">MonsterInsights</a>.', 'wp-mail-smtp' ),
|
185 |
-
array(
|
186 |
-
'a' => array(
|
187 |
-
'href' => array(),
|
188 |
-
'rel' => array(),
|
189 |
-
'target' => array(),
|
190 |
-
),
|
191 |
-
)
|
192 |
-
),
|
193 |
-
'https://wpforms.com/?utm_source=wpmailsmtpplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpmailsmtp',
|
194 |
-
'https://www.wpbeginner.com/?utm_source=wpmailsmtpplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpmailsmtp',
|
195 |
-
'https://optinmonster.com/?utm_source=wpmailsmtpplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpmailsmtp',
|
196 |
-
'https://www.monsterinsights.com/?utm_source=wpmailsmtpplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpmailsmtp'
|
197 |
-
);
|
198 |
-
?>
|
199 |
-
</p>
|
200 |
-
<p>
|
201 |
-
<?php esc_html_e( 'Yup, we know a thing or two about building awesome products that customers love.', 'wp-mail-smtp' ); ?>
|
202 |
-
</p>
|
203 |
-
</div>
|
204 |
-
|
205 |
-
<div class="wp-mail-smtp-admin-column-40 wp-mail-smtp-admin-column-last">
|
206 |
-
<figure>
|
207 |
-
<img src="<?php echo esc_url( wp_mail_smtp()->assets_url . '/images/about/team.jpg' ); ?>" alt="<?php esc_attr_e( 'The WPForms Team photo', 'wp-mail-smtp' ); ?>">
|
208 |
-
<figcaption>
|
209 |
-
<?php esc_html_e( 'The WPForms Team', 'wp-mail-smtp' ); ?>
|
210 |
-
</figcaption>
|
211 |
-
</figure>
|
212 |
-
</div>
|
213 |
-
|
214 |
-
</div>
|
215 |
-
|
216 |
-
<div class="wp-mail-smtp-admin-about-plugins">
|
217 |
-
<div class="plugins-container">
|
218 |
-
<?php
|
219 |
-
foreach ( $this->get_am_plugins() as $key => $plugin ) :
|
220 |
-
$is_url_external = false;
|
221 |
-
|
222 |
-
$data = $this->get_about_plugins_data( $plugin );
|
223 |
-
|
224 |
-
if ( isset( $plugin['pro'] ) && \array_key_exists( $plugin['pro']['path'], \get_plugins() ) ) {
|
225 |
-
$is_url_external = true;
|
226 |
-
$plugin = $plugin['pro'];
|
227 |
-
|
228 |
-
$data = array_merge( $data, $this->get_about_plugins_data( $plugin, true ) );
|
229 |
-
}
|
230 |
-
|
231 |
-
?>
|
232 |
-
<div class="plugin-container">
|
233 |
-
<div class="plugin-item">
|
234 |
-
<div class="details wp-mail-smtp-clear">
|
235 |
-
<img src="<?php echo \esc_url( $plugin['icon'] ); ?>">
|
236 |
-
<h5 class="plugin-name">
|
237 |
-
<?php echo $plugin['name']; ?>
|
238 |
-
</h5>
|
239 |
-
<p class="plugin-desc">
|
240 |
-
<?php echo $plugin['desc']; ?>
|
241 |
-
</p>
|
242 |
-
</div>
|
243 |
-
<div class="actions wp-mail-smtp-clear">
|
244 |
-
<div class="status">
|
245 |
-
<strong>
|
246 |
-
<?php
|
247 |
-
\printf(
|
248 |
-
/* translators: %s - status HTML text. */
|
249 |
-
\esc_html__( 'Status: %s', 'wp-mail-smtp' ),
|
250 |
-
'<span class="status-label ' . $data['status_class'] . '">' . $data['status_text'] . '</span>'
|
251 |
-
);
|
252 |
-
?>
|
253 |
-
</strong>
|
254 |
-
</div>
|
255 |
-
<div class="action-button">
|
256 |
-
<?php
|
257 |
-
$go_to_class = '';
|
258 |
-
if ( $is_url_external && $data['status_class'] === 'status-download' ) {
|
259 |
-
$go_to_class = 'go_to';
|
260 |
-
}
|
261 |
-
?>
|
262 |
-
<a href="<?php echo \esc_url( $plugin['url'] ); ?>"
|
263 |
-
class="<?php echo \esc_attr( $data['action_class'] ); ?> <?php echo $go_to_class; ?>"
|
264 |
-
data-plugin="<?php echo $data['plugin_src']; ?>">
|
265 |
-
<?php echo $data['action_text']; ?>
|
266 |
-
</a>
|
267 |
-
</div>
|
268 |
-
</div>
|
269 |
-
</div>
|
270 |
-
</div>
|
271 |
-
<?php endforeach; ?>
|
272 |
-
</div>
|
273 |
-
</div>
|
274 |
-
|
275 |
-
<?php
|
276 |
-
}
|
277 |
-
|
278 |
-
/**
|
279 |
-
* Generate all the required CSS classed and labels to be used in rendering.
|
280 |
-
*
|
281 |
-
* @since 1.5.0
|
282 |
-
*
|
283 |
-
* @param array $plugin
|
284 |
-
* @param bool $is_pro
|
285 |
-
*
|
286 |
-
* @return mixed
|
287 |
-
*/
|
288 |
-
protected function get_about_plugins_data( $plugin, $is_pro = false ) {
|
289 |
-
|
290 |
-
$data = array();
|
291 |
-
|
292 |
-
if ( \array_key_exists( $plugin['path'], \get_plugins() ) ) {
|
293 |
-
if ( \is_plugin_active( $plugin['path'] ) ) {
|
294 |
-
// Status text/status.
|
295 |
-
$data['status_class'] = 'status-active';
|
296 |
-
$data['status_text'] = \esc_html__( 'Active', 'wp-mail-smtp' );
|
297 |
-
// Button text/status.
|
298 |
-
$data['action_class'] = $data['status_class'] . ' button button-secondary disabled';
|
299 |
-
$data['action_text'] = \esc_html__( 'Activated', 'wp-mail-smtp' );
|
300 |
-
$data['plugin_src'] = \esc_attr( $plugin['path'] );
|
301 |
-
} else {
|
302 |
-
// Status text/status.
|
303 |
-
$data['status_class'] = 'status-inactive';
|
304 |
-
$data['status_text'] = \esc_html__( 'Inactive', 'wp-mail-smtp' );
|
305 |
-
// Button text/status.
|
306 |
-
$data['action_class'] = $data['status_class'] . ' button button-secondary';
|
307 |
-
$data['action_text'] = \esc_html__( 'Activate', 'wp-mail-smtp' );
|
308 |
-
$data['plugin_src'] = \esc_attr( $plugin['path'] );
|
309 |
-
}
|
310 |
-
} else {
|
311 |
-
if ( ! $is_pro ) {
|
312 |
-
// Doesn't exist, install.
|
313 |
-
// Status text/status.
|
314 |
-
$data['status_class'] = 'status-download';
|
315 |
-
$data['status_text'] = \esc_html__( 'Not Installed', 'wp-mail-smtp' );
|
316 |
-
// Button text/status.
|
317 |
-
$data['action_class'] = $data['status_class'] . ' button button-primary';
|
318 |
-
$data['action_text'] = \esc_html__( 'Install Plugin', 'wp-mail-smtp' );
|
319 |
-
$data['plugin_src'] = \esc_url( $plugin['url'] );
|
320 |
-
}
|
321 |
-
}
|
322 |
-
|
323 |
-
return $data;
|
324 |
-
}
|
325 |
-
|
326 |
-
/**
|
327 |
-
* List of AM plugins that we propose to install.
|
328 |
-
*
|
329 |
-
* @since 1.5.0
|
330 |
-
*
|
331 |
-
* @return array
|
332 |
-
*/
|
333 |
-
private function get_am_plugins() {
|
334 |
-
|
335 |
-
$data = array(
|
336 |
-
'mi' => array(
|
337 |
-
'path' => 'google-analytics-for-wordpress/googleanalytics.php',
|
338 |
-
'icon' => \wp_mail_smtp()->assets_url . '/images/about/plugin-mi.png',
|
339 |
-
'name' => \esc_html__( 'MonsterInsights', 'wp-mail-smtp' ),
|
340 |
-
'desc' => \esc_html__( 'MonsterInsights makes it “effortless” to properly connect your WordPress site with Google Analytics, so you can start making data-driven decisions to grow your business.', 'wp-mail-smtp' ),
|
341 |
-
'url' => 'https://downloads.wordpress.org/plugin/google-analytics-for-wordpress.zip',
|
342 |
-
'pro' => array(
|
343 |
-
'path' => 'google-analytics-premium/googleanalytics-premium.php',
|
344 |
-
'icon' => \wp_mail_smtp()->assets_url . '/images/about/plugin-mi.png',
|
345 |
-
'name' => \esc_html__( 'MonsterInsights Pro', 'wp-mail-smtp' ),
|
346 |
-
'desc' => \esc_html__( 'MonsterInsights makes it “effortless” to properly connect your WordPress site with Google Analytics, so you can start making data-driven decisions to grow your business.', 'wp-mail-smtp' ),
|
347 |
-
'url' => 'https://www.monsterinsights.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
|
348 |
-
),
|
349 |
-
),
|
350 |
-
'om' => array(
|
351 |
-
'path' => 'optinmonster/optin-monster-wp-api.php',
|
352 |
-
'icon' => \wp_mail_smtp()->assets_url . '/images/about/plugin-om.png',
|
353 |
-
'name' => \esc_html__( 'OptinMonster', 'wp-mail-smtp' ),
|
354 |
-
'desc' => \esc_html__( 'Our high-converting optin forms like Exit-Intent® popups, Fullscreen Welcome Mats, and Scroll boxes help you dramatically boost conversions and get more email subscribers.', 'wp-mail-smtp' ),
|
355 |
-
'url' => 'https://downloads.wordpress.org/plugin/optinmonster.zip',
|
356 |
-
),
|
357 |
-
'wpforms' => array(
|
358 |
-
'path' => 'wpforms-lite/wpforms.php',
|
359 |
-
'icon' => \wp_mail_smtp()->assets_url . '/images/about/plugin-wpf.png',
|
360 |
-
'name' => \esc_html__( 'Contact Forms by WPForms', 'wp-mail-smtp' ),
|
361 |
-
'desc' => \esc_html__( 'The best WordPress contact form plugin. Drag & Drop online form builder that helps you create beautiful contact forms with just a few clicks.', 'wp-mail-smtp' ),
|
362 |
-
'url' => 'https://downloads.wordpress.org/plugin/wpforms-lite.zip',
|
363 |
-
'pro' => array(
|
364 |
-
'path' => 'wpforms/wpforms.php',
|
365 |
-
'icon' => \wp_mail_smtp()->assets_url . '/images/about/plugin-wpf.png',
|
366 |
-
'name' => \esc_html__( 'WPForms Pro', 'wp-mail-smtp' ),
|
367 |
-
'desc' => \esc_html__( 'The best WordPress contact form plugin. Drag & Drop online form builder that helps you create beautiful contact forms with just a few clicks.', 'wp-mail-smtp' ),
|
368 |
-
'url' => 'https://wpforms.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
|
369 |
-
),
|
370 |
-
),
|
371 |
-
);
|
372 |
-
|
373 |
-
return $data;
|
374 |
-
}
|
375 |
-
|
376 |
-
/**
|
377 |
-
* Active the given plugin.
|
378 |
-
*
|
379 |
-
* @since 1.5.0
|
380 |
-
*/
|
381 |
-
public static function ajax_plugin_activate() {
|
382 |
-
|
383 |
-
// Run a security check.
|
384 |
-
\check_ajax_referer( 'wp-mail-smtp-about', 'nonce' );
|
385 |
-
|
386 |
-
$error = \esc_html__( 'Could not activate the plugin. Please activate it from the Plugins page.', 'wp-mail-smtp' );
|
387 |
-
|
388 |
-
// Check for permissions.
|
389 |
-
if ( ! \current_user_can( 'activate_plugins' ) ) {
|
390 |
-
\wp_send_json_error( $error );
|
391 |
-
}
|
392 |
-
|
393 |
-
if ( isset( $_POST['plugin'] ) ) {
|
394 |
-
|
395 |
-
$activate = \activate_plugins( $_POST['plugin'] ); // phpcs:ignore
|
396 |
-
|
397 |
-
if ( ! \is_wp_error( $activate ) ) {
|
398 |
-
\wp_send_json_success( esc_html__( 'Plugin activated.', 'wp-mail-smtp' ) );
|
399 |
-
}
|
400 |
-
}
|
401 |
-
|
402 |
-
\wp_send_json_error( $error );
|
403 |
-
}
|
404 |
-
|
405 |
-
/**
|
406 |
-
* Install & activate the given plugin.
|
407 |
-
*
|
408 |
-
* @since 1.5.0
|
409 |
-
*/
|
410 |
-
public static function ajax_plugin_install() {
|
411 |
-
|
412 |
-
// Run a security check.
|
413 |
-
\check_ajax_referer( 'wp-mail-smtp-about', 'nonce' );
|
414 |
-
|
415 |
-
$error = \esc_html__( 'Could not install the plugin.', 'wp-mail-smtp' );
|
416 |
-
|
417 |
-
// Check for permissions.
|
418 |
-
if ( ! \current_user_can( 'activate_plugins' ) ) {
|
419 |
-
\wp_send_json_error( $error );
|
420 |
-
}
|
421 |
-
|
422 |
-
if ( empty( $_POST['plugin'] ) ) {
|
423 |
-
\wp_send_json_error();
|
424 |
-
}
|
425 |
-
|
426 |
-
// Set the current screen to avoid undefined notices.
|
427 |
-
\set_current_screen( 'wp-mail-smtp_page_wp-mail-smtp-about' );
|
428 |
-
|
429 |
-
// Prepare variables.
|
430 |
-
$url = \esc_url_raw(
|
431 |
-
\add_query_arg(
|
432 |
-
array(
|
433 |
-
'page' => 'wp-mail-smtp-about',
|
434 |
-
),
|
435 |
-
\admin_url( 'admin.php' )
|
436 |
-
)
|
437 |
-
);
|
438 |
-
|
439 |
-
$creds = \request_filesystem_credentials( $url, '', false, false, null );
|
440 |
-
|
441 |
-
// Check for file system permissions.
|
442 |
-
if ( false === $creds ) {
|
443 |
-
\wp_send_json_error( $error );
|
444 |
-
}
|
445 |
-
|
446 |
-
if ( ! \WP_Filesystem( $creds ) ) {
|
447 |
-
\wp_send_json_error( $error );
|
448 |
-
}
|
449 |
-
|
450 |
-
// Do not allow WordPress to search/download translations, as this will break JS output.
|
451 |
-
\remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
|
452 |
-
|
453 |
-
// Create the plugin upgrader with our custom skin.
|
454 |
-
$installer = new PluginsInstallUpgrader( new PluginsInstallSkin() );
|
455 |
-
|
456 |
-
// Error check.
|
457 |
-
if ( ! \method_exists( $installer, 'install' ) || empty( $_POST['plugin'] ) ) {
|
458 |
-
\wp_send_json_error( $error );
|
459 |
-
}
|
460 |
-
|
461 |
-
$installer->install( $_POST['plugin'] ); // phpcs:ignore
|
462 |
-
|
463 |
-
// Flush the cache and return the newly installed plugin basename.
|
464 |
-
\wp_cache_flush();
|
465 |
-
|
466 |
-
if ( $installer->plugin_info() ) {
|
467 |
-
|
468 |
-
$plugin_basename = $installer->plugin_info();
|
469 |
-
|
470 |
-
// Activate the plugin silently.
|
471 |
-
$activated = \activate_plugin( $plugin_basename );
|
472 |
-
|
473 |
-
if ( ! \is_wp_error( $activated ) ) {
|
474 |
-
\wp_send_json_success(
|
475 |
-
array(
|
476 |
-
'msg' => \esc_html__( 'Plugin installed & activated.', 'wp-mail-smtp' ),
|
477 |
-
'is_activated' => true,
|
478 |
-
'basename' => $plugin_basename,
|
479 |
-
)
|
480 |
-
);
|
481 |
-
} else {
|
482 |
-
\wp_send_json_success(
|
483 |
-
array(
|
484 |
-
'msg' => esc_html__( 'Plugin installed.', 'wp-mail-smtp' ),
|
485 |
-
'is_activated' => false,
|
486 |
-
'basename' => $plugin_basename,
|
487 |
-
)
|
488 |
-
);
|
489 |
-
}
|
490 |
-
}
|
491 |
-
|
492 |
-
\wp_send_json_error( $error );
|
493 |
-
}
|
494 |
-
|
495 |
-
/**
|
496 |
-
* Display a "Lite vs Pro" tab content.
|
497 |
-
*
|
498 |
-
* @since 1.5.0
|
499 |
-
*/
|
500 |
-
protected function display_versus() {
|
501 |
-
|
502 |
-
$license = \wp_mail_smtp()->get_license_type();
|
503 |
-
?>
|
504 |
-
|
505 |
-
<div class="wp-mail-smtp-admin-about-section wp-mail-smtp-admin-about-section-squashed">
|
506 |
-
<h1 class="centered">
|
507 |
-
<strong>
|
508 |
-
<?php
|
509 |
-
\printf(
|
510 |
-
/* translators: %s - plugin current license type. */
|
511 |
-
\esc_html__( '%s vs Pro', 'wp-mail-smtp' ),
|
512 |
-
\esc_html( \ucfirst( $license ) )
|
513 |
-
);
|
514 |
-
?>
|
515 |
-
</strong>
|
516 |
-
</h1>
|
517 |
-
|
518 |
-
<p class="centered <?php echo ( $license === 'pro' ? 'hidden' : '' ); ?>">
|
519 |
-
<?php esc_html_e( 'Get the most out of WP Mail SMTP by upgrading to Pro and unlocking all of the powerful features.', 'wp-mail-smtp' ); ?>
|
520 |
-
</p>
|
521 |
-
</div>
|
522 |
-
|
523 |
-
<div class="wp-mail-smtp-admin-about-section wp-mail-smtp-admin-about-section-squashed wp-mail-smtp-admin-about-section-hero wp-mail-smtp-admin-about-section-table">
|
524 |
-
|
525 |
-
<div class="wp-mail-smtp-admin-about-section-hero-main wp-mail-smtp-admin-columns">
|
526 |
-
<div class="wp-mail-smtp-admin-column-33">
|
527 |
-
<h3 class="no-margin">
|
528 |
-
<?php esc_html_e( 'Feature', 'wp-mail-smtp' ); ?>
|
529 |
-
</h3>
|
530 |
-
</div>
|
531 |
-
<div class="wp-mail-smtp-admin-column-33">
|
532 |
-
<h3 class="no-margin">
|
533 |
-
<?php echo esc_html( ucfirst( $license ) ); ?>
|
534 |
-
</h3>
|
535 |
-
</div>
|
536 |
-
<div class="wp-mail-smtp-admin-column-33">
|
537 |
-
<h3 class="no-margin">
|
538 |
-
<?php esc_html_e( 'Pro', 'wp-mail-smtp' ); ?>
|
539 |
-
</h3>
|
540 |
-
</div>
|
541 |
-
</div>
|
542 |
-
<div class="wp-mail-smtp-admin-about-section-hero-extra no-padding wp-mail-smtp-admin-columns">
|
543 |
-
|
544 |
-
<table>
|
545 |
-
<?php
|
546 |
-
foreach ( $this->get_license_features() as $slug => $name ) {
|
547 |
-
$current = $this->get_license_data( $slug, $license );
|
548 |
-
$pro = $this->get_license_data( $slug, 'pro' );
|
549 |
-
?>
|
550 |
-
<tr class="wp-mail-smtp-admin-columns">
|
551 |
-
<td class="wp-mail-smtp-admin-column-33">
|
552 |
-
<p><?php echo $name; ?></p>
|
553 |
-
</td>
|
554 |
-
<td class="wp-mail-smtp-admin-column-33">
|
555 |
-
<p class="features-<?php echo esc_attr( $current['status'] ); ?>">
|
556 |
-
<?php echo \implode( '<br>', $current['text'] ); ?>
|
557 |
-
</p>
|
558 |
-
</td>
|
559 |
-
<td class="wp-mail-smtp-admin-column-33">
|
560 |
-
<p class="features-full">
|
561 |
-
<?php echo \implode( '<br>', $pro['text'] ); ?>
|
562 |
-
</p>
|
563 |
-
</td>
|
564 |
-
</tr>
|
565 |
-
<?php
|
566 |
-
}
|
567 |
-
?>
|
568 |
-
</table>
|
569 |
-
|
570 |
-
</div>
|
571 |
-
|
572 |
-
</div>
|
573 |
-
|
574 |
-
<?php if ( 'lite' === $license ) : ?>
|
575 |
-
<div class="wp-mail-smtp-admin-about-section wp-mail-smtp-admin-about-section-hero">
|
576 |
-
<div class="wp-mail-smtp-admin-about-section-hero-main no-border">
|
577 |
-
<h3 class="call-to-action centered">
|
578 |
-
<a href="<?php echo esc_url( wp_mail_smtp()->get_upgrade_link( 'lite-vs-pro' ) ); ?>" target="_blank" rel="noopener noreferrer">
|
579 |
-
<?php \esc_html_e( 'Get WP Mail SMTP Pro Today and Unlock all of these Powerful Features', 'wp-mail-smtp' ); ?>
|
580 |
-
</a>
|
581 |
-
</h3>
|
582 |
-
|
583 |
-
<p class="centered">
|
584 |
-
<?php
|
585 |
-
echo \wp_kses(
|
586 |
-
\__( 'Bonus: WP Mail SMTP Lite users get <span class="price-off">20% off regular price</span>, automatically applied at checkout.', 'wp-mail-smtp' ),
|
587 |
-
array(
|
588 |
-
'span' => array(
|
589 |
-
'class' => array(),
|
590 |
-
),
|
591 |
-
)
|
592 |
-
);
|
593 |
-
?>
|
594 |
-
</p>
|
595 |
-
</div>
|
596 |
-
</div>
|
597 |
-
<?php endif; ?>
|
598 |
-
|
599 |
-
<?php
|
600 |
-
}
|
601 |
-
|
602 |
-
/**
|
603 |
-
* Get the list of features for all licenses.
|
604 |
-
*
|
605 |
-
* @since 1.5.0
|
606 |
-
*
|
607 |
-
* @return array
|
608 |
-
*/
|
609 |
-
private function get_license_features() {
|
610 |
-
|
611 |
-
return array(
|
612 |
-
'log' => \esc_html__( 'Email Log', 'wp-mail-smtp' ),
|
613 |
-
'control' => \esc_html__( 'Email Controls', 'wp-mail-smtp' ),
|
614 |
-
'mailers' => \esc_html__( 'Additional Mailers', 'wp-mail-smtp' ),
|
615 |
-
'support' => \esc_html__( 'Customer Support', 'wp-mail-smtp' ),
|
616 |
-
);
|
617 |
-
}
|
618 |
-
|
619 |
-
/**
|
620 |
-
* Get the array of data that compared the license data.
|
621 |
-
*
|
622 |
-
* @since 1.5.0
|
623 |
-
*
|
624 |
-
* @param string $feature Feature name.
|
625 |
-
* @param string $license License type to get data for.
|
626 |
-
*
|
627 |
-
* @return array|false
|
628 |
-
*/
|
629 |
-
private function get_license_data( $feature, $license ) {
|
630 |
-
|
631 |
-
$data = array(
|
632 |
-
'log' => array(
|
633 |
-
'lite' => array(
|
634 |
-
'status' => 'none',
|
635 |
-
'text' => array(
|
636 |
-
'<strong>' . esc_html__( 'Emails are not logged', 'wp-mail-smtp' ) . '</strong>',
|
637 |
-
),
|
638 |
-
),
|
639 |
-
'pro' => array(
|
640 |
-
'status' => 'full',
|
641 |
-
'text' => array(
|
642 |
-
'<strong>' . esc_html__( 'Complete Email Log management inside WordPress', 'wp-mail-smtp' ) . '</strong>',
|
643 |
-
),
|
644 |
-
),
|
645 |
-
),
|
646 |
-
'control' => array(
|
647 |
-
'lite' => array(
|
648 |
-
'status' => 'none',
|
649 |
-
'text' => array(
|
650 |
-
'<strong>' . esc_html__( 'No controls over whether default WordPress emails are sent', 'wp-mail-smtp' ) . '</strong>',
|
651 |
-
),
|
652 |
-
),
|
653 |
-
'pro' => array(
|
654 |
-
'status' => 'full',
|
655 |
-
'text' => array(
|
656 |
-
'<strong>' . esc_html__( 'Complete Email Controls management for most default WordPress emails', 'wp-mail-smtp' ) . '</strong>',
|
657 |
-
),
|
658 |
-
),
|
659 |
-
),
|
660 |
-
'mailers' => array(
|
661 |
-
'lite' => array(
|
662 |
-
'status' => 'none',
|
663 |
-
'text' => array(
|
664 |
-
'<strong>' . esc_html__( 'Only default list of mailers', 'wp-mail-smtp' ) . '</strong>',
|
665 |
-
),
|
666 |
-
),
|
667 |
-
'pro' => array(
|
668 |
-
'status' => 'full',
|
669 |
-
'text' => array(
|
670 |
-
'<strong>' . esc_html__( 'Additional mailers: Microsoft Outlook (with Office365 support) and Amazon SES', 'wp-mail-smtp' ) . '</strong>',
|
671 |
-
),
|
672 |
-
),
|
673 |
-
),
|
674 |
-
'support' => array(
|
675 |
-
'lite' => array(
|
676 |
-
'status' => 'none',
|
677 |
-
'text' => array(
|
678 |
-
'<strong>' . esc_html__( 'Limited Support', 'wp-mail-smtp' ) . '</strong>',
|
679 |
-
),
|
680 |
-
),
|
681 |
-
'pro' => array(
|
682 |
-
'status' => 'full',
|
683 |
-
'text' => array(
|
684 |
-
'<strong>' . esc_html__( 'Priority Support', 'wp-mail-smtp' ) . '</strong>',
|
685 |
-
),
|
686 |
-
),
|
687 |
-
),
|
688 |
-
);
|
689 |
-
|
690 |
-
// Wrong feature?
|
691 |
-
if ( ! isset( $data[ $feature ] ) ) {
|
692 |
-
return false;
|
693 |
-
}
|
694 |
-
|
695 |
-
// Wrong license type?
|
696 |
-
if ( ! isset( $data[ $feature ][ $license ] ) ) {
|
697 |
-
return false;
|
698 |
-
}
|
699 |
-
|
700 |
-
return $data[ $feature ][ $license ];
|
701 |
-
}
|
702 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Admin\Pages;
|
4 |
+
|
5 |
+
use WPMailSMTP\Admin\Area;
|
6 |
+
use WPMailSMTP\Admin\PageAbstract;
|
7 |
+
use WPMailSMTP\Admin\PluginsInstallSkin;
|
8 |
+
use WPMailSMTP\Admin\PluginsInstallUpgrader;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class About to display a page with About Us and Versus content.
|
12 |
+
*
|
13 |
+
* @since 1.5.0
|
14 |
+
*/
|
15 |
+
class About extends PageAbstract {
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @since 1.5.0
|
19 |
+
*
|
20 |
+
* @var string Slug of a page.
|
21 |
+
*/
|
22 |
+
protected $slug = 'about';
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @since 1.5.0
|
26 |
+
*
|
27 |
+
* @var array List of supported tabs.
|
28 |
+
*/
|
29 |
+
protected $tabs = array( 'about', 'versus' );
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Get the page/tab link.
|
33 |
+
*
|
34 |
+
* @since 1.5.0
|
35 |
+
*
|
36 |
+
* @param string $tab Tab to generate a link to.
|
37 |
+
*
|
38 |
+
* @return string
|
39 |
+
*/
|
40 |
+
public function get_link( $tab = '' ) {
|
41 |
+
|
42 |
+
return add_query_arg(
|
43 |
+
'tab',
|
44 |
+
$this->get_defined_tab( $tab ),
|
45 |
+
admin_url( 'admin.php?page=' . Area::SLUG . '-' . $this->slug )
|
46 |
+
);
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Get the current tab.
|
51 |
+
*
|
52 |
+
* @since 1.5.0
|
53 |
+
*
|
54 |
+
* @return string Current tab.
|
55 |
+
*/
|
56 |
+
public function get_current_tab() {
|
57 |
+
|
58 |
+
if ( empty( $_GET['tab'] ) ) { // phpcs:ignore
|
59 |
+
return $this->slug;
|
60 |
+
}
|
61 |
+
|
62 |
+
return $this->get_defined_tab( $_GET['tab'] ); // phpcs:ignore
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Get the defined or default tab.
|
67 |
+
*
|
68 |
+
* @since 1.5.0
|
69 |
+
*
|
70 |
+
* @param string $tab Tab to check.
|
71 |
+
*
|
72 |
+
* @return string Defined tab. Fallback to default one if it doesn't exist.
|
73 |
+
*/
|
74 |
+
protected function get_defined_tab( $tab ) {
|
75 |
+
|
76 |
+
$tab = \sanitize_key( $tab );
|
77 |
+
|
78 |
+
return \in_array( $tab, $this->tabs, true ) ? $tab : $this->slug;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Get label for a tab.
|
83 |
+
* Process only those that exists.
|
84 |
+
* Defaults to "About Us".
|
85 |
+
*
|
86 |
+
* @since 1.5.0
|
87 |
+
*
|
88 |
+
* @param string $tab Tab to get label for.
|
89 |
+
*
|
90 |
+
* @return string
|
91 |
+
*/
|
92 |
+
public function get_label( $tab = '' ) {
|
93 |
+
|
94 |
+
switch ( $this->get_defined_tab( $tab ) ) {
|
95 |
+
case 'versus':
|
96 |
+
$label = \sprintf(
|
97 |
+
/* translators: %s - plugin current license type. */
|
98 |
+
\esc_html__( '%s vs Pro', 'wp-mail-smtp' ),
|
99 |
+
\ucfirst( \wp_mail_smtp()->get_license_type() )
|
100 |
+
);
|
101 |
+
break;
|
102 |
+
|
103 |
+
case 'about':
|
104 |
+
default:
|
105 |
+
$label = \esc_html__( 'About Us', 'wp-mail-smtp' );
|
106 |
+
break;
|
107 |
+
}
|
108 |
+
|
109 |
+
return $label;
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* @inheritdoc
|
114 |
+
*/
|
115 |
+
public function get_title() {
|
116 |
+
return $this->get_label( $this->get_current_tab() );
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Display About page content based on the current tab.
|
121 |
+
*
|
122 |
+
* @since 1.5.0
|
123 |
+
*/
|
124 |
+
public function display() {
|
125 |
+
?>
|
126 |
+
|
127 |
+
<div class="wp-mail-smtp-page-title">
|
128 |
+
<a href="<?php echo \esc_url( $this->get_link() ); ?>" class="tab <?php echo $this->get_current_tab() === 'about' ? 'active' : ''; ?>">
|
129 |
+
<?php echo \esc_html( $this->get_label( 'about' ) ); ?>
|
130 |
+
</a>
|
131 |
+
|
132 |
+
<?php if ( \wp_mail_smtp()->get_license_type() === 'lite' ) : ?>
|
133 |
+
<a href="<?php echo \esc_url( $this->get_link( 'versus' ) ); ?>" class="tab <?php echo $this->get_current_tab() === 'versus' ? 'active' : ''; ?>">
|
134 |
+
<?php echo \esc_html( $this->get_label( 'versus' ) ); ?>
|
135 |
+
</a>
|
136 |
+
<?php endif; ?>
|
137 |
+
</div>
|
138 |
+
|
139 |
+
<div class="wp-mail-smtp-page-content">
|
140 |
+
<h1 class="screen-reader-text">
|
141 |
+
<?php echo \esc_html( $this->get_label( $this->get_current_tab() ) ); ?>
|
142 |
+
</h1>
|
143 |
+
|
144 |
+
<?php
|
145 |
+
$callback = 'display_' . $this->get_current_tab();
|
146 |
+
|
147 |
+
if ( \method_exists( $this, $callback ) ) {
|
148 |
+
$this->{$callback}();
|
149 |
+
} else {
|
150 |
+
$this->display_about();
|
151 |
+
}
|
152 |
+
?>
|
153 |
+
</div>
|
154 |
+
|
155 |
+
<?php
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Display an "About Us" tab content.
|
160 |
+
*
|
161 |
+
* @since 1.5.0
|
162 |
+
*/
|
163 |
+
protected function display_about() {
|
164 |
+
?>
|
165 |
+
|
166 |
+
<div class="wp-mail-smtp-admin-about-section wp-mail-smtp-admin-columns">
|
167 |
+
|
168 |
+
<div class="wp-mail-smtp-admin-column-60">
|
169 |
+
<h3>
|
170 |
+
<?php esc_html_e( 'Hello and welcome to WP Mail SMTP, the easiest and most popular WordPress SMTP plugin. We build software that helps your site reliably deliver emails every time.', 'wp-mail-smtp' ); ?>
|
171 |
+
</h3>
|
172 |
+
|
173 |
+
<p>
|
174 |
+
<?php esc_html_e( 'Email deliverability has been a well-documented problem for all WordPress websites. However as WPForms grew, we became more aware of this painful issue that affects our users and the larger WordPress community. So we decided to solve this problem and make a solution that\'s beginner friendly.', 'wp-mail-smtp' ); ?>
|
175 |
+
</p>
|
176 |
+
<p>
|
177 |
+
<?php esc_html_e( 'Our goal is to make reliable email deliverability easy for WordPress.', 'wp-mail-smtp' ); ?>
|
178 |
+
</p>
|
179 |
+
<p>
|
180 |
+
<?php
|
181 |
+
printf(
|
182 |
+
wp_kses(
|
183 |
+
/* translators: %1$s - WPBeginner URL, %2$s - OptinMonster URL, %3$s - MonsterInsights URL. */
|
184 |
+
__( 'WP Mail SMTP is brought to you by the same team that\'s behind the most user friendly WordPress forms, <a href="%1$s" target="_blank" rel="noopener noreferrer">WPForms</a>, the largest WordPress resource site, <a href="%2$s" target="_blank" rel="noopener noreferrer">WPBeginner</a>, the most popular lead-generation software, <a href="%3$s" target="_blank" rel="noopener noreferrer">OptinMonster</a>, and the best WordPress analytics plugin, <a href="%4$s" target="_blank" rel="noopener noreferrer">MonsterInsights</a>.', 'wp-mail-smtp' ),
|
185 |
+
array(
|
186 |
+
'a' => array(
|
187 |
+
'href' => array(),
|
188 |
+
'rel' => array(),
|
189 |
+
'target' => array(),
|
190 |
+
),
|
191 |
+
)
|
192 |
+
),
|
193 |
+
'https://wpforms.com/?utm_source=wpmailsmtpplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpmailsmtp',
|
194 |
+
'https://www.wpbeginner.com/?utm_source=wpmailsmtpplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpmailsmtp',
|
195 |
+
'https://optinmonster.com/?utm_source=wpmailsmtpplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpmailsmtp',
|
196 |
+
'https://www.monsterinsights.com/?utm_source=wpmailsmtpplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpmailsmtp'
|
197 |
+
);
|
198 |
+
?>
|
199 |
+
</p>
|
200 |
+
<p>
|
201 |
+
<?php esc_html_e( 'Yup, we know a thing or two about building awesome products that customers love.', 'wp-mail-smtp' ); ?>
|
202 |
+
</p>
|
203 |
+
</div>
|
204 |
+
|
205 |
+
<div class="wp-mail-smtp-admin-column-40 wp-mail-smtp-admin-column-last">
|
206 |
+
<figure>
|
207 |
+
<img src="<?php echo esc_url( wp_mail_smtp()->assets_url . '/images/about/team.jpg' ); ?>" alt="<?php esc_attr_e( 'The WPForms Team photo', 'wp-mail-smtp' ); ?>">
|
208 |
+
<figcaption>
|
209 |
+
<?php esc_html_e( 'The WPForms Team', 'wp-mail-smtp' ); ?>
|
210 |
+
</figcaption>
|
211 |
+
</figure>
|
212 |
+
</div>
|
213 |
+
|
214 |
+
</div>
|
215 |
+
|
216 |
+
<div class="wp-mail-smtp-admin-about-plugins">
|
217 |
+
<div class="plugins-container">
|
218 |
+
<?php
|
219 |
+
foreach ( $this->get_am_plugins() as $key => $plugin ) :
|
220 |
+
$is_url_external = false;
|
221 |
+
|
222 |
+
$data = $this->get_about_plugins_data( $plugin );
|
223 |
+
|
224 |
+
if ( isset( $plugin['pro'] ) && \array_key_exists( $plugin['pro']['path'], \get_plugins() ) ) {
|
225 |
+
$is_url_external = true;
|
226 |
+
$plugin = $plugin['pro'];
|
227 |
+
|
228 |
+
$data = array_merge( $data, $this->get_about_plugins_data( $plugin, true ) );
|
229 |
+
}
|
230 |
+
|
231 |
+
?>
|
232 |
+
<div class="plugin-container">
|
233 |
+
<div class="plugin-item">
|
234 |
+
<div class="details wp-mail-smtp-clear">
|
235 |
+
<img src="<?php echo \esc_url( $plugin['icon'] ); ?>">
|
236 |
+
<h5 class="plugin-name">
|
237 |
+
<?php echo $plugin['name']; ?>
|
238 |
+
</h5>
|
239 |
+
<p class="plugin-desc">
|
240 |
+
<?php echo $plugin['desc']; ?>
|
241 |
+
</p>
|
242 |
+
</div>
|
243 |
+
<div class="actions wp-mail-smtp-clear">
|
244 |
+
<div class="status">
|
245 |
+
<strong>
|
246 |
+
<?php
|
247 |
+
\printf(
|
248 |
+
/* translators: %s - status HTML text. */
|
249 |
+
\esc_html__( 'Status: %s', 'wp-mail-smtp' ),
|
250 |
+
'<span class="status-label ' . $data['status_class'] . '">' . $data['status_text'] . '</span>'
|
251 |
+
);
|
252 |
+
?>
|
253 |
+
</strong>
|
254 |
+
</div>
|
255 |
+
<div class="action-button">
|
256 |
+
<?php
|
257 |
+
$go_to_class = '';
|
258 |
+
if ( $is_url_external && $data['status_class'] === 'status-download' ) {
|
259 |
+
$go_to_class = 'go_to';
|
260 |
+
}
|
261 |
+
?>
|
262 |
+
<a href="<?php echo \esc_url( $plugin['url'] ); ?>"
|
263 |
+
class="<?php echo \esc_attr( $data['action_class'] ); ?> <?php echo $go_to_class; ?>"
|
264 |
+
data-plugin="<?php echo $data['plugin_src']; ?>">
|
265 |
+
<?php echo $data['action_text']; ?>
|
266 |
+
</a>
|
267 |
+
</div>
|
268 |
+
</div>
|
269 |
+
</div>
|
270 |
+
</div>
|
271 |
+
<?php endforeach; ?>
|
272 |
+
</div>
|
273 |
+
</div>
|
274 |
+
|
275 |
+
<?php
|
276 |
+
}
|
277 |
+
|
278 |
+
/**
|
279 |
+
* Generate all the required CSS classed and labels to be used in rendering.
|
280 |
+
*
|
281 |
+
* @since 1.5.0
|
282 |
+
*
|
283 |
+
* @param array $plugin
|
284 |
+
* @param bool $is_pro
|
285 |
+
*
|
286 |
+
* @return mixed
|
287 |
+
*/
|
288 |
+
protected function get_about_plugins_data( $plugin, $is_pro = false ) {
|
289 |
+
|
290 |
+
$data = array();
|
291 |
+
|
292 |
+
if ( \array_key_exists( $plugin['path'], \get_plugins() ) ) {
|
293 |
+
if ( \is_plugin_active( $plugin['path'] ) ) {
|
294 |
+
// Status text/status.
|
295 |
+
$data['status_class'] = 'status-active';
|
296 |
+
$data['status_text'] = \esc_html__( 'Active', 'wp-mail-smtp' );
|
297 |
+
// Button text/status.
|
298 |
+
$data['action_class'] = $data['status_class'] . ' button button-secondary disabled';
|
299 |
+
$data['action_text'] = \esc_html__( 'Activated', 'wp-mail-smtp' );
|
300 |
+
$data['plugin_src'] = \esc_attr( $plugin['path'] );
|
301 |
+
} else {
|
302 |
+
// Status text/status.
|
303 |
+
$data['status_class'] = 'status-inactive';
|
304 |
+
$data['status_text'] = \esc_html__( 'Inactive', 'wp-mail-smtp' );
|
305 |
+
// Button text/status.
|
306 |
+
$data['action_class'] = $data['status_class'] . ' button button-secondary';
|
307 |
+
$data['action_text'] = \esc_html__( 'Activate', 'wp-mail-smtp' );
|
308 |
+
$data['plugin_src'] = \esc_attr( $plugin['path'] );
|
309 |
+
}
|
310 |
+
} else {
|
311 |
+
if ( ! $is_pro ) {
|
312 |
+
// Doesn't exist, install.
|
313 |
+
// Status text/status.
|
314 |
+
$data['status_class'] = 'status-download';
|
315 |
+
$data['status_text'] = \esc_html__( 'Not Installed', 'wp-mail-smtp' );
|
316 |
+
// Button text/status.
|
317 |
+
$data['action_class'] = $data['status_class'] . ' button button-primary';
|
318 |
+
$data['action_text'] = \esc_html__( 'Install Plugin', 'wp-mail-smtp' );
|
319 |
+
$data['plugin_src'] = \esc_url( $plugin['url'] );
|
320 |
+
}
|
321 |
+
}
|
322 |
+
|
323 |
+
return $data;
|
324 |
+
}
|
325 |
+
|
326 |
+
/**
|
327 |
+
* List of AM plugins that we propose to install.
|
328 |
+
*
|
329 |
+
* @since 1.5.0
|
330 |
+
*
|
331 |
+
* @return array
|
332 |
+
*/
|
333 |
+
private function get_am_plugins() {
|
334 |
+
|
335 |
+
$data = array(
|
336 |
+
'mi' => array(
|
337 |
+
'path' => 'google-analytics-for-wordpress/googleanalytics.php',
|
338 |
+
'icon' => \wp_mail_smtp()->assets_url . '/images/about/plugin-mi.png',
|
339 |
+
'name' => \esc_html__( 'MonsterInsights', 'wp-mail-smtp' ),
|
340 |
+
'desc' => \esc_html__( 'MonsterInsights makes it “effortless” to properly connect your WordPress site with Google Analytics, so you can start making data-driven decisions to grow your business.', 'wp-mail-smtp' ),
|
341 |
+
'url' => 'https://downloads.wordpress.org/plugin/google-analytics-for-wordpress.zip',
|
342 |
+
'pro' => array(
|
343 |
+
'path' => 'google-analytics-premium/googleanalytics-premium.php',
|
344 |
+
'icon' => \wp_mail_smtp()->assets_url . '/images/about/plugin-mi.png',
|
345 |
+
'name' => \esc_html__( 'MonsterInsights Pro', 'wp-mail-smtp' ),
|
346 |
+
'desc' => \esc_html__( 'MonsterInsights makes it “effortless” to properly connect your WordPress site with Google Analytics, so you can start making data-driven decisions to grow your business.', 'wp-mail-smtp' ),
|
347 |
+
'url' => 'https://www.monsterinsights.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
|
348 |
+
),
|
349 |
+
),
|
350 |
+
'om' => array(
|
351 |
+
'path' => 'optinmonster/optin-monster-wp-api.php',
|
352 |
+
'icon' => \wp_mail_smtp()->assets_url . '/images/about/plugin-om.png',
|
353 |
+
'name' => \esc_html__( 'OptinMonster', 'wp-mail-smtp' ),
|
354 |
+
'desc' => \esc_html__( 'Our high-converting optin forms like Exit-Intent® popups, Fullscreen Welcome Mats, and Scroll boxes help you dramatically boost conversions and get more email subscribers.', 'wp-mail-smtp' ),
|
355 |
+
'url' => 'https://downloads.wordpress.org/plugin/optinmonster.zip',
|
356 |
+
),
|
357 |
+
'wpforms' => array(
|
358 |
+
'path' => 'wpforms-lite/wpforms.php',
|
359 |
+
'icon' => \wp_mail_smtp()->assets_url . '/images/about/plugin-wpf.png',
|
360 |
+
'name' => \esc_html__( 'Contact Forms by WPForms', 'wp-mail-smtp' ),
|
361 |
+
'desc' => \esc_html__( 'The best WordPress contact form plugin. Drag & Drop online form builder that helps you create beautiful contact forms with just a few clicks.', 'wp-mail-smtp' ),
|
362 |
+
'url' => 'https://downloads.wordpress.org/plugin/wpforms-lite.zip',
|
363 |
+
'pro' => array(
|
364 |
+
'path' => 'wpforms/wpforms.php',
|
365 |
+
'icon' => \wp_mail_smtp()->assets_url . '/images/about/plugin-wpf.png',
|
366 |
+
'name' => \esc_html__( 'WPForms Pro', 'wp-mail-smtp' ),
|
367 |
+
'desc' => \esc_html__( 'The best WordPress contact form plugin. Drag & Drop online form builder that helps you create beautiful contact forms with just a few clicks.', 'wp-mail-smtp' ),
|
368 |
+
'url' => 'https://wpforms.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
|
369 |
+
),
|
370 |
+
),
|
371 |
+
);
|
372 |
+
|
373 |
+
return $data;
|
374 |
+
}
|
375 |
+
|
376 |
+
/**
|
377 |
+
* Active the given plugin.
|
378 |
+
*
|
379 |
+
* @since 1.5.0
|
380 |
+
*/
|
381 |
+
public static function ajax_plugin_activate() {
|
382 |
+
|
383 |
+
// Run a security check.
|
384 |
+
\check_ajax_referer( 'wp-mail-smtp-about', 'nonce' );
|
385 |
+
|
386 |
+
$error = \esc_html__( 'Could not activate the plugin. Please activate it from the Plugins page.', 'wp-mail-smtp' );
|
387 |
+
|
388 |
+
// Check for permissions.
|
389 |
+
if ( ! \current_user_can( 'activate_plugins' ) ) {
|
390 |
+
\wp_send_json_error( $error );
|
391 |
+
}
|
392 |
+
|
393 |
+
if ( isset( $_POST['plugin'] ) ) {
|
394 |
+
|
395 |
+
$activate = \activate_plugins( $_POST['plugin'] ); // phpcs:ignore
|
396 |
+
|
397 |
+
if ( ! \is_wp_error( $activate ) ) {
|
398 |
+
\wp_send_json_success( esc_html__( 'Plugin activated.', 'wp-mail-smtp' ) );
|
399 |
+
}
|
400 |
+
}
|
401 |
+
|
402 |
+
\wp_send_json_error( $error );
|
403 |
+
}
|
404 |
+
|
405 |
+
/**
|
406 |
+
* Install & activate the given plugin.
|
407 |
+
*
|
408 |
+
* @since 1.5.0
|
409 |
+
*/
|
410 |
+
public static function ajax_plugin_install() {
|
411 |
+
|
412 |
+
// Run a security check.
|
413 |
+
\check_ajax_referer( 'wp-mail-smtp-about', 'nonce' );
|
414 |
+
|
415 |
+
$error = \esc_html__( 'Could not install the plugin.', 'wp-mail-smtp' );
|
416 |
+
|
417 |
+
// Check for permissions.
|
418 |
+
if ( ! \current_user_can( 'activate_plugins' ) ) {
|
419 |
+
\wp_send_json_error( $error );
|
420 |
+
}
|
421 |
+
|
422 |
+
if ( empty( $_POST['plugin'] ) ) {
|
423 |
+
\wp_send_json_error();
|
424 |
+
}
|
425 |
+
|
426 |
+
// Set the current screen to avoid undefined notices.
|
427 |
+
\set_current_screen( 'wp-mail-smtp_page_wp-mail-smtp-about' );
|
428 |
+
|
429 |
+
// Prepare variables.
|
430 |
+
$url = \esc_url_raw(
|
431 |
+
\add_query_arg(
|
432 |
+
array(
|
433 |
+
'page' => 'wp-mail-smtp-about',
|
434 |
+
),
|
435 |
+
\admin_url( 'admin.php' )
|
436 |
+
)
|
437 |
+
);
|
438 |
+
|
439 |
+
$creds = \request_filesystem_credentials( $url, '', false, false, null );
|
440 |
+
|
441 |
+
// Check for file system permissions.
|
442 |
+
if ( false === $creds ) {
|
443 |
+
\wp_send_json_error( $error );
|
444 |
+
}
|
445 |
+
|
446 |
+
if ( ! \WP_Filesystem( $creds ) ) {
|
447 |
+
\wp_send_json_error( $error );
|
448 |
+
}
|
449 |
+
|
450 |
+
// Do not allow WordPress to search/download translations, as this will break JS output.
|
451 |
+
\remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
|
452 |
+
|
453 |
+
// Create the plugin upgrader with our custom skin.
|
454 |
+
$installer = new PluginsInstallUpgrader( new PluginsInstallSkin() );
|
455 |
+
|
456 |
+
// Error check.
|
457 |
+
if ( ! \method_exists( $installer, 'install' ) || empty( $_POST['plugin'] ) ) {
|
458 |
+
\wp_send_json_error( $error );
|
459 |
+
}
|
460 |
+
|
461 |
+
$installer->install( $_POST['plugin'] ); // phpcs:ignore
|
462 |
+
|
463 |
+
// Flush the cache and return the newly installed plugin basename.
|
464 |
+
\wp_cache_flush();
|
465 |
+
|
466 |
+
if ( $installer->plugin_info() ) {
|
467 |
+
|
468 |
+
$plugin_basename = $installer->plugin_info();
|
469 |
+
|
470 |
+
// Activate the plugin silently.
|
471 |
+
$activated = \activate_plugin( $plugin_basename );
|
472 |
+
|
473 |
+
if ( ! \is_wp_error( $activated ) ) {
|
474 |
+
\wp_send_json_success(
|
475 |
+
array(
|
476 |
+
'msg' => \esc_html__( 'Plugin installed & activated.', 'wp-mail-smtp' ),
|
477 |
+
'is_activated' => true,
|
478 |
+
'basename' => $plugin_basename,
|
479 |
+
)
|
480 |
+
);
|
481 |
+
} else {
|
482 |
+
\wp_send_json_success(
|
483 |
+
array(
|
484 |
+
'msg' => esc_html__( 'Plugin installed.', 'wp-mail-smtp' ),
|
485 |
+
'is_activated' => false,
|
486 |
+
'basename' => $plugin_basename,
|
487 |
+
)
|
488 |
+
);
|
489 |
+
}
|
490 |
+
}
|
491 |
+
|
492 |
+
\wp_send_json_error( $error );
|
493 |
+
}
|
494 |
+
|
495 |
+
/**
|
496 |
+
* Display a "Lite vs Pro" tab content.
|
497 |
+
*
|
498 |
+
* @since 1.5.0
|
499 |
+
*/
|
500 |
+
protected function display_versus() {
|
501 |
+
|
502 |
+
$license = \wp_mail_smtp()->get_license_type();
|
503 |
+
?>
|
504 |
+
|
505 |
+
<div class="wp-mail-smtp-admin-about-section wp-mail-smtp-admin-about-section-squashed">
|
506 |
+
<h1 class="centered">
|
507 |
+
<strong>
|
508 |
+
<?php
|
509 |
+
\printf(
|
510 |
+
/* translators: %s - plugin current license type. */
|
511 |
+
\esc_html__( '%s vs Pro', 'wp-mail-smtp' ),
|
512 |
+
\esc_html( \ucfirst( $license ) )
|
513 |
+
);
|
514 |
+
?>
|
515 |
+
</strong>
|
516 |
+
</h1>
|
517 |
+
|
518 |
+
<p class="centered <?php echo ( $license === 'pro' ? 'hidden' : '' ); ?>">
|
519 |
+
<?php esc_html_e( 'Get the most out of WP Mail SMTP by upgrading to Pro and unlocking all of the powerful features.', 'wp-mail-smtp' ); ?>
|
520 |
+
</p>
|
521 |
+
</div>
|
522 |
+
|
523 |
+
<div class="wp-mail-smtp-admin-about-section wp-mail-smtp-admin-about-section-squashed wp-mail-smtp-admin-about-section-hero wp-mail-smtp-admin-about-section-table">
|
524 |
+
|
525 |
+
<div class="wp-mail-smtp-admin-about-section-hero-main wp-mail-smtp-admin-columns">
|
526 |
+
<div class="wp-mail-smtp-admin-column-33">
|
527 |
+
<h3 class="no-margin">
|
528 |
+
<?php esc_html_e( 'Feature', 'wp-mail-smtp' ); ?>
|
529 |
+
</h3>
|
530 |
+
</div>
|
531 |
+
<div class="wp-mail-smtp-admin-column-33">
|
532 |
+
<h3 class="no-margin">
|
533 |
+
<?php echo esc_html( ucfirst( $license ) ); ?>
|
534 |
+
</h3>
|
535 |
+
</div>
|
536 |
+
<div class="wp-mail-smtp-admin-column-33">
|
537 |
+
<h3 class="no-margin">
|
538 |
+
<?php esc_html_e( 'Pro', 'wp-mail-smtp' ); ?>
|
539 |
+
</h3>
|
540 |
+
</div>
|
541 |
+
</div>
|
542 |
+
<div class="wp-mail-smtp-admin-about-section-hero-extra no-padding wp-mail-smtp-admin-columns">
|
543 |
+
|
544 |
+
<table>
|
545 |
+
<?php
|
546 |
+
foreach ( $this->get_license_features() as $slug => $name ) {
|
547 |
+
$current = $this->get_license_data( $slug, $license );
|
548 |
+
$pro = $this->get_license_data( $slug, 'pro' );
|
549 |
+
?>
|
550 |
+
<tr class="wp-mail-smtp-admin-columns">
|
551 |
+
<td class="wp-mail-smtp-admin-column-33">
|
552 |
+
<p><?php echo $name; ?></p>
|
553 |
+
</td>
|
554 |
+
<td class="wp-mail-smtp-admin-column-33">
|
555 |
+
<p class="features-<?php echo esc_attr( $current['status'] ); ?>">
|
556 |
+
<?php echo \implode( '<br>', $current['text'] ); ?>
|
557 |
+
</p>
|
558 |
+
</td>
|
559 |
+
<td class="wp-mail-smtp-admin-column-33">
|
560 |
+
<p class="features-full">
|
561 |
+
<?php echo \implode( '<br>', $pro['text'] ); ?>
|
562 |
+
</p>
|
563 |
+
</td>
|
564 |
+
</tr>
|
565 |
+
<?php
|
566 |
+
}
|
567 |
+
?>
|
568 |
+
</table>
|
569 |
+
|
570 |
+
</div>
|
571 |
+
|
572 |
+
</div>
|
573 |
+
|
574 |
+
<?php if ( 'lite' === $license ) : ?>
|
575 |
+
<div class="wp-mail-smtp-admin-about-section wp-mail-smtp-admin-about-section-hero">
|
576 |
+
<div class="wp-mail-smtp-admin-about-section-hero-main no-border">
|
577 |
+
<h3 class="call-to-action centered">
|
578 |
+
<a href="<?php echo esc_url( wp_mail_smtp()->get_upgrade_link( 'lite-vs-pro' ) ); ?>" target="_blank" rel="noopener noreferrer">
|
579 |
+
<?php \esc_html_e( 'Get WP Mail SMTP Pro Today and Unlock all of these Powerful Features', 'wp-mail-smtp' ); ?>
|
580 |
+
</a>
|
581 |
+
</h3>
|
582 |
+
|
583 |
+
<p class="centered">
|
584 |
+
<?php
|
585 |
+
echo \wp_kses(
|
586 |
+
\__( 'Bonus: WP Mail SMTP Lite users get <span class="price-off">20% off regular price</span>, automatically applied at checkout.', 'wp-mail-smtp' ),
|
587 |
+
array(
|
588 |
+
'span' => array(
|
589 |
+
'class' => array(),
|
590 |
+
),
|
591 |
+
)
|
592 |
+
);
|
593 |
+
?>
|
594 |
+
</p>
|
595 |
+
</div>
|
596 |
+
</div>
|
597 |
+
<?php endif; ?>
|
598 |
+
|
599 |
+
<?php
|
600 |
+
}
|
601 |
+
|
602 |
+
/**
|
603 |
+
* Get the list of features for all licenses.
|
604 |
+
*
|
605 |
+
* @since 1.5.0
|
606 |
+
*
|
607 |
+
* @return array
|
608 |
+
*/
|
609 |
+
private function get_license_features() {
|
610 |
+
|
611 |
+
return array(
|
612 |
+
'log' => \esc_html__( 'Email Log', 'wp-mail-smtp' ),
|
613 |
+
'control' => \esc_html__( 'Email Controls', 'wp-mail-smtp' ),
|
614 |
+
'mailers' => \esc_html__( 'Additional Mailers', 'wp-mail-smtp' ),
|
615 |
+
'support' => \esc_html__( 'Customer Support', 'wp-mail-smtp' ),
|
616 |
+
);
|
617 |
+
}
|
618 |
+
|
619 |
+
/**
|
620 |
+
* Get the array of data that compared the license data.
|
621 |
+
*
|
622 |
+
* @since 1.5.0
|
623 |
+
*
|
624 |
+
* @param string $feature Feature name.
|
625 |
+
* @param string $license License type to get data for.
|
626 |
+
*
|
627 |
+
* @return array|false
|
628 |
+
*/
|
629 |
+
private function get_license_data( $feature, $license ) {
|
630 |
+
|
631 |
+
$data = array(
|
632 |
+
'log' => array(
|
633 |
+
'lite' => array(
|
634 |
+
'status' => 'none',
|
635 |
+
'text' => array(
|
636 |
+
'<strong>' . esc_html__( 'Emails are not logged', 'wp-mail-smtp' ) . '</strong>',
|
637 |
+
),
|
638 |
+
),
|
639 |
+
'pro' => array(
|
640 |
+
'status' => 'full',
|
641 |
+
'text' => array(
|
642 |
+
'<strong>' . esc_html__( 'Complete Email Log management inside WordPress', 'wp-mail-smtp' ) . '</strong>',
|
643 |
+
),
|
644 |
+
),
|
645 |
+
),
|
646 |
+
'control' => array(
|
647 |
+
'lite' => array(
|
648 |
+
'status' => 'none',
|
649 |
+
'text' => array(
|
650 |
+
'<strong>' . esc_html__( 'No controls over whether default WordPress emails are sent', 'wp-mail-smtp' ) . '</strong>',
|
651 |
+
),
|
652 |
+
),
|
653 |
+
'pro' => array(
|
654 |
+
'status' => 'full',
|
655 |
+
'text' => array(
|
656 |
+
'<strong>' . esc_html__( 'Complete Email Controls management for most default WordPress emails', 'wp-mail-smtp' ) . '</strong>',
|
657 |
+
),
|
658 |
+
),
|
659 |
+
),
|
660 |
+
'mailers' => array(
|
661 |
+
'lite' => array(
|
662 |
+
'status' => 'none',
|
663 |
+
'text' => array(
|
664 |
+
'<strong>' . esc_html__( 'Only default list of mailers', 'wp-mail-smtp' ) . '</strong>',
|
665 |
+
),
|
666 |
+
),
|
667 |
+
'pro' => array(
|
668 |
+
'status' => 'full',
|
669 |
+
'text' => array(
|
670 |
+
'<strong>' . esc_html__( 'Additional mailers: Microsoft Outlook (with Office365 support) and Amazon SES', 'wp-mail-smtp' ) . '</strong>',
|
671 |
+
),
|
672 |
+
),
|
673 |
+
),
|
674 |
+
'support' => array(
|
675 |
+
'lite' => array(
|
676 |
+
'status' => 'none',
|
677 |
+
'text' => array(
|
678 |
+
'<strong>' . esc_html__( 'Limited Support', 'wp-mail-smtp' ) . '</strong>',
|
679 |
+
),
|
680 |
+
),
|
681 |
+
'pro' => array(
|
682 |
+
'status' => 'full',
|
683 |
+
'text' => array(
|
684 |
+
'<strong>' . esc_html__( 'Priority Support', 'wp-mail-smtp' ) . '</strong>',
|
685 |
+
),
|
686 |
+
),
|
687 |
+
),
|
688 |
+
);
|
689 |
+
|
690 |
+
// Wrong feature?
|
691 |
+
if ( ! isset( $data[ $feature ] ) ) {
|
692 |
+
return false;
|
693 |
+
}
|
694 |
+
|
695 |
+
// Wrong license type?
|
696 |
+
if ( ! isset( $data[ $feature ][ $license ] ) ) {
|
697 |
+
return false;
|
698 |
+
}
|
699 |
+
|
700 |
+
return $data[ $feature ][ $license ];
|
701 |
+
}
|
702 |
+
}
|
src/Admin/Pages/SettingsTab.php
CHANGED
@@ -1,537 +1,546 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Admin\Pages;
|
4 |
-
|
5 |
-
use WPMailSMTP\Admin\PageAbstract;
|
6 |
-
use WPMailSMTP\Debug;
|
7 |
-
use WPMailSMTP\Options;
|
8 |
-
use WPMailSMTP\WP;
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Class SettingsTab is part of Area, displays general settings of the plugin.
|
12 |
-
*
|
13 |
-
* @since 1.0.0
|
14 |
-
*/
|
15 |
-
class SettingsTab extends PageAbstract {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Settings constructor.
|
19 |
-
*
|
20 |
-
* @since 1.5.0
|
21 |
-
*/
|
22 |
-
public function __construct() {
|
23 |
-
|
24 |
-
add_action( 'wp_mail_smtp_admin_pages_settings_license_key', array( __CLASS__, 'display_license_key_field_content' ) );
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @var string Slug of a tab.
|
29 |
-
*/
|
30 |
-
protected $slug = 'settings';
|
31 |
-
|
32 |
-
/**
|
33 |
-
* @inheritdoc
|
34 |
-
*/
|
35 |
-
public function get_label() {
|
36 |
-
return esc_html__( 'General', 'wp-mail-smtp' );
|
37 |
-
}
|
38 |
-
|
39 |
-
/**
|
40 |
-
* @inheritdoc
|
41 |
-
*/
|
42 |
-
public function get_title() {
|
43 |
-
return $this->get_label();
|
44 |
-
}
|
45 |
-
|
46 |
-
/**
|
47 |
-
* @inheritdoc
|
48 |
-
*/
|
49 |
-
public function display() {
|
50 |
-
|
51 |
-
$options = new Options();
|
52 |
-
$mailer = $options->get( 'mail', 'mailer' );
|
53 |
-
|
54 |
-
$disabled_email = 'gmail' === $mailer || 'outlook' === $mailer ? 'disabled' : '';
|
55 |
-
$disabled_name = 'outlook' === $mailer ? 'disabled' : '';
|
56 |
-
?>
|
57 |
-
|
58 |
-
<form method="POST" action="" autocomplete="off">
|
59 |
-
<?php $this->wp_nonce_field(); ?>
|
60 |
-
|
61 |
-
<!-- License Section Title -->
|
62 |
-
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading" id="wp-mail-smtp-setting-row-license-heading">
|
63 |
-
<div class="wp-mail-smtp-setting-field">
|
64 |
-
<h2><?php esc_html_e( 'License', 'wp-mail-smtp' ); ?></h2>
|
65 |
-
|
66 |
-
<p class="desc">
|
67 |
-
<?php esc_html_e( 'Your license key provides access to updates and support.', 'wp-mail-smtp' ); ?>
|
68 |
-
</p>
|
69 |
-
</div>
|
70 |
-
</div>
|
71 |
-
|
72 |
-
<!-- License Key -->
|
73 |
-
<div id="wp-mail-smtp-setting-row-license_key" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-license_key wp-mail-smtp-clear">
|
74 |
-
<div class="wp-mail-smtp-setting-label">
|
75 |
-
<label for="wp-mail-smtp-setting-license_key"><?php esc_html_e( 'License Key', 'wp-mail-smtp' ); ?></label>
|
76 |
-
</div>
|
77 |
-
<div class="wp-mail-smtp-setting-field">
|
78 |
-
<?php do_action( 'wp_mail_smtp_admin_pages_settings_license_key', $options ); ?>
|
79 |
-
</div>
|
80 |
-
</div>
|
81 |
-
|
82 |
-
<!-- Mail Section Title -->
|
83 |
-
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading no-desc" id="wp-mail-smtp-setting-row-email-heading">
|
84 |
-
<div class="wp-mail-smtp-setting-field">
|
85 |
-
<h2><?php esc_html_e( 'Mail', 'wp-mail-smtp' ); ?></h2>
|
86 |
-
</div>
|
87 |
-
</div>
|
88 |
-
|
89 |
-
<!-- From Email -->
|
90 |
-
<div id="wp-mail-smtp-setting-row-from_email" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-email wp-mail-smtp-clear">
|
91 |
-
<div class="wp-mail-smtp-setting-label">
|
92 |
-
<label for="wp-mail-smtp-setting-from_email"><?php esc_html_e( 'From Email', 'wp-mail-smtp' ); ?></label>
|
93 |
-
</div>
|
94 |
-
<div class="wp-mail-smtp-setting-field">
|
95 |
-
<input name="wp-mail-smtp[mail][from_email]" type="email"
|
96 |
-
value="<?php echo esc_attr( $options->get( 'mail', 'from_email' ) ); ?>"
|
97 |
-
<?php echo $options->is_const_defined( 'mail', 'from_email' ) || ! empty( $disabled_email ) ? 'disabled' : ''; ?>
|
98 |
-
id="wp-mail-smtp-setting-from_email" spellcheck="false"
|
99 |
-
placeholder="<?php echo esc_attr( wp_mail_smtp()->get_processor()->get_default_email() ); ?>">
|
100 |
-
|
101 |
-
<?php if ( empty( $disabled_email ) ) : ?>
|
102 |
-
<p class="desc">
|
103 |
-
<?php esc_html_e( 'The email address which emails are sent from.', 'wp-mail-smtp' ); ?><br/>
|
104 |
-
<?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' ); ?>
|
105 |
-
</p>
|
106 |
-
<p class="desc">
|
107 |
-
<?php esc_html_e( 'Please note that other plugins can change this, to prevent this use the setting below.', 'wp-mail-smtp' ); ?>
|
108 |
-
</p>
|
109 |
-
<?php endif; ?>
|
110 |
-
|
111 |
-
<hr class="wp-mail-smtp-setting-mid-row-sep">
|
112 |
-
|
113 |
-
<input name="wp-mail-smtp[mail][from_email_force]" type="checkbox"
|
114 |
-
value="true" <?php checked( true, (bool) $options->get( 'mail', 'from_email_force' ) ); ?>
|
115 |
-
<?php echo $options->is_const_defined( 'mail', 'from_email_force' ) || ! empty( $disabled_email ) ? 'disabled' : ''; ?>
|
116 |
-
id="wp-mail-smtp-setting-from_email_force">
|
117 |
-
|
118 |
-
<label for="wp-mail-smtp-setting-from_email_force">
|
119 |
-
<?php esc_html_e( 'Force From Email', 'wp-mail-smtp' ); ?>
|
120 |
-
</label>
|
121 |
-
|
122 |
-
<?php if ( ! empty( $disabled_email ) ) : ?>
|
123 |
-
<p class="desc">
|
124 |
-
<?php esc_html_e( 'Current provider will automatically force From Email to be the email address that you use to set up the connection below.', 'wp-mail-smtp' ); ?>
|
125 |
-
</p>
|
126 |
-
<?php else : ?>
|
127 |
-
<p class="desc">
|
128 |
-
<?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' ); ?>
|
129 |
-
</p>
|
130 |
-
<?php endif; ?>
|
131 |
-
|
132 |
-
</div>
|
133 |
-
</div>
|
134 |
-
|
135 |
-
<!-- From Name -->
|
136 |
-
<div id="wp-mail-smtp-setting-row-from_name" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
137 |
-
<div class="wp-mail-smtp-setting-label">
|
138 |
-
<label for="wp-mail-smtp-setting-from_name"><?php esc_html_e( 'From Name', 'wp-mail-smtp' ); ?></label>
|
139 |
-
</div>
|
140 |
-
<div class="wp-mail-smtp-setting-field">
|
141 |
-
<input name="wp-mail-smtp[mail][from_name]" type="text"
|
142 |
-
value="<?php echo esc_attr( $options->get( 'mail', 'from_name' ) ); ?>"
|
143 |
-
<?php echo $options->is_const_defined( 'mail', 'from_name' ) || ! empty( $disabled_name ) ? 'disabled' : ''; ?>
|
144 |
-
id="wp-mail-smtp-setting-from_name" spellcheck="false"
|
145 |
-
placeholder="<?php echo esc_attr( wp_mail_smtp()->get_processor()->get_default_name() ); ?>">
|
146 |
-
|
147 |
-
<?php if ( empty( $disabled_name ) ) : ?>
|
148 |
-
<p class="desc">
|
149 |
-
<?php esc_html_e( 'The name which emails are sent from.', 'wp-mail-smtp' ); ?>
|
150 |
-
</p>
|
151 |
-
<?php endif; ?>
|
152 |
-
|
153 |
-
<hr class="wp-mail-smtp-setting-mid-row-sep">
|
154 |
-
|
155 |
-
<input name="wp-mail-smtp[mail][from_name_force]" type="checkbox"
|
156 |
-
value="true" <?php checked( true, (bool) $options->get( 'mail', 'from_name_force' ) ); ?>
|
157 |
-
<?php echo $options->is_const_defined( 'mail', 'from_name_force' ) || ! empty( $disabled_name ) ? 'disabled' : ''; ?>
|
158 |
-
id="wp-mail-smtp-setting-from_name_force">
|
159 |
-
|
160 |
-
<label for="wp-mail-smtp-setting-from_name_force">
|
161 |
-
<?php esc_html_e( 'Force From Name', 'wp-mail-smtp' ); ?>
|
162 |
-
</label>
|
163 |
-
|
164 |
-
<?php if ( ! empty( $disabled_name ) ) : ?>
|
165 |
-
<p class="desc">
|
166 |
-
<?php esc_html_e( 'Current provider doesn\'t support setting and forcing From Name. Emails will be sent on behalf of the account name used to setup the connection below.', 'wp-mail-smtp' ); ?>
|
167 |
-
</p>
|
168 |
-
<?php else : ?>
|
169 |
-
<p class="desc">
|
170 |
-
<?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' ); ?>
|
171 |
-
</p>
|
172 |
-
<?php endif; ?>
|
173 |
-
</div>
|
174 |
-
</div>
|
175 |
-
|
176 |
-
<!-- Return Path -->
|
177 |
-
<div id="wp-mail-smtp-setting-row-return_path" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox wp-mail-smtp-clear">
|
178 |
-
<div class="wp-mail-smtp-setting-label">
|
179 |
-
<label for="wp-mail-smtp-setting-return_path"><?php esc_html_e( 'Return Path', 'wp-mail-smtp' ); ?></label>
|
180 |
-
</div>
|
181 |
-
<div class="wp-mail-smtp-setting-field">
|
182 |
-
<input name="wp-mail-smtp[mail][return_path]" type="checkbox"
|
183 |
-
value="true" <?php checked( true, (bool) $options->get( 'mail', 'return_path' ) ); ?>
|
184 |
-
<?php echo $options->is_const_defined( 'mail', 'return_path' ) ? 'disabled' : ''; ?>
|
185 |
-
id="wp-mail-smtp-setting-return_path">
|
186 |
-
|
187 |
-
<label for="wp-mail-smtp-setting-return_path">
|
188 |
-
<?php esc_html_e( 'Set the return-path to match the From Email', 'wp-mail-smtp' ); ?>
|
189 |
-
</label>
|
190 |
-
|
191 |
-
<p class="desc">
|
192 |
-
<?php esc_html_e( 'Return Path indicates where non-delivery receipts - or bounce messages - are to be sent.', 'wp-mail-smtp' ); ?><br/>
|
193 |
-
<?php esc_html_e( 'If unchecked, bounce messages may be lost. Some providers may ignore this option.', 'wp-mail-smtp' ); ?>
|
194 |
-
</p>
|
195 |
-
</div>
|
196 |
-
</div>
|
197 |
-
|
198 |
-
<!-- Mailer -->
|
199 |
-
<div id="wp-mail-smtp-setting-row-mailer" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-mailer wp-mail-smtp-clear">
|
200 |
-
<div class="wp-mail-smtp-setting-label">
|
201 |
-
<label for="wp-mail-smtp-setting-mailer"><?php esc_html_e( 'Mailer', 'wp-mail-smtp' ); ?></label>
|
202 |
-
</div>
|
203 |
-
<div class="wp-mail-smtp-setting-field">
|
204 |
-
<div class="wp-mail-smtp-mailers">
|
205 |
-
|
206 |
-
<?php foreach ( wp_mail_smtp()->get_providers()->get_options_all() as $provider ) : ?>
|
207 |
-
|
208 |
-
<div class="wp-mail-smtp-mailer wp-mail-smtp-mailer-<?php echo esc_attr( $provider->get_slug() ); ?> <?php echo $mailer === $provider->get_slug() ? 'active' : ''; ?>">
|
209 |
-
|
210 |
-
<div class="wp-mail-smtp-mailer-image <?php echo $provider->is_recommended() ? 'is-recommended' : ''; ?>">
|
211 |
-
<img src="<?php echo esc_url( $provider->get_logo_url() ); ?>"
|
212 |
-
alt="<?php echo esc_attr( $provider->get_title() ); ?>">
|
213 |
-
</div>
|
214 |
-
|
215 |
-
<div class="wp-mail-smtp-mailer-text">
|
216 |
-
<?php if ( $provider->is_disabled() ) : ?>
|
217 |
-
<input type="radio" name="wp-mail-smtp[mail][mailer]" disabled class="educate"
|
218 |
-
id="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>"
|
219 |
-
value="<?php echo esc_attr( $provider->get_slug() ); ?>"
|
220 |
-
/>
|
221 |
-
<?php else : ?>
|
222 |
-
<input id="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>"
|
223 |
-
type="radio" name="wp-mail-smtp[mail][mailer]"
|
224 |
-
value="<?php echo esc_attr( $provider->get_slug() ); ?>"
|
225 |
-
<?php checked( $provider->get_slug(), $mailer ); ?>
|
226 |
-
<?php echo $options->is_const_defined( 'mail', 'mailer' ) || $provider->is_disabled() ? 'disabled' : ''; ?>
|
227 |
-
<?php echo $provider->is_disabled() ? 'class="educate"' : ''; ?>
|
228 |
-
/>
|
229 |
-
<?php endif; ?>
|
230 |
-
<label for="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>">
|
231 |
-
<?php echo esc_html( $provider->get_title() ); ?>
|
232 |
-
</label>
|
233 |
-
</div>
|
234 |
-
</div>
|
235 |
-
|
236 |
-
<?php endforeach; ?>
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
)
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
<li
|
418 |
-
<li
|
419 |
-
<li
|
420 |
-
<li
|
421 |
-
<li
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
if ( ! isset( $data['
|
484 |
-
$data['
|
485 |
-
}
|
486 |
-
if ( ! isset( $data['
|
487 |
-
$data['
|
488 |
-
}
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
) {
|
496 |
-
|
497 |
-
}
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
$
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
$
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Admin\Pages;
|
4 |
+
|
5 |
+
use WPMailSMTP\Admin\PageAbstract;
|
6 |
+
use WPMailSMTP\Debug;
|
7 |
+
use WPMailSMTP\Options;
|
8 |
+
use WPMailSMTP\WP;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class SettingsTab is part of Area, displays general settings of the plugin.
|
12 |
+
*
|
13 |
+
* @since 1.0.0
|
14 |
+
*/
|
15 |
+
class SettingsTab extends PageAbstract {
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Settings constructor.
|
19 |
+
*
|
20 |
+
* @since 1.5.0
|
21 |
+
*/
|
22 |
+
public function __construct() {
|
23 |
+
|
24 |
+
add_action( 'wp_mail_smtp_admin_pages_settings_license_key', array( __CLASS__, 'display_license_key_field_content' ) );
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var string Slug of a tab.
|
29 |
+
*/
|
30 |
+
protected $slug = 'settings';
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @inheritdoc
|
34 |
+
*/
|
35 |
+
public function get_label() {
|
36 |
+
return esc_html__( 'General', 'wp-mail-smtp' );
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @inheritdoc
|
41 |
+
*/
|
42 |
+
public function get_title() {
|
43 |
+
return $this->get_label();
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @inheritdoc
|
48 |
+
*/
|
49 |
+
public function display() {
|
50 |
+
|
51 |
+
$options = new Options();
|
52 |
+
$mailer = $options->get( 'mail', 'mailer' );
|
53 |
+
|
54 |
+
$disabled_email = 'gmail' === $mailer || 'outlook' === $mailer ? 'disabled' : '';
|
55 |
+
$disabled_name = 'outlook' === $mailer ? 'disabled' : '';
|
56 |
+
?>
|
57 |
+
|
58 |
+
<form method="POST" action="" autocomplete="off">
|
59 |
+
<?php $this->wp_nonce_field(); ?>
|
60 |
+
|
61 |
+
<!-- License Section Title -->
|
62 |
+
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading" id="wp-mail-smtp-setting-row-license-heading">
|
63 |
+
<div class="wp-mail-smtp-setting-field">
|
64 |
+
<h2><?php esc_html_e( 'License', 'wp-mail-smtp' ); ?></h2>
|
65 |
+
|
66 |
+
<p class="desc">
|
67 |
+
<?php esc_html_e( 'Your license key provides access to updates and support.', 'wp-mail-smtp' ); ?>
|
68 |
+
</p>
|
69 |
+
</div>
|
70 |
+
</div>
|
71 |
+
|
72 |
+
<!-- License Key -->
|
73 |
+
<div id="wp-mail-smtp-setting-row-license_key" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-license_key wp-mail-smtp-clear">
|
74 |
+
<div class="wp-mail-smtp-setting-label">
|
75 |
+
<label for="wp-mail-smtp-setting-license_key"><?php esc_html_e( 'License Key', 'wp-mail-smtp' ); ?></label>
|
76 |
+
</div>
|
77 |
+
<div class="wp-mail-smtp-setting-field">
|
78 |
+
<?php do_action( 'wp_mail_smtp_admin_pages_settings_license_key', $options ); ?>
|
79 |
+
</div>
|
80 |
+
</div>
|
81 |
+
|
82 |
+
<!-- Mail Section Title -->
|
83 |
+
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading no-desc" id="wp-mail-smtp-setting-row-email-heading">
|
84 |
+
<div class="wp-mail-smtp-setting-field">
|
85 |
+
<h2><?php esc_html_e( 'Mail', 'wp-mail-smtp' ); ?></h2>
|
86 |
+
</div>
|
87 |
+
</div>
|
88 |
+
|
89 |
+
<!-- From Email -->
|
90 |
+
<div id="wp-mail-smtp-setting-row-from_email" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-email wp-mail-smtp-clear">
|
91 |
+
<div class="wp-mail-smtp-setting-label">
|
92 |
+
<label for="wp-mail-smtp-setting-from_email"><?php esc_html_e( 'From Email', 'wp-mail-smtp' ); ?></label>
|
93 |
+
</div>
|
94 |
+
<div class="wp-mail-smtp-setting-field">
|
95 |
+
<input name="wp-mail-smtp[mail][from_email]" type="email"
|
96 |
+
value="<?php echo esc_attr( $options->get( 'mail', 'from_email' ) ); ?>"
|
97 |
+
<?php echo $options->is_const_defined( 'mail', 'from_email' ) || ! empty( $disabled_email ) ? 'disabled' : ''; ?>
|
98 |
+
id="wp-mail-smtp-setting-from_email" spellcheck="false"
|
99 |
+
placeholder="<?php echo esc_attr( wp_mail_smtp()->get_processor()->get_default_email() ); ?>">
|
100 |
+
|
101 |
+
<?php if ( empty( $disabled_email ) ) : ?>
|
102 |
+
<p class="desc">
|
103 |
+
<?php esc_html_e( 'The email address which emails are sent from.', 'wp-mail-smtp' ); ?><br/>
|
104 |
+
<?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' ); ?>
|
105 |
+
</p>
|
106 |
+
<p class="desc">
|
107 |
+
<?php esc_html_e( 'Please note that other plugins can change this, to prevent this use the setting below.', 'wp-mail-smtp' ); ?>
|
108 |
+
</p>
|
109 |
+
<?php endif; ?>
|
110 |
+
|
111 |
+
<hr class="wp-mail-smtp-setting-mid-row-sep">
|
112 |
+
|
113 |
+
<input name="wp-mail-smtp[mail][from_email_force]" type="checkbox"
|
114 |
+
value="true" <?php checked( true, (bool) $options->get( 'mail', 'from_email_force' ) ); ?>
|
115 |
+
<?php echo $options->is_const_defined( 'mail', 'from_email_force' ) || ! empty( $disabled_email ) ? 'disabled' : ''; ?>
|
116 |
+
id="wp-mail-smtp-setting-from_email_force">
|
117 |
+
|
118 |
+
<label for="wp-mail-smtp-setting-from_email_force">
|
119 |
+
<?php esc_html_e( 'Force From Email', 'wp-mail-smtp' ); ?>
|
120 |
+
</label>
|
121 |
+
|
122 |
+
<?php if ( ! empty( $disabled_email ) ) : ?>
|
123 |
+
<p class="desc">
|
124 |
+
<?php esc_html_e( 'Current provider will automatically force From Email to be the email address that you use to set up the connection below.', 'wp-mail-smtp' ); ?>
|
125 |
+
</p>
|
126 |
+
<?php else : ?>
|
127 |
+
<p class="desc">
|
128 |
+
<?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' ); ?>
|
129 |
+
</p>
|
130 |
+
<?php endif; ?>
|
131 |
+
|
132 |
+
</div>
|
133 |
+
</div>
|
134 |
+
|
135 |
+
<!-- From Name -->
|
136 |
+
<div id="wp-mail-smtp-setting-row-from_name" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
137 |
+
<div class="wp-mail-smtp-setting-label">
|
138 |
+
<label for="wp-mail-smtp-setting-from_name"><?php esc_html_e( 'From Name', 'wp-mail-smtp' ); ?></label>
|
139 |
+
</div>
|
140 |
+
<div class="wp-mail-smtp-setting-field">
|
141 |
+
<input name="wp-mail-smtp[mail][from_name]" type="text"
|
142 |
+
value="<?php echo esc_attr( $options->get( 'mail', 'from_name' ) ); ?>"
|
143 |
+
<?php echo $options->is_const_defined( 'mail', 'from_name' ) || ! empty( $disabled_name ) ? 'disabled' : ''; ?>
|
144 |
+
id="wp-mail-smtp-setting-from_name" spellcheck="false"
|
145 |
+
placeholder="<?php echo esc_attr( wp_mail_smtp()->get_processor()->get_default_name() ); ?>">
|
146 |
+
|
147 |
+
<?php if ( empty( $disabled_name ) ) : ?>
|
148 |
+
<p class="desc">
|
149 |
+
<?php esc_html_e( 'The name which emails are sent from.', 'wp-mail-smtp' ); ?>
|
150 |
+
</p>
|
151 |
+
<?php endif; ?>
|
152 |
+
|
153 |
+
<hr class="wp-mail-smtp-setting-mid-row-sep">
|
154 |
+
|
155 |
+
<input name="wp-mail-smtp[mail][from_name_force]" type="checkbox"
|
156 |
+
value="true" <?php checked( true, (bool) $options->get( 'mail', 'from_name_force' ) ); ?>
|
157 |
+
<?php echo $options->is_const_defined( 'mail', 'from_name_force' ) || ! empty( $disabled_name ) ? 'disabled' : ''; ?>
|
158 |
+
id="wp-mail-smtp-setting-from_name_force">
|
159 |
+
|
160 |
+
<label for="wp-mail-smtp-setting-from_name_force">
|
161 |
+
<?php esc_html_e( 'Force From Name', 'wp-mail-smtp' ); ?>
|
162 |
+
</label>
|
163 |
+
|
164 |
+
<?php if ( ! empty( $disabled_name ) ) : ?>
|
165 |
+
<p class="desc">
|
166 |
+
<?php esc_html_e( 'Current provider doesn\'t support setting and forcing From Name. Emails will be sent on behalf of the account name used to setup the connection below.', 'wp-mail-smtp' ); ?>
|
167 |
+
</p>
|
168 |
+
<?php else : ?>
|
169 |
+
<p class="desc">
|
170 |
+
<?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' ); ?>
|
171 |
+
</p>
|
172 |
+
<?php endif; ?>
|
173 |
+
</div>
|
174 |
+
</div>
|
175 |
+
|
176 |
+
<!-- Return Path -->
|
177 |
+
<div id="wp-mail-smtp-setting-row-return_path" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox wp-mail-smtp-clear">
|
178 |
+
<div class="wp-mail-smtp-setting-label">
|
179 |
+
<label for="wp-mail-smtp-setting-return_path"><?php esc_html_e( 'Return Path', 'wp-mail-smtp' ); ?></label>
|
180 |
+
</div>
|
181 |
+
<div class="wp-mail-smtp-setting-field">
|
182 |
+
<input name="wp-mail-smtp[mail][return_path]" type="checkbox"
|
183 |
+
value="true" <?php checked( true, (bool) $options->get( 'mail', 'return_path' ) ); ?>
|
184 |
+
<?php echo $options->is_const_defined( 'mail', 'return_path' ) ? 'disabled' : ''; ?>
|
185 |
+
id="wp-mail-smtp-setting-return_path">
|
186 |
+
|
187 |
+
<label for="wp-mail-smtp-setting-return_path">
|
188 |
+
<?php esc_html_e( 'Set the return-path to match the From Email', 'wp-mail-smtp' ); ?>
|
189 |
+
</label>
|
190 |
+
|
191 |
+
<p class="desc">
|
192 |
+
<?php esc_html_e( 'Return Path indicates where non-delivery receipts - or bounce messages - are to be sent.', 'wp-mail-smtp' ); ?><br/>
|
193 |
+
<?php esc_html_e( 'If unchecked, bounce messages may be lost. Some providers may ignore this option.', 'wp-mail-smtp' ); ?>
|
194 |
+
</p>
|
195 |
+
</div>
|
196 |
+
</div>
|
197 |
+
|
198 |
+
<!-- Mailer -->
|
199 |
+
<div id="wp-mail-smtp-setting-row-mailer" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-mailer wp-mail-smtp-clear">
|
200 |
+
<div class="wp-mail-smtp-setting-label">
|
201 |
+
<label for="wp-mail-smtp-setting-mailer"><?php esc_html_e( 'Mailer', 'wp-mail-smtp' ); ?></label>
|
202 |
+
</div>
|
203 |
+
<div class="wp-mail-smtp-setting-field">
|
204 |
+
<div class="wp-mail-smtp-mailers">
|
205 |
+
|
206 |
+
<?php foreach ( wp_mail_smtp()->get_providers()->get_options_all() as $provider ) : ?>
|
207 |
+
|
208 |
+
<div class="wp-mail-smtp-mailer wp-mail-smtp-mailer-<?php echo esc_attr( $provider->get_slug() ); ?> <?php echo $mailer === $provider->get_slug() ? 'active' : ''; ?>">
|
209 |
+
|
210 |
+
<div class="wp-mail-smtp-mailer-image <?php echo $provider->is_recommended() ? 'is-recommended' : ''; ?>">
|
211 |
+
<img src="<?php echo esc_url( $provider->get_logo_url() ); ?>"
|
212 |
+
alt="<?php echo esc_attr( $provider->get_title() ); ?>">
|
213 |
+
</div>
|
214 |
+
|
215 |
+
<div class="wp-mail-smtp-mailer-text">
|
216 |
+
<?php if ( $provider->is_disabled() ) : ?>
|
217 |
+
<input type="radio" name="wp-mail-smtp[mail][mailer]" disabled class="educate"
|
218 |
+
id="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>"
|
219 |
+
value="<?php echo esc_attr( $provider->get_slug() ); ?>"
|
220 |
+
/>
|
221 |
+
<?php else : ?>
|
222 |
+
<input id="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>"
|
223 |
+
type="radio" name="wp-mail-smtp[mail][mailer]"
|
224 |
+
value="<?php echo esc_attr( $provider->get_slug() ); ?>"
|
225 |
+
<?php checked( $provider->get_slug(), $mailer ); ?>
|
226 |
+
<?php echo $options->is_const_defined( 'mail', 'mailer' ) || $provider->is_disabled() ? 'disabled' : ''; ?>
|
227 |
+
<?php echo $provider->is_disabled() ? 'class="educate"' : ''; ?>
|
228 |
+
/>
|
229 |
+
<?php endif; ?>
|
230 |
+
<label for="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>">
|
231 |
+
<?php echo esc_html( $provider->get_title() ); ?>
|
232 |
+
</label>
|
233 |
+
</div>
|
234 |
+
</div>
|
235 |
+
|
236 |
+
<?php endforeach; ?>
|
237 |
+
|
238 |
+
<!-- Suggest a mailer -->
|
239 |
+
<div class="wp-mail-smtp-mailer suggest-new">
|
240 |
+
<a href="https://wpmailsmtp.com/suggest-a-mailer" class="wp-mail-smtp-mailer-image" target="_blank" rel="noopener noreferrer">
|
241 |
+
<?php esc_html_e( 'Suggest a Mailer', 'wp-mail-smtp' ); ?>
|
242 |
+
</a>
|
243 |
+
|
244 |
+
<div class="wp-mail-smtp-mailer-text">
|
245 |
+
<label><?php esc_html_e( 'Suggest a Mailer', 'wp-mail-smtp' ); ?></label>
|
246 |
+
</div>
|
247 |
+
</div>
|
248 |
+
|
249 |
+
</div>
|
250 |
+
</div>
|
251 |
+
</div>
|
252 |
+
|
253 |
+
<!-- Mailer Options -->
|
254 |
+
<div class="wp-mail-smtp-mailer-options">
|
255 |
+
<?php foreach ( wp_mail_smtp()->get_providers()->get_options_all() as $provider ) : ?>
|
256 |
+
<?php $provider_desc = $provider->get_description(); ?>
|
257 |
+
<div class="wp-mail-smtp-mailer-option wp-mail-smtp-mailer-option-<?php echo esc_attr( $provider->get_slug() ); ?> <?php echo $mailer === $provider->get_slug() ? 'active' : 'hidden'; ?>">
|
258 |
+
|
259 |
+
<!-- Mailer Title/Notice/Description -->
|
260 |
+
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading <?php echo empty( $provider_desc ) ? 'no-desc' : ''; ?>" id="wp-mail-smtp-setting-row-email-heading">
|
261 |
+
<div class="wp-mail-smtp-setting-field">
|
262 |
+
<?php if ( $provider->is_disabled() ) : ?>
|
263 |
+
<?php $provider->display_options(); ?>
|
264 |
+
<?php else : ?>
|
265 |
+
<h2><?php echo $provider->get_title(); ?></h2>
|
266 |
+
<?php
|
267 |
+
$provider_edu_notice = $provider->get_notice( 'educational' );
|
268 |
+
$is_dismissed = (bool) get_user_meta( get_current_user_id(), "wp_mail_smtp_notice_educational_for_{$provider->get_slug()}_dismissed", true );
|
269 |
+
if ( ! empty( $provider_edu_notice ) && ! $is_dismissed ) :
|
270 |
+
?>
|
271 |
+
<p class="inline-notice inline-edu-notice"
|
272 |
+
data-notice="educational"
|
273 |
+
data-mailer="<?php echo esc_attr( $provider->get_slug() ); ?>">
|
274 |
+
<a href="#" title="<?php esc_attr_e( 'Dismiss this notice', 'wp-mail-smtp' ); ?>"
|
275 |
+
class="wp-mail-smtp-mailer-notice-dismiss js-wp-mail-smtp-mailer-notice-dismiss">
|
276 |
+
<span class="dashicons dashicons-dismiss"></span>
|
277 |
+
</a>
|
278 |
+
|
279 |
+
<?php echo $provider_edu_notice; ?>
|
280 |
+
</p>
|
281 |
+
<?php endif; ?>
|
282 |
+
|
283 |
+
<?php if ( ! empty( $provider_desc ) ) : ?>
|
284 |
+
<p class="desc"><?php echo $provider_desc; ?></p>
|
285 |
+
<?php endif; ?>
|
286 |
+
<?php endif; ?>
|
287 |
+
</div>
|
288 |
+
</div>
|
289 |
+
|
290 |
+
<?php $provider->display_options(); ?>
|
291 |
+
</div>
|
292 |
+
|
293 |
+
<?php endforeach; ?>
|
294 |
+
|
295 |
+
</div>
|
296 |
+
|
297 |
+
<?php $this->display_save_btn(); ?>
|
298 |
+
|
299 |
+
</form>
|
300 |
+
|
301 |
+
<?php
|
302 |
+
$this->display_wpforms();
|
303 |
+
$this->display_pro_banner();
|
304 |
+
}
|
305 |
+
|
306 |
+
/**
|
307 |
+
* License key text for a Lite version of the plugin.
|
308 |
+
*
|
309 |
+
* @since 1.5.0
|
310 |
+
*
|
311 |
+
* @param Options $options
|
312 |
+
*/
|
313 |
+
public static function display_license_key_field_content( $options ) {
|
314 |
+
?>
|
315 |
+
|
316 |
+
<p><?php esc_html_e( 'You\'re using WP Mail SMTP Lite - no license needed. Enjoy!', 'wp-mail-smtp' ); ?> 🙂</p>
|
317 |
+
|
318 |
+
<p>
|
319 |
+
<?php
|
320 |
+
printf(
|
321 |
+
wp_kses( /* translators: %s - WPMailSMTP.com upgrade URL. */
|
322 |
+
__( 'To unlock more features consider <strong><a href="%s" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-upgrade-modal">upgrading to PRO</a></strong>.', 'wp-mail-smtp' ),
|
323 |
+
array(
|
324 |
+
'a' => array(
|
325 |
+
'href' => array(),
|
326 |
+
'class' => array(),
|
327 |
+
'target' => array(),
|
328 |
+
'rel' => array(),
|
329 |
+
),
|
330 |
+
'strong' => array(),
|
331 |
+
)
|
332 |
+
),
|
333 |
+
esc_url( wp_mail_smtp()->get_upgrade_link( 'general-license-key' ) )
|
334 |
+
);
|
335 |
+
?>
|
336 |
+
</p>
|
337 |
+
|
338 |
+
<p class="desc">
|
339 |
+
<?php
|
340 |
+
echo wp_kses(
|
341 |
+
__( 'As a valued WP Mail SMTP Lite user you receive <strong>20% off</strong>, automatically applied at checkout!', 'wp-mail-smtp' ),
|
342 |
+
array(
|
343 |
+
'strong' => array(),
|
344 |
+
'br' => array(),
|
345 |
+
)
|
346 |
+
);
|
347 |
+
?>
|
348 |
+
</p>
|
349 |
+
|
350 |
+
<?php
|
351 |
+
}
|
352 |
+
|
353 |
+
/**
|
354 |
+
* Display a WPForms related message.
|
355 |
+
*
|
356 |
+
* @since 1.3.0
|
357 |
+
* @since 1.4.0 Display only to site admins.
|
358 |
+
* @since 1.5.0 Do nothing.
|
359 |
+
*/
|
360 |
+
protected function display_wpforms() {
|
361 |
+
/*
|
362 |
+
* Used to have this check:
|
363 |
+
*
|
364 |
+
* $is_dismissed = get_user_meta( get_current_user_id(), 'wp_mail_smtp_wpforms_dismissed', true );
|
365 |
+
*/
|
366 |
+
}
|
367 |
+
|
368 |
+
/**
|
369 |
+
* Display WP Mail SMTP Pro upgrade banner.
|
370 |
+
*
|
371 |
+
* @since 1.5.0
|
372 |
+
*/
|
373 |
+
protected function display_pro_banner() {
|
374 |
+
|
375 |
+
// Display only to site admins. Only site admins can install plugins.
|
376 |
+
if ( ! is_super_admin() ) {
|
377 |
+
return;
|
378 |
+
}
|
379 |
+
|
380 |
+
// Do not display if WP Mail SMTP Pro already installed.
|
381 |
+
if ( wp_mail_smtp()->is_pro() ) {
|
382 |
+
return;
|
383 |
+
}
|
384 |
+
|
385 |
+
$is_dismissed = get_user_meta( get_current_user_id(), 'wp_mail_smtp_pro_banner_dismissed', true );
|
386 |
+
|
387 |
+
// Do not display if user dismissed.
|
388 |
+
if ( (bool) $is_dismissed === true ) {
|
389 |
+
return;
|
390 |
+
}
|
391 |
+
?>
|
392 |
+
|
393 |
+
<div id="wp-mail-smtp-pro-banner">
|
394 |
+
|
395 |
+
<span class="wp-mail-smtp-pro-banner-dismiss">
|
396 |
+
<button id="wp-mail-smtp-pro-banner-dismiss">
|
397 |
+
<span class="dashicons dashicons-dismiss"></span>
|
398 |
+
</button>
|
399 |
+
</span>
|
400 |
+
|
401 |
+
<h2>
|
402 |
+
<?php esc_html_e( 'Get WP Mail SMTP Pro and Unlock all the Powerful Features', 'wp-mail-smtp' ); ?>
|
403 |
+
</h2>
|
404 |
+
|
405 |
+
<p>
|
406 |
+
<?php esc_html_e( 'Thanks for being a loyal WP Mail SMTP user. Upgrade to WP Mail SMTP Pro to unlock more awesome features and experience why WP Mail SMTP is the most popular SMTP plugin.', 'wp-mail-smtp' ); ?>
|
407 |
+
</p>
|
408 |
+
|
409 |
+
<p>
|
410 |
+
<?php esc_html_e( 'We know that you will truly love WP Mail SMTP. It\'s used by over 1,000,000 websites.', 'wp-mail-smtp' ); ?>
|
411 |
+
</p>
|
412 |
+
|
413 |
+
<p><strong><?php esc_html_e( 'Pro Features:', 'wp-mail-smtp' ); ?></strong></p>
|
414 |
+
|
415 |
+
<div class="benefits">
|
416 |
+
<ul>
|
417 |
+
<li><?php esc_html_e( 'Manage Notifications - control which emails your site sends', 'wp-mail-smtp' ); ?></li>
|
418 |
+
<li><?php esc_html_e( 'Email Logging - keep track of every email sent from your site', 'wp-mail-smtp' ); ?></li>
|
419 |
+
<li><?php esc_html_e( 'Office 365 - send emails using your Office 365 account', 'wp-mail-smtp' ); ?></li>
|
420 |
+
<li><?php esc_html_e( 'Amazon SES - harness the power of AWS', 'wp-mail-smtp' ); ?></li>
|
421 |
+
<li><?php esc_html_e( 'Outlook.com - send emails using your Outlook.com account', 'wp-mail-smtp' ); ?></li>
|
422 |
+
<li><?php esc_html_e( 'Access to our world class support team', 'wp-mail-smtp' ); ?></li>
|
423 |
+
</ul>
|
424 |
+
<ul>
|
425 |
+
<li><?php esc_html_e( 'White Glove Setup - sit back and relax while we handle everything for you', 'wp-mail-smtp' ); ?></li>
|
426 |
+
<li class="arrow-right"><?php esc_html_e( 'Install WP Mail SMTP Pro plugin', 'wp-mail-smtp' ); ?></li>
|
427 |
+
<li class="arrow-right"><?php esc_html_e( 'Set up domain name verification (DNS)', 'wp-mail-smtp' ); ?></li>
|
428 |
+
<li class="arrow-right"><?php esc_html_e( 'Configure Mailgun service', 'wp-mail-smtp' ); ?></li>
|
429 |
+
<li class="arrow-right"><?php esc_html_e( 'Set up WP Mail SMTP Pro plugin', 'wp-mail-smtp' ); ?></li>
|
430 |
+
<li class="arrow-right"><?php esc_html_e( 'Test and verify email delivery', 'wp-mail-smtp' ); ?></li>
|
431 |
+
</ul>
|
432 |
+
</div>
|
433 |
+
|
434 |
+
<p>
|
435 |
+
<?php
|
436 |
+
printf(
|
437 |
+
wp_kses( /* translators: %s - WPMailSMTP.com URL. */
|
438 |
+
__( '<a href="%s" target="_blank" rel="noopener noreferrer">Get WP Mail SMTP Pro Today and Unlock all the Powerful Features »</a>', 'wp-mail-smtp' ),
|
439 |
+
array(
|
440 |
+
'a' => array(
|
441 |
+
'href' => array(),
|
442 |
+
'target' => array(),
|
443 |
+
'rel' => array(),
|
444 |
+
),
|
445 |
+
'strong' => array(),
|
446 |
+
)
|
447 |
+
),
|
448 |
+
esc_url( wp_mail_smtp()->get_upgrade_link( 'general-cta' ) )
|
449 |
+
);
|
450 |
+
?>
|
451 |
+
</p>
|
452 |
+
|
453 |
+
<p>
|
454 |
+
<?php
|
455 |
+
echo wp_kses(
|
456 |
+
__( '<strong>Bonus:</strong> WP Mail SMTP users get <span class="price-off">20% off regular price</span>, automatically applied at checkout.', 'wp-mail-smtp' ),
|
457 |
+
array(
|
458 |
+
'strong' => array(),
|
459 |
+
'span' => array(
|
460 |
+
'class' => array(),
|
461 |
+
),
|
462 |
+
)
|
463 |
+
);
|
464 |
+
?>
|
465 |
+
</p>
|
466 |
+
|
467 |
+
</div>
|
468 |
+
|
469 |
+
<?php
|
470 |
+
}
|
471 |
+
|
472 |
+
/**
|
473 |
+
* @inheritdoc
|
474 |
+
*/
|
475 |
+
public function process_post( $data ) {
|
476 |
+
|
477 |
+
$this->check_admin_referer();
|
478 |
+
|
479 |
+
$options = new Options();
|
480 |
+
$old_opt = $options->get_all();
|
481 |
+
|
482 |
+
// When checkbox is unchecked - it's not submitted at all, so we need to define its default false value.
|
483 |
+
if ( ! isset( $data['mail']['from_email_force'] ) ) {
|
484 |
+
$data['mail']['from_email_force'] = false;
|
485 |
+
}
|
486 |
+
if ( ! isset( $data['mail']['from_name_force'] ) ) {
|
487 |
+
$data['mail']['from_name_force'] = false;
|
488 |
+
}
|
489 |
+
if ( ! isset( $data['mail']['return_path'] ) ) {
|
490 |
+
$data['mail']['return_path'] = false;
|
491 |
+
}
|
492 |
+
if ( ! isset( $data['smtp']['autotls'] ) ) {
|
493 |
+
$data['smtp']['autotls'] = false;
|
494 |
+
}
|
495 |
+
if ( ! isset( $data['smtp']['auth'] ) ) {
|
496 |
+
$data['smtp']['auth'] = false;
|
497 |
+
}
|
498 |
+
|
499 |
+
// Remove all debug messages when switching mailers.
|
500 |
+
if (
|
501 |
+
! empty( $old_opt['mail']['mailer'] ) &&
|
502 |
+
! empty( $data['mail']['mailer'] ) &&
|
503 |
+
$old_opt['mail']['mailer'] !== $data['mail']['mailer']
|
504 |
+
) {
|
505 |
+
Debug::clear();
|
506 |
+
}
|
507 |
+
|
508 |
+
$to_redirect = false;
|
509 |
+
|
510 |
+
// Old and new Gmail client id/secret values are different - we need to invalidate tokens and scroll to Auth button.
|
511 |
+
if (
|
512 |
+
$options->get( 'mail', 'mailer' ) === 'gmail' &&
|
513 |
+
! empty( $data['gmail']['client_id'] ) &&
|
514 |
+
! empty( $data['gmail']['client_secret'] ) &&
|
515 |
+
(
|
516 |
+
$options->get( 'gmail', 'client_id' ) !== $data['gmail']['client_id'] ||
|
517 |
+
$options->get( 'gmail', 'client_secret' ) !== $data['gmail']['client_secret']
|
518 |
+
)
|
519 |
+
) {
|
520 |
+
unset( $old_opt['gmail'] );
|
521 |
+
|
522 |
+
if (
|
523 |
+
! empty( $data['gmail']['client_id'] ) &&
|
524 |
+
! empty( $data['gmail']['client_secret'] )
|
525 |
+
) {
|
526 |
+
$to_redirect = true;
|
527 |
+
}
|
528 |
+
}
|
529 |
+
|
530 |
+
// New gmail clients data will be added from new $data.
|
531 |
+
$to_save = Options::array_merge_recursive( $old_opt, $data );
|
532 |
+
|
533 |
+
// All the sanitization is done in Options class.
|
534 |
+
$options->set( $to_save );
|
535 |
+
|
536 |
+
if ( $to_redirect ) {
|
537 |
+
wp_redirect( $_POST['_wp_http_referer'] . '#wp-mail-smtp-setting-row-gmail-authorize' );
|
538 |
+
exit;
|
539 |
+
}
|
540 |
+
|
541 |
+
WP::add_admin_notice(
|
542 |
+
esc_html__( 'Settings were successfully saved.', 'wp-mail-smtp' ),
|
543 |
+
WP::ADMIN_NOTICE_SUCCESS
|
544 |
+
);
|
545 |
+
}
|
546 |
+
}
|
src/Admin/PluginsInstallSkin.php
CHANGED
@@ -1,55 +1,55 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Admin;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* WordPress class extended for on-the-fly plugin installations.
|
7 |
-
*
|
8 |
-
* @since 1.5.0
|
9 |
-
* @since 1.7.1 Removed feedback() method override to be compatible with PHP5.3+ and WP5.3.
|
10 |
-
*/
|
11 |
-
class PluginsInstallSkin extends \WP_Upgrader_Skin {
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Empty out the header of its HTML content and only check to see if it has
|
15 |
-
* been performed or not.
|
16 |
-
*
|
17 |
-
* @since 1.5.0
|
18 |
-
*/
|
19 |
-
public function header() {
|
20 |
-
}
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Empty out the footer of its HTML contents.
|
24 |
-
*
|
25 |
-
* @since 1.5.0
|
26 |
-
*/
|
27 |
-
public function footer() {
|
28 |
-
}
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Instead of outputting HTML for errors, json_encode the errors and send them
|
32 |
-
* back to the Ajax script for processing.
|
33 |
-
*
|
34 |
-
* @since 1.5.0
|
35 |
-
*
|
36 |
-
* @param array $errors Array of errors with the install process.
|
37 |
-
*/
|
38 |
-
public function error( $errors ) {
|
39 |
-
|
40 |
-
if ( ! empty( $errors ) ) {
|
41 |
-
wp_send_json_error( $errors );
|
42 |
-
}
|
43 |
-
}
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Empty out JavaScript output that calls function to decrement the update counts.
|
47 |
-
*
|
48 |
-
* @since 1.5.0
|
49 |
-
*
|
50 |
-
* @param string $type Type of update count to decrement.
|
51 |
-
*/
|
52 |
-
public function decrement_update_count( $type ) {
|
53 |
-
}
|
54 |
-
}
|
55 |
-
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Admin;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* WordPress class extended for on-the-fly plugin installations.
|
7 |
+
*
|
8 |
+
* @since 1.5.0
|
9 |
+
* @since 1.7.1 Removed feedback() method override to be compatible with PHP5.3+ and WP5.3.
|
10 |
+
*/
|
11 |
+
class PluginsInstallSkin extends \WP_Upgrader_Skin {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Empty out the header of its HTML content and only check to see if it has
|
15 |
+
* been performed or not.
|
16 |
+
*
|
17 |
+
* @since 1.5.0
|
18 |
+
*/
|
19 |
+
public function header() {
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Empty out the footer of its HTML contents.
|
24 |
+
*
|
25 |
+
* @since 1.5.0
|
26 |
+
*/
|
27 |
+
public function footer() {
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Instead of outputting HTML for errors, json_encode the errors and send them
|
32 |
+
* back to the Ajax script for processing.
|
33 |
+
*
|
34 |
+
* @since 1.5.0
|
35 |
+
*
|
36 |
+
* @param array $errors Array of errors with the install process.
|
37 |
+
*/
|
38 |
+
public function error( $errors ) {
|
39 |
+
|
40 |
+
if ( ! empty( $errors ) ) {
|
41 |
+
wp_send_json_error( $errors );
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Empty out JavaScript output that calls function to decrement the update counts.
|
47 |
+
*
|
48 |
+
* @since 1.5.0
|
49 |
+
*
|
50 |
+
* @param string $type Type of update count to decrement.
|
51 |
+
*/
|
52 |
+
public function decrement_update_count( $type ) {
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
src/Options.php
CHANGED
@@ -18,13 +18,14 @@ class Options {
|
|
18 |
* @since 1.3.0
|
19 |
* @since 1.4.0 Added Mailgun:region.
|
20 |
* @since 1.5.0 Added Outlook/AmazonSES.
|
|
|
21 |
*
|
22 |
* @since
|
23 |
*
|
24 |
* @var array Map of all the default options of the plugin.
|
25 |
*/
|
26 |
private static $map = array(
|
27 |
-
'mail'
|
28 |
'from_name',
|
29 |
'from_email',
|
30 |
'mailer',
|
@@ -32,7 +33,7 @@ class Options {
|
|
32 |
'from_name_force',
|
33 |
'from_email_force',
|
34 |
),
|
35 |
-
'smtp'
|
36 |
'host',
|
37 |
'port',
|
38 |
'encryption',
|
@@ -41,32 +42,35 @@ class Options {
|
|
41 |
'user',
|
42 |
'pass',
|
43 |
),
|
44 |
-
'gmail'
|
45 |
'client_id',
|
46 |
'client_secret',
|
47 |
),
|
48 |
-
'outlook'
|
49 |
'client_id',
|
50 |
'client_secret',
|
51 |
),
|
52 |
-
'amazonses'
|
53 |
'client_id',
|
54 |
'client_secret',
|
55 |
'region',
|
56 |
'emails_pending',
|
57 |
),
|
58 |
-
'mailgun'
|
59 |
'api_key',
|
60 |
'domain',
|
61 |
'region',
|
62 |
),
|
63 |
-
'sendgrid'
|
64 |
'api_key',
|
65 |
),
|
66 |
-
'sendinblue'
|
67 |
'api_key',
|
68 |
),
|
69 |
-
'
|
|
|
|
|
|
|
70 |
'host',
|
71 |
'port',
|
72 |
'encryption',
|
@@ -74,7 +78,7 @@ class Options {
|
|
74 |
'user',
|
75 |
'pass',
|
76 |
),
|
77 |
-
'license'
|
78 |
'key',
|
79 |
),
|
80 |
);
|
@@ -340,6 +344,7 @@ class Options {
|
|
340 |
* @since 1.5.0 Added Outlook/AmazonSES, license key support.
|
341 |
* @since 1.6.0 Added Sendinblue.
|
342 |
* @since 1.7.0 Added Do Not Send.
|
|
|
343 |
*
|
344 |
* @param string $group
|
345 |
* @param string $key
|
@@ -504,6 +509,16 @@ class Options {
|
|
504 |
|
505 |
break;
|
506 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
507 |
case 'license':
|
508 |
switch ( $key ) {
|
509 |
case 'key':
|
@@ -556,6 +571,7 @@ class Options {
|
|
556 |
* @since 1.5.0 Added a filter, Outlook/AmazonSES, license key support.
|
557 |
* @since 1.6.0 Added Sendinblue.
|
558 |
* @since 1.7.0 Added Do Not Send.
|
|
|
559 |
*
|
560 |
* @param string $group
|
561 |
* @param string $key
|
@@ -697,6 +713,15 @@ class Options {
|
|
697 |
|
698 |
break;
|
699 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
700 |
case 'license':
|
701 |
switch ( $key ) {
|
702 |
case 'key':
|
@@ -776,7 +801,7 @@ class Options {
|
|
776 |
if (
|
777 |
! empty( $options['mail']['mailer'] ) &&
|
778 |
isset( $options[ $options['mail']['mailer'] ] ) &&
|
779 |
-
in_array( $options['mail']['mailer'], array( 'pepipost', 'smtp', 'sendgrid', 'mailgun', 'gmail', 'outlook' ), true )
|
780 |
) {
|
781 |
|
782 |
$mailer = $options['mail']['mailer'];
|
@@ -804,7 +829,7 @@ class Options {
|
|
804 |
$options[ $mailer ][ $option_name ] = $this->is_const_defined( $mailer, $option_name ) ? '' : trim( (string) $option_value );
|
805 |
break;
|
806 |
|
807 |
-
case 'api_key': // mailgun/sendgrid/sendinblue.
|
808 |
case 'domain': // mailgun.
|
809 |
case 'client_id': // gmail/outlook/amazonses.
|
810 |
case 'client_secret': // gmail/outlook/amazonses.
|
@@ -885,7 +910,7 @@ class Options {
|
|
885 |
}
|
886 |
|
887 |
/**
|
888 |
-
* Check whether the site is using Pepipost or not.
|
889 |
*
|
890 |
* @since 1.0.0
|
891 |
*
|
18 |
* @since 1.3.0
|
19 |
* @since 1.4.0 Added Mailgun:region.
|
20 |
* @since 1.5.0 Added Outlook/AmazonSES.
|
21 |
+
* @since 1.8.0 Added Pepipost API.
|
22 |
*
|
23 |
* @since
|
24 |
*
|
25 |
* @var array Map of all the default options of the plugin.
|
26 |
*/
|
27 |
private static $map = array(
|
28 |
+
'mail' => array(
|
29 |
'from_name',
|
30 |
'from_email',
|
31 |
'mailer',
|
33 |
'from_name_force',
|
34 |
'from_email_force',
|
35 |
),
|
36 |
+
'smtp' => array(
|
37 |
'host',
|
38 |
'port',
|
39 |
'encryption',
|
42 |
'user',
|
43 |
'pass',
|
44 |
),
|
45 |
+
'gmail' => array(
|
46 |
'client_id',
|
47 |
'client_secret',
|
48 |
),
|
49 |
+
'outlook' => array(
|
50 |
'client_id',
|
51 |
'client_secret',
|
52 |
),
|
53 |
+
'amazonses' => array(
|
54 |
'client_id',
|
55 |
'client_secret',
|
56 |
'region',
|
57 |
'emails_pending',
|
58 |
),
|
59 |
+
'mailgun' => array(
|
60 |
'api_key',
|
61 |
'domain',
|
62 |
'region',
|
63 |
),
|
64 |
+
'sendgrid' => array(
|
65 |
'api_key',
|
66 |
),
|
67 |
+
'sendinblue' => array(
|
68 |
'api_key',
|
69 |
),
|
70 |
+
'pepipostapi' => array(
|
71 |
+
'api_key',
|
72 |
+
),
|
73 |
+
'pepipost' => array(
|
74 |
'host',
|
75 |
'port',
|
76 |
'encryption',
|
78 |
'user',
|
79 |
'pass',
|
80 |
),
|
81 |
+
'license' => array(
|
82 |
'key',
|
83 |
),
|
84 |
);
|
344 |
* @since 1.5.0 Added Outlook/AmazonSES, license key support.
|
345 |
* @since 1.6.0 Added Sendinblue.
|
346 |
* @since 1.7.0 Added Do Not Send.
|
347 |
+
* @since 1.8.0 Added Pepipost API.
|
348 |
*
|
349 |
* @param string $group
|
350 |
* @param string $key
|
509 |
|
510 |
break;
|
511 |
|
512 |
+
case 'pepipostapi':
|
513 |
+
switch ( $key ) {
|
514 |
+
case 'api_key':
|
515 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
516 |
+
$return = $this->is_const_defined( $group, $key ) ? WPMS_PEPIPOST_API_KEY : $value;
|
517 |
+
break;
|
518 |
+
}
|
519 |
+
|
520 |
+
break;
|
521 |
+
|
522 |
case 'license':
|
523 |
switch ( $key ) {
|
524 |
case 'key':
|
571 |
* @since 1.5.0 Added a filter, Outlook/AmazonSES, license key support.
|
572 |
* @since 1.6.0 Added Sendinblue.
|
573 |
* @since 1.7.0 Added Do Not Send.
|
574 |
+
* @since 1.8.0 Added Pepipost API.
|
575 |
*
|
576 |
* @param string $group
|
577 |
* @param string $key
|
713 |
|
714 |
break;
|
715 |
|
716 |
+
case 'pepipostapi':
|
717 |
+
switch ( $key ) {
|
718 |
+
case 'api_key':
|
719 |
+
$return = defined( 'WPMS_PEPIPOST_API_KEY' ) && WPMS_PEPIPOST_API_KEY;
|
720 |
+
break;
|
721 |
+
}
|
722 |
+
|
723 |
+
break;
|
724 |
+
|
725 |
case 'license':
|
726 |
switch ( $key ) {
|
727 |
case 'key':
|
801 |
if (
|
802 |
! empty( $options['mail']['mailer'] ) &&
|
803 |
isset( $options[ $options['mail']['mailer'] ] ) &&
|
804 |
+
in_array( $options['mail']['mailer'], array( 'pepipost', 'pepipostapi', 'smtp', 'sendgrid', 'sendinblue', 'mailgun', 'gmail', 'outlook' ), true )
|
805 |
) {
|
806 |
|
807 |
$mailer = $options['mail']['mailer'];
|
829 |
$options[ $mailer ][ $option_name ] = $this->is_const_defined( $mailer, $option_name ) ? '' : trim( (string) $option_value );
|
830 |
break;
|
831 |
|
832 |
+
case 'api_key': // mailgun/sendgrid/sendinblue/pepipostapi.
|
833 |
case 'domain': // mailgun.
|
834 |
case 'client_id': // gmail/outlook/amazonses.
|
835 |
case 'client_secret': // gmail/outlook/amazonses.
|
910 |
}
|
911 |
|
912 |
/**
|
913 |
+
* Check whether the site is using Pepipost SMTP or not.
|
914 |
*
|
915 |
* @since 1.0.0
|
916 |
*
|
src/Processor.php
CHANGED
@@ -1,232 +1,232 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Class Processor modifies the behaviour of wp_mail() function.
|
7 |
-
*
|
8 |
-
* @since 1.0.0
|
9 |
-
*/
|
10 |
-
class Processor {
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Processor constructor.
|
14 |
-
*
|
15 |
-
* @since 1.0.0
|
16 |
-
*/
|
17 |
-
public function __construct() {
|
18 |
-
$this->hooks();
|
19 |
-
}
|
20 |
-
|
21 |
-
/**
|
22 |
-
* Assign all hooks to proper places.
|
23 |
-
*
|
24 |
-
* @since 1.0.0
|
25 |
-
*/
|
26 |
-
public function hooks() {
|
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 |
-
/**
|
35 |
-
* Redefine certain PHPMailer options with our custom ones.
|
36 |
-
*
|
37 |
-
* @since 1.0.0
|
38 |
-
*
|
39 |
-
* @param \PHPMailer $phpmailer It's passed by reference, so no need to return anything.
|
40 |
-
*/
|
41 |
-
public function phpmailer_init( $phpmailer ) {
|
42 |
-
|
43 |
-
$options = new Options();
|
44 |
-
$mailer = $options->get( 'mail', 'mailer' );
|
45 |
-
|
46 |
-
// Check that mailer is not blank, and if mailer=smtp, host is not blank.
|
47 |
-
if (
|
48 |
-
! $mailer ||
|
49 |
-
( 'smtp' === $mailer && ! $options->get( 'smtp', 'host' ) )
|
50 |
-
) {
|
51 |
-
return;
|
52 |
-
}
|
53 |
-
|
54 |
-
// If the mailer is pepipost, make sure we have a username and password.
|
55 |
-
if (
|
56 |
-
'pepipost' === $mailer &&
|
57 |
-
( ! $options->get( 'pepipost', 'user' ) && ! $options->get( 'pepipost', 'pass' ) )
|
58 |
-
) {
|
59 |
-
return;
|
60 |
-
}
|
61 |
-
|
62 |
-
// Set the mailer type as per config above, this overrides the already called isMail method.
|
63 |
-
// It's basically always 'smtp'.
|
64 |
-
$phpmailer->Mailer = $mailer;
|
65 |
-
|
66 |
-
// Set the Sender (return-path) if required.
|
67 |
-
if ( $options->get( 'mail', 'return_path' ) ) {
|
68 |
-
$phpmailer->Sender = $phpmailer->From;
|
69 |
-
}
|
70 |
-
|
71 |
-
// Set the SMTPSecure value, if set to none, leave this blank. Possible values: 'ssl', 'tls', ''.
|
72 |
-
if ( 'none' === $options->get( $mailer, 'encryption' ) ) {
|
73 |
-
$phpmailer->SMTPSecure = '';
|
74 |
-
} else {
|
75 |
-
$phpmailer->SMTPSecure = $options->get( $mailer, 'encryption' );
|
76 |
-
}
|
77 |
-
|
78 |
-
// Check if user has disabled SMTPAutoTLS.
|
79 |
-
if ( $options->get( $mailer, 'encryption' ) !== 'tls' && ! $options->get( $mailer, 'autotls' ) ) {
|
80 |
-
$phpmailer->SMTPAutoTLS = false;
|
81 |
-
}
|
82 |
-
|
83 |
-
// If we're sending via SMTP, set the host.
|
84 |
-
if ( 'smtp' === $mailer ) {
|
85 |
-
// Set the other options.
|
86 |
-
$phpmailer->Host = $options->get( $mailer, 'host' );
|
87 |
-
$phpmailer->Port = $options->get( $mailer, 'port' );
|
88 |
-
|
89 |
-
// If we're using smtp auth, set the username & password.
|
90 |
-
if ( $options->get( $mailer, 'auth' ) ) {
|
91 |
-
$phpmailer->SMTPAuth = true;
|
92 |
-
$phpmailer->Username = $options->get( $mailer, 'user' );
|
93 |
-
$phpmailer->Password = $options->get( $mailer, 'pass' );
|
94 |
-
}
|
95 |
-
} elseif ( 'pepipost' === $mailer ) {
|
96 |
-
// Set the Pepipost settings for BC.
|
97 |
-
$phpmailer->Mailer = 'smtp';
|
98 |
-
$phpmailer->Host = 'smtp.pepipost.com';
|
99 |
-
$phpmailer->Port = $options->get( $mailer, 'port' );
|
100 |
-
$phpmailer->SMTPSecure = $options->get( $mailer, 'encryption' ) === 'none' ? '' : $options->get( $mailer, 'encryption' );
|
101 |
-
$phpmailer->SMTPAuth = true;
|
102 |
-
$phpmailer->Username = $options->get( $mailer, 'user' );
|
103 |
-
$phpmailer->Password = $options->get( $mailer, 'pass' );
|
104 |
-
}
|
105 |
-
|
106 |
-
// You can add your own options here.
|
107 |
-
// See the phpmailer documentation for more info: https://github.com/PHPMailer/PHPMailer/tree/5.2-stable.
|
108 |
-
/** @noinspection PhpUnusedLocalVariableInspection It's passed by reference. */
|
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 |
-
* @since 1.5.0 Added a do_action() to be able to hook into.
|
117 |
-
*
|
118 |
-
* @param bool $is_sent
|
119 |
-
* @param array $to
|
120 |
-
* @param array $cc
|
121 |
-
* @param array $bcc
|
122 |
-
* @param string $subject
|
123 |
-
* @param string $body
|
124 |
-
* @param string $from
|
125 |
-
*/
|
126 |
-
public static function send_callback( $is_sent, $to, $cc, $bcc, $subject, $body, $from ) {
|
127 |
-
|
128 |
-
if ( ! $is_sent ) {
|
129 |
-
// Add mailer to the beginning and save to display later.
|
130 |
-
Debug::set(
|
131 |
-
'Mailer: ' . esc_html( wp_mail_smtp()->get_providers()->get_options( Options::init()->get( 'mail', 'mailer' ) )->get_title() ) . "\r\n" .
|
132 |
-
'PHPMailer was able to connect to SMTP server but failed while trying to send an email.'
|
133 |
-
);
|
134 |
-
} else {
|
135 |
-
Debug::clear();
|
136 |
-
}
|
137 |
-
|
138 |
-
do_action( 'wp_mail_smtp_mailcatcher_smtp_send_after', $is_sent, $to, $cc, $bcc, $subject, $body, $from );
|
139 |
-
}
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Modify the email address that is used for sending emails.
|
143 |
-
*
|
144 |
-
* @since 1.0.0
|
145 |
-
* @since 1.3.0 Forcing email rewrite if option is selected.
|
146 |
-
* @since 1.7.0 Default email may be empty, so pay attention to that as well.
|
147 |
-
*
|
148 |
-
* @param string $wp_email
|
149 |
-
*
|
150 |
-
* @return string
|
151 |
-
*/
|
152 |
-
public function filter_mail_from_email( $wp_email ) {
|
153 |
-
|
154 |
-
$options = new Options();
|
155 |
-
$forced = $options->get( 'mail', 'from_email_force' );
|
156 |
-
$from_email = $options->get( 'mail', 'from_email' );
|
157 |
-
$def_email = $this->get_default_email();
|
158 |
-
|
159 |
-
// Return FROM EMAIL if forced in settings.
|
160 |
-
if ( $forced & ! empty( $from_email ) ) {
|
161 |
-
return $from_email;
|
162 |
-
}
|
163 |
-
|
164 |
-
// If the FROM EMAIL is not the default, return it unchanged.
|
165 |
-
if ( ! empty( $def_email ) && $wp_email !== $def_email ) {
|
166 |
-
return $wp_email;
|
167 |
-
}
|
168 |
-
|
169 |
-
return ! empty( $from_email ) ? $from_email : $wp_email;
|
170 |
-
}
|
171 |
-
|
172 |
-
/**
|
173 |
-
* Modify the sender name that is used for sending emails.
|
174 |
-
*
|
175 |
-
* @since 1.0.0
|
176 |
-
* @since 1.3.0 Forcing name rewrite if option is selected.
|
177 |
-
*
|
178 |
-
* @param string $name
|
179 |
-
*
|
180 |
-
* @return string
|
181 |
-
*/
|
182 |
-
public function filter_mail_from_name( $name ) {
|
183 |
-
|
184 |
-
$options = new Options();
|
185 |
-
$force = $options->get( 'mail', 'from_name_force' );
|
186 |
-
|
187 |
-
// If the FROM NAME is not the default and not forced, return it unchanged.
|
188 |
-
if ( ! $force && $name !== $this->get_default_name() ) {
|
189 |
-
return $name;
|
190 |
-
}
|
191 |
-
|
192 |
-
$name = $options->get( 'mail', 'from_name' );
|
193 |
-
|
194 |
-
return $name;
|
195 |
-
}
|
196 |
-
|
197 |
-
/**
|
198 |
-
* Get the default email address based on domain name.
|
199 |
-
*
|
200 |
-
* @since 1.0.0
|
201 |
-
* @since 1.7.0 May return an empty string.
|
202 |
-
*
|
203 |
-
* @return string Empty string when we aren't able to get the site domain (CLI, misconfigured server etc).
|
204 |
-
*/
|
205 |
-
public function get_default_email() {
|
206 |
-
|
207 |
-
$server_name = Geo::get_site_domain();
|
208 |
-
|
209 |
-
if ( empty( $server_name ) ) {
|
210 |
-
return '';
|
211 |
-
}
|
212 |
-
|
213 |
-
// Get rid of www.
|
214 |
-
$sitename = strtolower( $server_name );
|
215 |
-
if ( substr( $sitename, 0, 4 ) === 'www.' ) {
|
216 |
-
$sitename = substr( $sitename, 4 );
|
217 |
-
}
|
218 |
-
|
219 |
-
return 'wordpress@' . $sitename;
|
220 |
-
}
|
221 |
-
|
222 |
-
/**
|
223 |
-
* Get the default email FROM NAME generated by WordPress.
|
224 |
-
*
|
225 |
-
* @since 1.3.0
|
226 |
-
*
|
227 |
-
* @return string
|
228 |
-
*/
|
229 |
-
public function get_default_name() {
|
230 |
-
return 'WordPress';
|
231 |
-
}
|
232 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class Processor modifies the behaviour of wp_mail() function.
|
7 |
+
*
|
8 |
+
* @since 1.0.0
|
9 |
+
*/
|
10 |
+
class Processor {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Processor constructor.
|
14 |
+
*
|
15 |
+
* @since 1.0.0
|
16 |
+
*/
|
17 |
+
public function __construct() {
|
18 |
+
$this->hooks();
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Assign all hooks to proper places.
|
23 |
+
*
|
24 |
+
* @since 1.0.0
|
25 |
+
*/
|
26 |
+
public function hooks() {
|
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 |
+
/**
|
35 |
+
* Redefine certain PHPMailer options with our custom ones.
|
36 |
+
*
|
37 |
+
* @since 1.0.0
|
38 |
+
*
|
39 |
+
* @param \PHPMailer $phpmailer It's passed by reference, so no need to return anything.
|
40 |
+
*/
|
41 |
+
public function phpmailer_init( $phpmailer ) {
|
42 |
+
|
43 |
+
$options = new Options();
|
44 |
+
$mailer = $options->get( 'mail', 'mailer' );
|
45 |
+
|
46 |
+
// Check that mailer is not blank, and if mailer=smtp, host is not blank.
|
47 |
+
if (
|
48 |
+
! $mailer ||
|
49 |
+
( 'smtp' === $mailer && ! $options->get( 'smtp', 'host' ) )
|
50 |
+
) {
|
51 |
+
return;
|
52 |
+
}
|
53 |
+
|
54 |
+
// If the mailer is pepipost, make sure we have a username and password.
|
55 |
+
if (
|
56 |
+
'pepipost' === $mailer &&
|
57 |
+
( ! $options->get( 'pepipost', 'user' ) && ! $options->get( 'pepipost', 'pass' ) )
|
58 |
+
) {
|
59 |
+
return;
|
60 |
+
}
|
61 |
+
|
62 |
+
// Set the mailer type as per config above, this overrides the already called isMail method.
|
63 |
+
// It's basically always 'smtp'.
|
64 |
+
$phpmailer->Mailer = $mailer;
|
65 |
+
|
66 |
+
// Set the Sender (return-path) if required.
|
67 |
+
if ( $options->get( 'mail', 'return_path' ) ) {
|
68 |
+
$phpmailer->Sender = $phpmailer->From;
|
69 |
+
}
|
70 |
+
|
71 |
+
// Set the SMTPSecure value, if set to none, leave this blank. Possible values: 'ssl', 'tls', ''.
|
72 |
+
if ( 'none' === $options->get( $mailer, 'encryption' ) ) {
|
73 |
+
$phpmailer->SMTPSecure = '';
|
74 |
+
} else {
|
75 |
+
$phpmailer->SMTPSecure = $options->get( $mailer, 'encryption' );
|
76 |
+
}
|
77 |
+
|
78 |
+
// Check if user has disabled SMTPAutoTLS.
|
79 |
+
if ( $options->get( $mailer, 'encryption' ) !== 'tls' && ! $options->get( $mailer, 'autotls' ) ) {
|
80 |
+
$phpmailer->SMTPAutoTLS = false;
|
81 |
+
}
|
82 |
+
|
83 |
+
// If we're sending via SMTP, set the host.
|
84 |
+
if ( 'smtp' === $mailer ) {
|
85 |
+
// Set the other options.
|
86 |
+
$phpmailer->Host = $options->get( $mailer, 'host' );
|
87 |
+
$phpmailer->Port = $options->get( $mailer, 'port' );
|
88 |
+
|
89 |
+
// If we're using smtp auth, set the username & password.
|
90 |
+
if ( $options->get( $mailer, 'auth' ) ) {
|
91 |
+
$phpmailer->SMTPAuth = true;
|
92 |
+
$phpmailer->Username = $options->get( $mailer, 'user' );
|
93 |
+
$phpmailer->Password = $options->get( $mailer, 'pass' );
|
94 |
+
}
|
95 |
+
} elseif ( 'pepipost' === $mailer ) {
|
96 |
+
// Set the Pepipost settings for BC.
|
97 |
+
$phpmailer->Mailer = 'smtp';
|
98 |
+
$phpmailer->Host = 'smtp.pepipost.com';
|
99 |
+
$phpmailer->Port = $options->get( $mailer, 'port' );
|
100 |
+
$phpmailer->SMTPSecure = $options->get( $mailer, 'encryption' ) === 'none' ? '' : $options->get( $mailer, 'encryption' );
|
101 |
+
$phpmailer->SMTPAuth = true;
|
102 |
+
$phpmailer->Username = $options->get( $mailer, 'user' );
|
103 |
+
$phpmailer->Password = $options->get( $mailer, 'pass' );
|
104 |
+
}
|
105 |
+
|
106 |
+
// You can add your own options here.
|
107 |
+
// See the phpmailer documentation for more info: https://github.com/PHPMailer/PHPMailer/tree/5.2-stable.
|
108 |
+
/** @noinspection PhpUnusedLocalVariableInspection It's passed by reference. */
|
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 |
+
* @since 1.5.0 Added a do_action() to be able to hook into.
|
117 |
+
*
|
118 |
+
* @param bool $is_sent
|
119 |
+
* @param array $to
|
120 |
+
* @param array $cc
|
121 |
+
* @param array $bcc
|
122 |
+
* @param string $subject
|
123 |
+
* @param string $body
|
124 |
+
* @param string $from
|
125 |
+
*/
|
126 |
+
public static function send_callback( $is_sent, $to, $cc, $bcc, $subject, $body, $from ) {
|
127 |
+
|
128 |
+
if ( ! $is_sent ) {
|
129 |
+
// Add mailer to the beginning and save to display later.
|
130 |
+
Debug::set(
|
131 |
+
'Mailer: ' . esc_html( wp_mail_smtp()->get_providers()->get_options( Options::init()->get( 'mail', 'mailer' ) )->get_title() ) . "\r\n" .
|
132 |
+
'PHPMailer was able to connect to SMTP server but failed while trying to send an email.'
|
133 |
+
);
|
134 |
+
} else {
|
135 |
+
Debug::clear();
|
136 |
+
}
|
137 |
+
|
138 |
+
do_action( 'wp_mail_smtp_mailcatcher_smtp_send_after', $is_sent, $to, $cc, $bcc, $subject, $body, $from );
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Modify the email address that is used for sending emails.
|
143 |
+
*
|
144 |
+
* @since 1.0.0
|
145 |
+
* @since 1.3.0 Forcing email rewrite if option is selected.
|
146 |
+
* @since 1.7.0 Default email may be empty, so pay attention to that as well.
|
147 |
+
*
|
148 |
+
* @param string $wp_email
|
149 |
+
*
|
150 |
+
* @return string
|
151 |
+
*/
|
152 |
+
public function filter_mail_from_email( $wp_email ) {
|
153 |
+
|
154 |
+
$options = new Options();
|
155 |
+
$forced = $options->get( 'mail', 'from_email_force' );
|
156 |
+
$from_email = $options->get( 'mail', 'from_email' );
|
157 |
+
$def_email = $this->get_default_email();
|
158 |
+
|
159 |
+
// Return FROM EMAIL if forced in settings.
|
160 |
+
if ( $forced & ! empty( $from_email ) ) {
|
161 |
+
return $from_email;
|
162 |
+
}
|
163 |
+
|
164 |
+
// If the FROM EMAIL is not the default, return it unchanged.
|
165 |
+
if ( ! empty( $def_email ) && $wp_email !== $def_email ) {
|
166 |
+
return $wp_email;
|
167 |
+
}
|
168 |
+
|
169 |
+
return ! empty( $from_email ) ? $from_email : $wp_email;
|
170 |
+
}
|
171 |
+
|
172 |
+
/**
|
173 |
+
* Modify the sender name that is used for sending emails.
|
174 |
+
*
|
175 |
+
* @since 1.0.0
|
176 |
+
* @since 1.3.0 Forcing name rewrite if option is selected.
|
177 |
+
*
|
178 |
+
* @param string $name
|
179 |
+
*
|
180 |
+
* @return string
|
181 |
+
*/
|
182 |
+
public function filter_mail_from_name( $name ) {
|
183 |
+
|
184 |
+
$options = new Options();
|
185 |
+
$force = $options->get( 'mail', 'from_name_force' );
|
186 |
+
|
187 |
+
// If the FROM NAME is not the default and not forced, return it unchanged.
|
188 |
+
if ( ! $force && $name !== $this->get_default_name() ) {
|
189 |
+
return $name;
|
190 |
+
}
|
191 |
+
|
192 |
+
$name = $options->get( 'mail', 'from_name' );
|
193 |
+
|
194 |
+
return $name;
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Get the default email address based on domain name.
|
199 |
+
*
|
200 |
+
* @since 1.0.0
|
201 |
+
* @since 1.7.0 May return an empty string.
|
202 |
+
*
|
203 |
+
* @return string Empty string when we aren't able to get the site domain (CLI, misconfigured server etc).
|
204 |
+
*/
|
205 |
+
public function get_default_email() {
|
206 |
+
|
207 |
+
$server_name = Geo::get_site_domain();
|
208 |
+
|
209 |
+
if ( empty( $server_name ) ) {
|
210 |
+
return '';
|
211 |
+
}
|
212 |
+
|
213 |
+
// Get rid of www.
|
214 |
+
$sitename = strtolower( $server_name );
|
215 |
+
if ( substr( $sitename, 0, 4 ) === 'www.' ) {
|
216 |
+
$sitename = substr( $sitename, 4 );
|
217 |
+
}
|
218 |
+
|
219 |
+
return 'wordpress@' . $sitename;
|
220 |
+
}
|
221 |
+
|
222 |
+
/**
|
223 |
+
* Get the default email FROM NAME generated by WordPress.
|
224 |
+
*
|
225 |
+
* @since 1.3.0
|
226 |
+
*
|
227 |
+
* @return string
|
228 |
+
*/
|
229 |
+
public function get_default_name() {
|
230 |
+
return 'WordPress';
|
231 |
+
}
|
232 |
+
}
|
src/Providers/Loader.php
CHANGED
@@ -1,204 +1,205 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers;
|
4 |
-
|
5 |
-
use WPMailSMTP\Debug;
|
6 |
-
use WPMailSMTP\MailCatcher;
|
7 |
-
use WPMailSMTP\Options;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Class Loader.
|
11 |
-
*
|
12 |
-
* @since 1.0.0
|
13 |
-
*/
|
14 |
-
class Loader {
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Key is the mailer option, value is the path to its classes.
|
18 |
-
*
|
19 |
-
* @since 1.0.0
|
20 |
-
* @since 1.6.0 Added Sendinblue.
|
21 |
-
* @since 1.7.0 Added AmazonSES/Outlook as indication of the Pro mailers.
|
22 |
-
*
|
23 |
-
* @var array
|
24 |
-
*/
|
25 |
-
protected $providers = array(
|
26 |
-
'mail'
|
27 |
-
'
|
28 |
-
'
|
29 |
-
'
|
30 |
-
'
|
31 |
-
'
|
32 |
-
'
|
33 |
-
'
|
34 |
-
'
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
*
|
40 |
-
*
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
*
|
47 |
-
*
|
48 |
-
*
|
49 |
-
*
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
*
|
63 |
-
*
|
64 |
-
*
|
65 |
-
*
|
66 |
-
*
|
67 |
-
*
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
$provider
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
*
|
85 |
-
*
|
86 |
-
*
|
87 |
-
*
|
88 |
-
*
|
89 |
-
*
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
*
|
99 |
-
*
|
100 |
-
*
|
101 |
-
*
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
$
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
*
|
131 |
-
*
|
132 |
-
*
|
133 |
-
*
|
134 |
-
* @param
|
135 |
-
*
|
136 |
-
*
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
$phpmailer instanceof
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
*
|
153 |
-
*
|
154 |
-
*
|
155 |
-
*
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
*
|
165 |
-
*
|
166 |
-
*
|
167 |
-
*
|
168 |
-
*
|
169 |
-
*
|
170 |
-
* @param string $
|
171 |
-
*
|
172 |
-
*
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
$
|
178 |
-
$
|
179 |
-
$
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
$
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
}
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers;
|
4 |
+
|
5 |
+
use WPMailSMTP\Debug;
|
6 |
+
use WPMailSMTP\MailCatcher;
|
7 |
+
use WPMailSMTP\Options;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Class Loader.
|
11 |
+
*
|
12 |
+
* @since 1.0.0
|
13 |
+
*/
|
14 |
+
class Loader {
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Key is the mailer option, value is the path to its classes.
|
18 |
+
*
|
19 |
+
* @since 1.0.0
|
20 |
+
* @since 1.6.0 Added Sendinblue.
|
21 |
+
* @since 1.7.0 Added AmazonSES/Outlook as indication of the Pro mailers.
|
22 |
+
*
|
23 |
+
* @var array
|
24 |
+
*/
|
25 |
+
protected $providers = array(
|
26 |
+
'mail' => 'WPMailSMTP\Providers\Mail\\',
|
27 |
+
'pepipostapi' => 'WPMailSMTP\Providers\PepipostAPI\\',
|
28 |
+
'sendinblue' => 'WPMailSMTP\Providers\Sendinblue\\',
|
29 |
+
'mailgun' => 'WPMailSMTP\Providers\Mailgun\\',
|
30 |
+
'sendgrid' => 'WPMailSMTP\Providers\Sendgrid\\',
|
31 |
+
'amazonses' => 'WPMailSMTP\Providers\AmazonSES\\',
|
32 |
+
'gmail' => 'WPMailSMTP\Providers\Gmail\\',
|
33 |
+
'outlook' => 'WPMailSMTP\Providers\Outlook\\',
|
34 |
+
'smtp' => 'WPMailSMTP\Providers\SMTP\\',
|
35 |
+
'pepipost' => 'WPMailSMTP\Providers\Pepipost\\',
|
36 |
+
);
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @since 1.0.0
|
40 |
+
*
|
41 |
+
* @var MailCatcher
|
42 |
+
*/
|
43 |
+
private $phpmailer;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Get all the supported providers.
|
47 |
+
*
|
48 |
+
* @since 1.0.0
|
49 |
+
*
|
50 |
+
* @return array
|
51 |
+
*/
|
52 |
+
public function get_providers() {
|
53 |
+
|
54 |
+
if ( ! Options::init()->is_pepipost_active() ) {
|
55 |
+
unset( $this->providers['pepipost'] );
|
56 |
+
}
|
57 |
+
|
58 |
+
return apply_filters( 'wp_mail_smtp_providers_loader_get_providers', $this->providers );
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Get a single provider FQN-path based on its name.
|
63 |
+
*
|
64 |
+
* @since 1.0.0
|
65 |
+
*
|
66 |
+
* @param string $provider
|
67 |
+
*
|
68 |
+
* @return string|null
|
69 |
+
*/
|
70 |
+
public function get_provider_path( $provider ) {
|
71 |
+
|
72 |
+
$provider = sanitize_key( $provider );
|
73 |
+
|
74 |
+
$providers = $this->get_providers();
|
75 |
+
|
76 |
+
return apply_filters(
|
77 |
+
'wp_mail_smtp_providers_loader_get_provider_path',
|
78 |
+
isset( $providers[ $provider ] ) ? $providers[ $provider ] : null,
|
79 |
+
$provider
|
80 |
+
);
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Get the provider options, if exists.
|
85 |
+
*
|
86 |
+
* @since 1.0.0
|
87 |
+
*
|
88 |
+
* @param string $provider
|
89 |
+
*
|
90 |
+
* @return OptionsAbstract|null
|
91 |
+
*/
|
92 |
+
public function get_options( $provider ) {
|
93 |
+
|
94 |
+
return $this->get_entity( $provider, 'Options' );
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Get all options of all providers.
|
99 |
+
*
|
100 |
+
* @since 1.0.0
|
101 |
+
*
|
102 |
+
* @return OptionsAbstract[]
|
103 |
+
*/
|
104 |
+
public function get_options_all() {
|
105 |
+
|
106 |
+
$options = array();
|
107 |
+
|
108 |
+
foreach ( $this->get_providers() as $provider => $path ) {
|
109 |
+
|
110 |
+
$option = $this->get_options( $provider );
|
111 |
+
|
112 |
+
if ( ! $option instanceof OptionsAbstract ) {
|
113 |
+
continue;
|
114 |
+
}
|
115 |
+
|
116 |
+
$slug = $option->get_slug();
|
117 |
+
$title = $option->get_title();
|
118 |
+
|
119 |
+
if ( empty( $title ) || empty( $slug ) ) {
|
120 |
+
continue;
|
121 |
+
}
|
122 |
+
|
123 |
+
$options[] = $option;
|
124 |
+
}
|
125 |
+
|
126 |
+
return apply_filters( 'wp_mail_smtp_providers_loader_get_providers_all', $options );
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Get the provider mailer, if exists.
|
131 |
+
*
|
132 |
+
* @since 1.0.0
|
133 |
+
*
|
134 |
+
* @param string $provider
|
135 |
+
* @param MailCatcher $phpmailer
|
136 |
+
*
|
137 |
+
* @return MailerAbstract|null
|
138 |
+
*/
|
139 |
+
public function get_mailer( $provider, $phpmailer ) {
|
140 |
+
|
141 |
+
if (
|
142 |
+
$phpmailer instanceof MailCatcher ||
|
143 |
+
$phpmailer instanceof \PHPMailer
|
144 |
+
) {
|
145 |
+
$this->phpmailer = $phpmailer;
|
146 |
+
}
|
147 |
+
|
148 |
+
return $this->get_entity( $provider, 'Mailer' );
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Get the provider auth, if exists.
|
153 |
+
*
|
154 |
+
* @param string $provider
|
155 |
+
*
|
156 |
+
* @return AuthAbstract|null
|
157 |
+
*/
|
158 |
+
public function get_auth( $provider ) {
|
159 |
+
|
160 |
+
return $this->get_entity( $provider, 'Auth' );
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Get a generic entity based on the request.
|
165 |
+
*
|
166 |
+
* @uses \ReflectionClass
|
167 |
+
*
|
168 |
+
* @since 1.0.0
|
169 |
+
*
|
170 |
+
* @param string $provider
|
171 |
+
* @param string $request
|
172 |
+
*
|
173 |
+
* @return OptionsAbstract|MailerAbstract|AuthAbstract|null
|
174 |
+
*/
|
175 |
+
protected function get_entity( $provider, $request ) {
|
176 |
+
|
177 |
+
$provider = sanitize_key( $provider );
|
178 |
+
$request = sanitize_text_field( $request );
|
179 |
+
$path = $this->get_provider_path( $provider );
|
180 |
+
$entity = null;
|
181 |
+
|
182 |
+
if ( empty( $path ) ) {
|
183 |
+
return $entity;
|
184 |
+
}
|
185 |
+
|
186 |
+
try {
|
187 |
+
$reflection = new \ReflectionClass( $path . $request );
|
188 |
+
|
189 |
+
if ( file_exists( $reflection->getFileName() ) ) {
|
190 |
+
$class = $path . $request;
|
191 |
+
if ( $this->phpmailer ) {
|
192 |
+
$entity = new $class( $this->phpmailer );
|
193 |
+
} else {
|
194 |
+
$entity = new $class();
|
195 |
+
}
|
196 |
+
}
|
197 |
+
}
|
198 |
+
catch ( \Exception $e ) {
|
199 |
+
Debug::set( "There was a problem while retrieving {$request} for {$provider}: {$e->getMessage()}" );
|
200 |
+
$entity = null;
|
201 |
+
}
|
202 |
+
|
203 |
+
return apply_filters( 'wp_mail_smtp_providers_loader_get_entity', $entity, $provider, $request );
|
204 |
+
}
|
205 |
+
}
|
src/Providers/MailerAbstract.php
CHANGED
@@ -223,7 +223,11 @@ abstract class MailerAbstract implements MailerInterface {
|
|
223 |
}
|
224 |
|
225 |
/**
|
226 |
-
*
|
|
|
|
|
|
|
|
|
227 |
*/
|
228 |
public function get_headers() {
|
229 |
|
@@ -231,15 +235,21 @@ abstract class MailerAbstract implements MailerInterface {
|
|
231 |
}
|
232 |
|
233 |
/**
|
234 |
-
*
|
|
|
|
|
|
|
235 |
*/
|
236 |
public function send() {
|
237 |
|
|
|
|
|
238 |
$params = Options::array_merge_recursive(
|
239 |
$this->get_default_params(),
|
240 |
array(
|
241 |
'headers' => $this->get_headers(),
|
242 |
'body' => $this->get_body(),
|
|
|
243 |
)
|
244 |
);
|
245 |
|
@@ -296,7 +306,13 @@ abstract class MailerAbstract implements MailerInterface {
|
|
296 |
}
|
297 |
|
298 |
/**
|
299 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
300 |
*/
|
301 |
public function is_email_sent() {
|
302 |
|
@@ -341,7 +357,11 @@ abstract class MailerAbstract implements MailerInterface {
|
|
341 |
}
|
342 |
|
343 |
/**
|
344 |
-
*
|
|
|
|
|
|
|
|
|
345 |
*/
|
346 |
public function is_php_compatible() {
|
347 |
|
223 |
}
|
224 |
|
225 |
/**
|
226 |
+
* Get the email headers.
|
227 |
+
*
|
228 |
+
* @since 1.0.0
|
229 |
+
*
|
230 |
+
* @return array
|
231 |
*/
|
232 |
public function get_headers() {
|
233 |
|
235 |
}
|
236 |
|
237 |
/**
|
238 |
+
* Send the email.
|
239 |
+
*
|
240 |
+
* @since 1.0.0
|
241 |
+
* @since 1.8.0 Added timeout for requests, same as max_execution_time.
|
242 |
*/
|
243 |
public function send() {
|
244 |
|
245 |
+
$timeout = (int) ini_get( 'max_execution_time' );
|
246 |
+
|
247 |
$params = Options::array_merge_recursive(
|
248 |
$this->get_default_params(),
|
249 |
array(
|
250 |
'headers' => $this->get_headers(),
|
251 |
'body' => $this->get_body(),
|
252 |
+
'timeout' => $timeout ? $timeout : 30,
|
253 |
)
|
254 |
);
|
255 |
|
306 |
}
|
307 |
|
308 |
/**
|
309 |
+
* Whether the email is sent or not.
|
310 |
+
* We basically check the response code from a request to provider.
|
311 |
+
* Might not be 100% correct, not guarantees that email is delivered.
|
312 |
+
*
|
313 |
+
* @since 1.0.0
|
314 |
+
*
|
315 |
+
* @return bool
|
316 |
*/
|
317 |
public function is_email_sent() {
|
318 |
|
357 |
}
|
358 |
|
359 |
/**
|
360 |
+
* Whether the mailer supports the current PHP version or not.
|
361 |
+
*
|
362 |
+
* @since 1.0.0
|
363 |
+
*
|
364 |
+
* @return bool
|
365 |
*/
|
366 |
public function is_php_compatible() {
|
367 |
|
src/Providers/Pepipost/Options.php
CHANGED
@@ -20,9 +20,9 @@ class Options extends OptionsAbstract {
|
|
20 |
|
21 |
parent::__construct(
|
22 |
array(
|
23 |
-
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/pepipost.png',
|
24 |
'slug' => 'pepipost',
|
25 |
-
'title' => esc_html__( 'Pepipost', 'wp-mail-smtp' ),
|
26 |
)
|
27 |
);
|
28 |
}
|
20 |
|
21 |
parent::__construct(
|
22 |
array(
|
23 |
+
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/pepipost-smtp.png',
|
24 |
'slug' => 'pepipost',
|
25 |
+
'title' => esc_html__( 'Pepipost SMTP', 'wp-mail-smtp' ),
|
26 |
)
|
27 |
);
|
28 |
}
|
src/Providers/PepipostAPI/Mailer.php
ADDED
@@ -0,0 +1,440 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers\PepipostAPI;
|
4 |
+
|
5 |
+
use WPMailSMTP\Providers\MailerAbstract;
|
6 |
+
use WPMailSMTP\WP;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class Mailer is basically a Sendgrid copy-paste, as Pepipost support SG migration.
|
10 |
+
* In the future we may rewrite the class to use the native Pepipost API.
|
11 |
+
*
|
12 |
+
* @since 1.8.0
|
13 |
+
*/
|
14 |
+
class Mailer extends MailerAbstract {
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Which response code from HTTP provider is considered to be successful?
|
18 |
+
*
|
19 |
+
* @since 1.8.0
|
20 |
+
*
|
21 |
+
* @var int
|
22 |
+
*/
|
23 |
+
protected $email_sent_code = 202;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* URL to make an API request to.
|
27 |
+
*
|
28 |
+
* @since 1.8.0
|
29 |
+
*
|
30 |
+
* @var string
|
31 |
+
*/
|
32 |
+
protected $url = 'https://sgapi.pepipost.com/v3/mail/send';
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Mailer constructor.
|
36 |
+
*
|
37 |
+
* @since 1.8.0
|
38 |
+
*
|
39 |
+
* @param \WPMailSMTP\MailCatcher $phpmailer
|
40 |
+
*/
|
41 |
+
public function __construct( $phpmailer ) {
|
42 |
+
|
43 |
+
// We want to prefill everything from \WPMailSMTP\MailCatcher class, which extends \PHPMailer.
|
44 |
+
parent::__construct( $phpmailer );
|
45 |
+
|
46 |
+
$this->set_header( 'Authorization', 'Bearer ' . $this->options->get( $this->mailer, 'api_key' ) );
|
47 |
+
$this->set_header( 'content-type', 'application/json' );
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Redefine the way email body is returned.
|
52 |
+
* By default we are sending an array of data.
|
53 |
+
* Pepipost requires a JSON, so we encode the body.
|
54 |
+
*
|
55 |
+
* @since 1.8.0
|
56 |
+
*
|
57 |
+
* @return string
|
58 |
+
*/
|
59 |
+
public function get_body() {
|
60 |
+
|
61 |
+
$body = parent::get_body();
|
62 |
+
|
63 |
+
return wp_json_encode( $body );
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Set the FROM header of the email.
|
68 |
+
*
|
69 |
+
* @since 1.8.0
|
70 |
+
*
|
71 |
+
* @param string $email From mail.
|
72 |
+
* @param string $name From name.
|
73 |
+
*/
|
74 |
+
public function set_from( $email, $name = '' ) {
|
75 |
+
|
76 |
+
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
|
77 |
+
return;
|
78 |
+
}
|
79 |
+
|
80 |
+
$from['email'] = $email;
|
81 |
+
|
82 |
+
if ( ! empty( $name ) ) {
|
83 |
+
$from['name'] = $name;
|
84 |
+
}
|
85 |
+
|
86 |
+
$this->set_body_param(
|
87 |
+
array(
|
88 |
+
'from' => $from,
|
89 |
+
)
|
90 |
+
);
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Set the names/emails of people who will receive the email.
|
95 |
+
*
|
96 |
+
* @since 1.8.0
|
97 |
+
*
|
98 |
+
* @param array $recipients List of recipients: cc/bcc/to.
|
99 |
+
*/
|
100 |
+
public function set_recipients( $recipients ) {
|
101 |
+
|
102 |
+
if ( empty( $recipients ) ) {
|
103 |
+
return;
|
104 |
+
}
|
105 |
+
|
106 |
+
// Allow for now only these recipient types.
|
107 |
+
$default = array( 'to', 'cc', 'bcc' );
|
108 |
+
$data = array();
|
109 |
+
|
110 |
+
foreach ( $recipients as $type => $emails ) {
|
111 |
+
if (
|
112 |
+
! in_array( $type, $default, true ) ||
|
113 |
+
empty( $emails ) ||
|
114 |
+
! is_array( $emails )
|
115 |
+
) {
|
116 |
+
continue;
|
117 |
+
}
|
118 |
+
|
119 |
+
$data[ $type ] = array();
|
120 |
+
|
121 |
+
// Iterate over all emails for each type.
|
122 |
+
// There might be multiple cc/to/bcc emails.
|
123 |
+
foreach ( $emails as $email ) {
|
124 |
+
$holder = array();
|
125 |
+
$addr = isset( $email[0] ) ? $email[0] : false;
|
126 |
+
$name = isset( $email[1] ) ? $email[1] : false;
|
127 |
+
|
128 |
+
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
|
129 |
+
continue;
|
130 |
+
}
|
131 |
+
|
132 |
+
$holder['email'] = $addr;
|
133 |
+
if ( ! empty( $name ) ) {
|
134 |
+
$holder['name'] = $name;
|
135 |
+
}
|
136 |
+
|
137 |
+
array_push( $data[ $type ], $holder );
|
138 |
+
}
|
139 |
+
}
|
140 |
+
|
141 |
+
if ( ! empty( $data ) ) {
|
142 |
+
$this->set_body_param(
|
143 |
+
array(
|
144 |
+
'personalizations' => array( $data ),
|
145 |
+
)
|
146 |
+
);
|
147 |
+
|
148 |
+
if ( ! empty( $data['bcc'] ) ) {
|
149 |
+
// Only the 1st BCC email address, ignore the rest - is not supported by Pepipost.
|
150 |
+
$bcc['mail_settings']['bcc']['email'] = $data['bcc'][0]['email'];
|
151 |
+
$this->set_body_param(
|
152 |
+
$bcc
|
153 |
+
);
|
154 |
+
}
|
155 |
+
}
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Set the email content.
|
160 |
+
*
|
161 |
+
* @since 1.8.0
|
162 |
+
*
|
163 |
+
* @param array|string $content Email content.
|
164 |
+
*/
|
165 |
+
public function set_content( $content ) {
|
166 |
+
|
167 |
+
if ( empty( $content ) ) {
|
168 |
+
return;
|
169 |
+
}
|
170 |
+
|
171 |
+
if ( is_array( $content ) ) {
|
172 |
+
|
173 |
+
$default = array( 'text', 'html' );
|
174 |
+
$data = array();
|
175 |
+
|
176 |
+
foreach ( $content as $type => $body ) {
|
177 |
+
if (
|
178 |
+
! in_array( $type, $default, true ) ||
|
179 |
+
empty( $body )
|
180 |
+
) {
|
181 |
+
continue;
|
182 |
+
}
|
183 |
+
|
184 |
+
$content_type = 'text/plain';
|
185 |
+
$content_value = $body;
|
186 |
+
|
187 |
+
if ( $type === 'html' ) {
|
188 |
+
$content_type = 'text/html';
|
189 |
+
}
|
190 |
+
|
191 |
+
$data[] = array(
|
192 |
+
'type' => $content_type,
|
193 |
+
'value' => $content_value,
|
194 |
+
);
|
195 |
+
}
|
196 |
+
|
197 |
+
$this->set_body_param(
|
198 |
+
array(
|
199 |
+
'content' => $data,
|
200 |
+
)
|
201 |
+
);
|
202 |
+
} else {
|
203 |
+
$data['type'] = 'text/html';
|
204 |
+
$data['value'] = $content;
|
205 |
+
|
206 |
+
if ( $this->phpmailer->ContentType === 'text/plain' ) {
|
207 |
+
$data['type'] = 'text/plain';
|
208 |
+
}
|
209 |
+
|
210 |
+
$this->set_body_param(
|
211 |
+
array(
|
212 |
+
'content' => array( $data ),
|
213 |
+
)
|
214 |
+
);
|
215 |
+
}
|
216 |
+
}
|
217 |
+
|
218 |
+
/**
|
219 |
+
* Redefine the way custom headers are processed for this mailer - they should be in body.
|
220 |
+
*
|
221 |
+
* @since 1.8.0
|
222 |
+
*
|
223 |
+
* @param array $headers
|
224 |
+
*/
|
225 |
+
public function set_headers( $headers ) {
|
226 |
+
|
227 |
+
foreach ( $headers as $header ) {
|
228 |
+
$name = isset( $header[0] ) ? $header[0] : false;
|
229 |
+
$value = isset( $header[1] ) ? $header[1] : false;
|
230 |
+
|
231 |
+
$this->set_body_header( $name, $value );
|
232 |
+
}
|
233 |
+
|
234 |
+
// Add custom PHPMailer-specific header.
|
235 |
+
$this->set_body_header( 'X-Mailer', 'WPMailSMTP/Mailer/' . $this->mailer . ' ' . WPMS_PLUGIN_VER );
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* This mailer supports email-related custom headers inside a body of the message.
|
240 |
+
*
|
241 |
+
* @since 1.8.0
|
242 |
+
*
|
243 |
+
* @param string $name
|
244 |
+
* @param string $value
|
245 |
+
*/
|
246 |
+
public function set_body_header( $name, $value ) {
|
247 |
+
|
248 |
+
$name = sanitize_text_field( $name );
|
249 |
+
if ( empty( $name ) ) {
|
250 |
+
return;
|
251 |
+
}
|
252 |
+
|
253 |
+
$headers = isset( $this->body['headers'] ) ? (array) $this->body['headers'] : array();
|
254 |
+
|
255 |
+
$headers[ $name ] = WP::sanitize_value( $value );
|
256 |
+
|
257 |
+
$this->set_body_param(
|
258 |
+
array(
|
259 |
+
'headers' => $headers,
|
260 |
+
)
|
261 |
+
);
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* Pepipost accepts an array of files content in body, so we will include all files and send.
|
266 |
+
* Doesn't handle exceeding the limits etc, as this is done and reported by SendGrid API.
|
267 |
+
*
|
268 |
+
* @since 1.8.0
|
269 |
+
*
|
270 |
+
* @param array $attachments
|
271 |
+
*/
|
272 |
+
public function set_attachments( $attachments ) {
|
273 |
+
|
274 |
+
if ( empty( $attachments ) ) {
|
275 |
+
return;
|
276 |
+
}
|
277 |
+
|
278 |
+
$data = array();
|
279 |
+
|
280 |
+
foreach ( $attachments as $attachment ) {
|
281 |
+
$file = false;
|
282 |
+
|
283 |
+
/*
|
284 |
+
* We are not using WP_Filesystem API as we can't reliably work with it.
|
285 |
+
* It is not always available, same as credentials for FTP.
|
286 |
+
*/
|
287 |
+
try {
|
288 |
+
if ( is_file( $attachment[0] ) && is_readable( $attachment[0] ) ) {
|
289 |
+
$file = file_get_contents( $attachment[0] ); // phpcs:ignore
|
290 |
+
}
|
291 |
+
}
|
292 |
+
catch ( \Exception $e ) {
|
293 |
+
$file = false;
|
294 |
+
}
|
295 |
+
|
296 |
+
if ( $file === false ) {
|
297 |
+
continue;
|
298 |
+
}
|
299 |
+
|
300 |
+
$data[] = array(
|
301 |
+
'content' => base64_encode( $file ),
|
302 |
+
'type' => $attachment[4],
|
303 |
+
'filename' => $attachment[2],
|
304 |
+
'disposition' => $attachment[6],
|
305 |
+
);
|
306 |
+
}
|
307 |
+
|
308 |
+
if ( ! empty( $data ) ) {
|
309 |
+
$this->set_body_param(
|
310 |
+
array(
|
311 |
+
'attachments' => $data,
|
312 |
+
)
|
313 |
+
);
|
314 |
+
}
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* Set the reply-to property of the email.
|
319 |
+
*
|
320 |
+
* @since 1.8.0
|
321 |
+
*
|
322 |
+
* @param array $reply_to Name/email for reply-to feature.
|
323 |
+
*/
|
324 |
+
public function set_reply_to( $reply_to ) {
|
325 |
+
|
326 |
+
if ( empty( $reply_to ) ) {
|
327 |
+
return;
|
328 |
+
}
|
329 |
+
|
330 |
+
$data = array();
|
331 |
+
|
332 |
+
foreach ( $reply_to as $key => $emails ) {
|
333 |
+
if (
|
334 |
+
empty( $emails ) ||
|
335 |
+
! is_array( $emails )
|
336 |
+
) {
|
337 |
+
continue;
|
338 |
+
}
|
339 |
+
|
340 |
+
$addr = isset( $emails[0] ) ? $emails[0] : false;
|
341 |
+
$name = isset( $emails[1] ) ? $emails[1] : false;
|
342 |
+
|
343 |
+
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
|
344 |
+
continue;
|
345 |
+
}
|
346 |
+
|
347 |
+
$data['email'] = $addr;
|
348 |
+
if ( ! empty( $name ) ) {
|
349 |
+
$data['name'] = $name;
|
350 |
+
}
|
351 |
+
}
|
352 |
+
|
353 |
+
if ( ! empty( $data ) ) {
|
354 |
+
$this->set_body_param(
|
355 |
+
array(
|
356 |
+
'reply_to' => $data,
|
357 |
+
)
|
358 |
+
);
|
359 |
+
}
|
360 |
+
}
|
361 |
+
|
362 |
+
/**
|
363 |
+
* Pepipost doesn't support sender or return_path params.
|
364 |
+
* So we do nothing.
|
365 |
+
*
|
366 |
+
* @since 1.8.0
|
367 |
+
*
|
368 |
+
* @param string $from_email
|
369 |
+
*/
|
370 |
+
public function set_return_path( $from_email ) {}
|
371 |
+
|
372 |
+
/**
|
373 |
+
* Get a Pepipost-specific response with a helpful error.
|
374 |
+
*
|
375 |
+
* @see https://developers.pepipost.com/migration-api/new-subpage/errorcodes
|
376 |
+
*
|
377 |
+
* @since 1.8.0
|
378 |
+
*
|
379 |
+
* @return string
|
380 |
+
*/
|
381 |
+
protected function get_response_error() {
|
382 |
+
|
383 |
+
$body = (array) wp_remote_retrieve_body( $this->response );
|
384 |
+
|
385 |
+
$error_text = array();
|
386 |
+
|
387 |
+
if ( ! empty( $body['errors'] ) ) {
|
388 |
+
foreach ( $body['errors'] as $error ) {
|
389 |
+
if ( property_exists( $error, 'message' ) ) {
|
390 |
+
// Prepare additional information from SendGrid API.
|
391 |
+
$extra = '';
|
392 |
+
if ( property_exists( $error, 'field' ) && ! empty( $error->field ) ) {
|
393 |
+
$extra .= $error->field . '; ';
|
394 |
+
}
|
395 |
+
if ( property_exists( $error, 'help' ) && ! empty( $error->help ) ) {
|
396 |
+
$extra .= $error->help;
|
397 |
+
}
|
398 |
+
|
399 |
+
// Assign both the main message and perhaps extra information, if exists.
|
400 |
+
$error_text[] = $error->message . ( ! empty( $extra ) ? ' - ' . $extra : '' );
|
401 |
+
}
|
402 |
+
}
|
403 |
+
}
|
404 |
+
|
405 |
+
return implode( '<br>', array_map( 'esc_textarea', $error_text ) );
|
406 |
+
}
|
407 |
+
|
408 |
+
/**
|
409 |
+
* Get mailer debug information, that is helpful during support.
|
410 |
+
*
|
411 |
+
* @since 1.8.0
|
412 |
+
*
|
413 |
+
* @return string
|
414 |
+
*/
|
415 |
+
public function get_debug_info() {
|
416 |
+
|
417 |
+
$sendgrid_text[] = '<strong>Api Key:</strong> ' . ( $this->is_mailer_complete() ? 'Yes' : 'No' );
|
418 |
+
|
419 |
+
return implode( '<br>', $sendgrid_text );
|
420 |
+
}
|
421 |
+
|
422 |
+
/**
|
423 |
+
* Whether the mailer has all its settings correctly set up and saved.
|
424 |
+
*
|
425 |
+
* @since 1.8.0
|
426 |
+
*
|
427 |
+
* @return bool
|
428 |
+
*/
|
429 |
+
public function is_mailer_complete() {
|
430 |
+
|
431 |
+
$options = $this->options->get_group( $this->mailer );
|
432 |
+
|
433 |
+
// API key is the only required option.
|
434 |
+
if ( ! empty( $options['api_key'] ) ) {
|
435 |
+
return true;
|
436 |
+
}
|
437 |
+
|
438 |
+
return false;
|
439 |
+
}
|
440 |
+
}
|
src/Providers/PepipostAPI/Options.php
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers\PepipostAPI;
|
4 |
+
|
5 |
+
use WPMailSMTP\Providers\OptionsAbstract;
|
6 |
+
use WPMailSMTP\Options as PluginOptions;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class Options.
|
10 |
+
*
|
11 |
+
* @since 1.8.0
|
12 |
+
*/
|
13 |
+
class Options extends OptionsAbstract {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Mailer slug.
|
17 |
+
*
|
18 |
+
* @since 1.8.0
|
19 |
+
*/
|
20 |
+
const SLUG = 'pepipostapi';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Options constructor.
|
24 |
+
*
|
25 |
+
* @since 1.8.0
|
26 |
+
*/
|
27 |
+
public function __construct() {
|
28 |
+
|
29 |
+
$description = sprintf(
|
30 |
+
wp_kses( /* translators: %1$s - URL to pepipost.com site. */
|
31 |
+
__( '<strong><a href="%1$s" target="_blank" rel="noopener noreferrer">Pepipost</a> is a recommended transactional email service.</strong> Every month Pepipost delivers over 8 billion emails from 20,000+ customers. Their mission is to reliably send emails in the most efficient way and at the most disruptive pricing ever. Pepipost provides users 30,000 free emails the first 30 days, then 100 emails per day.', 'wp-mail-smtp' ) .
|
32 |
+
'<br><br>' .
|
33 |
+
/* translators: %1$s - URL to wpmailsmtp.com doc. */
|
34 |
+
__( 'Read our <a href="%2$s" target="_blank" rel="noopener noreferrer">Pepipost documentation</a> to learn how to configure Pepipost and improve your email deliverability.', 'wp-mail-smtp' ),
|
35 |
+
array(
|
36 |
+
'br' => true,
|
37 |
+
'strong' => true,
|
38 |
+
'a' => array(
|
39 |
+
'href' => true,
|
40 |
+
'rel' => true,
|
41 |
+
'target' => true,
|
42 |
+
),
|
43 |
+
)
|
44 |
+
),
|
45 |
+
'https://wpmailsmtp.com/go/pepipost/',
|
46 |
+
'https://wpmailsmtp.com/docs/how-to-set-up-the-pepipost-mailer-in-wp-mail-smtp'
|
47 |
+
);
|
48 |
+
|
49 |
+
$api_key = PluginOptions::init()->get( self::SLUG, 'api_key' );
|
50 |
+
|
51 |
+
if ( empty( $api_key ) ) {
|
52 |
+
$description .= '</p><p class="buttonned"><a href="https://wpmailsmtp.com/go/pepipost/" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-blueish">' .
|
53 |
+
esc_html__( 'Get Pepipost Now (Free)', 'wp-mail-smtp' ) .
|
54 |
+
'</a></p>';
|
55 |
+
}
|
56 |
+
|
57 |
+
parent::__construct(
|
58 |
+
array(
|
59 |
+
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/pepipost.png',
|
60 |
+
'slug' => self::SLUG,
|
61 |
+
'title' => esc_html__( 'Pepipost', 'wp-mail-smtp' ),
|
62 |
+
'description' => $description,
|
63 |
+
'recommended' => true,
|
64 |
+
'php' => '5.3',
|
65 |
+
)
|
66 |
+
);
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Output the mailer provider options.
|
71 |
+
*
|
72 |
+
* @since 1.8.0
|
73 |
+
*/
|
74 |
+
public function display_options() {
|
75 |
+
|
76 |
+
// Do not display options if PHP version is not correct.
|
77 |
+
if ( ! $this->is_php_correct() ) {
|
78 |
+
$this->display_php_warning();
|
79 |
+
|
80 |
+
return;
|
81 |
+
}
|
82 |
+
?>
|
83 |
+
|
84 |
+
<!-- API Key -->
|
85 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_id"
|
86 |
+
class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
87 |
+
<div class="wp-mail-smtp-setting-label">
|
88 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'API Key', 'wp-mail-smtp' ); ?></label>
|
89 |
+
</div>
|
90 |
+
<div class="wp-mail-smtp-setting-field">
|
91 |
+
<?php if ( $this->options->is_const_defined( $this->get_slug(), 'api_key' ) ) : ?>
|
92 |
+
<input type="text" disabled value="****************************************"
|
93 |
+
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
|
94 |
+
/>
|
95 |
+
<?php $this->display_const_set_message( 'WPMS_PEPIPOST_API_KEY' ); ?>
|
96 |
+
<?php else : ?>
|
97 |
+
<input type="password" spellcheck="false"
|
98 |
+
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]"
|
99 |
+
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'api_key' ) ); ?>"
|
100 |
+
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
|
101 |
+
/>
|
102 |
+
<?php endif; ?>
|
103 |
+
|
104 |
+
<p class="desc">
|
105 |
+
<?php
|
106 |
+
printf( /* translators: %s - pepipost.com link to get an API Key. */
|
107 |
+
esc_html__( 'Follow this link to get an API Key: %s.', 'wp-mail-smtp' ),
|
108 |
+
'<a href="https://app.pepipost.com/app/settings/integration" target="_blank" rel="noopener noreferrer">' .
|
109 |
+
esc_html__( 'Get the API Key', 'wp-mail-smtp' ) .
|
110 |
+
'</a>'
|
111 |
+
);
|
112 |
+
?>
|
113 |
+
</p>
|
114 |
+
</div>
|
115 |
+
</div>
|
116 |
+
|
117 |
+
<?php
|
118 |
+
}
|
119 |
+
}
|
src/Providers/Sendgrid/Mailer.php
CHANGED
@@ -278,6 +278,7 @@ class Mailer extends MailerAbstract {
|
|
278 |
'type' => $attachment[4],
|
279 |
'filename' => $attachment[2],
|
280 |
'disposition' => $attachment[6],
|
|
|
281 |
);
|
282 |
}
|
283 |
|
278 |
'type' => $attachment[4],
|
279 |
'filename' => $attachment[2],
|
280 |
'disposition' => $attachment[6],
|
281 |
+
'content_id' => $attachment[7],
|
282 |
);
|
283 |
}
|
284 |
|
src/Providers/Sendinblue/Options.php
CHANGED
@@ -1,119 +1,119 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers\Sendinblue;
|
4 |
-
|
5 |
-
use WPMailSMTP\Providers\OptionsAbstract;
|
6 |
-
use WPMailSMTP\Options as PluginOptions;
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Class
|
10 |
-
*
|
11 |
-
* @since 1.6.0
|
12 |
-
*/
|
13 |
-
class Options extends OptionsAbstract {
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Mailer slug.
|
17 |
-
*
|
18 |
-
* @since 1.6.0
|
19 |
-
*/
|
20 |
-
const SLUG = 'sendinblue';
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Options constructor.
|
24 |
-
*
|
25 |
-
* @since 1.6.0
|
26 |
-
*/
|
27 |
-
public function __construct() {
|
28 |
-
|
29 |
-
$description = sprintf(
|
30 |
-
wp_kses( /* translators: %1$s - URL to sendinblue.com site. */
|
31 |
-
__( '<strong><a href="%1$s" target="_blank" rel="noopener noreferrer">Sendinblue</a> is
|
32 |
-
'<br><br>' .
|
33 |
-
/* translators: %2$s - URL to wpmailsmtp.com doc. */
|
34 |
-
__( 'Read our <a href="%2$s" target="_blank" rel="noopener noreferrer">Sendinblue documentation</a> to learn how to configure Sendinblue and improve your email deliverability.', 'wp-mail-smtp' ),
|
35 |
-
array(
|
36 |
-
'br' => true,
|
37 |
-
'strong' => true,
|
38 |
-
'a' => array(
|
39 |
-
'href' => true,
|
40 |
-
'rel' => true,
|
41 |
-
'target' => true,
|
42 |
-
),
|
43 |
-
)
|
44 |
-
),
|
45 |
-
'https://wpmailsmtp.com/go/sendinblue/',
|
46 |
-
'https://wpmailsmtp.com/docs/how-to-set-up-the-sendinblue-mailer-in-wp-mail-smtp'
|
47 |
-
);
|
48 |
-
|
49 |
-
$api_key = PluginOptions::init()->get( self::SLUG, 'api_key' );
|
50 |
-
|
51 |
-
if ( empty( $api_key ) ) {
|
52 |
-
$description .= '</p><p class="buttonned"><a href="https://wpmailsmtp.com/go/sendinblue/" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-blueish">' .
|
53 |
-
esc_html__( 'Get Sendinblue Now (Free)', 'wp-mail-smtp' ) .
|
54 |
-
'</a></p>';
|
55 |
-
}
|
56 |
-
|
57 |
-
parent::__construct(
|
58 |
-
array(
|
59 |
-
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/sendinblue.svg',
|
60 |
-
'slug' => self::SLUG,
|
61 |
-
'title' => esc_html__( 'Sendinblue', 'wp-mail-smtp' ),
|
62 |
-
'description' => $description,
|
63 |
-
'recommended' => true,
|
64 |
-
'php' => '5.6',
|
65 |
-
)
|
66 |
-
);
|
67 |
-
}
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Output the mailer provider options.
|
71 |
-
*
|
72 |
-
* @since 1.6.0
|
73 |
-
*/
|
74 |
-
public function display_options() {
|
75 |
-
|
76 |
-
// Do not display options if PHP version is not correct.
|
77 |
-
if ( ! $this->is_php_correct() ) {
|
78 |
-
$this->display_php_warning();
|
79 |
-
|
80 |
-
return;
|
81 |
-
}
|
82 |
-
?>
|
83 |
-
|
84 |
-
<!-- API Key -->
|
85 |
-
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_id"
|
86 |
-
class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
87 |
-
<div class="wp-mail-smtp-setting-label">
|
88 |
-
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'API Key', 'wp-mail-smtp' ); ?></label>
|
89 |
-
</div>
|
90 |
-
<div class="wp-mail-smtp-setting-field">
|
91 |
-
<?php if ( $this->options->is_const_defined( $this->get_slug(), 'api_key' ) ) : ?>
|
92 |
-
<input type="text" disabled value="****************************************"
|
93 |
-
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
|
94 |
-
/>
|
95 |
-
<?php $this->display_const_set_message( 'WPMS_SENDINBLUE_API_KEY' ); ?>
|
96 |
-
<?php else : ?>
|
97 |
-
<input type="password" spellcheck="false"
|
98 |
-
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]"
|
99 |
-
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'api_key' ) ); ?>"
|
100 |
-
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
|
101 |
-
/>
|
102 |
-
<?php endif; ?>
|
103 |
-
|
104 |
-
<p class="desc">
|
105 |
-
<?php
|
106 |
-
printf( /* translators: %s - sendinblue.com link to get an API Key. */
|
107 |
-
esc_html__( 'Follow this link to get an API Key: %s.', 'wp-mail-smtp' ),
|
108 |
-
'<a href="https://account.sendinblue.com/advanced/api" target="_blank" rel="noopener noreferrer">' .
|
109 |
-
esc_html__( 'Get v3 API Key', 'wp-mail-smtp' ) .
|
110 |
-
'</a>'
|
111 |
-
);
|
112 |
-
?>
|
113 |
-
</p>
|
114 |
-
</div>
|
115 |
-
</div>
|
116 |
-
|
117 |
-
<?php
|
118 |
-
}
|
119 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers\Sendinblue;
|
4 |
+
|
5 |
+
use WPMailSMTP\Providers\OptionsAbstract;
|
6 |
+
use WPMailSMTP\Options as PluginOptions;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class Options.
|
10 |
+
*
|
11 |
+
* @since 1.6.0
|
12 |
+
*/
|
13 |
+
class Options extends OptionsAbstract {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Mailer slug.
|
17 |
+
*
|
18 |
+
* @since 1.6.0
|
19 |
+
*/
|
20 |
+
const SLUG = 'sendinblue';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Options constructor.
|
24 |
+
*
|
25 |
+
* @since 1.6.0
|
26 |
+
*/
|
27 |
+
public function __construct() {
|
28 |
+
|
29 |
+
$description = sprintf(
|
30 |
+
wp_kses( /* translators: %1$s - URL to sendinblue.com site. */
|
31 |
+
__( '<strong><a href="%1$s" target="_blank" rel="noopener noreferrer">Sendinblue</a> is a recommended transactional email service.</strong> Founded in 2012, they serve 80,000+ growing companies around the world and send over 30 million emails each day. They understand that transactional emails are the heart of your customer relationships. Their email deliverability experts are constantly at work optimizing the reliability and speed of their SMTP infrastructure. Sendinblue provides users 300 free emails per day.', 'wp-mail-smtp' ) .
|
32 |
+
'<br><br>' .
|
33 |
+
/* translators: %2$s - URL to wpmailsmtp.com doc. */
|
34 |
+
__( 'Read our <a href="%2$s" target="_blank" rel="noopener noreferrer">Sendinblue documentation</a> to learn how to configure Sendinblue and improve your email deliverability.', 'wp-mail-smtp' ),
|
35 |
+
array(
|
36 |
+
'br' => true,
|
37 |
+
'strong' => true,
|
38 |
+
'a' => array(
|
39 |
+
'href' => true,
|
40 |
+
'rel' => true,
|
41 |
+
'target' => true,
|
42 |
+
),
|
43 |
+
)
|
44 |
+
),
|
45 |
+
'https://wpmailsmtp.com/go/sendinblue/',
|
46 |
+
'https://wpmailsmtp.com/docs/how-to-set-up-the-sendinblue-mailer-in-wp-mail-smtp'
|
47 |
+
);
|
48 |
+
|
49 |
+
$api_key = PluginOptions::init()->get( self::SLUG, 'api_key' );
|
50 |
+
|
51 |
+
if ( empty( $api_key ) ) {
|
52 |
+
$description .= '</p><p class="buttonned"><a href="https://wpmailsmtp.com/go/sendinblue/" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-blueish">' .
|
53 |
+
esc_html__( 'Get Sendinblue Now (Free)', 'wp-mail-smtp' ) .
|
54 |
+
'</a></p>';
|
55 |
+
}
|
56 |
+
|
57 |
+
parent::__construct(
|
58 |
+
array(
|
59 |
+
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/sendinblue.svg',
|
60 |
+
'slug' => self::SLUG,
|
61 |
+
'title' => esc_html__( 'Sendinblue', 'wp-mail-smtp' ),
|
62 |
+
'description' => $description,
|
63 |
+
'recommended' => true,
|
64 |
+
'php' => '5.6',
|
65 |
+
)
|
66 |
+
);
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Output the mailer provider options.
|
71 |
+
*
|
72 |
+
* @since 1.6.0
|
73 |
+
*/
|
74 |
+
public function display_options() {
|
75 |
+
|
76 |
+
// Do not display options if PHP version is not correct.
|
77 |
+
if ( ! $this->is_php_correct() ) {
|
78 |
+
$this->display_php_warning();
|
79 |
+
|
80 |
+
return;
|
81 |
+
}
|
82 |
+
?>
|
83 |
+
|
84 |
+
<!-- API Key -->
|
85 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_id"
|
86 |
+
class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
87 |
+
<div class="wp-mail-smtp-setting-label">
|
88 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'API Key', 'wp-mail-smtp' ); ?></label>
|
89 |
+
</div>
|
90 |
+
<div class="wp-mail-smtp-setting-field">
|
91 |
+
<?php if ( $this->options->is_const_defined( $this->get_slug(), 'api_key' ) ) : ?>
|
92 |
+
<input type="text" disabled value="****************************************"
|
93 |
+
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
|
94 |
+
/>
|
95 |
+
<?php $this->display_const_set_message( 'WPMS_SENDINBLUE_API_KEY' ); ?>
|
96 |
+
<?php else : ?>
|
97 |
+
<input type="password" spellcheck="false"
|
98 |
+
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]"
|
99 |
+
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'api_key' ) ); ?>"
|
100 |
+
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
|
101 |
+
/>
|
102 |
+
<?php endif; ?>
|
103 |
+
|
104 |
+
<p class="desc">
|
105 |
+
<?php
|
106 |
+
printf( /* translators: %s - sendinblue.com link to get an API Key. */
|
107 |
+
esc_html__( 'Follow this link to get an API Key: %s.', 'wp-mail-smtp' ),
|
108 |
+
'<a href="https://account.sendinblue.com/advanced/api" target="_blank" rel="noopener noreferrer">' .
|
109 |
+
esc_html__( 'Get v3 API Key', 'wp-mail-smtp' ) .
|
110 |
+
'</a>'
|
111 |
+
);
|
112 |
+
?>
|
113 |
+
</p>
|
114 |
+
</div>
|
115 |
+
</div>
|
116 |
+
|
117 |
+
<?php
|
118 |
+
}
|
119 |
+
}
|
vendor/guzzlehttp/guzzle/phpstan-baseline.neon
ADDED
@@ -0,0 +1,1412 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
parameters:
|
2 |
+
ignoreErrors:
|
3 |
+
-
|
4 |
+
message: "#^Property GuzzleHttp\\\\Client\\:\\:\\$config type has no value type specified in iterable type array\\.$#"
|
5 |
+
count: 1
|
6 |
+
path: src/Client.php
|
7 |
+
|
8 |
+
-
|
9 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:__construct\\(\\) has parameter \\$config with no value type specified in iterable type array\\.$#"
|
10 |
+
count: 1
|
11 |
+
path: src/Client.php
|
12 |
+
|
13 |
+
-
|
14 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:__call\\(\\) has parameter \\$args with no value type specified in iterable type array\\.$#"
|
15 |
+
count: 1
|
16 |
+
path: src/Client.php
|
17 |
+
|
18 |
+
-
|
19 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:__call\\(\\) should return GuzzleHttp\\\\Promise\\\\PromiseInterface but returns GuzzleHttp\\\\PromiseInterface\\|Psr\\\\Http\\\\Message\\\\ResponseInterface\\.$#"
|
20 |
+
count: 1
|
21 |
+
path: src/Client.php
|
22 |
+
|
23 |
+
-
|
24 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:sendAsync\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
25 |
+
count: 1
|
26 |
+
path: src/Client.php
|
27 |
+
|
28 |
+
-
|
29 |
+
message: "#^Return typehint of method GuzzleHttp\\\\Client\\:\\:sendAsync\\(\\) has invalid type GuzzleHttp\\\\PromiseInterface\\.$#"
|
30 |
+
count: 1
|
31 |
+
path: src/Client.php
|
32 |
+
|
33 |
+
-
|
34 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:sendAsync\\(\\) should return GuzzleHttp\\\\PromiseInterface but returns GuzzleHttp\\\\Promise\\\\PromiseInterface\\.$#"
|
35 |
+
count: 1
|
36 |
+
path: src/Client.php
|
37 |
+
|
38 |
+
-
|
39 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:send\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
40 |
+
count: 1
|
41 |
+
path: src/Client.php
|
42 |
+
|
43 |
+
-
|
44 |
+
message: "#^PHPDoc tag @throws with type GuzzleHttp\\\\GuzzleException is not subtype of Throwable$#"
|
45 |
+
count: 2
|
46 |
+
path: src/Client.php
|
47 |
+
|
48 |
+
-
|
49 |
+
message: "#^Call to method wait\\(\\) on an unknown class GuzzleHttp\\\\PromiseInterface\\.$#"
|
50 |
+
count: 2
|
51 |
+
path: src/Client.php
|
52 |
+
|
53 |
+
-
|
54 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:requestAsync\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
55 |
+
count: 1
|
56 |
+
path: src/Client.php
|
57 |
+
|
58 |
+
-
|
59 |
+
message: "#^Return typehint of method GuzzleHttp\\\\Client\\:\\:requestAsync\\(\\) has invalid type GuzzleHttp\\\\PromiseInterface\\.$#"
|
60 |
+
count: 1
|
61 |
+
path: src/Client.php
|
62 |
+
|
63 |
+
-
|
64 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:requestAsync\\(\\) should return GuzzleHttp\\\\PromiseInterface but returns GuzzleHttp\\\\Promise\\\\PromiseInterface\\.$#"
|
65 |
+
count: 1
|
66 |
+
path: src/Client.php
|
67 |
+
|
68 |
+
-
|
69 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:request\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
70 |
+
count: 1
|
71 |
+
path: src/Client.php
|
72 |
+
|
73 |
+
-
|
74 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:buildUri\\(\\) has parameter \\$config with no value type specified in iterable type array\\.$#"
|
75 |
+
count: 1
|
76 |
+
path: src/Client.php
|
77 |
+
|
78 |
+
-
|
79 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:configureDefaults\\(\\) has parameter \\$config with no value type specified in iterable type array\\.$#"
|
80 |
+
count: 1
|
81 |
+
path: src/Client.php
|
82 |
+
|
83 |
+
-
|
84 |
+
message: "#^Parameter \\#1 \\$str of function strtolower expects string, int\\|string given\\.$#"
|
85 |
+
count: 1
|
86 |
+
path: src/Client.php
|
87 |
+
|
88 |
+
-
|
89 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:prepareDefaults\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
90 |
+
count: 1
|
91 |
+
path: src/Client.php
|
92 |
+
|
93 |
+
-
|
94 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:prepareDefaults\\(\\) return type has no value type specified in iterable type array\\.$#"
|
95 |
+
count: 1
|
96 |
+
path: src/Client.php
|
97 |
+
|
98 |
+
-
|
99 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:transfer\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
100 |
+
count: 1
|
101 |
+
path: src/Client.php
|
102 |
+
|
103 |
+
-
|
104 |
+
message: "#^Method GuzzleHttp\\\\Client\\:\\:applyOptions\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
105 |
+
count: 1
|
106 |
+
path: src/Client.php
|
107 |
+
|
108 |
+
-
|
109 |
+
message: "#^Parameter \\#2 \\$prefix of function http_build_query expects string, null given\\.$#"
|
110 |
+
count: 1
|
111 |
+
path: src/Client.php
|
112 |
+
|
113 |
+
-
|
114 |
+
message: "#^Method GuzzleHttp\\\\ClientInterface\\:\\:send\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
115 |
+
count: 1
|
116 |
+
path: src/ClientInterface.php
|
117 |
+
|
118 |
+
-
|
119 |
+
message: "#^Method GuzzleHttp\\\\ClientInterface\\:\\:sendAsync\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
120 |
+
count: 1
|
121 |
+
path: src/ClientInterface.php
|
122 |
+
|
123 |
+
-
|
124 |
+
message: "#^Method GuzzleHttp\\\\ClientInterface\\:\\:request\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
125 |
+
count: 1
|
126 |
+
path: src/ClientInterface.php
|
127 |
+
|
128 |
+
-
|
129 |
+
message: "#^Method GuzzleHttp\\\\ClientInterface\\:\\:requestAsync\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
130 |
+
count: 1
|
131 |
+
path: src/ClientInterface.php
|
132 |
+
|
133 |
+
-
|
134 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJar\\:\\:__construct\\(\\) has parameter \\$cookieArray with no value type specified in iterable type array\\.$#"
|
135 |
+
count: 1
|
136 |
+
path: src/Cookie/CookieJar.php
|
137 |
+
|
138 |
+
-
|
139 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJar\\:\\:fromArray\\(\\) has parameter \\$cookies with no value type specified in iterable type array\\.$#"
|
140 |
+
count: 1
|
141 |
+
path: src/Cookie/CookieJar.php
|
142 |
+
|
143 |
+
-
|
144 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJar\\:\\:fromArray\\(\\) return type has no value type specified in iterable type GuzzleHttp\\\\Cookie\\\\CookieJar\\.$#"
|
145 |
+
count: 1
|
146 |
+
path: src/Cookie/CookieJar.php
|
147 |
+
|
148 |
+
-
|
149 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJar\\:\\:getCookieValue\\(\\) has no return typehint specified\\.$#"
|
150 |
+
count: 1
|
151 |
+
path: src/Cookie/CookieJar.php
|
152 |
+
|
153 |
+
-
|
154 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJar\\:\\:getCookieValue\\(\\) has parameter \\$value with no typehint specified\\.$#"
|
155 |
+
count: 1
|
156 |
+
path: src/Cookie/CookieJar.php
|
157 |
+
|
158 |
+
-
|
159 |
+
message: "#^Result of \\|\\| is always false\\.$#"
|
160 |
+
count: 1
|
161 |
+
path: src/Cookie/CookieJar.php
|
162 |
+
|
163 |
+
-
|
164 |
+
message: "#^Strict comparison using \\=\\=\\= between string and null will always evaluate to false\\.$#"
|
165 |
+
count: 2
|
166 |
+
path: src/Cookie/CookieJar.php
|
167 |
+
|
168 |
+
-
|
169 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJar\\:\\:toArray\\(\\) return type has no value type specified in iterable type array\\.$#"
|
170 |
+
count: 1
|
171 |
+
path: src/Cookie/CookieJar.php
|
172 |
+
|
173 |
+
-
|
174 |
+
message: "#^Call to an undefined method Traversable\\<mixed, mixed\\>\\:\\:getArrayCopy\\(\\)\\.$#"
|
175 |
+
count: 1
|
176 |
+
path: src/Cookie/CookieJar.php
|
177 |
+
|
178 |
+
-
|
179 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJar\\:\\:clear\\(\\) return type has no value type specified in iterable type GuzzleHttp\\\\Cookie\\\\CookieJarInterface\\.$#"
|
180 |
+
count: 1
|
181 |
+
path: src/Cookie/CookieJar.php
|
182 |
+
|
183 |
+
-
|
184 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJar\\:\\:clear\\(\\) should return GuzzleHttp\\\\Cookie\\\\CookieJarInterface but return statement is missing\\.$#"
|
185 |
+
count: 1
|
186 |
+
path: src/Cookie/CookieJar.php
|
187 |
+
|
188 |
+
-
|
189 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJar\\:\\:clear\\(\\) should return GuzzleHttp\\\\Cookie\\\\CookieJarInterface but empty return statement found\\.$#"
|
190 |
+
count: 1
|
191 |
+
path: src/Cookie/CookieJar.php
|
192 |
+
|
193 |
+
-
|
194 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJar\\:\\:clearSessionCookies\\(\\) has no return typehint specified\\.$#"
|
195 |
+
count: 1
|
196 |
+
path: src/Cookie/CookieJar.php
|
197 |
+
|
198 |
+
-
|
199 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJar\\:\\:count\\(\\) has no return typehint specified\\.$#"
|
200 |
+
count: 1
|
201 |
+
path: src/Cookie/CookieJar.php
|
202 |
+
|
203 |
+
-
|
204 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJar\\:\\:getIterator\\(\\) return type has no value type specified in iterable type Traversable\\<mixed, mixed\\>\\.$#"
|
205 |
+
count: 1
|
206 |
+
path: src/Cookie/CookieJar.php
|
207 |
+
|
208 |
+
-
|
209 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJar\\:\\:extractCookies\\(\\) has no return typehint specified\\.$#"
|
210 |
+
count: 1
|
211 |
+
path: src/Cookie/CookieJar.php
|
212 |
+
|
213 |
+
-
|
214 |
+
message: "#^Parameter \\#3 \\$length of function substr expects int, int\\|false given\\.$#"
|
215 |
+
count: 1
|
216 |
+
path: src/Cookie/CookieJar.php
|
217 |
+
|
218 |
+
-
|
219 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJar\\:\\:removeCookieIfEmpty\\(\\) has no return typehint specified\\.$#"
|
220 |
+
count: 1
|
221 |
+
path: src/Cookie/CookieJar.php
|
222 |
+
|
223 |
+
-
|
224 |
+
message: "#^Interface GuzzleHttp\\\\Cookie\\\\CookieJarInterface extends generic interface IteratorAggregate but does not specify its types\\: TKey, TValue$#"
|
225 |
+
count: 1
|
226 |
+
path: src/Cookie/CookieJarInterface.php
|
227 |
+
|
228 |
+
-
|
229 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJarInterface\\:\\:extractCookies\\(\\) has no return typehint specified\\.$#"
|
230 |
+
count: 1
|
231 |
+
path: src/Cookie/CookieJarInterface.php
|
232 |
+
|
233 |
+
-
|
234 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJarInterface\\:\\:clear\\(\\) return type has no value type specified in iterable type GuzzleHttp\\\\Cookie\\\\CookieJarInterface\\.$#"
|
235 |
+
count: 1
|
236 |
+
path: src/Cookie/CookieJarInterface.php
|
237 |
+
|
238 |
+
-
|
239 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJarInterface\\:\\:clearSessionCookies\\(\\) has no return typehint specified\\.$#"
|
240 |
+
count: 1
|
241 |
+
path: src/Cookie/CookieJarInterface.php
|
242 |
+
|
243 |
+
-
|
244 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\CookieJarInterface\\:\\:toArray\\(\\) return type has no value type specified in iterable type array\\.$#"
|
245 |
+
count: 1
|
246 |
+
path: src/Cookie/CookieJarInterface.php
|
247 |
+
|
248 |
+
-
|
249 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\FileCookieJar\\:\\:save\\(\\) has no return typehint specified\\.$#"
|
250 |
+
count: 1
|
251 |
+
path: src/Cookie/FileCookieJar.php
|
252 |
+
|
253 |
+
-
|
254 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\FileCookieJar\\:\\:load\\(\\) has no return typehint specified\\.$#"
|
255 |
+
count: 1
|
256 |
+
path: src/Cookie/FileCookieJar.php
|
257 |
+
|
258 |
+
-
|
259 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\SessionCookieJar\\:\\:save\\(\\) has no return typehint specified\\.$#"
|
260 |
+
count: 1
|
261 |
+
path: src/Cookie/SessionCookieJar.php
|
262 |
+
|
263 |
+
-
|
264 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\SessionCookieJar\\:\\:load\\(\\) has no return typehint specified\\.$#"
|
265 |
+
count: 1
|
266 |
+
path: src/Cookie/SessionCookieJar.php
|
267 |
+
|
268 |
+
-
|
269 |
+
message: "#^Property GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:\\$defaults type has no value type specified in iterable type array\\.$#"
|
270 |
+
count: 1
|
271 |
+
path: src/Cookie/SetCookie.php
|
272 |
+
|
273 |
+
-
|
274 |
+
message: "#^Property GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:\\$data type has no value type specified in iterable type array\\.$#"
|
275 |
+
count: 1
|
276 |
+
path: src/Cookie/SetCookie.php
|
277 |
+
|
278 |
+
-
|
279 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:__construct\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#"
|
280 |
+
count: 1
|
281 |
+
path: src/Cookie/SetCookie.php
|
282 |
+
|
283 |
+
-
|
284 |
+
message: "#^Property GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:\\$data \\(array\\) does not accept array\\|null\\.$#"
|
285 |
+
count: 1
|
286 |
+
path: src/Cookie/SetCookie.php
|
287 |
+
|
288 |
+
-
|
289 |
+
message: "#^Parameter \\#1 \\$timestamp of method GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:setExpires\\(\\) expects int, mixed given\\.$#"
|
290 |
+
count: 1
|
291 |
+
path: src/Cookie/SetCookie.php
|
292 |
+
|
293 |
+
-
|
294 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:toArray\\(\\) has no return typehint specified\\.$#"
|
295 |
+
count: 1
|
296 |
+
path: src/Cookie/SetCookie.php
|
297 |
+
|
298 |
+
-
|
299 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:setName\\(\\) has no return typehint specified\\.$#"
|
300 |
+
count: 1
|
301 |
+
path: src/Cookie/SetCookie.php
|
302 |
+
|
303 |
+
-
|
304 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:setValue\\(\\) has no return typehint specified\\.$#"
|
305 |
+
count: 1
|
306 |
+
path: src/Cookie/SetCookie.php
|
307 |
+
|
308 |
+
-
|
309 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:setDomain\\(\\) has no return typehint specified\\.$#"
|
310 |
+
count: 1
|
311 |
+
path: src/Cookie/SetCookie.php
|
312 |
+
|
313 |
+
-
|
314 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:setPath\\(\\) has no return typehint specified\\.$#"
|
315 |
+
count: 1
|
316 |
+
path: src/Cookie/SetCookie.php
|
317 |
+
|
318 |
+
-
|
319 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:setMaxAge\\(\\) has no return typehint specified\\.$#"
|
320 |
+
count: 1
|
321 |
+
path: src/Cookie/SetCookie.php
|
322 |
+
|
323 |
+
-
|
324 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:setExpires\\(\\) has no return typehint specified\\.$#"
|
325 |
+
count: 1
|
326 |
+
path: src/Cookie/SetCookie.php
|
327 |
+
|
328 |
+
-
|
329 |
+
message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#"
|
330 |
+
count: 1
|
331 |
+
path: src/Cookie/SetCookie.php
|
332 |
+
|
333 |
+
-
|
334 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:setSecure\\(\\) has no return typehint specified\\.$#"
|
335 |
+
count: 1
|
336 |
+
path: src/Cookie/SetCookie.php
|
337 |
+
|
338 |
+
-
|
339 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:setDiscard\\(\\) has no return typehint specified\\.$#"
|
340 |
+
count: 1
|
341 |
+
path: src/Cookie/SetCookie.php
|
342 |
+
|
343 |
+
-
|
344 |
+
message: "#^Method GuzzleHttp\\\\Cookie\\\\SetCookie\\:\\:setHttpOnly\\(\\) has no return typehint specified\\.$#"
|
345 |
+
count: 1
|
346 |
+
path: src/Cookie/SetCookie.php
|
347 |
+
|
348 |
+
-
|
349 |
+
message: "#^Parameter \\#1 \\$str of function ltrim expects string, string\\|null given\\.$#"
|
350 |
+
count: 1
|
351 |
+
path: src/Cookie/SetCookie.php
|
352 |
+
|
353 |
+
-
|
354 |
+
message: "#^Method GuzzleHttp\\\\Exception\\\\BadResponseException\\:\\:__construct\\(\\) has parameter \\$handlerContext with no value type specified in iterable type array\\.$#"
|
355 |
+
count: 1
|
356 |
+
path: src/Exception/BadResponseException.php
|
357 |
+
|
358 |
+
-
|
359 |
+
message: "#^Method GuzzleHttp\\\\Exception\\\\BadResponseException\\:\\:__construct\\(\\) has parameter \\$message with no typehint specified\\.$#"
|
360 |
+
count: 1
|
361 |
+
path: src/Exception/BadResponseException.php
|
362 |
+
|
363 |
+
-
|
364 |
+
message: "#^Method GuzzleHttp\\\\Exception\\\\ConnectException\\:\\:__construct\\(\\) has parameter \\$handlerContext with no value type specified in iterable type array\\.$#"
|
365 |
+
count: 1
|
366 |
+
path: src/Exception/ConnectException.php
|
367 |
+
|
368 |
+
-
|
369 |
+
message: "#^Method GuzzleHttp\\\\Exception\\\\ConnectException\\:\\:__construct\\(\\) has parameter \\$message with no typehint specified\\.$#"
|
370 |
+
count: 1
|
371 |
+
path: src/Exception/ConnectException.php
|
372 |
+
|
373 |
+
-
|
374 |
+
message: "#^Property GuzzleHttp\\\\Exception\\\\RequestException\\:\\:\\$handlerContext type has no value type specified in iterable type array\\.$#"
|
375 |
+
count: 1
|
376 |
+
path: src/Exception/RequestException.php
|
377 |
+
|
378 |
+
-
|
379 |
+
message: "#^Method GuzzleHttp\\\\Exception\\\\RequestException\\:\\:__construct\\(\\) has parameter \\$handlerContext with no value type specified in iterable type array\\.$#"
|
380 |
+
count: 1
|
381 |
+
path: src/Exception/RequestException.php
|
382 |
+
|
383 |
+
-
|
384 |
+
message: "#^Method GuzzleHttp\\\\Exception\\\\RequestException\\:\\:__construct\\(\\) has parameter \\$message with no typehint specified\\.$#"
|
385 |
+
count: 1
|
386 |
+
path: src/Exception/RequestException.php
|
387 |
+
|
388 |
+
-
|
389 |
+
message: "#^Method GuzzleHttp\\\\Exception\\\\RequestException\\:\\:create\\(\\) has parameter \\$ctx with no value type specified in iterable type array\\.$#"
|
390 |
+
count: 1
|
391 |
+
path: src/Exception/RequestException.php
|
392 |
+
|
393 |
+
-
|
394 |
+
message: "#^Method GuzzleHttp\\\\Exception\\\\RequestException\\:\\:getHandlerContext\\(\\) return type has no value type specified in iterable type array\\.$#"
|
395 |
+
count: 1
|
396 |
+
path: src/Exception/RequestException.php
|
397 |
+
|
398 |
+
-
|
399 |
+
message: "#^Property GuzzleHttp\\\\Exception\\\\SeekException\\:\\:\\$stream has no typehint specified\\.$#"
|
400 |
+
count: 1
|
401 |
+
path: src/Exception/SeekException.php
|
402 |
+
|
403 |
+
-
|
404 |
+
message: "#^Method GuzzleHttp\\\\Exception\\\\SeekException\\:\\:__construct\\(\\) has parameter \\$msg with no typehint specified\\.$#"
|
405 |
+
count: 1
|
406 |
+
path: src/Exception/SeekException.php
|
407 |
+
|
408 |
+
-
|
409 |
+
message: "#^Method GuzzleHttp\\\\Exception\\\\SeekException\\:\\:__construct\\(\\) has parameter \\$pos with no typehint specified\\.$#"
|
410 |
+
count: 1
|
411 |
+
path: src/Exception/SeekException.php
|
412 |
+
|
413 |
+
-
|
414 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:\\$handles type has no value type specified in iterable type array\\.$#"
|
415 |
+
count: 1
|
416 |
+
path: src/Handler/CurlFactory.php
|
417 |
+
|
418 |
+
-
|
419 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:create\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
420 |
+
count: 1
|
421 |
+
path: src/Handler/CurlFactory.php
|
422 |
+
|
423 |
+
-
|
424 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:release\\(\\) has no return typehint specified\\.$#"
|
425 |
+
count: 1
|
426 |
+
path: src/Handler/CurlFactory.php
|
427 |
+
|
428 |
+
-
|
429 |
+
message: "#^Negated boolean expression is always false\\.$#"
|
430 |
+
count: 1
|
431 |
+
path: src/Handler/CurlFactory.php
|
432 |
+
|
433 |
+
-
|
434 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:invokeStats\\(\\) has no return typehint specified\\.$#"
|
435 |
+
count: 1
|
436 |
+
path: src/Handler/CurlFactory.php
|
437 |
+
|
438 |
+
-
|
439 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:finishError\\(\\) has no return typehint specified\\.$#"
|
440 |
+
count: 1
|
441 |
+
path: src/Handler/CurlFactory.php
|
442 |
+
|
443 |
+
-
|
444 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:createRejection\\(\\) has no return typehint specified\\.$#"
|
445 |
+
count: 1
|
446 |
+
path: src/Handler/CurlFactory.php
|
447 |
+
|
448 |
+
-
|
449 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:createRejection\\(\\) has parameter \\$ctx with no value type specified in iterable type array\\.$#"
|
450 |
+
count: 1
|
451 |
+
path: src/Handler/CurlFactory.php
|
452 |
+
|
453 |
+
-
|
454 |
+
message: "#^If condition is always true\\.$#"
|
455 |
+
count: 1
|
456 |
+
path: src/Handler/CurlFactory.php
|
457 |
+
|
458 |
+
-
|
459 |
+
message: "#^Unreachable statement \\- code above always terminates\\.$#"
|
460 |
+
count: 1
|
461 |
+
path: src/Handler/CurlFactory.php
|
462 |
+
|
463 |
+
-
|
464 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:getDefaultConf\\(\\) has no return typehint specified\\.$#"
|
465 |
+
count: 1
|
466 |
+
path: src/Handler/CurlFactory.php
|
467 |
+
|
468 |
+
-
|
469 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:applyMethod\\(\\) has no return typehint specified\\.$#"
|
470 |
+
count: 1
|
471 |
+
path: src/Handler/CurlFactory.php
|
472 |
+
|
473 |
+
-
|
474 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:applyMethod\\(\\) has parameter \\$conf with no value type specified in iterable type array\\.$#"
|
475 |
+
count: 1
|
476 |
+
path: src/Handler/CurlFactory.php
|
477 |
+
|
478 |
+
-
|
479 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:applyBody\\(\\) has no return typehint specified\\.$#"
|
480 |
+
count: 1
|
481 |
+
path: src/Handler/CurlFactory.php
|
482 |
+
|
483 |
+
-
|
484 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:applyBody\\(\\) has parameter \\$conf with no value type specified in iterable type array\\.$#"
|
485 |
+
count: 1
|
486 |
+
path: src/Handler/CurlFactory.php
|
487 |
+
|
488 |
+
-
|
489 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:applyBody\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
490 |
+
count: 1
|
491 |
+
path: src/Handler/CurlFactory.php
|
492 |
+
|
493 |
+
-
|
494 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:applyHeaders\\(\\) has no return typehint specified\\.$#"
|
495 |
+
count: 1
|
496 |
+
path: src/Handler/CurlFactory.php
|
497 |
+
|
498 |
+
-
|
499 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:applyHeaders\\(\\) has parameter \\$conf with no value type specified in iterable type array\\.$#"
|
500 |
+
count: 1
|
501 |
+
path: src/Handler/CurlFactory.php
|
502 |
+
|
503 |
+
-
|
504 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:removeHeader\\(\\) has no return typehint specified\\.$#"
|
505 |
+
count: 1
|
506 |
+
path: src/Handler/CurlFactory.php
|
507 |
+
|
508 |
+
-
|
509 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:removeHeader\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
510 |
+
count: 1
|
511 |
+
path: src/Handler/CurlFactory.php
|
512 |
+
|
513 |
+
-
|
514 |
+
message: "#^Parameter \\#1 \\$str1 of function strcasecmp expects string, int\\|string given\\.$#"
|
515 |
+
count: 1
|
516 |
+
path: src/Handler/CurlFactory.php
|
517 |
+
|
518 |
+
-
|
519 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:applyHandlerOptions\\(\\) has no return typehint specified\\.$#"
|
520 |
+
count: 1
|
521 |
+
path: src/Handler/CurlFactory.php
|
522 |
+
|
523 |
+
-
|
524 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:applyHandlerOptions\\(\\) has parameter \\$conf with no value type specified in iterable type array\\.$#"
|
525 |
+
count: 1
|
526 |
+
path: src/Handler/CurlFactory.php
|
527 |
+
|
528 |
+
-
|
529 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:retryFailedRewind\\(\\) has no return typehint specified\\.$#"
|
530 |
+
count: 1
|
531 |
+
path: src/Handler/CurlFactory.php
|
532 |
+
|
533 |
+
-
|
534 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:retryFailedRewind\\(\\) has parameter \\$ctx with no value type specified in iterable type array\\.$#"
|
535 |
+
count: 1
|
536 |
+
path: src/Handler/CurlFactory.php
|
537 |
+
|
538 |
+
-
|
539 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactory\\:\\:createHeaderFn\\(\\) has no return typehint specified\\.$#"
|
540 |
+
count: 1
|
541 |
+
path: src/Handler/CurlFactory.php
|
542 |
+
|
543 |
+
-
|
544 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactoryInterface\\:\\:create\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
545 |
+
count: 1
|
546 |
+
path: src/Handler/CurlFactoryInterface.php
|
547 |
+
|
548 |
+
-
|
549 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlFactoryInterface\\:\\:release\\(\\) has no return typehint specified\\.$#"
|
550 |
+
count: 1
|
551 |
+
path: src/Handler/CurlFactoryInterface.php
|
552 |
+
|
553 |
+
-
|
554 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlHandler\\:\\:__construct\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
555 |
+
count: 1
|
556 |
+
path: src/Handler/CurlHandler.php
|
557 |
+
|
558 |
+
-
|
559 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlHandler\\:\\:__invoke\\(\\) has no return typehint specified\\.$#"
|
560 |
+
count: 1
|
561 |
+
path: src/Handler/CurlHandler.php
|
562 |
+
|
563 |
+
-
|
564 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlHandler\\:\\:__invoke\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
565 |
+
count: 1
|
566 |
+
path: src/Handler/CurlHandler.php
|
567 |
+
|
568 |
+
-
|
569 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:\\$selectTimeout has no typehint specified\\.$#"
|
570 |
+
count: 1
|
571 |
+
path: src/Handler/CurlMultiHandler.php
|
572 |
+
|
573 |
+
-
|
574 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:\\$active has no typehint specified\\.$#"
|
575 |
+
count: 1
|
576 |
+
path: src/Handler/CurlMultiHandler.php
|
577 |
+
|
578 |
+
-
|
579 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:\\$handles has no typehint specified\\.$#"
|
580 |
+
count: 1
|
581 |
+
path: src/Handler/CurlMultiHandler.php
|
582 |
+
|
583 |
+
-
|
584 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:\\$delays has no typehint specified\\.$#"
|
585 |
+
count: 1
|
586 |
+
path: src/Handler/CurlMultiHandler.php
|
587 |
+
|
588 |
+
-
|
589 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:\\$options has no typehint specified\\.$#"
|
590 |
+
count: 1
|
591 |
+
path: src/Handler/CurlMultiHandler.php
|
592 |
+
|
593 |
+
-
|
594 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:__construct\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
595 |
+
count: 1
|
596 |
+
path: src/Handler/CurlMultiHandler.php
|
597 |
+
|
598 |
+
-
|
599 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:__get\\(\\) has no return typehint specified\\.$#"
|
600 |
+
count: 1
|
601 |
+
path: src/Handler/CurlMultiHandler.php
|
602 |
+
|
603 |
+
-
|
604 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:__get\\(\\) has parameter \\$name with no typehint specified\\.$#"
|
605 |
+
count: 1
|
606 |
+
path: src/Handler/CurlMultiHandler.php
|
607 |
+
|
608 |
+
-
|
609 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:\\$_mh \\(resource\\) does not accept resource\\|false\\.$#"
|
610 |
+
count: 1
|
611 |
+
path: src/Handler/CurlMultiHandler.php
|
612 |
+
|
613 |
+
-
|
614 |
+
message: "#^Parameter \\#1 \\$mh of function curl_multi_setopt expects resource, resource\\|false given\\.$#"
|
615 |
+
count: 1
|
616 |
+
path: src/Handler/CurlMultiHandler.php
|
617 |
+
|
618 |
+
-
|
619 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:__invoke\\(\\) has no return typehint specified\\.$#"
|
620 |
+
count: 1
|
621 |
+
path: src/Handler/CurlMultiHandler.php
|
622 |
+
|
623 |
+
-
|
624 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:__invoke\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
625 |
+
count: 1
|
626 |
+
path: src/Handler/CurlMultiHandler.php
|
627 |
+
|
628 |
+
-
|
629 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:tick\\(\\) has no return typehint specified\\.$#"
|
630 |
+
count: 1
|
631 |
+
path: src/Handler/CurlMultiHandler.php
|
632 |
+
|
633 |
+
-
|
634 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:execute\\(\\) has no return typehint specified\\.$#"
|
635 |
+
count: 1
|
636 |
+
path: src/Handler/CurlMultiHandler.php
|
637 |
+
|
638 |
+
-
|
639 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:addRequest\\(\\) has no return typehint specified\\.$#"
|
640 |
+
count: 1
|
641 |
+
path: src/Handler/CurlMultiHandler.php
|
642 |
+
|
643 |
+
-
|
644 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:addRequest\\(\\) has parameter \\$entry with no value type specified in iterable type array\\.$#"
|
645 |
+
count: 1
|
646 |
+
path: src/Handler/CurlMultiHandler.php
|
647 |
+
|
648 |
+
-
|
649 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:processMessages\\(\\) has no return typehint specified\\.$#"
|
650 |
+
count: 1
|
651 |
+
path: src/Handler/CurlMultiHandler.php
|
652 |
+
|
653 |
+
-
|
654 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\CurlMultiHandler\\:\\:timeToNext\\(\\) has no return typehint specified\\.$#"
|
655 |
+
count: 1
|
656 |
+
path: src/Handler/CurlMultiHandler.php
|
657 |
+
|
658 |
+
-
|
659 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\EasyHandle\\:\\:\\$headers type has no value type specified in iterable type array\\.$#"
|
660 |
+
count: 1
|
661 |
+
path: src/Handler/EasyHandle.php
|
662 |
+
|
663 |
+
-
|
664 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\EasyHandle\\:\\:\\$options type has no value type specified in iterable type array\\.$#"
|
665 |
+
count: 1
|
666 |
+
path: src/Handler/EasyHandle.php
|
667 |
+
|
668 |
+
-
|
669 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\EasyHandle\\:\\:createResponse\\(\\) has no return typehint specified\\.$#"
|
670 |
+
count: 1
|
671 |
+
path: src/Handler/EasyHandle.php
|
672 |
+
|
673 |
+
-
|
674 |
+
message: "#^Parameter \\#1 \\$status of class GuzzleHttp\\\\Psr7\\\\Response constructor expects int, string given\\.$#"
|
675 |
+
count: 1
|
676 |
+
path: src/Handler/EasyHandle.php
|
677 |
+
|
678 |
+
-
|
679 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\EasyHandle\\:\\:__get\\(\\) has no return typehint specified\\.$#"
|
680 |
+
count: 1
|
681 |
+
path: src/Handler/EasyHandle.php
|
682 |
+
|
683 |
+
-
|
684 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\EasyHandle\\:\\:__get\\(\\) has parameter \\$name with no typehint specified\\.$#"
|
685 |
+
count: 1
|
686 |
+
path: src/Handler/EasyHandle.php
|
687 |
+
|
688 |
+
-
|
689 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:\\$queue has no typehint specified\\.$#"
|
690 |
+
count: 1
|
691 |
+
path: src/Handler/MockHandler.php
|
692 |
+
|
693 |
+
-
|
694 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:\\$lastRequest has no typehint specified\\.$#"
|
695 |
+
count: 1
|
696 |
+
path: src/Handler/MockHandler.php
|
697 |
+
|
698 |
+
-
|
699 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:\\$lastOptions has no typehint specified\\.$#"
|
700 |
+
count: 1
|
701 |
+
path: src/Handler/MockHandler.php
|
702 |
+
|
703 |
+
-
|
704 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:\\$onFulfilled has no typehint specified\\.$#"
|
705 |
+
count: 1
|
706 |
+
path: src/Handler/MockHandler.php
|
707 |
+
|
708 |
+
-
|
709 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:\\$onRejected has no typehint specified\\.$#"
|
710 |
+
count: 1
|
711 |
+
path: src/Handler/MockHandler.php
|
712 |
+
|
713 |
+
-
|
714 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:createWithMiddleware\\(\\) has parameter \\$queue with no value type specified in iterable type array\\.$#"
|
715 |
+
count: 1
|
716 |
+
path: src/Handler/MockHandler.php
|
717 |
+
|
718 |
+
-
|
719 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:__construct\\(\\) has parameter \\$queue with no value type specified in iterable type array\\.$#"
|
720 |
+
count: 1
|
721 |
+
path: src/Handler/MockHandler.php
|
722 |
+
|
723 |
+
-
|
724 |
+
message: "#^Parameter \\#2 \\$parameters of function call_user_func_array expects array\\<int, mixed\\>, array given\\.$#"
|
725 |
+
count: 1
|
726 |
+
path: src/Handler/MockHandler.php
|
727 |
+
|
728 |
+
-
|
729 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:__invoke\\(\\) has no return typehint specified\\.$#"
|
730 |
+
count: 1
|
731 |
+
path: src/Handler/MockHandler.php
|
732 |
+
|
733 |
+
-
|
734 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:__invoke\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
735 |
+
count: 1
|
736 |
+
path: src/Handler/MockHandler.php
|
737 |
+
|
738 |
+
-
|
739 |
+
message: "#^Binary operation \"\\*\" between float\\|int\\|string and 1000 results in an error\\.$#"
|
740 |
+
count: 1
|
741 |
+
path: src/Handler/MockHandler.php
|
742 |
+
|
743 |
+
-
|
744 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:append\\(\\) has no return typehint specified\\.$#"
|
745 |
+
count: 1
|
746 |
+
path: src/Handler/MockHandler.php
|
747 |
+
|
748 |
+
-
|
749 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:getLastOptions\\(\\) return type has no value type specified in iterable type array\\.$#"
|
750 |
+
count: 1
|
751 |
+
path: src/Handler/MockHandler.php
|
752 |
+
|
753 |
+
-
|
754 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:reset\\(\\) has no return typehint specified\\.$#"
|
755 |
+
count: 1
|
756 |
+
path: src/Handler/MockHandler.php
|
757 |
+
|
758 |
+
-
|
759 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:invokeStats\\(\\) has no return typehint specified\\.$#"
|
760 |
+
count: 1
|
761 |
+
path: src/Handler/MockHandler.php
|
762 |
+
|
763 |
+
-
|
764 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:invokeStats\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
765 |
+
count: 1
|
766 |
+
path: src/Handler/MockHandler.php
|
767 |
+
|
768 |
+
-
|
769 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\MockHandler\\:\\:invokeStats\\(\\) has parameter \\$reason with no typehint specified\\.$#"
|
770 |
+
count: 1
|
771 |
+
path: src/Handler/MockHandler.php
|
772 |
+
|
773 |
+
-
|
774 |
+
message: "#^Property GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:\\$lastHeaders has no typehint specified\\.$#"
|
775 |
+
count: 1
|
776 |
+
path: src/Handler/StreamHandler.php
|
777 |
+
|
778 |
+
-
|
779 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:__invoke\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
780 |
+
count: 1
|
781 |
+
path: src/Handler/StreamHandler.php
|
782 |
+
|
783 |
+
-
|
784 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:invokeStats\\(\\) has no return typehint specified\\.$#"
|
785 |
+
count: 1
|
786 |
+
path: src/Handler/StreamHandler.php
|
787 |
+
|
788 |
+
-
|
789 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:invokeStats\\(\\) has parameter \\$error with no typehint specified\\.$#"
|
790 |
+
count: 1
|
791 |
+
path: src/Handler/StreamHandler.php
|
792 |
+
|
793 |
+
-
|
794 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:invokeStats\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
795 |
+
count: 1
|
796 |
+
path: src/Handler/StreamHandler.php
|
797 |
+
|
798 |
+
-
|
799 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:invokeStats\\(\\) has parameter \\$startTime with no typehint specified\\.$#"
|
800 |
+
count: 1
|
801 |
+
path: src/Handler/StreamHandler.php
|
802 |
+
|
803 |
+
-
|
804 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:createResponse\\(\\) has no return typehint specified\\.$#"
|
805 |
+
count: 1
|
806 |
+
path: src/Handler/StreamHandler.php
|
807 |
+
|
808 |
+
-
|
809 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:createResponse\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
810 |
+
count: 1
|
811 |
+
path: src/Handler/StreamHandler.php
|
812 |
+
|
813 |
+
-
|
814 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:createResponse\\(\\) has parameter \\$startTime with no typehint specified\\.$#"
|
815 |
+
count: 1
|
816 |
+
path: src/Handler/StreamHandler.php
|
817 |
+
|
818 |
+
-
|
819 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:createResponse\\(\\) has parameter \\$stream with no typehint specified\\.$#"
|
820 |
+
count: 1
|
821 |
+
path: src/Handler/StreamHandler.php
|
822 |
+
|
823 |
+
-
|
824 |
+
message: "#^Parameter \\#1 \\$status of class GuzzleHttp\\\\Psr7\\\\Response constructor expects int, string given\\.$#"
|
825 |
+
count: 1
|
826 |
+
path: src/Handler/StreamHandler.php
|
827 |
+
|
828 |
+
-
|
829 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:createSink\\(\\) has no return typehint specified\\.$#"
|
830 |
+
count: 1
|
831 |
+
path: src/Handler/StreamHandler.php
|
832 |
+
|
833 |
+
-
|
834 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:createSink\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
835 |
+
count: 1
|
836 |
+
path: src/Handler/StreamHandler.php
|
837 |
+
|
838 |
+
-
|
839 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:checkDecode\\(\\) has no return typehint specified\\.$#"
|
840 |
+
count: 1
|
841 |
+
path: src/Handler/StreamHandler.php
|
842 |
+
|
843 |
+
-
|
844 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:checkDecode\\(\\) has parameter \\$headers with no value type specified in iterable type array\\.$#"
|
845 |
+
count: 1
|
846 |
+
path: src/Handler/StreamHandler.php
|
847 |
+
|
848 |
+
-
|
849 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:checkDecode\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
850 |
+
count: 1
|
851 |
+
path: src/Handler/StreamHandler.php
|
852 |
+
|
853 |
+
-
|
854 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:checkDecode\\(\\) has parameter \\$stream with no typehint specified\\.$#"
|
855 |
+
count: 1
|
856 |
+
path: src/Handler/StreamHandler.php
|
857 |
+
|
858 |
+
-
|
859 |
+
message: "#^Argument of an invalid type array\\<int, array\\<string, int\\|string\\>\\>\\|null supplied for foreach, only iterables are supported\\.$#"
|
860 |
+
count: 1
|
861 |
+
path: src/Handler/StreamHandler.php
|
862 |
+
|
863 |
+
-
|
864 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:createStream\\(\\) has no return typehint specified\\.$#"
|
865 |
+
count: 1
|
866 |
+
path: src/Handler/StreamHandler.php
|
867 |
+
|
868 |
+
-
|
869 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:createStream\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
870 |
+
count: 1
|
871 |
+
path: src/Handler/StreamHandler.php
|
872 |
+
|
873 |
+
-
|
874 |
+
message: "#^Parameter \\#3 \\$use_include_path of function fopen expects bool, null given\\.$#"
|
875 |
+
count: 1
|
876 |
+
path: src/Handler/StreamHandler.php
|
877 |
+
|
878 |
+
-
|
879 |
+
message: "#^Parameter \\#1 \\$stream of function stream_set_timeout expects resource, resource\\|false given\\.$#"
|
880 |
+
count: 1
|
881 |
+
path: src/Handler/StreamHandler.php
|
882 |
+
|
883 |
+
-
|
884 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:resolveHost\\(\\) has no return typehint specified\\.$#"
|
885 |
+
count: 1
|
886 |
+
path: src/Handler/StreamHandler.php
|
887 |
+
|
888 |
+
-
|
889 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:resolveHost\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
890 |
+
count: 1
|
891 |
+
path: src/Handler/StreamHandler.php
|
892 |
+
|
893 |
+
-
|
894 |
+
message: "#^Cannot access offset 0 on array\\|false\\.$#"
|
895 |
+
count: 2
|
896 |
+
path: src/Handler/StreamHandler.php
|
897 |
+
|
898 |
+
-
|
899 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:getDefaultContext\\(\\) has no return typehint specified\\.$#"
|
900 |
+
count: 1
|
901 |
+
path: src/Handler/StreamHandler.php
|
902 |
+
|
903 |
+
-
|
904 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_proxy\\(\\) has no return typehint specified\\.$#"
|
905 |
+
count: 1
|
906 |
+
path: src/Handler/StreamHandler.php
|
907 |
+
|
908 |
+
-
|
909 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_proxy\\(\\) has parameter \\$options with no typehint specified\\.$#"
|
910 |
+
count: 1
|
911 |
+
path: src/Handler/StreamHandler.php
|
912 |
+
|
913 |
+
-
|
914 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_proxy\\(\\) has parameter \\$params with no typehint specified\\.$#"
|
915 |
+
count: 1
|
916 |
+
path: src/Handler/StreamHandler.php
|
917 |
+
|
918 |
+
-
|
919 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_proxy\\(\\) has parameter \\$value with no typehint specified\\.$#"
|
920 |
+
count: 1
|
921 |
+
path: src/Handler/StreamHandler.php
|
922 |
+
|
923 |
+
-
|
924 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_timeout\\(\\) has no return typehint specified\\.$#"
|
925 |
+
count: 1
|
926 |
+
path: src/Handler/StreamHandler.php
|
927 |
+
|
928 |
+
-
|
929 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_timeout\\(\\) has parameter \\$options with no typehint specified\\.$#"
|
930 |
+
count: 1
|
931 |
+
path: src/Handler/StreamHandler.php
|
932 |
+
|
933 |
+
-
|
934 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_timeout\\(\\) has parameter \\$params with no typehint specified\\.$#"
|
935 |
+
count: 1
|
936 |
+
path: src/Handler/StreamHandler.php
|
937 |
+
|
938 |
+
-
|
939 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_timeout\\(\\) has parameter \\$value with no typehint specified\\.$#"
|
940 |
+
count: 1
|
941 |
+
path: src/Handler/StreamHandler.php
|
942 |
+
|
943 |
+
-
|
944 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_verify\\(\\) has no return typehint specified\\.$#"
|
945 |
+
count: 1
|
946 |
+
path: src/Handler/StreamHandler.php
|
947 |
+
|
948 |
+
-
|
949 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_verify\\(\\) has parameter \\$options with no typehint specified\\.$#"
|
950 |
+
count: 1
|
951 |
+
path: src/Handler/StreamHandler.php
|
952 |
+
|
953 |
+
-
|
954 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_verify\\(\\) has parameter \\$params with no typehint specified\\.$#"
|
955 |
+
count: 1
|
956 |
+
path: src/Handler/StreamHandler.php
|
957 |
+
|
958 |
+
-
|
959 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_verify\\(\\) has parameter \\$value with no typehint specified\\.$#"
|
960 |
+
count: 1
|
961 |
+
path: src/Handler/StreamHandler.php
|
962 |
+
|
963 |
+
-
|
964 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_cert\\(\\) has no return typehint specified\\.$#"
|
965 |
+
count: 1
|
966 |
+
path: src/Handler/StreamHandler.php
|
967 |
+
|
968 |
+
-
|
969 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_cert\\(\\) has parameter \\$options with no typehint specified\\.$#"
|
970 |
+
count: 1
|
971 |
+
path: src/Handler/StreamHandler.php
|
972 |
+
|
973 |
+
-
|
974 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_cert\\(\\) has parameter \\$params with no typehint specified\\.$#"
|
975 |
+
count: 1
|
976 |
+
path: src/Handler/StreamHandler.php
|
977 |
+
|
978 |
+
-
|
979 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_cert\\(\\) has parameter \\$value with no typehint specified\\.$#"
|
980 |
+
count: 1
|
981 |
+
path: src/Handler/StreamHandler.php
|
982 |
+
|
983 |
+
-
|
984 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_progress\\(\\) has no return typehint specified\\.$#"
|
985 |
+
count: 1
|
986 |
+
path: src/Handler/StreamHandler.php
|
987 |
+
|
988 |
+
-
|
989 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_progress\\(\\) has parameter \\$options with no typehint specified\\.$#"
|
990 |
+
count: 1
|
991 |
+
path: src/Handler/StreamHandler.php
|
992 |
+
|
993 |
+
-
|
994 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_progress\\(\\) has parameter \\$params with no typehint specified\\.$#"
|
995 |
+
count: 1
|
996 |
+
path: src/Handler/StreamHandler.php
|
997 |
+
|
998 |
+
-
|
999 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_progress\\(\\) has parameter \\$value with no typehint specified\\.$#"
|
1000 |
+
count: 1
|
1001 |
+
path: src/Handler/StreamHandler.php
|
1002 |
+
|
1003 |
+
-
|
1004 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_debug\\(\\) has no return typehint specified\\.$#"
|
1005 |
+
count: 1
|
1006 |
+
path: src/Handler/StreamHandler.php
|
1007 |
+
|
1008 |
+
-
|
1009 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_debug\\(\\) has parameter \\$options with no typehint specified\\.$#"
|
1010 |
+
count: 1
|
1011 |
+
path: src/Handler/StreamHandler.php
|
1012 |
+
|
1013 |
+
-
|
1014 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_debug\\(\\) has parameter \\$params with no typehint specified\\.$#"
|
1015 |
+
count: 1
|
1016 |
+
path: src/Handler/StreamHandler.php
|
1017 |
+
|
1018 |
+
-
|
1019 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:add_debug\\(\\) has parameter \\$value with no typehint specified\\.$#"
|
1020 |
+
count: 1
|
1021 |
+
path: src/Handler/StreamHandler.php
|
1022 |
+
|
1023 |
+
-
|
1024 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:addNotification\\(\\) has no return typehint specified\\.$#"
|
1025 |
+
count: 1
|
1026 |
+
path: src/Handler/StreamHandler.php
|
1027 |
+
|
1028 |
+
-
|
1029 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:addNotification\\(\\) has parameter \\$params with no value type specified in iterable type array\\.$#"
|
1030 |
+
count: 1
|
1031 |
+
path: src/Handler/StreamHandler.php
|
1032 |
+
|
1033 |
+
-
|
1034 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:callArray\\(\\) has no return typehint specified\\.$#"
|
1035 |
+
count: 1
|
1036 |
+
path: src/Handler/StreamHandler.php
|
1037 |
+
|
1038 |
+
-
|
1039 |
+
message: "#^Method GuzzleHttp\\\\Handler\\\\StreamHandler\\:\\:callArray\\(\\) has parameter \\$functions with no value type specified in iterable type array\\.$#"
|
1040 |
+
count: 1
|
1041 |
+
path: src/Handler/StreamHandler.php
|
1042 |
+
|
1043 |
+
-
|
1044 |
+
message: "#^Property GuzzleHttp\\\\HandlerStack\\:\\:\\$stack type has no value type specified in iterable type array\\.$#"
|
1045 |
+
count: 1
|
1046 |
+
path: src/HandlerStack.php
|
1047 |
+
|
1048 |
+
-
|
1049 |
+
message: "#^Method GuzzleHttp\\\\HandlerStack\\:\\:__invoke\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
1050 |
+
count: 1
|
1051 |
+
path: src/HandlerStack.php
|
1052 |
+
|
1053 |
+
-
|
1054 |
+
message: "#^Method GuzzleHttp\\\\HandlerStack\\:\\:setHandler\\(\\) has no return typehint specified\\.$#"
|
1055 |
+
count: 1
|
1056 |
+
path: src/HandlerStack.php
|
1057 |
+
|
1058 |
+
-
|
1059 |
+
message: "#^Method GuzzleHttp\\\\HandlerStack\\:\\:unshift\\(\\) has no return typehint specified\\.$#"
|
1060 |
+
count: 1
|
1061 |
+
path: src/HandlerStack.php
|
1062 |
+
|
1063 |
+
-
|
1064 |
+
message: "#^Method GuzzleHttp\\\\HandlerStack\\:\\:push\\(\\) has no return typehint specified\\.$#"
|
1065 |
+
count: 1
|
1066 |
+
path: src/HandlerStack.php
|
1067 |
+
|
1068 |
+
-
|
1069 |
+
message: "#^Method GuzzleHttp\\\\HandlerStack\\:\\:before\\(\\) has no return typehint specified\\.$#"
|
1070 |
+
count: 1
|
1071 |
+
path: src/HandlerStack.php
|
1072 |
+
|
1073 |
+
-
|
1074 |
+
message: "#^Method GuzzleHttp\\\\HandlerStack\\:\\:after\\(\\) has no return typehint specified\\.$#"
|
1075 |
+
count: 1
|
1076 |
+
path: src/HandlerStack.php
|
1077 |
+
|
1078 |
+
-
|
1079 |
+
message: "#^Method GuzzleHttp\\\\HandlerStack\\:\\:remove\\(\\) has no return typehint specified\\.$#"
|
1080 |
+
count: 1
|
1081 |
+
path: src/HandlerStack.php
|
1082 |
+
|
1083 |
+
-
|
1084 |
+
message: "#^Method GuzzleHttp\\\\HandlerStack\\:\\:splice\\(\\) has no return typehint specified\\.$#"
|
1085 |
+
count: 1
|
1086 |
+
path: src/HandlerStack.php
|
1087 |
+
|
1088 |
+
-
|
1089 |
+
message: "#^Method GuzzleHttp\\\\HandlerStack\\:\\:debugCallable\\(\\) has parameter \\$fn with no value type specified in iterable type array\\.$#"
|
1090 |
+
count: 1
|
1091 |
+
path: src/HandlerStack.php
|
1092 |
+
|
1093 |
+
-
|
1094 |
+
message: "#^Parameter \\#1 \\$obj of function spl_object_hash expects object, callable given\\.$#"
|
1095 |
+
count: 1
|
1096 |
+
path: src/HandlerStack.php
|
1097 |
+
|
1098 |
+
-
|
1099 |
+
message: "#^Method GuzzleHttp\\\\MessageFormatter\\:\\:format\\(\\) should return string but returns string\\|null\\.$#"
|
1100 |
+
count: 1
|
1101 |
+
path: src/MessageFormatter.php
|
1102 |
+
|
1103 |
+
-
|
1104 |
+
message: "#^Method GuzzleHttp\\\\Middleware\\:\\:history\\(\\) has parameter \\$container with generic interface ArrayAccess but does not specify its types\\: TKey, TValue$#"
|
1105 |
+
count: 1
|
1106 |
+
path: src/Middleware.php
|
1107 |
+
|
1108 |
+
-
|
1109 |
+
message: "#^Method GuzzleHttp\\\\Middleware\\:\\:history\\(\\) has parameter \\$container with no value type specified in iterable type array\\.$#"
|
1110 |
+
count: 1
|
1111 |
+
path: src/Middleware.php
|
1112 |
+
|
1113 |
+
-
|
1114 |
+
message: "#^Result of && is always false\\.$#"
|
1115 |
+
count: 1
|
1116 |
+
path: src/Middleware.php
|
1117 |
+
|
1118 |
+
-
|
1119 |
+
message: "#^Method GuzzleHttp\\\\Pool\\:\\:__construct\\(\\) has parameter \\$config with no value type specified in iterable type array\\.$#"
|
1120 |
+
count: 1
|
1121 |
+
path: src/Pool.php
|
1122 |
+
|
1123 |
+
-
|
1124 |
+
message: "#^Method GuzzleHttp\\\\Pool\\:\\:__construct\\(\\) has parameter \\$requests with no value type specified in iterable type array\\|Iterator\\.$#"
|
1125 |
+
count: 1
|
1126 |
+
path: src/Pool.php
|
1127 |
+
|
1128 |
+
-
|
1129 |
+
message: "#^Return typehint of method GuzzleHttp\\\\Pool\\:\\:promise\\(\\) has invalid type GuzzleHttp\\\\GuzzleHttp\\\\Promise\\\\Promise\\.$#"
|
1130 |
+
count: 1
|
1131 |
+
path: src/Pool.php
|
1132 |
+
|
1133 |
+
-
|
1134 |
+
message: "#^Method GuzzleHttp\\\\Pool\\:\\:promise\\(\\) should return GuzzleHttp\\\\GuzzleHttp\\\\Promise\\\\Promise but returns GuzzleHttp\\\\Promise\\\\PromiseInterface\\.$#"
|
1135 |
+
count: 1
|
1136 |
+
path: src/Pool.php
|
1137 |
+
|
1138 |
+
-
|
1139 |
+
message: "#^Method GuzzleHttp\\\\Pool\\:\\:batch\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
1140 |
+
count: 1
|
1141 |
+
path: src/Pool.php
|
1142 |
+
|
1143 |
+
-
|
1144 |
+
message: "#^Method GuzzleHttp\\\\Pool\\:\\:batch\\(\\) has parameter \\$requests with no value type specified in iterable type array\\|Iterator\\.$#"
|
1145 |
+
count: 1
|
1146 |
+
path: src/Pool.php
|
1147 |
+
|
1148 |
+
-
|
1149 |
+
message: "#^Method GuzzleHttp\\\\Pool\\:\\:batch\\(\\) return type has no value type specified in iterable type array\\.$#"
|
1150 |
+
count: 1
|
1151 |
+
path: src/Pool.php
|
1152 |
+
|
1153 |
+
-
|
1154 |
+
message: "#^Unsafe usage of new static\\(\\)\\.$#"
|
1155 |
+
count: 1
|
1156 |
+
path: src/Pool.php
|
1157 |
+
|
1158 |
+
-
|
1159 |
+
message: "#^Call to method wait\\(\\) on an unknown class GuzzleHttp\\\\GuzzleHttp\\\\Promise\\\\Promise\\.$#"
|
1160 |
+
count: 1
|
1161 |
+
path: src/Pool.php
|
1162 |
+
|
1163 |
+
-
|
1164 |
+
message: "#^Method GuzzleHttp\\\\Pool\\:\\:cmpCallback\\(\\) has parameter \\$name with no typehint specified\\.$#"
|
1165 |
+
count: 1
|
1166 |
+
path: src/Pool.php
|
1167 |
+
|
1168 |
+
-
|
1169 |
+
message: "#^Method GuzzleHttp\\\\Pool\\:\\:cmpCallback\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
1170 |
+
count: 1
|
1171 |
+
path: src/Pool.php
|
1172 |
+
|
1173 |
+
-
|
1174 |
+
message: "#^Method GuzzleHttp\\\\Pool\\:\\:cmpCallback\\(\\) has parameter \\$results with no value type specified in iterable type array\\.$#"
|
1175 |
+
count: 1
|
1176 |
+
path: src/Pool.php
|
1177 |
+
|
1178 |
+
-
|
1179 |
+
message: "#^Method GuzzleHttp\\\\PrepareBodyMiddleware\\:\\:__invoke\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
1180 |
+
count: 1
|
1181 |
+
path: src/PrepareBodyMiddleware.php
|
1182 |
+
|
1183 |
+
-
|
1184 |
+
message: "#^Method GuzzleHttp\\\\PrepareBodyMiddleware\\:\\:addExpectHeader\\(\\) has parameter \\$modify with no value type specified in iterable type array\\.$#"
|
1185 |
+
count: 1
|
1186 |
+
path: src/PrepareBodyMiddleware.php
|
1187 |
+
|
1188 |
+
-
|
1189 |
+
message: "#^Method GuzzleHttp\\\\PrepareBodyMiddleware\\:\\:addExpectHeader\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
1190 |
+
count: 1
|
1191 |
+
path: src/PrepareBodyMiddleware.php
|
1192 |
+
|
1193 |
+
-
|
1194 |
+
message: "#^Property GuzzleHttp\\\\RedirectMiddleware\\:\\:\\$defaultSettings has no typehint specified\\.$#"
|
1195 |
+
count: 1
|
1196 |
+
path: src/RedirectMiddleware.php
|
1197 |
+
|
1198 |
+
-
|
1199 |
+
message: "#^Method GuzzleHttp\\\\RedirectMiddleware\\:\\:__invoke\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
1200 |
+
count: 1
|
1201 |
+
path: src/RedirectMiddleware.php
|
1202 |
+
|
1203 |
+
-
|
1204 |
+
message: "#^Method GuzzleHttp\\\\RedirectMiddleware\\:\\:checkRedirect\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
1205 |
+
count: 1
|
1206 |
+
path: src/RedirectMiddleware.php
|
1207 |
+
|
1208 |
+
-
|
1209 |
+
message: "#^Parameter \\#1 \\$str of function substr expects string, int given\\.$#"
|
1210 |
+
count: 1
|
1211 |
+
path: src/RedirectMiddleware.php
|
1212 |
+
|
1213 |
+
-
|
1214 |
+
message: "#^Parameter \\#1 \\$promise of method GuzzleHttp\\\\RedirectMiddleware\\:\\:withTracking\\(\\) expects GuzzleHttp\\\\Promise\\\\PromiseInterface, GuzzleHttp\\\\Promise\\\\PromiseInterface\\|Psr\\\\Http\\\\Message\\\\ResponseInterface given\\.$#"
|
1215 |
+
count: 1
|
1216 |
+
path: src/RedirectMiddleware.php
|
1217 |
+
|
1218 |
+
-
|
1219 |
+
message: "#^Method GuzzleHttp\\\\RedirectMiddleware\\:\\:withTracking\\(\\) has parameter \\$statusCode with no typehint specified\\.$#"
|
1220 |
+
count: 1
|
1221 |
+
path: src/RedirectMiddleware.php
|
1222 |
+
|
1223 |
+
-
|
1224 |
+
message: "#^Method GuzzleHttp\\\\RedirectMiddleware\\:\\:withTracking\\(\\) has parameter \\$uri with no typehint specified\\.$#"
|
1225 |
+
count: 1
|
1226 |
+
path: src/RedirectMiddleware.php
|
1227 |
+
|
1228 |
+
-
|
1229 |
+
message: "#^Parameter \\#2 \\$value of method Psr\\\\Http\\\\Message\\\\MessageInterface\\:\\:withHeader\\(\\) expects array\\<string\\>\\|string, array given\\.$#"
|
1230 |
+
count: 2
|
1231 |
+
path: src/RedirectMiddleware.php
|
1232 |
+
|
1233 |
+
-
|
1234 |
+
message: "#^Method GuzzleHttp\\\\RedirectMiddleware\\:\\:guardMax\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
1235 |
+
count: 1
|
1236 |
+
path: src/RedirectMiddleware.php
|
1237 |
+
|
1238 |
+
-
|
1239 |
+
message: "#^Method GuzzleHttp\\\\RedirectMiddleware\\:\\:modifyRequest\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
1240 |
+
count: 1
|
1241 |
+
path: src/RedirectMiddleware.php
|
1242 |
+
|
1243 |
+
-
|
1244 |
+
message: "#^Method GuzzleHttp\\\\RedirectMiddleware\\:\\:redirectUri\\(\\) has parameter \\$protocols with no value type specified in iterable type array\\.$#"
|
1245 |
+
count: 1
|
1246 |
+
path: src/RedirectMiddleware.php
|
1247 |
+
|
1248 |
+
-
|
1249 |
+
message: "#^Method GuzzleHttp\\\\RetryMiddleware\\:\\:__invoke\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
1250 |
+
count: 1
|
1251 |
+
path: src/RetryMiddleware.php
|
1252 |
+
|
1253 |
+
-
|
1254 |
+
message: "#^Method GuzzleHttp\\\\RetryMiddleware\\:\\:onFulfilled\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
1255 |
+
count: 1
|
1256 |
+
path: src/RetryMiddleware.php
|
1257 |
+
|
1258 |
+
-
|
1259 |
+
message: "#^Method GuzzleHttp\\\\RetryMiddleware\\:\\:onRejected\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
1260 |
+
count: 1
|
1261 |
+
path: src/RetryMiddleware.php
|
1262 |
+
|
1263 |
+
-
|
1264 |
+
message: "#^Method GuzzleHttp\\\\RetryMiddleware\\:\\:doRetry\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
1265 |
+
count: 1
|
1266 |
+
path: src/RetryMiddleware.php
|
1267 |
+
|
1268 |
+
-
|
1269 |
+
message: "#^Method GuzzleHttp\\\\RetryMiddleware\\:\\:doRetry\\(\\) should return GuzzleHttp\\\\RetryMiddleware but returns GuzzleHttp\\\\Promise\\\\PromiseInterface\\.$#"
|
1270 |
+
count: 1
|
1271 |
+
path: src/RetryMiddleware.php
|
1272 |
+
|
1273 |
+
-
|
1274 |
+
message: "#^Property GuzzleHttp\\\\TransferStats\\:\\:\\$request has no typehint specified\\.$#"
|
1275 |
+
count: 1
|
1276 |
+
path: src/TransferStats.php
|
1277 |
+
|
1278 |
+
-
|
1279 |
+
message: "#^Property GuzzleHttp\\\\TransferStats\\:\\:\\$response has no typehint specified\\.$#"
|
1280 |
+
count: 1
|
1281 |
+
path: src/TransferStats.php
|
1282 |
+
|
1283 |
+
-
|
1284 |
+
message: "#^Property GuzzleHttp\\\\TransferStats\\:\\:\\$transferTime has no typehint specified\\.$#"
|
1285 |
+
count: 1
|
1286 |
+
path: src/TransferStats.php
|
1287 |
+
|
1288 |
+
-
|
1289 |
+
message: "#^Property GuzzleHttp\\\\TransferStats\\:\\:\\$handlerStats has no typehint specified\\.$#"
|
1290 |
+
count: 1
|
1291 |
+
path: src/TransferStats.php
|
1292 |
+
|
1293 |
+
-
|
1294 |
+
message: "#^Property GuzzleHttp\\\\TransferStats\\:\\:\\$handlerErrorData has no typehint specified\\.$#"
|
1295 |
+
count: 1
|
1296 |
+
path: src/TransferStats.php
|
1297 |
+
|
1298 |
+
-
|
1299 |
+
message: "#^Method GuzzleHttp\\\\TransferStats\\:\\:__construct\\(\\) has parameter \\$handlerStats with no value type specified in iterable type array\\.$#"
|
1300 |
+
count: 1
|
1301 |
+
path: src/TransferStats.php
|
1302 |
+
|
1303 |
+
-
|
1304 |
+
message: "#^Method GuzzleHttp\\\\TransferStats\\:\\:getHandlerStats\\(\\) return type has no value type specified in iterable type array\\.$#"
|
1305 |
+
count: 1
|
1306 |
+
path: src/TransferStats.php
|
1307 |
+
|
1308 |
+
-
|
1309 |
+
message: "#^Property GuzzleHttp\\\\UriTemplate\\:\\:\\$variables type has no value type specified in iterable type array\\.$#"
|
1310 |
+
count: 1
|
1311 |
+
path: src/UriTemplate.php
|
1312 |
+
|
1313 |
+
-
|
1314 |
+
message: "#^Property GuzzleHttp\\\\UriTemplate\\:\\:\\$operatorHash type has no value type specified in iterable type array\\.$#"
|
1315 |
+
count: 1
|
1316 |
+
path: src/UriTemplate.php
|
1317 |
+
|
1318 |
+
-
|
1319 |
+
message: "#^Property GuzzleHttp\\\\UriTemplate\\:\\:\\$delims type has no value type specified in iterable type array\\.$#"
|
1320 |
+
count: 1
|
1321 |
+
path: src/UriTemplate.php
|
1322 |
+
|
1323 |
+
-
|
1324 |
+
message: "#^Property GuzzleHttp\\\\UriTemplate\\:\\:\\$delimsPct type has no value type specified in iterable type array\\.$#"
|
1325 |
+
count: 1
|
1326 |
+
path: src/UriTemplate.php
|
1327 |
+
|
1328 |
+
-
|
1329 |
+
message: "#^Method GuzzleHttp\\\\UriTemplate\\:\\:expand\\(\\) has no return typehint specified\\.$#"
|
1330 |
+
count: 1
|
1331 |
+
path: src/UriTemplate.php
|
1332 |
+
|
1333 |
+
-
|
1334 |
+
message: "#^Method GuzzleHttp\\\\UriTemplate\\:\\:expand\\(\\) has parameter \\$template with no typehint specified\\.$#"
|
1335 |
+
count: 1
|
1336 |
+
path: src/UriTemplate.php
|
1337 |
+
|
1338 |
+
-
|
1339 |
+
message: "#^Method GuzzleHttp\\\\UriTemplate\\:\\:expand\\(\\) has parameter \\$variables with no value type specified in iterable type array\\.$#"
|
1340 |
+
count: 1
|
1341 |
+
path: src/UriTemplate.php
|
1342 |
+
|
1343 |
+
-
|
1344 |
+
message: "#^Method GuzzleHttp\\\\UriTemplate\\:\\:parseExpression\\(\\) return type has no value type specified in iterable type array\\.$#"
|
1345 |
+
count: 1
|
1346 |
+
path: src/UriTemplate.php
|
1347 |
+
|
1348 |
+
-
|
1349 |
+
message: "#^Method GuzzleHttp\\\\UriTemplate\\:\\:expandMatch\\(\\) has parameter \\$matches with no value type specified in iterable type array\\.$#"
|
1350 |
+
count: 1
|
1351 |
+
path: src/UriTemplate.php
|
1352 |
+
|
1353 |
+
-
|
1354 |
+
message: "#^Method GuzzleHttp\\\\UriTemplate\\:\\:isAssoc\\(\\) has parameter \\$array with no value type specified in iterable type array\\.$#"
|
1355 |
+
count: 1
|
1356 |
+
path: src/UriTemplate.php
|
1357 |
+
|
1358 |
+
-
|
1359 |
+
message: "#^Function GuzzleHttp\\\\uri_template\\(\\) has parameter \\$variables with no value type specified in iterable type array\\.$#"
|
1360 |
+
count: 1
|
1361 |
+
path: src/functions.php
|
1362 |
+
|
1363 |
+
-
|
1364 |
+
message: "#^Function uri_template not found\\.$#"
|
1365 |
+
count: 1
|
1366 |
+
path: src/functions.php
|
1367 |
+
|
1368 |
+
-
|
1369 |
+
message: "#^Parameter \\#1 \\$str of function rtrim expects string, string\\|false given\\.$#"
|
1370 |
+
count: 1
|
1371 |
+
path: src/functions.php
|
1372 |
+
|
1373 |
+
-
|
1374 |
+
message: "#^Function GuzzleHttp\\\\headers_from_lines\\(\\) has parameter \\$lines with no value type specified in iterable type iterable\\.$#"
|
1375 |
+
count: 1
|
1376 |
+
path: src/functions.php
|
1377 |
+
|
1378 |
+
-
|
1379 |
+
message: "#^Function GuzzleHttp\\\\headers_from_lines\\(\\) return type has no value type specified in iterable type array\\.$#"
|
1380 |
+
count: 1
|
1381 |
+
path: src/functions.php
|
1382 |
+
|
1383 |
+
-
|
1384 |
+
message: "#^Function GuzzleHttp\\\\debug_resource\\(\\) should return resource but returns resource\\|false\\.$#"
|
1385 |
+
count: 1
|
1386 |
+
path: src/functions.php
|
1387 |
+
|
1388 |
+
-
|
1389 |
+
message: "#^Function GuzzleHttp\\\\normalize_header_keys\\(\\) has parameter \\$headers with no value type specified in iterable type array\\.$#"
|
1390 |
+
count: 1
|
1391 |
+
path: src/functions.php
|
1392 |
+
|
1393 |
+
-
|
1394 |
+
message: "#^Function GuzzleHttp\\\\normalize_header_keys\\(\\) return type has no value type specified in iterable type array\\.$#"
|
1395 |
+
count: 1
|
1396 |
+
path: src/functions.php
|
1397 |
+
|
1398 |
+
-
|
1399 |
+
message: "#^Function GuzzleHttp\\\\is_host_in_noproxy\\(\\) has parameter \\$noProxyArray with no value type specified in iterable type array\\.$#"
|
1400 |
+
count: 1
|
1401 |
+
path: src/functions.php
|
1402 |
+
|
1403 |
+
-
|
1404 |
+
message: "#^Cannot access offset 0 on array\\<int, string\\>\\|false\\.$#"
|
1405 |
+
count: 1
|
1406 |
+
path: src/functions.php
|
1407 |
+
|
1408 |
+
-
|
1409 |
+
message: "#^Function GuzzleHttp\\\\json_encode\\(\\) should return string but returns string\\|false\\.$#"
|
1410 |
+
count: 1
|
1411 |
+
path: src/functions.php
|
1412 |
+
|
vendor/guzzlehttp/guzzle/src/Client.php
CHANGED
@@ -1,422 +1,531 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp;
|
3 |
-
|
4 |
-
use GuzzleHttp\Cookie\CookieJar;
|
5 |
-
use GuzzleHttp\
|
6 |
-
use GuzzleHttp\
|
7 |
-
use
|
8 |
-
use Psr\Http\Message\RequestInterface;
|
9 |
-
use Psr\Http\Message\ResponseInterface;
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
* @method ResponseInterface
|
14 |
-
* @method ResponseInterface
|
15 |
-
* @method ResponseInterface
|
16 |
-
* @method ResponseInterface
|
17 |
-
* @method ResponseInterface
|
18 |
-
* @method
|
19 |
-
* @method Promise\PromiseInterface
|
20 |
-
* @method Promise\PromiseInterface
|
21 |
-
* @method Promise\PromiseInterface
|
22 |
-
* @method Promise\PromiseInterface
|
23 |
-
* @method Promise\PromiseInterface
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
*
|
33 |
-
*
|
34 |
-
*
|
35 |
-
*
|
36 |
-
*
|
37 |
-
*
|
38 |
-
* '
|
39 |
-
* '
|
40 |
-
* '
|
41 |
-
*
|
42 |
-
*
|
43 |
-
*
|
44 |
-
*
|
45 |
-
*
|
46 |
-
*
|
47 |
-
*
|
48 |
-
*
|
49 |
-
*
|
50 |
-
*
|
51 |
-
*
|
52 |
-
*
|
53 |
-
*
|
54 |
-
*
|
55 |
-
*
|
56 |
-
*
|
57 |
-
*
|
58 |
-
*
|
59 |
-
*
|
60 |
-
*
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
$options
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
*
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
$
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
}
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
*
|
255 |
-
*
|
256 |
-
*
|
257 |
-
* @return
|
258 |
-
*/
|
259 |
-
private function
|
260 |
-
{
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
if (isset($
|
298 |
-
$
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
$
|
324 |
-
unset($
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use GuzzleHttp\Cookie\CookieJar;
|
5 |
+
use GuzzleHttp\Exception\InvalidArgumentException;
|
6 |
+
use GuzzleHttp\Promise;
|
7 |
+
use GuzzleHttp\Psr7;
|
8 |
+
use Psr\Http\Message\RequestInterface;
|
9 |
+
use Psr\Http\Message\ResponseInterface;
|
10 |
+
use Psr\Http\Message\UriInterface;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @method ResponseInterface get(string|UriInterface $uri, array $options = [])
|
14 |
+
* @method ResponseInterface head(string|UriInterface $uri, array $options = [])
|
15 |
+
* @method ResponseInterface put(string|UriInterface $uri, array $options = [])
|
16 |
+
* @method ResponseInterface post(string|UriInterface $uri, array $options = [])
|
17 |
+
* @method ResponseInterface patch(string|UriInterface $uri, array $options = [])
|
18 |
+
* @method ResponseInterface delete(string|UriInterface $uri, array $options = [])
|
19 |
+
* @method Promise\PromiseInterface getAsync(string|UriInterface $uri, array $options = [])
|
20 |
+
* @method Promise\PromiseInterface headAsync(string|UriInterface $uri, array $options = [])
|
21 |
+
* @method Promise\PromiseInterface putAsync(string|UriInterface $uri, array $options = [])
|
22 |
+
* @method Promise\PromiseInterface postAsync(string|UriInterface $uri, array $options = [])
|
23 |
+
* @method Promise\PromiseInterface patchAsync(string|UriInterface $uri, array $options = [])
|
24 |
+
* @method Promise\PromiseInterface deleteAsync(string|UriInterface $uri, array $options = [])
|
25 |
+
*/
|
26 |
+
class Client implements ClientInterface
|
27 |
+
{
|
28 |
+
/** @var array Default request options */
|
29 |
+
private $config;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Clients accept an array of constructor parameters.
|
33 |
+
*
|
34 |
+
* Here's an example of creating a client using a base_uri and an array of
|
35 |
+
* default request options to apply to each request:
|
36 |
+
*
|
37 |
+
* $client = new Client([
|
38 |
+
* 'base_uri' => 'http://www.foo.com/1.0/',
|
39 |
+
* 'timeout' => 0,
|
40 |
+
* 'allow_redirects' => false,
|
41 |
+
* 'proxy' => '192.168.16.1:10'
|
42 |
+
* ]);
|
43 |
+
*
|
44 |
+
* Client configuration settings include the following options:
|
45 |
+
*
|
46 |
+
* - handler: (callable) Function that transfers HTTP requests over the
|
47 |
+
* wire. The function is called with a Psr7\Http\Message\RequestInterface
|
48 |
+
* and array of transfer options, and must return a
|
49 |
+
* GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
|
50 |
+
* Psr7\Http\Message\ResponseInterface on success. "handler" is a
|
51 |
+
* constructor only option that cannot be overridden in per/request
|
52 |
+
* options. If no handler is provided, a default handler will be created
|
53 |
+
* that enables all of the request options below by attaching all of the
|
54 |
+
* default middleware to the handler.
|
55 |
+
* - base_uri: (string|UriInterface) Base URI of the client that is merged
|
56 |
+
* into relative URIs. Can be a string or instance of UriInterface.
|
57 |
+
* - **: any request option
|
58 |
+
*
|
59 |
+
* @param array $config Client configuration settings.
|
60 |
+
*
|
61 |
+
* @see \GuzzleHttp\RequestOptions for a list of available request options.
|
62 |
+
*/
|
63 |
+
public function __construct(array $config = [])
|
64 |
+
{
|
65 |
+
if (!isset($config['handler'])) {
|
66 |
+
$config['handler'] = HandlerStack::create();
|
67 |
+
} elseif (!is_callable($config['handler'])) {
|
68 |
+
throw new \InvalidArgumentException('handler must be a callable');
|
69 |
+
}
|
70 |
+
|
71 |
+
// Convert the base_uri to a UriInterface
|
72 |
+
if (isset($config['base_uri'])) {
|
73 |
+
$config['base_uri'] = Psr7\uri_for($config['base_uri']);
|
74 |
+
}
|
75 |
+
|
76 |
+
$this->configureDefaults($config);
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* @param string $method
|
81 |
+
* @param array $args
|
82 |
+
*
|
83 |
+
* @return Promise\PromiseInterface
|
84 |
+
*/
|
85 |
+
public function __call($method, $args)
|
86 |
+
{
|
87 |
+
if (count($args) < 1) {
|
88 |
+
throw new \InvalidArgumentException('Magic request methods require a URI and optional options array');
|
89 |
+
}
|
90 |
+
|
91 |
+
$uri = $args[0];
|
92 |
+
$opts = isset($args[1]) ? $args[1] : [];
|
93 |
+
|
94 |
+
return substr($method, -5) === 'Async'
|
95 |
+
? $this->requestAsync(substr($method, 0, -5), $uri, $opts)
|
96 |
+
: $this->request($method, $uri, $opts);
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Asynchronously send an HTTP request.
|
101 |
+
*
|
102 |
+
* @param array $options Request options to apply to the given
|
103 |
+
* request and to the transfer. See \GuzzleHttp\RequestOptions.
|
104 |
+
*
|
105 |
+
* @return PromiseInterface
|
106 |
+
*/
|
107 |
+
public function sendAsync(RequestInterface $request, array $options = [])
|
108 |
+
{
|
109 |
+
// Merge the base URI into the request URI if needed.
|
110 |
+
$options = $this->prepareDefaults($options);
|
111 |
+
|
112 |
+
return $this->transfer(
|
113 |
+
$request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')),
|
114 |
+
$options
|
115 |
+
);
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Send an HTTP request.
|
120 |
+
*
|
121 |
+
* @param array $options Request options to apply to the given
|
122 |
+
* request and to the transfer. See \GuzzleHttp\RequestOptions.
|
123 |
+
*
|
124 |
+
* @return ResponseInterface
|
125 |
+
* @throws GuzzleException
|
126 |
+
*/
|
127 |
+
public function send(RequestInterface $request, array $options = [])
|
128 |
+
{
|
129 |
+
$options[RequestOptions::SYNCHRONOUS] = true;
|
130 |
+
return $this->sendAsync($request, $options)->wait();
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Create and send an asynchronous HTTP request.
|
135 |
+
*
|
136 |
+
* Use an absolute path to override the base path of the client, or a
|
137 |
+
* relative path to append to the base path of the client. The URL can
|
138 |
+
* contain the query string as well. Use an array to provide a URL
|
139 |
+
* template and additional variables to use in the URL template expansion.
|
140 |
+
*
|
141 |
+
* @param string $method HTTP method
|
142 |
+
* @param string|UriInterface $uri URI object or string.
|
143 |
+
* @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
|
144 |
+
*
|
145 |
+
* @return PromiseInterface
|
146 |
+
*/
|
147 |
+
public function requestAsync($method, $uri = '', array $options = [])
|
148 |
+
{
|
149 |
+
$options = $this->prepareDefaults($options);
|
150 |
+
// Remove request modifying parameter because it can be done up-front.
|
151 |
+
$headers = isset($options['headers']) ? $options['headers'] : [];
|
152 |
+
$body = isset($options['body']) ? $options['body'] : null;
|
153 |
+
$version = isset($options['version']) ? $options['version'] : '1.1';
|
154 |
+
// Merge the URI into the base URI.
|
155 |
+
$uri = $this->buildUri($uri, $options);
|
156 |
+
if (is_array($body)) {
|
157 |
+
$this->invalidBody();
|
158 |
+
}
|
159 |
+
$request = new Psr7\Request($method, $uri, $headers, $body, $version);
|
160 |
+
// Remove the option so that they are not doubly-applied.
|
161 |
+
unset($options['headers'], $options['body'], $options['version']);
|
162 |
+
|
163 |
+
return $this->transfer($request, $options);
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Create and send an HTTP request.
|
168 |
+
*
|
169 |
+
* Use an absolute path to override the base path of the client, or a
|
170 |
+
* relative path to append to the base path of the client. The URL can
|
171 |
+
* contain the query string as well.
|
172 |
+
*
|
173 |
+
* @param string $method HTTP method.
|
174 |
+
* @param string|UriInterface $uri URI object or string.
|
175 |
+
* @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
|
176 |
+
*
|
177 |
+
* @return ResponseInterface
|
178 |
+
* @throws GuzzleException
|
179 |
+
*/
|
180 |
+
public function request($method, $uri = '', array $options = [])
|
181 |
+
{
|
182 |
+
$options[RequestOptions::SYNCHRONOUS] = true;
|
183 |
+
return $this->requestAsync($method, $uri, $options)->wait();
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Get a client configuration option.
|
188 |
+
*
|
189 |
+
* These options include default request options of the client, a "handler"
|
190 |
+
* (if utilized by the concrete client), and a "base_uri" if utilized by
|
191 |
+
* the concrete client.
|
192 |
+
*
|
193 |
+
* @param string|null $option The config option to retrieve.
|
194 |
+
*
|
195 |
+
* @return mixed
|
196 |
+
*/
|
197 |
+
public function getConfig($option = null)
|
198 |
+
{
|
199 |
+
return $option === null
|
200 |
+
? $this->config
|
201 |
+
: (isset($this->config[$option]) ? $this->config[$option] : null);
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* @param string|null $uri
|
206 |
+
*
|
207 |
+
* @return UriInterface
|
208 |
+
*/
|
209 |
+
private function buildUri($uri, array $config)
|
210 |
+
{
|
211 |
+
// for BC we accept null which would otherwise fail in uri_for
|
212 |
+
$uri = Psr7\uri_for($uri === null ? '' : $uri);
|
213 |
+
|
214 |
+
if (isset($config['base_uri'])) {
|
215 |
+
$uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri);
|
216 |
+
}
|
217 |
+
|
218 |
+
if ($uri->getHost() && isset($config['idn_conversion']) && ($config['idn_conversion'] !== false)) {
|
219 |
+
$idnOptions = ($config['idn_conversion'] === true) ? IDNA_DEFAULT : $config['idn_conversion'];
|
220 |
+
|
221 |
+
$asciiHost = idn_to_ascii($uri->getHost(), $idnOptions, INTL_IDNA_VARIANT_UTS46, $info);
|
222 |
+
if ($asciiHost === false) {
|
223 |
+
$errorBitSet = isset($info['errors']) ? $info['errors'] : 0;
|
224 |
+
|
225 |
+
$errorConstants = array_filter(array_keys(get_defined_constants()), function ($name) {
|
226 |
+
return substr($name, 0, 11) === 'IDNA_ERROR_';
|
227 |
+
});
|
228 |
+
|
229 |
+
$errors = [];
|
230 |
+
foreach ($errorConstants as $errorConstant) {
|
231 |
+
if ($errorBitSet & constant($errorConstant)) {
|
232 |
+
$errors[] = $errorConstant;
|
233 |
+
}
|
234 |
+
}
|
235 |
+
|
236 |
+
$errorMessage = 'IDN conversion failed';
|
237 |
+
if ($errors) {
|
238 |
+
$errorMessage .= ' (errors: ' . implode(', ', $errors) . ')';
|
239 |
+
}
|
240 |
+
|
241 |
+
throw new InvalidArgumentException($errorMessage);
|
242 |
+
} else {
|
243 |
+
if ($uri->getHost() !== $asciiHost) {
|
244 |
+
// Replace URI only if the ASCII version is different
|
245 |
+
$uri = $uri->withHost($asciiHost);
|
246 |
+
}
|
247 |
+
}
|
248 |
+
}
|
249 |
+
|
250 |
+
return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
|
251 |
+
}
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Configures the default options for a client.
|
255 |
+
*
|
256 |
+
* @param array $config
|
257 |
+
* @return void
|
258 |
+
*/
|
259 |
+
private function configureDefaults(array $config)
|
260 |
+
{
|
261 |
+
$defaults = [
|
262 |
+
'allow_redirects' => RedirectMiddleware::$defaultSettings,
|
263 |
+
'http_errors' => true,
|
264 |
+
'decode_content' => true,
|
265 |
+
'verify' => true,
|
266 |
+
'cookies' => false
|
267 |
+
];
|
268 |
+
|
269 |
+
// idn_to_ascii() is a part of ext-intl and might be not available
|
270 |
+
$defaults['idn_conversion'] = function_exists('idn_to_ascii');
|
271 |
+
|
272 |
+
// Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
|
273 |
+
|
274 |
+
// We can only trust the HTTP_PROXY environment variable in a CLI
|
275 |
+
// process due to the fact that PHP has no reliable mechanism to
|
276 |
+
// get environment variables that start with "HTTP_".
|
277 |
+
if (php_sapi_name() === 'cli' && getenv('HTTP_PROXY')) {
|
278 |
+
$defaults['proxy']['http'] = getenv('HTTP_PROXY');
|
279 |
+
}
|
280 |
+
|
281 |
+
if ($proxy = getenv('HTTPS_PROXY')) {
|
282 |
+
$defaults['proxy']['https'] = $proxy;
|
283 |
+
}
|
284 |
+
|
285 |
+
if ($noProxy = getenv('NO_PROXY')) {
|
286 |
+
$cleanedNoProxy = str_replace(' ', '', $noProxy);
|
287 |
+
$defaults['proxy']['no'] = explode(',', $cleanedNoProxy);
|
288 |
+
}
|
289 |
+
|
290 |
+
$this->config = $config + $defaults;
|
291 |
+
|
292 |
+
if (!empty($config['cookies']) && $config['cookies'] === true) {
|
293 |
+
$this->config['cookies'] = new CookieJar();
|
294 |
+
}
|
295 |
+
|
296 |
+
// Add the default user-agent header.
|
297 |
+
if (!isset($this->config['headers'])) {
|
298 |
+
$this->config['headers'] = ['User-Agent' => default_user_agent()];
|
299 |
+
} else {
|
300 |
+
// Add the User-Agent header if one was not already set.
|
301 |
+
foreach (array_keys($this->config['headers']) as $name) {
|
302 |
+
if (strtolower($name) === 'user-agent') {
|
303 |
+
return;
|
304 |
+
}
|
305 |
+
}
|
306 |
+
$this->config['headers']['User-Agent'] = default_user_agent();
|
307 |
+
}
|
308 |
+
}
|
309 |
+
|
310 |
+
/**
|
311 |
+
* Merges default options into the array.
|
312 |
+
*
|
313 |
+
* @param array $options Options to modify by reference
|
314 |
+
*
|
315 |
+
* @return array
|
316 |
+
*/
|
317 |
+
private function prepareDefaults(array $options)
|
318 |
+
{
|
319 |
+
$defaults = $this->config;
|
320 |
+
|
321 |
+
if (!empty($defaults['headers'])) {
|
322 |
+
// Default headers are only added if they are not present.
|
323 |
+
$defaults['_conditional'] = $defaults['headers'];
|
324 |
+
unset($defaults['headers']);
|
325 |
+
}
|
326 |
+
|
327 |
+
// Special handling for headers is required as they are added as
|
328 |
+
// conditional headers and as headers passed to a request ctor.
|
329 |
+
if (array_key_exists('headers', $options)) {
|
330 |
+
// Allows default headers to be unset.
|
331 |
+
if ($options['headers'] === null) {
|
332 |
+
$defaults['_conditional'] = [];
|
333 |
+
unset($options['headers']);
|
334 |
+
} elseif (!is_array($options['headers'])) {
|
335 |
+
throw new \InvalidArgumentException('headers must be an array');
|
336 |
+
}
|
337 |
+
}
|
338 |
+
|
339 |
+
// Shallow merge defaults underneath options.
|
340 |
+
$result = $options + $defaults;
|
341 |
+
|
342 |
+
// Remove null values.
|
343 |
+
foreach ($result as $k => $v) {
|
344 |
+
if ($v === null) {
|
345 |
+
unset($result[$k]);
|
346 |
+
}
|
347 |
+
}
|
348 |
+
|
349 |
+
return $result;
|
350 |
+
}
|
351 |
+
|
352 |
+
/**
|
353 |
+
* Transfers the given request and applies request options.
|
354 |
+
*
|
355 |
+
* The URI of the request is not modified and the request options are used
|
356 |
+
* as-is without merging in default options.
|
357 |
+
*
|
358 |
+
* @param array $options See \GuzzleHttp\RequestOptions.
|
359 |
+
*
|
360 |
+
* @return Promise\PromiseInterface
|
361 |
+
*/
|
362 |
+
private function transfer(RequestInterface $request, array $options)
|
363 |
+
{
|
364 |
+
// save_to -> sink
|
365 |
+
if (isset($options['save_to'])) {
|
366 |
+
$options['sink'] = $options['save_to'];
|
367 |
+
unset($options['save_to']);
|
368 |
+
}
|
369 |
+
|
370 |
+
// exceptions -> http_errors
|
371 |
+
if (isset($options['exceptions'])) {
|
372 |
+
$options['http_errors'] = $options['exceptions'];
|
373 |
+
unset($options['exceptions']);
|
374 |
+
}
|
375 |
+
|
376 |
+
$request = $this->applyOptions($request, $options);
|
377 |
+
/** @var HandlerStack $handler */
|
378 |
+
$handler = $options['handler'];
|
379 |
+
|
380 |
+
try {
|
381 |
+
return Promise\promise_for($handler($request, $options));
|
382 |
+
} catch (\Exception $e) {
|
383 |
+
return Promise\rejection_for($e);
|
384 |
+
}
|
385 |
+
}
|
386 |
+
|
387 |
+
/**
|
388 |
+
* Applies the array of request options to a request.
|
389 |
+
*
|
390 |
+
* @param RequestInterface $request
|
391 |
+
* @param array $options
|
392 |
+
*
|
393 |
+
* @return RequestInterface
|
394 |
+
*/
|
395 |
+
private function applyOptions(RequestInterface $request, array &$options)
|
396 |
+
{
|
397 |
+
$modify = [
|
398 |
+
'set_headers' => [],
|
399 |
+
];
|
400 |
+
|
401 |
+
if (isset($options['headers'])) {
|
402 |
+
$modify['set_headers'] = $options['headers'];
|
403 |
+
unset($options['headers']);
|
404 |
+
}
|
405 |
+
|
406 |
+
if (isset($options['form_params'])) {
|
407 |
+
if (isset($options['multipart'])) {
|
408 |
+
throw new \InvalidArgumentException('You cannot use '
|
409 |
+
. 'form_params and multipart at the same time. Use the '
|
410 |
+
. 'form_params option if you want to send application/'
|
411 |
+
. 'x-www-form-urlencoded requests, and the multipart '
|
412 |
+
. 'option to send multipart/form-data requests.');
|
413 |
+
}
|
414 |
+
$options['body'] = http_build_query($options['form_params'], '', '&');
|
415 |
+
unset($options['form_params']);
|
416 |
+
// Ensure that we don't have the header in different case and set the new value.
|
417 |
+
$options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
418 |
+
$options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
|
419 |
+
}
|
420 |
+
|
421 |
+
if (isset($options['multipart'])) {
|
422 |
+
$options['body'] = new Psr7\MultipartStream($options['multipart']);
|
423 |
+
unset($options['multipart']);
|
424 |
+
}
|
425 |
+
|
426 |
+
if (isset($options['json'])) {
|
427 |
+
$options['body'] = \GuzzleHttp\json_encode($options['json']);
|
428 |
+
unset($options['json']);
|
429 |
+
// Ensure that we don't have the header in different case and set the new value.
|
430 |
+
$options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
431 |
+
$options['_conditional']['Content-Type'] = 'application/json';
|
432 |
+
}
|
433 |
+
|
434 |
+
if (!empty($options['decode_content'])
|
435 |
+
&& $options['decode_content'] !== true
|
436 |
+
) {
|
437 |
+
// Ensure that we don't have the header in different case and set the new value.
|
438 |
+
$options['_conditional'] = Psr7\_caseless_remove(['Accept-Encoding'], $options['_conditional']);
|
439 |
+
$modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
|
440 |
+
}
|
441 |
+
|
442 |
+
if (isset($options['body'])) {
|
443 |
+
if (is_array($options['body'])) {
|
444 |
+
$this->invalidBody();
|
445 |
+
}
|
446 |
+
$modify['body'] = Psr7\stream_for($options['body']);
|
447 |
+
unset($options['body']);
|
448 |
+
}
|
449 |
+
|
450 |
+
if (!empty($options['auth']) && is_array($options['auth'])) {
|
451 |
+
$value = $options['auth'];
|
452 |
+
$type = isset($value[2]) ? strtolower($value[2]) : 'basic';
|
453 |
+
switch ($type) {
|
454 |
+
case 'basic':
|
455 |
+
// Ensure that we don't have the header in different case and set the new value.
|
456 |
+
$modify['set_headers'] = Psr7\_caseless_remove(['Authorization'], $modify['set_headers']);
|
457 |
+
$modify['set_headers']['Authorization'] = 'Basic '
|
458 |
+
. base64_encode("$value[0]:$value[1]");
|
459 |
+
break;
|
460 |
+
case 'digest':
|
461 |
+
// @todo: Do not rely on curl
|
462 |
+
$options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST;
|
463 |
+
$options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
|
464 |
+
break;
|
465 |
+
case 'ntlm':
|
466 |
+
$options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_NTLM;
|
467 |
+
$options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
|
468 |
+
break;
|
469 |
+
}
|
470 |
+
}
|
471 |
+
|
472 |
+
if (isset($options['query'])) {
|
473 |
+
$value = $options['query'];
|
474 |
+
if (is_array($value)) {
|
475 |
+
$value = http_build_query($value, null, '&', PHP_QUERY_RFC3986);
|
476 |
+
}
|
477 |
+
if (!is_string($value)) {
|
478 |
+
throw new \InvalidArgumentException('query must be a string or array');
|
479 |
+
}
|
480 |
+
$modify['query'] = $value;
|
481 |
+
unset($options['query']);
|
482 |
+
}
|
483 |
+
|
484 |
+
// Ensure that sink is not an invalid value.
|
485 |
+
if (isset($options['sink'])) {
|
486 |
+
// TODO: Add more sink validation?
|
487 |
+
if (is_bool($options['sink'])) {
|
488 |
+
throw new \InvalidArgumentException('sink must not be a boolean');
|
489 |
+
}
|
490 |
+
}
|
491 |
+
|
492 |
+
$request = Psr7\modify_request($request, $modify);
|
493 |
+
if ($request->getBody() instanceof Psr7\MultipartStream) {
|
494 |
+
// Use a multipart/form-data POST if a Content-Type is not set.
|
495 |
+
// Ensure that we don't have the header in different case and set the new value.
|
496 |
+
$options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
497 |
+
$options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
|
498 |
+
. $request->getBody()->getBoundary();
|
499 |
+
}
|
500 |
+
|
501 |
+
// Merge in conditional headers if they are not present.
|
502 |
+
if (isset($options['_conditional'])) {
|
503 |
+
// Build up the changes so it's in a single clone of the message.
|
504 |
+
$modify = [];
|
505 |
+
foreach ($options['_conditional'] as $k => $v) {
|
506 |
+
if (!$request->hasHeader($k)) {
|
507 |
+
$modify['set_headers'][$k] = $v;
|
508 |
+
}
|
509 |
+
}
|
510 |
+
$request = Psr7\modify_request($request, $modify);
|
511 |
+
// Don't pass this internal value along to middleware/handlers.
|
512 |
+
unset($options['_conditional']);
|
513 |
+
}
|
514 |
+
|
515 |
+
return $request;
|
516 |
+
}
|
517 |
+
|
518 |
+
/**
|
519 |
+
* Throw Exception with pre-set message.
|
520 |
+
* @return void
|
521 |
+
* @throws InvalidArgumentException Invalid body.
|
522 |
+
*/
|
523 |
+
private function invalidBody()
|
524 |
+
{
|
525 |
+
throw new \InvalidArgumentException('Passing in the "body" request '
|
526 |
+
. 'option as an array to send a POST request has been deprecated. '
|
527 |
+
. 'Please use the "form_params" request option to send a '
|
528 |
+
. 'application/x-www-form-urlencoded request, or the "multipart" '
|
529 |
+
. 'request option to send a multipart/form-data request.');
|
530 |
+
}
|
531 |
+
}
|
vendor/guzzlehttp/guzzle/src/ClientInterface.php
CHANGED
@@ -1,84 +1,87 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp;
|
3 |
-
|
4 |
-
use GuzzleHttp\
|
5 |
-
use GuzzleHttp\
|
6 |
-
use Psr\Http\Message\RequestInterface;
|
7 |
-
use Psr\Http\Message\ResponseInterface;
|
8 |
-
use Psr\Http\Message\UriInterface;
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Client interface for sending HTTP requests.
|
12 |
-
*/
|
13 |
-
interface ClientInterface
|
14 |
-
{
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
*
|
22 |
-
*
|
23 |
-
*
|
24 |
-
* @
|
25 |
-
*
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
*
|
34 |
-
*
|
35 |
-
*
|
36 |
-
* @
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
*
|
45 |
-
*
|
46 |
-
*
|
47 |
-
*
|
48 |
-
*
|
49 |
-
*
|
50 |
-
*
|
51 |
-
* @
|
52 |
-
* @
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
*
|
61 |
-
*
|
62 |
-
*
|
63 |
-
*
|
64 |
-
*
|
65 |
-
*
|
66 |
-
*
|
67 |
-
*
|
68 |
-
* @
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
*
|
77 |
-
*
|
78 |
-
*
|
79 |
-
*
|
80 |
-
*
|
81 |
-
*
|
82 |
-
|
83 |
-
|
84 |
-
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use GuzzleHttp\Exception\GuzzleException;
|
5 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
6 |
+
use Psr\Http\Message\RequestInterface;
|
7 |
+
use Psr\Http\Message\ResponseInterface;
|
8 |
+
use Psr\Http\Message\UriInterface;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Client interface for sending HTTP requests.
|
12 |
+
*/
|
13 |
+
interface ClientInterface
|
14 |
+
{
|
15 |
+
/**
|
16 |
+
* @deprecated Will be removed in Guzzle 7.0.0
|
17 |
+
*/
|
18 |
+
const VERSION = '6.5.0';
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Send an HTTP request.
|
22 |
+
*
|
23 |
+
* @param RequestInterface $request Request to send
|
24 |
+
* @param array $options Request options to apply to the given
|
25 |
+
* request and to the transfer.
|
26 |
+
*
|
27 |
+
* @return ResponseInterface
|
28 |
+
* @throws GuzzleException
|
29 |
+
*/
|
30 |
+
public function send(RequestInterface $request, array $options = []);
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Asynchronously send an HTTP request.
|
34 |
+
*
|
35 |
+
* @param RequestInterface $request Request to send
|
36 |
+
* @param array $options Request options to apply to the given
|
37 |
+
* request and to the transfer.
|
38 |
+
*
|
39 |
+
* @return PromiseInterface
|
40 |
+
*/
|
41 |
+
public function sendAsync(RequestInterface $request, array $options = []);
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Create and send an HTTP request.
|
45 |
+
*
|
46 |
+
* Use an absolute path to override the base path of the client, or a
|
47 |
+
* relative path to append to the base path of the client. The URL can
|
48 |
+
* contain the query string as well.
|
49 |
+
*
|
50 |
+
* @param string $method HTTP method.
|
51 |
+
* @param string|UriInterface $uri URI object or string.
|
52 |
+
* @param array $options Request options to apply.
|
53 |
+
*
|
54 |
+
* @return ResponseInterface
|
55 |
+
* @throws GuzzleException
|
56 |
+
*/
|
57 |
+
public function request($method, $uri, array $options = []);
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Create and send an asynchronous HTTP request.
|
61 |
+
*
|
62 |
+
* Use an absolute path to override the base path of the client, or a
|
63 |
+
* relative path to append to the base path of the client. The URL can
|
64 |
+
* contain the query string as well. Use an array to provide a URL
|
65 |
+
* template and additional variables to use in the URL template expansion.
|
66 |
+
*
|
67 |
+
* @param string $method HTTP method
|
68 |
+
* @param string|UriInterface $uri URI object or string.
|
69 |
+
* @param array $options Request options to apply.
|
70 |
+
*
|
71 |
+
* @return PromiseInterface
|
72 |
+
*/
|
73 |
+
public function requestAsync($method, $uri, array $options = []);
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Get a client configuration option.
|
77 |
+
*
|
78 |
+
* These options include default request options of the client, a "handler"
|
79 |
+
* (if utilized by the concrete client), and a "base_uri" if utilized by
|
80 |
+
* the concrete client.
|
81 |
+
*
|
82 |
+
* @param string|null $option The config option to retrieve.
|
83 |
+
*
|
84 |
+
* @return mixed
|
85 |
+
*/
|
86 |
+
public function getConfig($option = null);
|
87 |
+
}
|
vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php
CHANGED
@@ -1,314 +1,316 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp\Cookie;
|
3 |
-
|
4 |
-
use Psr\Http\Message\RequestInterface;
|
5 |
-
use Psr\Http\Message\ResponseInterface;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Cookie jar that stores cookies as an array
|
9 |
-
*/
|
10 |
-
class CookieJar implements CookieJarInterface
|
11 |
-
{
|
12 |
-
/** @var SetCookie[] Loaded cookie data */
|
13 |
-
private $cookies = [];
|
14 |
-
|
15 |
-
/** @var bool */
|
16 |
-
private $strictMode;
|
17 |
-
|
18 |
-
/**
|
19 |
-
* @param bool $strictMode Set to true to throw exceptions when invalid
|
20 |
-
* cookies are added to the cookie jar.
|
21 |
-
* @param array $cookieArray Array of SetCookie objects or a hash of
|
22 |
-
* arrays that can be used with the SetCookie
|
23 |
-
* constructor
|
24 |
-
*/
|
25 |
-
public function __construct($strictMode = false, $cookieArray = [])
|
26 |
-
{
|
27 |
-
$this->strictMode = $strictMode;
|
28 |
-
|
29 |
-
foreach ($cookieArray as $cookie) {
|
30 |
-
if (!($cookie instanceof SetCookie)) {
|
31 |
-
$cookie = new SetCookie($cookie);
|
32 |
-
}
|
33 |
-
$this->setCookie($cookie);
|
34 |
-
}
|
35 |
-
}
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Create a new Cookie jar from an associative array and domain.
|
39 |
-
*
|
40 |
-
* @param array $cookies Cookies to create the jar from
|
41 |
-
* @param string $domain Domain to set the cookies to
|
42 |
-
*
|
43 |
-
* @return self
|
44 |
-
*/
|
45 |
-
public static function fromArray(array $cookies, $domain)
|
46 |
-
{
|
47 |
-
$cookieJar = new self();
|
48 |
-
foreach ($cookies as $name => $value) {
|
49 |
-
$cookieJar->setCookie(new SetCookie([
|
50 |
-
'Domain' => $domain,
|
51 |
-
'Name' => $name,
|
52 |
-
'Value' => $value,
|
53 |
-
'Discard' => true
|
54 |
-
]));
|
55 |
-
}
|
56 |
-
|
57 |
-
return $cookieJar;
|
58 |
-
}
|
59 |
-
|
60 |
-
/**
|
61 |
-
* @deprecated
|
62 |
-
*/
|
63 |
-
public static function getCookieValue($value)
|
64 |
-
{
|
65 |
-
return $value;
|
66 |
-
}
|
67 |
-
|
68 |
-
/**
|
69 |
-
* Evaluate if this cookie should be persisted to storage
|
70 |
-
* that survives between requests.
|
71 |
-
*
|
72 |
-
* @param SetCookie $cookie Being evaluated.
|
73 |
-
* @param bool $allowSessionCookies If we should persist session cookies
|
74 |
-
* @return bool
|
75 |
-
*/
|
76 |
-
public static function shouldPersist(
|
77 |
-
SetCookie $cookie,
|
78 |
-
$allowSessionCookies = false
|
79 |
-
) {
|
80 |
-
if ($cookie->getExpires() || $allowSessionCookies) {
|
81 |
-
if (!$cookie->getDiscard()) {
|
82 |
-
return true;
|
83 |
-
}
|
84 |
-
}
|
85 |
-
|
86 |
-
return false;
|
87 |
-
}
|
88 |
-
|
89 |
-
/**
|
90 |
-
* Finds and returns the cookie based on the name
|
91 |
-
*
|
92 |
-
* @param string $name cookie name to search for
|
93 |
-
* @return SetCookie|null cookie that was found or null if not found
|
94 |
-
*/
|
95 |
-
public function getCookieByName($name)
|
96 |
-
{
|
97 |
-
// don't allow a
|
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 |
-
}
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
*
|
250 |
-
*
|
251 |
-
* @
|
252 |
-
*
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
$
|
278 |
-
$
|
279 |
-
$
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
*
|
301 |
-
*
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
$cookie->
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
}
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Cookie;
|
3 |
+
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
use Psr\Http\Message\ResponseInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Cookie jar that stores cookies as an array
|
9 |
+
*/
|
10 |
+
class CookieJar implements CookieJarInterface
|
11 |
+
{
|
12 |
+
/** @var SetCookie[] Loaded cookie data */
|
13 |
+
private $cookies = [];
|
14 |
+
|
15 |
+
/** @var bool */
|
16 |
+
private $strictMode;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @param bool $strictMode Set to true to throw exceptions when invalid
|
20 |
+
* cookies are added to the cookie jar.
|
21 |
+
* @param array $cookieArray Array of SetCookie objects or a hash of
|
22 |
+
* arrays that can be used with the SetCookie
|
23 |
+
* constructor
|
24 |
+
*/
|
25 |
+
public function __construct($strictMode = false, $cookieArray = [])
|
26 |
+
{
|
27 |
+
$this->strictMode = $strictMode;
|
28 |
+
|
29 |
+
foreach ($cookieArray as $cookie) {
|
30 |
+
if (!($cookie instanceof SetCookie)) {
|
31 |
+
$cookie = new SetCookie($cookie);
|
32 |
+
}
|
33 |
+
$this->setCookie($cookie);
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Create a new Cookie jar from an associative array and domain.
|
39 |
+
*
|
40 |
+
* @param array $cookies Cookies to create the jar from
|
41 |
+
* @param string $domain Domain to set the cookies to
|
42 |
+
*
|
43 |
+
* @return self
|
44 |
+
*/
|
45 |
+
public static function fromArray(array $cookies, $domain)
|
46 |
+
{
|
47 |
+
$cookieJar = new self();
|
48 |
+
foreach ($cookies as $name => $value) {
|
49 |
+
$cookieJar->setCookie(new SetCookie([
|
50 |
+
'Domain' => $domain,
|
51 |
+
'Name' => $name,
|
52 |
+
'Value' => $value,
|
53 |
+
'Discard' => true
|
54 |
+
]));
|
55 |
+
}
|
56 |
+
|
57 |
+
return $cookieJar;
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* @deprecated
|
62 |
+
*/
|
63 |
+
public static function getCookieValue($value)
|
64 |
+
{
|
65 |
+
return $value;
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Evaluate if this cookie should be persisted to storage
|
70 |
+
* that survives between requests.
|
71 |
+
*
|
72 |
+
* @param SetCookie $cookie Being evaluated.
|
73 |
+
* @param bool $allowSessionCookies If we should persist session cookies
|
74 |
+
* @return bool
|
75 |
+
*/
|
76 |
+
public static function shouldPersist(
|
77 |
+
SetCookie $cookie,
|
78 |
+
$allowSessionCookies = false
|
79 |
+
) {
|
80 |
+
if ($cookie->getExpires() || $allowSessionCookies) {
|
81 |
+
if (!$cookie->getDiscard()) {
|
82 |
+
return true;
|
83 |
+
}
|
84 |
+
}
|
85 |
+
|
86 |
+
return false;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Finds and returns the cookie based on the name
|
91 |
+
*
|
92 |
+
* @param string $name cookie name to search for
|
93 |
+
* @return SetCookie|null cookie that was found or null if not found
|
94 |
+
*/
|
95 |
+
public function getCookieByName($name)
|
96 |
+
{
|
97 |
+
// don't allow a non string name
|
98 |
+
if ($name === null || !is_scalar($name)) {
|
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 |
+
}
|
106 |
+
|
107 |
+
return null;
|
108 |
+
}
|
109 |
+
|
110 |
+
public function toArray()
|
111 |
+
{
|
112 |
+
return array_map(function (SetCookie $cookie) {
|
113 |
+
return $cookie->toArray();
|
114 |
+
}, $this->getIterator()->getArrayCopy());
|
115 |
+
}
|
116 |
+
|
117 |
+
public function clear($domain = null, $path = null, $name = null)
|
118 |
+
{
|
119 |
+
if (!$domain) {
|
120 |
+
$this->cookies = [];
|
121 |
+
return;
|
122 |
+
} elseif (!$path) {
|
123 |
+
$this->cookies = array_filter(
|
124 |
+
$this->cookies,
|
125 |
+
function (SetCookie $cookie) use ($domain) {
|
126 |
+
return !$cookie->matchesDomain($domain);
|
127 |
+
}
|
128 |
+
);
|
129 |
+
} elseif (!$name) {
|
130 |
+
$this->cookies = array_filter(
|
131 |
+
$this->cookies,
|
132 |
+
function (SetCookie $cookie) use ($path, $domain) {
|
133 |
+
return !($cookie->matchesPath($path) &&
|
134 |
+
$cookie->matchesDomain($domain));
|
135 |
+
}
|
136 |
+
);
|
137 |
+
} else {
|
138 |
+
$this->cookies = array_filter(
|
139 |
+
$this->cookies,
|
140 |
+
function (SetCookie $cookie) use ($path, $domain, $name) {
|
141 |
+
return !($cookie->getName() == $name &&
|
142 |
+
$cookie->matchesPath($path) &&
|
143 |
+
$cookie->matchesDomain($domain));
|
144 |
+
}
|
145 |
+
);
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
public function clearSessionCookies()
|
150 |
+
{
|
151 |
+
$this->cookies = array_filter(
|
152 |
+
$this->cookies,
|
153 |
+
function (SetCookie $cookie) {
|
154 |
+
return !$cookie->getDiscard() && $cookie->getExpires();
|
155 |
+
}
|
156 |
+
);
|
157 |
+
}
|
158 |
+
|
159 |
+
public function setCookie(SetCookie $cookie)
|
160 |
+
{
|
161 |
+
// If the name string is empty (but not 0), ignore the set-cookie
|
162 |
+
// string entirely.
|
163 |
+
$name = $cookie->getName();
|
164 |
+
if (!$name && $name !== '0') {
|
165 |
+
return false;
|
166 |
+
}
|
167 |
+
|
168 |
+
// Only allow cookies with set and valid domain, name, value
|
169 |
+
$result = $cookie->validate();
|
170 |
+
if ($result !== true) {
|
171 |
+
if ($this->strictMode) {
|
172 |
+
throw new \RuntimeException('Invalid cookie: ' . $result);
|
173 |
+
} else {
|
174 |
+
$this->removeCookieIfEmpty($cookie);
|
175 |
+
return false;
|
176 |
+
}
|
177 |
+
}
|
178 |
+
|
179 |
+
// Resolve conflicts with previously set cookies
|
180 |
+
foreach ($this->cookies as $i => $c) {
|
181 |
+
|
182 |
+
// Two cookies are identical, when their path, and domain are
|
183 |
+
// identical.
|
184 |
+
if ($c->getPath() != $cookie->getPath() ||
|
185 |
+
$c->getDomain() != $cookie->getDomain() ||
|
186 |
+
$c->getName() != $cookie->getName()
|
187 |
+
) {
|
188 |
+
continue;
|
189 |
+
}
|
190 |
+
|
191 |
+
// The previously set cookie is a discard cookie and this one is
|
192 |
+
// not so allow the new cookie to be set
|
193 |
+
if (!$cookie->getDiscard() && $c->getDiscard()) {
|
194 |
+
unset($this->cookies[$i]);
|
195 |
+
continue;
|
196 |
+
}
|
197 |
+
|
198 |
+
// If the new cookie's expiration is further into the future, then
|
199 |
+
// replace the old cookie
|
200 |
+
if ($cookie->getExpires() > $c->getExpires()) {
|
201 |
+
unset($this->cookies[$i]);
|
202 |
+
continue;
|
203 |
+
}
|
204 |
+
|
205 |
+
// If the value has changed, we better change it
|
206 |
+
if ($cookie->getValue() !== $c->getValue()) {
|
207 |
+
unset($this->cookies[$i]);
|
208 |
+
continue;
|
209 |
+
}
|
210 |
+
|
211 |
+
// The cookie exists, so no need to continue
|
212 |
+
return false;
|
213 |
+
}
|
214 |
+
|
215 |
+
$this->cookies[] = $cookie;
|
216 |
+
|
217 |
+
return true;
|
218 |
+
}
|
219 |
+
|
220 |
+
public function count()
|
221 |
+
{
|
222 |
+
return count($this->cookies);
|
223 |
+
}
|
224 |
+
|
225 |
+
public function getIterator()
|
226 |
+
{
|
227 |
+
return new \ArrayIterator(array_values($this->cookies));
|
228 |
+
}
|
229 |
+
|
230 |
+
public function extractCookies(
|
231 |
+
RequestInterface $request,
|
232 |
+
ResponseInterface $response
|
233 |
+
) {
|
234 |
+
if ($cookieHeader = $response->getHeader('Set-Cookie')) {
|
235 |
+
foreach ($cookieHeader as $cookie) {
|
236 |
+
$sc = SetCookie::fromString($cookie);
|
237 |
+
if (!$sc->getDomain()) {
|
238 |
+
$sc->setDomain($request->getUri()->getHost());
|
239 |
+
}
|
240 |
+
if (0 !== strpos($sc->getPath(), '/')) {
|
241 |
+
$sc->setPath($this->getCookiePathFromRequest($request));
|
242 |
+
}
|
243 |
+
$this->setCookie($sc);
|
244 |
+
}
|
245 |
+
}
|
246 |
+
}
|
247 |
+
|
248 |
+
/**
|
249 |
+
* Computes cookie path following RFC 6265 section 5.1.4
|
250 |
+
*
|
251 |
+
* @link https://tools.ietf.org/html/rfc6265#section-5.1.4
|
252 |
+
*
|
253 |
+
* @param RequestInterface $request
|
254 |
+
* @return string
|
255 |
+
*/
|
256 |
+
private function getCookiePathFromRequest(RequestInterface $request)
|
257 |
+
{
|
258 |
+
$uriPath = $request->getUri()->getPath();
|
259 |
+
if ('' === $uriPath) {
|
260 |
+
return '/';
|
261 |
+
}
|
262 |
+
if (0 !== strpos($uriPath, '/')) {
|
263 |
+
return '/';
|
264 |
+
}
|
265 |
+
if ('/' === $uriPath) {
|
266 |
+
return '/';
|
267 |
+
}
|
268 |
+
if (0 === $lastSlashPos = strrpos($uriPath, '/')) {
|
269 |
+
return '/';
|
270 |
+
}
|
271 |
+
|
272 |
+
return substr($uriPath, 0, $lastSlashPos);
|
273 |
+
}
|
274 |
+
|
275 |
+
public function withCookieHeader(RequestInterface $request)
|
276 |
+
{
|
277 |
+
$values = [];
|
278 |
+
$uri = $request->getUri();
|
279 |
+
$scheme = $uri->getScheme();
|
280 |
+
$host = $uri->getHost();
|
281 |
+
$path = $uri->getPath() ?: '/';
|
282 |
+
|
283 |
+
foreach ($this->cookies as $cookie) {
|
284 |
+
if ($cookie->matchesPath($path) &&
|
285 |
+
$cookie->matchesDomain($host) &&
|
286 |
+
!$cookie->isExpired() &&
|
287 |
+
(!$cookie->getSecure() || $scheme === 'https')
|
288 |
+
) {
|
289 |
+
$values[] = $cookie->getName() . '='
|
290 |
+
. $cookie->getValue();
|
291 |
+
}
|
292 |
+
}
|
293 |
+
|
294 |
+
return $values
|
295 |
+
? $request->withHeader('Cookie', implode('; ', $values))
|
296 |
+
: $request;
|
297 |
+
}
|
298 |
+
|
299 |
+
/**
|
300 |
+
* If a cookie already exists and the server asks to set it again with a
|
301 |
+
* null value, the cookie must be deleted.
|
302 |
+
*
|
303 |
+
* @param SetCookie $cookie
|
304 |
+
*/
|
305 |
+
private function removeCookieIfEmpty(SetCookie $cookie)
|
306 |
+
{
|
307 |
+
$cookieValue = $cookie->getValue();
|
308 |
+
if ($cookieValue === null || $cookieValue === '') {
|
309 |
+
$this->clear(
|
310 |
+
$cookie->getDomain(),
|
311 |
+
$cookie->getPath(),
|
312 |
+
$cookie->getName()
|
313 |
+
);
|
314 |
+
}
|
315 |
+
}
|
316 |
+
}
|
vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php
CHANGED
@@ -1,84 +1,84 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp\Cookie;
|
3 |
-
|
4 |
-
use Psr\Http\Message\RequestInterface;
|
5 |
-
use Psr\Http\Message\ResponseInterface;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Stores HTTP cookies.
|
9 |
-
*
|
10 |
-
* It extracts cookies from HTTP requests, and returns them in HTTP responses.
|
11 |
-
* CookieJarInterface instances automatically expire contained cookies when
|
12 |
-
* necessary. Subclasses are also responsible for storing and retrieving
|
13 |
-
* cookies from a file, database, etc.
|
14 |
-
*
|
15 |
-
* @link http://docs.python.org/2/library/cookielib.html Inspiration
|
16 |
-
*/
|
17 |
-
interface CookieJarInterface extends \Countable, \IteratorAggregate
|
18 |
-
{
|
19 |
-
/**
|
20 |
-
* Create a request with added cookie headers.
|
21 |
-
*
|
22 |
-
* If no matching cookies are found in the cookie jar, then no Cookie
|
23 |
-
* header is added to the request and the same request is returned.
|
24 |
-
*
|
25 |
-
* @param RequestInterface $request Request object to modify.
|
26 |
-
*
|
27 |
-
* @return RequestInterface returns the modified request.
|
28 |
-
*/
|
29 |
-
public function withCookieHeader(RequestInterface $request);
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Extract cookies from an HTTP response and store them in the CookieJar.
|
33 |
-
*
|
34 |
-
* @param RequestInterface $request Request that was sent
|
35 |
-
* @param ResponseInterface $response Response that was received
|
36 |
-
*/
|
37 |
-
public function extractCookies(
|
38 |
-
RequestInterface $request,
|
39 |
-
ResponseInterface $response
|
40 |
-
);
|
41 |
-
|
42 |
-
/**
|
43 |
-
* Sets a cookie in the cookie jar.
|
44 |
-
*
|
45 |
-
* @param SetCookie $cookie Cookie to set.
|
46 |
-
*
|
47 |
-
* @return bool Returns true on success or false on failure
|
48 |
-
*/
|
49 |
-
public function setCookie(SetCookie $cookie);
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Remove cookies currently held in the cookie jar.
|
53 |
-
*
|
54 |
-
* Invoking this method without arguments will empty the whole cookie jar.
|
55 |
-
* If given a $domain argument only cookies belonging to that domain will
|
56 |
-
* be removed. If given a $domain and $path argument, cookies belonging to
|
57 |
-
* the specified path within that domain are removed. If given all three
|
58 |
-
* arguments, then the cookie with the specified name, path and domain is
|
59 |
-
* removed.
|
60 |
-
*
|
61 |
-
* @param string $domain Clears cookies matching a domain
|
62 |
-
* @param string $path Clears cookies matching a domain and path
|
63 |
-
* @param string $name Clears cookies matching a domain, path, and name
|
64 |
-
*
|
65 |
-
* @return CookieJarInterface
|
66 |
-
*/
|
67 |
-
public function clear($domain = null, $path = null, $name = null);
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Discard all sessions cookies.
|
71 |
-
*
|
72 |
-
* Removes cookies that don't have an expire field or a have a discard
|
73 |
-
* field set to true. To be called when the user agent shuts down according
|
74 |
-
* to RFC 2965.
|
75 |
-
*/
|
76 |
-
public function clearSessionCookies();
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Converts the cookie jar to an array.
|
80 |
-
*
|
81 |
-
* @return array
|
82 |
-
*/
|
83 |
-
public function toArray();
|
84 |
-
}
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Cookie;
|
3 |
+
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
use Psr\Http\Message\ResponseInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Stores HTTP cookies.
|
9 |
+
*
|
10 |
+
* It extracts cookies from HTTP requests, and returns them in HTTP responses.
|
11 |
+
* CookieJarInterface instances automatically expire contained cookies when
|
12 |
+
* necessary. Subclasses are also responsible for storing and retrieving
|
13 |
+
* cookies from a file, database, etc.
|
14 |
+
*
|
15 |
+
* @link http://docs.python.org/2/library/cookielib.html Inspiration
|
16 |
+
*/
|
17 |
+
interface CookieJarInterface extends \Countable, \IteratorAggregate
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Create a request with added cookie headers.
|
21 |
+
*
|
22 |
+
* If no matching cookies are found in the cookie jar, then no Cookie
|
23 |
+
* header is added to the request and the same request is returned.
|
24 |
+
*
|
25 |
+
* @param RequestInterface $request Request object to modify.
|
26 |
+
*
|
27 |
+
* @return RequestInterface returns the modified request.
|
28 |
+
*/
|
29 |
+
public function withCookieHeader(RequestInterface $request);
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Extract cookies from an HTTP response and store them in the CookieJar.
|
33 |
+
*
|
34 |
+
* @param RequestInterface $request Request that was sent
|
35 |
+
* @param ResponseInterface $response Response that was received
|
36 |
+
*/
|
37 |
+
public function extractCookies(
|
38 |
+
RequestInterface $request,
|
39 |
+
ResponseInterface $response
|
40 |
+
);
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Sets a cookie in the cookie jar.
|
44 |
+
*
|
45 |
+
* @param SetCookie $cookie Cookie to set.
|
46 |
+
*
|
47 |
+
* @return bool Returns true on success or false on failure
|
48 |
+
*/
|
49 |
+
public function setCookie(SetCookie $cookie);
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Remove cookies currently held in the cookie jar.
|
53 |
+
*
|
54 |
+
* Invoking this method without arguments will empty the whole cookie jar.
|
55 |
+
* If given a $domain argument only cookies belonging to that domain will
|
56 |
+
* be removed. If given a $domain and $path argument, cookies belonging to
|
57 |
+
* the specified path within that domain are removed. If given all three
|
58 |
+
* arguments, then the cookie with the specified name, path and domain is
|
59 |
+
* removed.
|
60 |
+
*
|
61 |
+
* @param string|null $domain Clears cookies matching a domain
|
62 |
+
* @param string|null $path Clears cookies matching a domain and path
|
63 |
+
* @param string|null $name Clears cookies matching a domain, path, and name
|
64 |
+
*
|
65 |
+
* @return CookieJarInterface
|
66 |
+
*/
|
67 |
+
public function clear($domain = null, $path = null, $name = null);
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Discard all sessions cookies.
|
71 |
+
*
|
72 |
+
* Removes cookies that don't have an expire field or a have a discard
|
73 |
+
* field set to true. To be called when the user agent shuts down according
|
74 |
+
* to RFC 2965.
|
75 |
+
*/
|
76 |
+
public function clearSessionCookies();
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Converts the cookie jar to an array.
|
80 |
+
*
|
81 |
+
* @return array
|
82 |
+
*/
|
83 |
+
public function toArray();
|
84 |
+
}
|
vendor/guzzlehttp/guzzle/src/Exception/RequestException.php
CHANGED
@@ -1,217 +1,192 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp\Exception;
|
3 |
-
|
4 |
-
use
|
5 |
-
use Psr\Http\Message\
|
6 |
-
use
|
7 |
-
use Psr\Http\Message\UriInterface;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* HTTP Request exception
|
11 |
-
*/
|
12 |
-
class RequestException extends TransferException
|
13 |
-
{
|
14 |
-
/** @var RequestInterface */
|
15 |
-
private $request;
|
16 |
-
|
17 |
-
/** @var ResponseInterface */
|
18 |
-
private $response;
|
19 |
-
|
20 |
-
/** @var array */
|
21 |
-
private $handlerContext;
|
22 |
-
|
23 |
-
public function __construct(
|
24 |
-
$message,
|
25 |
-
RequestInterface $request,
|
26 |
-
ResponseInterface $response = null,
|
27 |
-
\Exception $previous = null,
|
28 |
-
array $handlerContext = []
|
29 |
-
) {
|
30 |
-
// Set the code of the exception if the response is set and not future.
|
31 |
-
$code = $response && !($response instanceof PromiseInterface)
|
32 |
-
? $response->getStatusCode()
|
33 |
-
: 0;
|
34 |
-
parent::__construct($message, $code, $previous);
|
35 |
-
$this->request = $request;
|
36 |
-
$this->response = $response;
|
37 |
-
$this->handlerContext = $handlerContext;
|
38 |
-
}
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Wrap non-RequestExceptions with a RequestException
|
42 |
-
*
|
43 |
-
* @param RequestInterface $request
|
44 |
-
* @param \Exception $e
|
45 |
-
*
|
46 |
-
* @return RequestException
|
47 |
-
*/
|
48 |
-
public static function wrapException(RequestInterface $request, \Exception $e)
|
49 |
-
{
|
50 |
-
return $e instanceof RequestException
|
51 |
-
? $e
|
52 |
-
: new RequestException($e->getMessage(), $request, null, $e);
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Factory method to create a new exception with a normalized error message
|
57 |
-
*
|
58 |
-
* @param RequestInterface $request Request
|
59 |
-
* @param ResponseInterface $response Response received
|
60 |
-
* @param \Exception $previous Previous exception
|
61 |
-
* @param array $ctx Optional handler context.
|
62 |
-
*
|
63 |
-
* @return self
|
64 |
-
*/
|
65 |
-
public static function create(
|
66 |
-
RequestInterface $request,
|
67 |
-
ResponseInterface $response = null,
|
68 |
-
\Exception $previous = null,
|
69 |
-
array $ctx = []
|
70 |
-
) {
|
71 |
-
if (!$response) {
|
72 |
-
return new self(
|
73 |
-
'Error completing request',
|
74 |
-
$request,
|
75 |
-
null,
|
76 |
-
$previous,
|
77 |
-
$ctx
|
78 |
-
);
|
79 |
-
}
|
80 |
-
|
81 |
-
$level = (int) floor($response->getStatusCode() / 100);
|
82 |
-
if ($level === 4) {
|
83 |
-
$label = 'Client error';
|
84 |
-
$className = ClientException::class;
|
85 |
-
} elseif ($level === 5) {
|
86 |
-
$label = 'Server error';
|
87 |
-
$className = ServerException::class;
|
88 |
-
} else {
|
89 |
-
$label = 'Unsuccessful request';
|
90 |
-
$className = __CLASS__;
|
91 |
-
}
|
92 |
-
|
93 |
-
$uri = $request->getUri();
|
94 |
-
$uri = static::obfuscateUri($uri);
|
95 |
-
|
96 |
-
// Client Error: `GET /` resulted in a `404 Not Found` response:
|
97 |
-
// <html> ... (truncated)
|
98 |
-
$message = sprintf(
|
99 |
-
'%s: `%s %s` resulted in a `%s %s` response',
|
100 |
-
$label,
|
101 |
-
$request->getMethod(),
|
102 |
-
$uri,
|
103 |
-
$response->getStatusCode(),
|
104 |
-
$response->getReasonPhrase()
|
105 |
-
);
|
106 |
-
|
107 |
-
$summary = static::getResponseBodySummary($response);
|
108 |
-
|
109 |
-
if ($summary !== null) {
|
110 |
-
$message .= ":\n{$summary}\n";
|
111 |
-
}
|
112 |
-
|
113 |
-
return new $className($message, $request, $response, $previous, $ctx);
|
114 |
-
}
|
115 |
-
|
116 |
-
/**
|
117 |
-
* Get a short summary of the response
|
118 |
-
*
|
119 |
-
* Will return `null` if the response is not printable.
|
120 |
-
*
|
121 |
-
* @param ResponseInterface $response
|
122 |
-
*
|
123 |
-
* @return string|null
|
124 |
-
*/
|
125 |
-
public static function getResponseBodySummary(ResponseInterface $response)
|
126 |
-
{
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
$
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
*
|
160 |
-
*
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
*
|
185 |
-
*
|
186 |
-
* @return
|
187 |
-
*/
|
188 |
-
public function
|
189 |
-
{
|
190 |
-
return $this->
|
191 |
-
}
|
192 |
-
|
193 |
-
/**
|
194 |
-
* Check if a response was received
|
195 |
-
*
|
196 |
-
* @return bool
|
197 |
-
*/
|
198 |
-
public function hasResponse()
|
199 |
-
{
|
200 |
-
return $this->response !== null;
|
201 |
-
}
|
202 |
-
|
203 |
-
/**
|
204 |
-
* Get contextual information about the error from the underlying handler.
|
205 |
-
*
|
206 |
-
* The contents of this array will vary depending on which handler you are
|
207 |
-
* using. It may also be just an empty array. Relying on this data will
|
208 |
-
* couple you to a specific handler, but can give more debug information
|
209 |
-
* when needed.
|
210 |
-
*
|
211 |
-
* @return array
|
212 |
-
*/
|
213 |
-
public function getHandlerContext()
|
214 |
-
{
|
215 |
-
return $this->handlerContext;
|
216 |
-
}
|
217 |
-
}
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Exception;
|
3 |
+
|
4 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
use Psr\Http\Message\ResponseInterface;
|
7 |
+
use Psr\Http\Message\UriInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* HTTP Request exception
|
11 |
+
*/
|
12 |
+
class RequestException extends TransferException
|
13 |
+
{
|
14 |
+
/** @var RequestInterface */
|
15 |
+
private $request;
|
16 |
+
|
17 |
+
/** @var ResponseInterface|null */
|
18 |
+
private $response;
|
19 |
+
|
20 |
+
/** @var array */
|
21 |
+
private $handlerContext;
|
22 |
+
|
23 |
+
public function __construct(
|
24 |
+
$message,
|
25 |
+
RequestInterface $request,
|
26 |
+
ResponseInterface $response = null,
|
27 |
+
\Exception $previous = null,
|
28 |
+
array $handlerContext = []
|
29 |
+
) {
|
30 |
+
// Set the code of the exception if the response is set and not future.
|
31 |
+
$code = $response && !($response instanceof PromiseInterface)
|
32 |
+
? $response->getStatusCode()
|
33 |
+
: 0;
|
34 |
+
parent::__construct($message, $code, $previous);
|
35 |
+
$this->request = $request;
|
36 |
+
$this->response = $response;
|
37 |
+
$this->handlerContext = $handlerContext;
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Wrap non-RequestExceptions with a RequestException
|
42 |
+
*
|
43 |
+
* @param RequestInterface $request
|
44 |
+
* @param \Exception $e
|
45 |
+
*
|
46 |
+
* @return RequestException
|
47 |
+
*/
|
48 |
+
public static function wrapException(RequestInterface $request, \Exception $e)
|
49 |
+
{
|
50 |
+
return $e instanceof RequestException
|
51 |
+
? $e
|
52 |
+
: new RequestException($e->getMessage(), $request, null, $e);
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Factory method to create a new exception with a normalized error message
|
57 |
+
*
|
58 |
+
* @param RequestInterface $request Request
|
59 |
+
* @param ResponseInterface $response Response received
|
60 |
+
* @param \Exception $previous Previous exception
|
61 |
+
* @param array $ctx Optional handler context.
|
62 |
+
*
|
63 |
+
* @return self
|
64 |
+
*/
|
65 |
+
public static function create(
|
66 |
+
RequestInterface $request,
|
67 |
+
ResponseInterface $response = null,
|
68 |
+
\Exception $previous = null,
|
69 |
+
array $ctx = []
|
70 |
+
) {
|
71 |
+
if (!$response) {
|
72 |
+
return new self(
|
73 |
+
'Error completing request',
|
74 |
+
$request,
|
75 |
+
null,
|
76 |
+
$previous,
|
77 |
+
$ctx
|
78 |
+
);
|
79 |
+
}
|
80 |
+
|
81 |
+
$level = (int) floor($response->getStatusCode() / 100);
|
82 |
+
if ($level === 4) {
|
83 |
+
$label = 'Client error';
|
84 |
+
$className = ClientException::class;
|
85 |
+
} elseif ($level === 5) {
|
86 |
+
$label = 'Server error';
|
87 |
+
$className = ServerException::class;
|
88 |
+
} else {
|
89 |
+
$label = 'Unsuccessful request';
|
90 |
+
$className = __CLASS__;
|
91 |
+
}
|
92 |
+
|
93 |
+
$uri = $request->getUri();
|
94 |
+
$uri = static::obfuscateUri($uri);
|
95 |
+
|
96 |
+
// Client Error: `GET /` resulted in a `404 Not Found` response:
|
97 |
+
// <html> ... (truncated)
|
98 |
+
$message = sprintf(
|
99 |
+
'%s: `%s %s` resulted in a `%s %s` response',
|
100 |
+
$label,
|
101 |
+
$request->getMethod(),
|
102 |
+
$uri,
|
103 |
+
$response->getStatusCode(),
|
104 |
+
$response->getReasonPhrase()
|
105 |
+
);
|
106 |
+
|
107 |
+
$summary = static::getResponseBodySummary($response);
|
108 |
+
|
109 |
+
if ($summary !== null) {
|
110 |
+
$message .= ":\n{$summary}\n";
|
111 |
+
}
|
112 |
+
|
113 |
+
return new $className($message, $request, $response, $previous, $ctx);
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Get a short summary of the response
|
118 |
+
*
|
119 |
+
* Will return `null` if the response is not printable.
|
120 |
+
*
|
121 |
+
* @param ResponseInterface $response
|
122 |
+
*
|
123 |
+
* @return string|null
|
124 |
+
*/
|
125 |
+
public static function getResponseBodySummary(ResponseInterface $response)
|
126 |
+
{
|
127 |
+
return \GuzzleHttp\Psr7\get_message_body_summary($response);
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Obfuscates URI if there is a username and a password present
|
132 |
+
*
|
133 |
+
* @param UriInterface $uri
|
134 |
+
*
|
135 |
+
* @return UriInterface
|
136 |
+
*/
|
137 |
+
private static function obfuscateUri(UriInterface $uri)
|
138 |
+
{
|
139 |
+
$userInfo = $uri->getUserInfo();
|
140 |
+
|
141 |
+
if (false !== ($pos = strpos($userInfo, ':'))) {
|
142 |
+
return $uri->withUserInfo(substr($userInfo, 0, $pos), '***');
|
143 |
+
}
|
144 |
+
|
145 |
+
return $uri;
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Get the request that caused the exception
|
150 |
+
*
|
151 |
+
* @return RequestInterface
|
152 |
+
*/
|
153 |
+
public function getRequest()
|
154 |
+
{
|
155 |
+
return $this->request;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Get the associated response
|
160 |
+
*
|
161 |
+
* @return ResponseInterface|null
|
162 |
+
*/
|
163 |
+
public function getResponse()
|
164 |
+
{
|
165 |
+
return $this->response;
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Check if a response was received
|
170 |
+
*
|
171 |
+
* @return bool
|
172 |
+
*/
|
173 |
+
public function hasResponse()
|
174 |
+
{
|
175 |
+
return $this->response !== null;
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Get contextual information about the error from the underlying handler.
|
180 |
+
*
|
181 |
+
* The contents of this array will vary depending on which handler you are
|
182 |
+
* using. It may also be just an empty array. Relying on this data will
|
183 |
+
* couple you to a specific handler, but can give more debug information
|
184 |
+
* when needed.
|
185 |
+
*
|
186 |
+
* @return array
|
187 |
+
*/
|
188 |
+
public function getHandlerContext()
|
189 |
+
{
|
190 |
+
return $this->handlerContext;
|
191 |
+
}
|
192 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php
CHANGED
@@ -1,580 +1,585 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp\Handler;
|
3 |
-
|
4 |
-
use GuzzleHttp\Exception\
|
5 |
-
use GuzzleHttp\Exception\
|
6 |
-
use GuzzleHttp\Promise\FulfilledPromise;
|
7 |
-
use GuzzleHttp\Psr7;
|
8 |
-
use GuzzleHttp\Psr7\LazyOpenStream;
|
9 |
-
use GuzzleHttp\TransferStats;
|
10 |
-
use Psr\Http\Message\RequestInterface;
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Creates curl resources from a request
|
14 |
-
*/
|
15 |
-
class CurlFactory implements CurlFactoryInterface
|
16 |
-
{
|
17 |
-
const CURL_VERSION_STR = 'curl_version';
|
18 |
-
const LOW_CURL_VERSION_NUMBER = '7.21.2';
|
19 |
-
|
20 |
-
/** @var array */
|
21 |
-
private $handles = [];
|
22 |
-
|
23 |
-
/** @var int Total number of idle handles to keep in cache */
|
24 |
-
private $maxHandles;
|
25 |
-
|
26 |
-
/**
|
27 |
-
* @param int $maxHandles Maximum number of idle handles.
|
28 |
-
*/
|
29 |
-
public function __construct($maxHandles)
|
30 |
-
{
|
31 |
-
$this->maxHandles = $maxHandles;
|
32 |
-
}
|
33 |
-
|
34 |
-
public function create(RequestInterface $request, array $options)
|
35 |
-
{
|
36 |
-
if (isset($options['curl']['body_as_string'])) {
|
37 |
-
$options['_body_as_string'] = $options['curl']['body_as_string'];
|
38 |
-
unset($options['curl']['body_as_string']);
|
39 |
-
}
|
40 |
-
|
41 |
-
$easy = new EasyHandle;
|
42 |
-
$easy->request = $request;
|
43 |
-
$easy->options = $options;
|
44 |
-
$conf = $this->getDefaultConf($easy);
|
45 |
-
$this->applyMethod($easy, $conf);
|
46 |
-
$this->applyHandlerOptions($easy, $conf);
|
47 |
-
$this->applyHeaders($easy, $conf);
|
48 |
-
unset($conf['_headers']);
|
49 |
-
|
50 |
-
// Add handler options from the request configuration options
|
51 |
-
if (isset($options['curl'])) {
|
52 |
-
$conf = array_replace($conf, $options['curl']);
|
53 |
-
}
|
54 |
-
|
55 |
-
$conf[CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
|
56 |
-
$easy->handle = $this->handles
|
57 |
-
? array_pop($this->handles)
|
58 |
-
: curl_init();
|
59 |
-
curl_setopt_array($easy->handle, $conf);
|
60 |
-
|
61 |
-
return $easy;
|
62 |
-
}
|
63 |
-
|
64 |
-
public function release(EasyHandle $easy)
|
65 |
-
{
|
66 |
-
$resource = $easy->handle;
|
67 |
-
unset($easy->handle);
|
68 |
-
|
69 |
-
if (count($this->handles) >= $this->maxHandles) {
|
70 |
-
curl_close($resource);
|
71 |
-
} else {
|
72 |
-
// Remove all callback functions as they can hold onto references
|
73 |
-
// and are not cleaned up by curl_reset. Using curl_setopt_array
|
74 |
-
// does not work for some reason, so removing each one
|
75 |
-
// individually.
|
76 |
-
curl_setopt($resource, CURLOPT_HEADERFUNCTION, null);
|
77 |
-
curl_setopt($resource, CURLOPT_READFUNCTION, null);
|
78 |
-
curl_setopt($resource, CURLOPT_WRITEFUNCTION, null);
|
79 |
-
curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null);
|
80 |
-
curl_reset($resource);
|
81 |
-
$this->handles[] = $resource;
|
82 |
-
}
|
83 |
-
}
|
84 |
-
|
85 |
-
/**
|
86 |
-
* Completes a cURL transaction, either returning a response promise or a
|
87 |
-
* rejected promise.
|
88 |
-
*
|
89 |
-
* @param callable $handler
|
90 |
-
* @param EasyHandle $easy
|
91 |
-
* @param CurlFactoryInterface $factory Dictates how the handle is released
|
92 |
-
*
|
93 |
-
* @return \GuzzleHttp\Promise\PromiseInterface
|
94 |
-
*/
|
95 |
-
public static function finish(
|
96 |
-
callable $handler,
|
97 |
-
EasyHandle $easy,
|
98 |
-
CurlFactoryInterface $factory
|
99 |
-
) {
|
100 |
-
if (isset($easy->options['on_stats'])) {
|
101 |
-
self::invokeStats($easy);
|
102 |
-
}
|
103 |
-
|
104 |
-
if (!$easy->response || $easy->errno) {
|
105 |
-
return self::finishError($handler, $easy, $factory);
|
106 |
-
}
|
107 |
-
|
108 |
-
// Return the response if it is present and there is no error.
|
109 |
-
$factory->release($easy);
|
110 |
-
|
111 |
-
// Rewind the body of the response if possible.
|
112 |
-
$body = $easy->response->getBody();
|
113 |
-
if ($body->isSeekable()) {
|
114 |
-
$body->rewind();
|
115 |
-
}
|
116 |
-
|
117 |
-
return new FulfilledPromise($easy->response);
|
118 |
-
}
|
119 |
-
|
120 |
-
private static function invokeStats(EasyHandle $easy)
|
121 |
-
{
|
122 |
-
$curlStats = curl_getinfo($easy->handle);
|
123 |
-
$curlStats['appconnect_time'] = curl_getinfo($easy->handle, CURLINFO_APPCONNECT_TIME);
|
124 |
-
$stats = new TransferStats(
|
125 |
-
$easy->request,
|
126 |
-
$easy->response,
|
127 |
-
$curlStats['total_time'],
|
128 |
-
$easy->errno,
|
129 |
-
$curlStats
|
130 |
-
);
|
131 |
-
call_user_func($easy->options['on_stats'], $stats);
|
132 |
-
}
|
133 |
-
|
134 |
-
private static function finishError(
|
135 |
-
callable $handler,
|
136 |
-
EasyHandle $easy,
|
137 |
-
CurlFactoryInterface $factory
|
138 |
-
) {
|
139 |
-
// Get error information and release the handle to the factory.
|
140 |
-
$ctx = [
|
141 |
-
'errno' => $easy->errno,
|
142 |
-
'error' => curl_error($easy->handle),
|
143 |
-
'appconnect_time' => curl_getinfo($easy->handle, CURLINFO_APPCONNECT_TIME),
|
144 |
-
] + curl_getinfo($easy->handle);
|
145 |
-
$ctx[self::CURL_VERSION_STR] = curl_version()['version'];
|
146 |
-
$factory->release($easy);
|
147 |
-
|
148 |
-
// Retry when nothing is present or when curl failed to rewind.
|
149 |
-
if (empty($easy->options['_err_message'])
|
150 |
-
&& (!$easy->errno || $easy->errno == 65)
|
151 |
-
) {
|
152 |
-
return self::retryFailedRewind($handler, $easy, $ctx);
|
153 |
-
}
|
154 |
-
|
155 |
-
return self::createRejection($easy, $ctx);
|
156 |
-
}
|
157 |
-
|
158 |
-
private static function createRejection(EasyHandle $easy, array $ctx)
|
159 |
-
{
|
160 |
-
static $connectionErrors = [
|
161 |
-
CURLE_OPERATION_TIMEOUTED => true,
|
162 |
-
CURLE_COULDNT_RESOLVE_HOST => true,
|
163 |
-
CURLE_COULDNT_CONNECT => true,
|
164 |
-
CURLE_SSL_CONNECT_ERROR => true,
|
165 |
-
CURLE_GOT_NOTHING => true,
|
166 |
-
];
|
167 |
-
|
168 |
-
// If an exception was encountered during the onHeaders event, then
|
169 |
-
// return a rejected promise that wraps that exception.
|
170 |
-
if ($easy->onHeadersException) {
|
171 |
-
return \GuzzleHttp\Promise\rejection_for(
|
172 |
-
new RequestException(
|
173 |
-
'An error was encountered during the on_headers event',
|
174 |
-
$easy->request,
|
175 |
-
$easy->response,
|
176 |
-
$easy->onHeadersException,
|
177 |
-
$ctx
|
178 |
-
)
|
179 |
-
);
|
180 |
-
}
|
181 |
-
if (version_compare($ctx[self::CURL_VERSION_STR], self::LOW_CURL_VERSION_NUMBER)) {
|
182 |
-
$message = sprintf(
|
183 |
-
'cURL error %s: %s (%s)',
|
184 |
-
$ctx['errno'],
|
185 |
-
$ctx['error'],
|
186 |
-
'see https://curl.haxx.se/libcurl/c/libcurl-errors.html'
|
187 |
-
);
|
188 |
-
} else {
|
189 |
-
$message = sprintf(
|
190 |
-
'cURL error %s: %s (%s) for %s',
|
191 |
-
$ctx['errno'],
|
192 |
-
$ctx['error'],
|
193 |
-
'see https://curl.haxx.se/libcurl/c/libcurl-errors.html',
|
194 |
-
$easy->request->getUri()
|
195 |
-
);
|
196 |
-
}
|
197 |
-
|
198 |
-
// Create a connection exception if it was a specific error code.
|
199 |
-
$error = isset($connectionErrors[$easy->errno])
|
200 |
-
? new ConnectException($message, $easy->request, null, $ctx)
|
201 |
-
: new RequestException($message, $easy->request, $easy->response, null, $ctx);
|
202 |
-
|
203 |
-
return \GuzzleHttp\Promise\rejection_for($error);
|
204 |
-
}
|
205 |
-
|
206 |
-
private function getDefaultConf(EasyHandle $easy)
|
207 |
-
{
|
208 |
-
$conf = [
|
209 |
-
'_headers' => $easy->request->getHeaders(),
|
210 |
-
CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
|
211 |
-
CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''),
|
212 |
-
CURLOPT_RETURNTRANSFER => false,
|
213 |
-
CURLOPT_HEADER => false,
|
214 |
-
CURLOPT_CONNECTTIMEOUT => 150,
|
215 |
-
];
|
216 |
-
|
217 |
-
if (defined('CURLOPT_PROTOCOLS')) {
|
218 |
-
$conf[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
|
219 |
-
}
|
220 |
-
|
221 |
-
$version = $easy->request->getProtocolVersion();
|
222 |
-
if ($version == 1.1) {
|
223 |
-
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
|
224 |
-
} elseif ($version == 2.0) {
|
225 |
-
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
|
226 |
-
} else {
|
227 |
-
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
|
228 |
-
}
|
229 |
-
|
230 |
-
return $conf;
|
231 |
-
}
|
232 |
-
|
233 |
-
private function applyMethod(EasyHandle $easy, array &$conf)
|
234 |
-
{
|
235 |
-
$body = $easy->request->getBody();
|
236 |
-
$size = $body->getSize();
|
237 |
-
|
238 |
-
if ($size === null || $size > 0) {
|
239 |
-
$this->applyBody($easy->request, $easy->options, $conf);
|
240 |
-
return;
|
241 |
-
}
|
242 |
-
|
243 |
-
$method = $easy->request->getMethod();
|
244 |
-
if ($method === 'PUT' || $method === 'POST') {
|
245 |
-
// See http://tools.ietf.org/html/rfc7230#section-3.3.2
|
246 |
-
if (!$easy->request->hasHeader('Content-Length')) {
|
247 |
-
$conf[CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
|
248 |
-
}
|
249 |
-
} elseif ($method === 'HEAD') {
|
250 |
-
$conf[CURLOPT_NOBODY] = true;
|
251 |
-
unset(
|
252 |
-
$conf[CURLOPT_WRITEFUNCTION],
|
253 |
-
$conf[CURLOPT_READFUNCTION],
|
254 |
-
$conf[CURLOPT_FILE],
|
255 |
-
$conf[CURLOPT_INFILE]
|
256 |
-
);
|
257 |
-
}
|
258 |
-
}
|
259 |
-
|
260 |
-
private function applyBody(RequestInterface $request, array $options, array &$conf)
|
261 |
-
{
|
262 |
-
$size = $request->hasHeader('Content-Length')
|
263 |
-
? (int) $request->getHeaderLine('Content-Length')
|
264 |
-
: null;
|
265 |
-
|
266 |
-
// Send the body as a string if the size is less than 1MB OR if the
|
267 |
-
// [curl][body_as_string] request value is set.
|
268 |
-
if (($size !== null && $size < 1000000) ||
|
269 |
-
!empty($options['_body_as_string'])
|
270 |
-
) {
|
271 |
-
$conf[CURLOPT_POSTFIELDS] = (string) $request->getBody();
|
272 |
-
// Don't duplicate the Content-Length header
|
273 |
-
$this->removeHeader('Content-Length', $conf);
|
274 |
-
$this->removeHeader('Transfer-Encoding', $conf);
|
275 |
-
} else {
|
276 |
-
$conf[CURLOPT_UPLOAD] = true;
|
277 |
-
if ($size !== null) {
|
278 |
-
$conf[CURLOPT_INFILESIZE] = $size;
|
279 |
-
$this->removeHeader('Content-Length', $conf);
|
280 |
-
}
|
281 |
-
$body = $request->getBody();
|
282 |
-
if ($body->isSeekable()) {
|
283 |
-
$body->rewind();
|
284 |
-
}
|
285 |
-
$conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
|
286 |
-
return $body->read($length);
|
287 |
-
};
|
288 |
-
}
|
289 |
-
|
290 |
-
// If the Expect header is not present, prevent curl from adding it
|
291 |
-
if (!$request->hasHeader('Expect')) {
|
292 |
-
$conf[CURLOPT_HTTPHEADER][] = 'Expect:';
|
293 |
-
}
|
294 |
-
|
295 |
-
// cURL sometimes adds a content-type by default. Prevent this.
|
296 |
-
if (!$request->hasHeader('Content-Type')) {
|
297 |
-
$conf[CURLOPT_HTTPHEADER][] = 'Content-Type:';
|
298 |
-
}
|
299 |
-
}
|
300 |
-
|
301 |
-
private function applyHeaders(EasyHandle $easy, array &$conf)
|
302 |
-
{
|
303 |
-
foreach ($conf['_headers'] as $name => $values) {
|
304 |
-
foreach ($values as $value) {
|
305 |
-
$value = (string) $value;
|
306 |
-
if ($value === '') {
|
307 |
-
// cURL requires a special format for empty headers.
|
308 |
-
// See https://github.com/guzzle/guzzle/issues/1882 for more details.
|
309 |
-
$conf[CURLOPT_HTTPHEADER][] = "$name;";
|
310 |
-
} else {
|
311 |
-
$conf[CURLOPT_HTTPHEADER][] = "$name: $value";
|
312 |
-
}
|
313 |
-
}
|
314 |
-
}
|
315 |
-
|
316 |
-
// Remove the Accept header if one was not set
|
317 |
-
if (!$easy->request->hasHeader('Accept')) {
|
318 |
-
$conf[CURLOPT_HTTPHEADER][] = 'Accept:';
|
319 |
-
}
|
320 |
-
}
|
321 |
-
|
322 |
-
/**
|
323 |
-
* Remove a header from the options array.
|
324 |
-
*
|
325 |
-
* @param string $name Case-insensitive header to remove
|
326 |
-
* @param array $options Array of options to modify
|
327 |
-
*/
|
328 |
-
private function removeHeader($name, array &$options)
|
329 |
-
{
|
330 |
-
foreach (array_keys($options['_headers']) as $key) {
|
331 |
-
if (!strcasecmp($key, $name)) {
|
332 |
-
unset($options['_headers'][$key]);
|
333 |
-
return;
|
334 |
-
}
|
335 |
-
}
|
336 |
-
}
|
337 |
-
|
338 |
-
private function applyHandlerOptions(EasyHandle $easy, array &$conf)
|
339 |
-
{
|
340 |
-
$options = $easy->options;
|
341 |
-
if (isset($options['verify'])) {
|
342 |
-
if ($options['verify'] === false) {
|
343 |
-
unset($conf[CURLOPT_CAINFO]);
|
344 |
-
$conf[CURLOPT_SSL_VERIFYHOST] = 0;
|
345 |
-
$conf[CURLOPT_SSL_VERIFYPEER] = false;
|
346 |
-
} else {
|
347 |
-
$conf[CURLOPT_SSL_VERIFYHOST] = 2;
|
348 |
-
$conf[CURLOPT_SSL_VERIFYPEER] = true;
|
349 |
-
if (is_string($options['verify'])) {
|
350 |
-
// Throw an error if the file/folder/link path is not valid or doesn't exist.
|
351 |
-
if (!file_exists($options['verify'])) {
|
352 |
-
throw new \InvalidArgumentException(
|
353 |
-
"SSL CA bundle not found: {$options['verify']}"
|
354 |
-
);
|
355 |
-
}
|
356 |
-
// If it's a directory or a link to a directory use CURLOPT_CAPATH.
|
357 |
-
// If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
|
358 |
-
if (is_dir($options['verify']) ||
|
359 |
-
(is_link($options['verify']) && is_dir(readlink($options['verify'])))) {
|
360 |
-
$conf[CURLOPT_CAPATH] = $options['verify'];
|
361 |
-
} else {
|
362 |
-
$conf[CURLOPT_CAINFO] = $options['verify'];
|
363 |
-
}
|
364 |
-
}
|
365 |
-
}
|
366 |
-
}
|
367 |
-
|
368 |
-
if (!empty($options['decode_content'])) {
|
369 |
-
$accept = $easy->request->getHeaderLine('Accept-Encoding');
|
370 |
-
if ($accept) {
|
371 |
-
$conf[CURLOPT_ENCODING] = $accept;
|
372 |
-
} else {
|
373 |
-
$conf[CURLOPT_ENCODING] = '';
|
374 |
-
// Don't let curl send the header over the wire
|
375 |
-
$conf[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
|
376 |
-
}
|
377 |
-
}
|
378 |
-
|
379 |
-
if (isset($options['sink'])) {
|
380 |
-
$sink = $options['sink'];
|
381 |
-
if (!is_string($sink)) {
|
382 |
-
$sink = \GuzzleHttp\Psr7\stream_for($sink);
|
383 |
-
} elseif (!is_dir(dirname($sink))) {
|
384 |
-
// Ensure that the directory exists before failing in curl.
|
385 |
-
throw new \RuntimeException(sprintf(
|
386 |
-
'Directory %s does not exist for sink value of %s',
|
387 |
-
dirname($sink),
|
388 |
-
$sink
|
389 |
-
));
|
390 |
-
} else {
|
391 |
-
$sink = new LazyOpenStream($sink, 'w+');
|
392 |
-
}
|
393 |
-
$easy->sink = $sink;
|
394 |
-
$conf[CURLOPT_WRITEFUNCTION] = function ($ch, $write) use ($sink) {
|
395 |
-
return $sink->write($write);
|
396 |
-
};
|
397 |
-
} else {
|
398 |
-
// Use a default temp stream if no sink was set.
|
399 |
-
$conf[CURLOPT_FILE] = fopen('php://temp', 'w+');
|
400 |
-
$easy->sink = Psr7\stream_for($conf[CURLOPT_FILE]);
|
401 |
-
}
|
402 |
-
$timeoutRequiresNoSignal = false;
|
403 |
-
if (isset($options['timeout'])) {
|
404 |
-
$timeoutRequiresNoSignal |= $options['timeout'] < 1;
|
405 |
-
$conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
|
406 |
-
}
|
407 |
-
|
408 |
-
// CURL default value is CURL_IPRESOLVE_WHATEVER
|
409 |
-
if (isset($options['force_ip_resolve'])) {
|
410 |
-
if ('v4' === $options['force_ip_resolve']) {
|
411 |
-
$conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
|
412 |
-
} elseif ('v6' === $options['force_ip_resolve']) {
|
413 |
-
$conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V6;
|
414 |
-
}
|
415 |
-
}
|
416 |
-
|
417 |
-
if (isset($options['connect_timeout'])) {
|
418 |
-
$timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;
|
419 |
-
$conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
|
420 |
-
}
|
421 |
-
|
422 |
-
if ($timeoutRequiresNoSignal && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
|
423 |
-
$conf[CURLOPT_NOSIGNAL] = true;
|
424 |
-
}
|
425 |
-
|
426 |
-
if (isset($options['proxy'])) {
|
427 |
-
if (!is_array($options['proxy'])) {
|
428 |
-
$conf[CURLOPT_PROXY] = $options['proxy'];
|
429 |
-
} else {
|
430 |
-
$scheme = $easy->request->getUri()->getScheme();
|
431 |
-
if (isset($options['proxy'][$scheme])) {
|
432 |
-
$host = $easy->request->getUri()->getHost();
|
433 |
-
if (!isset($options['proxy']['no']) ||
|
434 |
-
!\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no'])
|
435 |
-
) {
|
436 |
-
$conf[CURLOPT_PROXY] = $options['proxy'][$scheme];
|
437 |
-
}
|
438 |
-
}
|
439 |
-
}
|
440 |
-
}
|
441 |
-
|
442 |
-
if (isset($options['cert'])) {
|
443 |
-
$cert = $options['cert'];
|
444 |
-
if (is_array($cert)) {
|
445 |
-
$conf[CURLOPT_SSLCERTPASSWD] = $cert[1];
|
446 |
-
$cert = $cert[0];
|
447 |
-
}
|
448 |
-
if (!file_exists($cert)) {
|
449 |
-
throw new \InvalidArgumentException(
|
450 |
-
"SSL certificate not found: {$cert}"
|
451 |
-
);
|
452 |
-
}
|
453 |
-
$conf[CURLOPT_SSLCERT] = $cert;
|
454 |
-
}
|
455 |
-
|
456 |
-
if (isset($options['ssl_key'])) {
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
$
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
}
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
*
|
501 |
-
*
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
$
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
$easy
|
525 |
-
}
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
$
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
}
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
}
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
+
|
4 |
+
use GuzzleHttp\Exception\ConnectException;
|
5 |
+
use GuzzleHttp\Exception\RequestException;
|
6 |
+
use GuzzleHttp\Promise\FulfilledPromise;
|
7 |
+
use GuzzleHttp\Psr7;
|
8 |
+
use GuzzleHttp\Psr7\LazyOpenStream;
|
9 |
+
use GuzzleHttp\TransferStats;
|
10 |
+
use Psr\Http\Message\RequestInterface;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Creates curl resources from a request
|
14 |
+
*/
|
15 |
+
class CurlFactory implements CurlFactoryInterface
|
16 |
+
{
|
17 |
+
const CURL_VERSION_STR = 'curl_version';
|
18 |
+
const LOW_CURL_VERSION_NUMBER = '7.21.2';
|
19 |
+
|
20 |
+
/** @var array */
|
21 |
+
private $handles = [];
|
22 |
+
|
23 |
+
/** @var int Total number of idle handles to keep in cache */
|
24 |
+
private $maxHandles;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @param int $maxHandles Maximum number of idle handles.
|
28 |
+
*/
|
29 |
+
public function __construct($maxHandles)
|
30 |
+
{
|
31 |
+
$this->maxHandles = $maxHandles;
|
32 |
+
}
|
33 |
+
|
34 |
+
public function create(RequestInterface $request, array $options)
|
35 |
+
{
|
36 |
+
if (isset($options['curl']['body_as_string'])) {
|
37 |
+
$options['_body_as_string'] = $options['curl']['body_as_string'];
|
38 |
+
unset($options['curl']['body_as_string']);
|
39 |
+
}
|
40 |
+
|
41 |
+
$easy = new EasyHandle;
|
42 |
+
$easy->request = $request;
|
43 |
+
$easy->options = $options;
|
44 |
+
$conf = $this->getDefaultConf($easy);
|
45 |
+
$this->applyMethod($easy, $conf);
|
46 |
+
$this->applyHandlerOptions($easy, $conf);
|
47 |
+
$this->applyHeaders($easy, $conf);
|
48 |
+
unset($conf['_headers']);
|
49 |
+
|
50 |
+
// Add handler options from the request configuration options
|
51 |
+
if (isset($options['curl'])) {
|
52 |
+
$conf = array_replace($conf, $options['curl']);
|
53 |
+
}
|
54 |
+
|
55 |
+
$conf[CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
|
56 |
+
$easy->handle = $this->handles
|
57 |
+
? array_pop($this->handles)
|
58 |
+
: curl_init();
|
59 |
+
curl_setopt_array($easy->handle, $conf);
|
60 |
+
|
61 |
+
return $easy;
|
62 |
+
}
|
63 |
+
|
64 |
+
public function release(EasyHandle $easy)
|
65 |
+
{
|
66 |
+
$resource = $easy->handle;
|
67 |
+
unset($easy->handle);
|
68 |
+
|
69 |
+
if (count($this->handles) >= $this->maxHandles) {
|
70 |
+
curl_close($resource);
|
71 |
+
} else {
|
72 |
+
// Remove all callback functions as they can hold onto references
|
73 |
+
// and are not cleaned up by curl_reset. Using curl_setopt_array
|
74 |
+
// does not work for some reason, so removing each one
|
75 |
+
// individually.
|
76 |
+
curl_setopt($resource, CURLOPT_HEADERFUNCTION, null);
|
77 |
+
curl_setopt($resource, CURLOPT_READFUNCTION, null);
|
78 |
+
curl_setopt($resource, CURLOPT_WRITEFUNCTION, null);
|
79 |
+
curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null);
|
80 |
+
curl_reset($resource);
|
81 |
+
$this->handles[] = $resource;
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Completes a cURL transaction, either returning a response promise or a
|
87 |
+
* rejected promise.
|
88 |
+
*
|
89 |
+
* @param callable $handler
|
90 |
+
* @param EasyHandle $easy
|
91 |
+
* @param CurlFactoryInterface $factory Dictates how the handle is released
|
92 |
+
*
|
93 |
+
* @return \GuzzleHttp\Promise\PromiseInterface
|
94 |
+
*/
|
95 |
+
public static function finish(
|
96 |
+
callable $handler,
|
97 |
+
EasyHandle $easy,
|
98 |
+
CurlFactoryInterface $factory
|
99 |
+
) {
|
100 |
+
if (isset($easy->options['on_stats'])) {
|
101 |
+
self::invokeStats($easy);
|
102 |
+
}
|
103 |
+
|
104 |
+
if (!$easy->response || $easy->errno) {
|
105 |
+
return self::finishError($handler, $easy, $factory);
|
106 |
+
}
|
107 |
+
|
108 |
+
// Return the response if it is present and there is no error.
|
109 |
+
$factory->release($easy);
|
110 |
+
|
111 |
+
// Rewind the body of the response if possible.
|
112 |
+
$body = $easy->response->getBody();
|
113 |
+
if ($body->isSeekable()) {
|
114 |
+
$body->rewind();
|
115 |
+
}
|
116 |
+
|
117 |
+
return new FulfilledPromise($easy->response);
|
118 |
+
}
|
119 |
+
|
120 |
+
private static function invokeStats(EasyHandle $easy)
|
121 |
+
{
|
122 |
+
$curlStats = curl_getinfo($easy->handle);
|
123 |
+
$curlStats['appconnect_time'] = curl_getinfo($easy->handle, CURLINFO_APPCONNECT_TIME);
|
124 |
+
$stats = new TransferStats(
|
125 |
+
$easy->request,
|
126 |
+
$easy->response,
|
127 |
+
$curlStats['total_time'],
|
128 |
+
$easy->errno,
|
129 |
+
$curlStats
|
130 |
+
);
|
131 |
+
call_user_func($easy->options['on_stats'], $stats);
|
132 |
+
}
|
133 |
+
|
134 |
+
private static function finishError(
|
135 |
+
callable $handler,
|
136 |
+
EasyHandle $easy,
|
137 |
+
CurlFactoryInterface $factory
|
138 |
+
) {
|
139 |
+
// Get error information and release the handle to the factory.
|
140 |
+
$ctx = [
|
141 |
+
'errno' => $easy->errno,
|
142 |
+
'error' => curl_error($easy->handle),
|
143 |
+
'appconnect_time' => curl_getinfo($easy->handle, CURLINFO_APPCONNECT_TIME),
|
144 |
+
] + curl_getinfo($easy->handle);
|
145 |
+
$ctx[self::CURL_VERSION_STR] = curl_version()['version'];
|
146 |
+
$factory->release($easy);
|
147 |
+
|
148 |
+
// Retry when nothing is present or when curl failed to rewind.
|
149 |
+
if (empty($easy->options['_err_message'])
|
150 |
+
&& (!$easy->errno || $easy->errno == 65)
|
151 |
+
) {
|
152 |
+
return self::retryFailedRewind($handler, $easy, $ctx);
|
153 |
+
}
|
154 |
+
|
155 |
+
return self::createRejection($easy, $ctx);
|
156 |
+
}
|
157 |
+
|
158 |
+
private static function createRejection(EasyHandle $easy, array $ctx)
|
159 |
+
{
|
160 |
+
static $connectionErrors = [
|
161 |
+
CURLE_OPERATION_TIMEOUTED => true,
|
162 |
+
CURLE_COULDNT_RESOLVE_HOST => true,
|
163 |
+
CURLE_COULDNT_CONNECT => true,
|
164 |
+
CURLE_SSL_CONNECT_ERROR => true,
|
165 |
+
CURLE_GOT_NOTHING => true,
|
166 |
+
];
|
167 |
+
|
168 |
+
// If an exception was encountered during the onHeaders event, then
|
169 |
+
// return a rejected promise that wraps that exception.
|
170 |
+
if ($easy->onHeadersException) {
|
171 |
+
return \GuzzleHttp\Promise\rejection_for(
|
172 |
+
new RequestException(
|
173 |
+
'An error was encountered during the on_headers event',
|
174 |
+
$easy->request,
|
175 |
+
$easy->response,
|
176 |
+
$easy->onHeadersException,
|
177 |
+
$ctx
|
178 |
+
)
|
179 |
+
);
|
180 |
+
}
|
181 |
+
if (version_compare($ctx[self::CURL_VERSION_STR], self::LOW_CURL_VERSION_NUMBER)) {
|
182 |
+
$message = sprintf(
|
183 |
+
'cURL error %s: %s (%s)',
|
184 |
+
$ctx['errno'],
|
185 |
+
$ctx['error'],
|
186 |
+
'see https://curl.haxx.se/libcurl/c/libcurl-errors.html'
|
187 |
+
);
|
188 |
+
} else {
|
189 |
+
$message = sprintf(
|
190 |
+
'cURL error %s: %s (%s) for %s',
|
191 |
+
$ctx['errno'],
|
192 |
+
$ctx['error'],
|
193 |
+
'see https://curl.haxx.se/libcurl/c/libcurl-errors.html',
|
194 |
+
$easy->request->getUri()
|
195 |
+
);
|
196 |
+
}
|
197 |
+
|
198 |
+
// Create a connection exception if it was a specific error code.
|
199 |
+
$error = isset($connectionErrors[$easy->errno])
|
200 |
+
? new ConnectException($message, $easy->request, null, $ctx)
|
201 |
+
: new RequestException($message, $easy->request, $easy->response, null, $ctx);
|
202 |
+
|
203 |
+
return \GuzzleHttp\Promise\rejection_for($error);
|
204 |
+
}
|
205 |
+
|
206 |
+
private function getDefaultConf(EasyHandle $easy)
|
207 |
+
{
|
208 |
+
$conf = [
|
209 |
+
'_headers' => $easy->request->getHeaders(),
|
210 |
+
CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
|
211 |
+
CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''),
|
212 |
+
CURLOPT_RETURNTRANSFER => false,
|
213 |
+
CURLOPT_HEADER => false,
|
214 |
+
CURLOPT_CONNECTTIMEOUT => 150,
|
215 |
+
];
|
216 |
+
|
217 |
+
if (defined('CURLOPT_PROTOCOLS')) {
|
218 |
+
$conf[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
|
219 |
+
}
|
220 |
+
|
221 |
+
$version = $easy->request->getProtocolVersion();
|
222 |
+
if ($version == 1.1) {
|
223 |
+
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
|
224 |
+
} elseif ($version == 2.0) {
|
225 |
+
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
|
226 |
+
} else {
|
227 |
+
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
|
228 |
+
}
|
229 |
+
|
230 |
+
return $conf;
|
231 |
+
}
|
232 |
+
|
233 |
+
private function applyMethod(EasyHandle $easy, array &$conf)
|
234 |
+
{
|
235 |
+
$body = $easy->request->getBody();
|
236 |
+
$size = $body->getSize();
|
237 |
+
|
238 |
+
if ($size === null || $size > 0) {
|
239 |
+
$this->applyBody($easy->request, $easy->options, $conf);
|
240 |
+
return;
|
241 |
+
}
|
242 |
+
|
243 |
+
$method = $easy->request->getMethod();
|
244 |
+
if ($method === 'PUT' || $method === 'POST') {
|
245 |
+
// See http://tools.ietf.org/html/rfc7230#section-3.3.2
|
246 |
+
if (!$easy->request->hasHeader('Content-Length')) {
|
247 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
|
248 |
+
}
|
249 |
+
} elseif ($method === 'HEAD') {
|
250 |
+
$conf[CURLOPT_NOBODY] = true;
|
251 |
+
unset(
|
252 |
+
$conf[CURLOPT_WRITEFUNCTION],
|
253 |
+
$conf[CURLOPT_READFUNCTION],
|
254 |
+
$conf[CURLOPT_FILE],
|
255 |
+
$conf[CURLOPT_INFILE]
|
256 |
+
);
|
257 |
+
}
|
258 |
+
}
|
259 |
+
|
260 |
+
private function applyBody(RequestInterface $request, array $options, array &$conf)
|
261 |
+
{
|
262 |
+
$size = $request->hasHeader('Content-Length')
|
263 |
+
? (int) $request->getHeaderLine('Content-Length')
|
264 |
+
: null;
|
265 |
+
|
266 |
+
// Send the body as a string if the size is less than 1MB OR if the
|
267 |
+
// [curl][body_as_string] request value is set.
|
268 |
+
if (($size !== null && $size < 1000000) ||
|
269 |
+
!empty($options['_body_as_string'])
|
270 |
+
) {
|
271 |
+
$conf[CURLOPT_POSTFIELDS] = (string) $request->getBody();
|
272 |
+
// Don't duplicate the Content-Length header
|
273 |
+
$this->removeHeader('Content-Length', $conf);
|
274 |
+
$this->removeHeader('Transfer-Encoding', $conf);
|
275 |
+
} else {
|
276 |
+
$conf[CURLOPT_UPLOAD] = true;
|
277 |
+
if ($size !== null) {
|
278 |
+
$conf[CURLOPT_INFILESIZE] = $size;
|
279 |
+
$this->removeHeader('Content-Length', $conf);
|
280 |
+
}
|
281 |
+
$body = $request->getBody();
|
282 |
+
if ($body->isSeekable()) {
|
283 |
+
$body->rewind();
|
284 |
+
}
|
285 |
+
$conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
|
286 |
+
return $body->read($length);
|
287 |
+
};
|
288 |
+
}
|
289 |
+
|
290 |
+
// If the Expect header is not present, prevent curl from adding it
|
291 |
+
if (!$request->hasHeader('Expect')) {
|
292 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Expect:';
|
293 |
+
}
|
294 |
+
|
295 |
+
// cURL sometimes adds a content-type by default. Prevent this.
|
296 |
+
if (!$request->hasHeader('Content-Type')) {
|
297 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Content-Type:';
|
298 |
+
}
|
299 |
+
}
|
300 |
+
|
301 |
+
private function applyHeaders(EasyHandle $easy, array &$conf)
|
302 |
+
{
|
303 |
+
foreach ($conf['_headers'] as $name => $values) {
|
304 |
+
foreach ($values as $value) {
|
305 |
+
$value = (string) $value;
|
306 |
+
if ($value === '') {
|
307 |
+
// cURL requires a special format for empty headers.
|
308 |
+
// See https://github.com/guzzle/guzzle/issues/1882 for more details.
|
309 |
+
$conf[CURLOPT_HTTPHEADER][] = "$name;";
|
310 |
+
} else {
|
311 |
+
$conf[CURLOPT_HTTPHEADER][] = "$name: $value";
|
312 |
+
}
|
313 |
+
}
|
314 |
+
}
|
315 |
+
|
316 |
+
// Remove the Accept header if one was not set
|
317 |
+
if (!$easy->request->hasHeader('Accept')) {
|
318 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Accept:';
|
319 |
+
}
|
320 |
+
}
|
321 |
+
|
322 |
+
/**
|
323 |
+
* Remove a header from the options array.
|
324 |
+
*
|
325 |
+
* @param string $name Case-insensitive header to remove
|
326 |
+
* @param array $options Array of options to modify
|
327 |
+
*/
|
328 |
+
private function removeHeader($name, array &$options)
|
329 |
+
{
|
330 |
+
foreach (array_keys($options['_headers']) as $key) {
|
331 |
+
if (!strcasecmp($key, $name)) {
|
332 |
+
unset($options['_headers'][$key]);
|
333 |
+
return;
|
334 |
+
}
|
335 |
+
}
|
336 |
+
}
|
337 |
+
|
338 |
+
private function applyHandlerOptions(EasyHandle $easy, array &$conf)
|
339 |
+
{
|
340 |
+
$options = $easy->options;
|
341 |
+
if (isset($options['verify'])) {
|
342 |
+
if ($options['verify'] === false) {
|
343 |
+
unset($conf[CURLOPT_CAINFO]);
|
344 |
+
$conf[CURLOPT_SSL_VERIFYHOST] = 0;
|
345 |
+
$conf[CURLOPT_SSL_VERIFYPEER] = false;
|
346 |
+
} else {
|
347 |
+
$conf[CURLOPT_SSL_VERIFYHOST] = 2;
|
348 |
+
$conf[CURLOPT_SSL_VERIFYPEER] = true;
|
349 |
+
if (is_string($options['verify'])) {
|
350 |
+
// Throw an error if the file/folder/link path is not valid or doesn't exist.
|
351 |
+
if (!file_exists($options['verify'])) {
|
352 |
+
throw new \InvalidArgumentException(
|
353 |
+
"SSL CA bundle not found: {$options['verify']}"
|
354 |
+
);
|
355 |
+
}
|
356 |
+
// If it's a directory or a link to a directory use CURLOPT_CAPATH.
|
357 |
+
// If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
|
358 |
+
if (is_dir($options['verify']) ||
|
359 |
+
(is_link($options['verify']) && is_dir(readlink($options['verify'])))) {
|
360 |
+
$conf[CURLOPT_CAPATH] = $options['verify'];
|
361 |
+
} else {
|
362 |
+
$conf[CURLOPT_CAINFO] = $options['verify'];
|
363 |
+
}
|
364 |
+
}
|
365 |
+
}
|
366 |
+
}
|
367 |
+
|
368 |
+
if (!empty($options['decode_content'])) {
|
369 |
+
$accept = $easy->request->getHeaderLine('Accept-Encoding');
|
370 |
+
if ($accept) {
|
371 |
+
$conf[CURLOPT_ENCODING] = $accept;
|
372 |
+
} else {
|
373 |
+
$conf[CURLOPT_ENCODING] = '';
|
374 |
+
// Don't let curl send the header over the wire
|
375 |
+
$conf[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
|
376 |
+
}
|
377 |
+
}
|
378 |
+
|
379 |
+
if (isset($options['sink'])) {
|
380 |
+
$sink = $options['sink'];
|
381 |
+
if (!is_string($sink)) {
|
382 |
+
$sink = \GuzzleHttp\Psr7\stream_for($sink);
|
383 |
+
} elseif (!is_dir(dirname($sink))) {
|
384 |
+
// Ensure that the directory exists before failing in curl.
|
385 |
+
throw new \RuntimeException(sprintf(
|
386 |
+
'Directory %s does not exist for sink value of %s',
|
387 |
+
dirname($sink),
|
388 |
+
$sink
|
389 |
+
));
|
390 |
+
} else {
|
391 |
+
$sink = new LazyOpenStream($sink, 'w+');
|
392 |
+
}
|
393 |
+
$easy->sink = $sink;
|
394 |
+
$conf[CURLOPT_WRITEFUNCTION] = function ($ch, $write) use ($sink) {
|
395 |
+
return $sink->write($write);
|
396 |
+
};
|
397 |
+
} else {
|
398 |
+
// Use a default temp stream if no sink was set.
|
399 |
+
$conf[CURLOPT_FILE] = fopen('php://temp', 'w+');
|
400 |
+
$easy->sink = Psr7\stream_for($conf[CURLOPT_FILE]);
|
401 |
+
}
|
402 |
+
$timeoutRequiresNoSignal = false;
|
403 |
+
if (isset($options['timeout'])) {
|
404 |
+
$timeoutRequiresNoSignal |= $options['timeout'] < 1;
|
405 |
+
$conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
|
406 |
+
}
|
407 |
+
|
408 |
+
// CURL default value is CURL_IPRESOLVE_WHATEVER
|
409 |
+
if (isset($options['force_ip_resolve'])) {
|
410 |
+
if ('v4' === $options['force_ip_resolve']) {
|
411 |
+
$conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
|
412 |
+
} elseif ('v6' === $options['force_ip_resolve']) {
|
413 |
+
$conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V6;
|
414 |
+
}
|
415 |
+
}
|
416 |
+
|
417 |
+
if (isset($options['connect_timeout'])) {
|
418 |
+
$timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;
|
419 |
+
$conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
|
420 |
+
}
|
421 |
+
|
422 |
+
if ($timeoutRequiresNoSignal && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
|
423 |
+
$conf[CURLOPT_NOSIGNAL] = true;
|
424 |
+
}
|
425 |
+
|
426 |
+
if (isset($options['proxy'])) {
|
427 |
+
if (!is_array($options['proxy'])) {
|
428 |
+
$conf[CURLOPT_PROXY] = $options['proxy'];
|
429 |
+
} else {
|
430 |
+
$scheme = $easy->request->getUri()->getScheme();
|
431 |
+
if (isset($options['proxy'][$scheme])) {
|
432 |
+
$host = $easy->request->getUri()->getHost();
|
433 |
+
if (!isset($options['proxy']['no']) ||
|
434 |
+
!\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no'])
|
435 |
+
) {
|
436 |
+
$conf[CURLOPT_PROXY] = $options['proxy'][$scheme];
|
437 |
+
}
|
438 |
+
}
|
439 |
+
}
|
440 |
+
}
|
441 |
+
|
442 |
+
if (isset($options['cert'])) {
|
443 |
+
$cert = $options['cert'];
|
444 |
+
if (is_array($cert)) {
|
445 |
+
$conf[CURLOPT_SSLCERTPASSWD] = $cert[1];
|
446 |
+
$cert = $cert[0];
|
447 |
+
}
|
448 |
+
if (!file_exists($cert)) {
|
449 |
+
throw new \InvalidArgumentException(
|
450 |
+
"SSL certificate not found: {$cert}"
|
451 |
+
);
|
452 |
+
}
|
453 |
+
$conf[CURLOPT_SSLCERT] = $cert;
|
454 |
+
}
|
455 |
+
|
456 |
+
if (isset($options['ssl_key'])) {
|
457 |
+
if (is_array($options['ssl_key'])) {
|
458 |
+
if (count($options['ssl_key']) === 2) {
|
459 |
+
list($sslKey, $conf[CURLOPT_SSLKEYPASSWD]) = $options['ssl_key'];
|
460 |
+
} else {
|
461 |
+
list($sslKey) = $options['ssl_key'];
|
462 |
+
}
|
463 |
+
}
|
464 |
+
|
465 |
+
$sslKey = isset($sslKey) ? $sslKey: $options['ssl_key'];
|
466 |
+
|
467 |
+
if (!file_exists($sslKey)) {
|
468 |
+
throw new \InvalidArgumentException(
|
469 |
+
"SSL private key not found: {$sslKey}"
|
470 |
+
);
|
471 |
+
}
|
472 |
+
$conf[CURLOPT_SSLKEY] = $sslKey;
|
473 |
+
}
|
474 |
+
|
475 |
+
if (isset($options['progress'])) {
|
476 |
+
$progress = $options['progress'];
|
477 |
+
if (!is_callable($progress)) {
|
478 |
+
throw new \InvalidArgumentException(
|
479 |
+
'progress client option must be callable'
|
480 |
+
);
|
481 |
+
}
|
482 |
+
$conf[CURLOPT_NOPROGRESS] = false;
|
483 |
+
$conf[CURLOPT_PROGRESSFUNCTION] = function () use ($progress) {
|
484 |
+
$args = func_get_args();
|
485 |
+
// PHP 5.5 pushed the handle onto the start of the args
|
486 |
+
if (is_resource($args[0])) {
|
487 |
+
array_shift($args);
|
488 |
+
}
|
489 |
+
call_user_func_array($progress, $args);
|
490 |
+
};
|
491 |
+
}
|
492 |
+
|
493 |
+
if (!empty($options['debug'])) {
|
494 |
+
$conf[CURLOPT_STDERR] = \GuzzleHttp\debug_resource($options['debug']);
|
495 |
+
$conf[CURLOPT_VERBOSE] = true;
|
496 |
+
}
|
497 |
+
}
|
498 |
+
|
499 |
+
/**
|
500 |
+
* This function ensures that a response was set on a transaction. If one
|
501 |
+
* was not set, then the request is retried if possible. This error
|
502 |
+
* typically means you are sending a payload, curl encountered a
|
503 |
+
* "Connection died, retrying a fresh connect" error, tried to rewind the
|
504 |
+
* stream, and then encountered a "necessary data rewind wasn't possible"
|
505 |
+
* error, causing the request to be sent through curl_multi_info_read()
|
506 |
+
* without an error status.
|
507 |
+
*/
|
508 |
+
private static function retryFailedRewind(
|
509 |
+
callable $handler,
|
510 |
+
EasyHandle $easy,
|
511 |
+
array $ctx
|
512 |
+
) {
|
513 |
+
try {
|
514 |
+
// Only rewind if the body has been read from.
|
515 |
+
$body = $easy->request->getBody();
|
516 |
+
if ($body->tell() > 0) {
|
517 |
+
$body->rewind();
|
518 |
+
}
|
519 |
+
} catch (\RuntimeException $e) {
|
520 |
+
$ctx['error'] = 'The connection unexpectedly failed without '
|
521 |
+
. 'providing an error. The request would have been retried, '
|
522 |
+
. 'but attempting to rewind the request body failed. '
|
523 |
+
. 'Exception: ' . $e;
|
524 |
+
return self::createRejection($easy, $ctx);
|
525 |
+
}
|
526 |
+
|
527 |
+
// Retry no more than 3 times before giving up.
|
528 |
+
if (!isset($easy->options['_curl_retries'])) {
|
529 |
+
$easy->options['_curl_retries'] = 1;
|
530 |
+
} elseif ($easy->options['_curl_retries'] == 2) {
|
531 |
+
$ctx['error'] = 'The cURL request was retried 3 times '
|
532 |
+
. 'and did not succeed. The most likely reason for the failure '
|
533 |
+
. 'is that cURL was unable to rewind the body of the request '
|
534 |
+
. 'and subsequent retries resulted in the same error. Turn on '
|
535 |
+
. 'the debug option to see what went wrong. See '
|
536 |
+
. 'https://bugs.php.net/bug.php?id=47204 for more information.';
|
537 |
+
return self::createRejection($easy, $ctx);
|
538 |
+
} else {
|
539 |
+
$easy->options['_curl_retries']++;
|
540 |
+
}
|
541 |
+
|
542 |
+
return $handler($easy->request, $easy->options);
|
543 |
+
}
|
544 |
+
|
545 |
+
private function createHeaderFn(EasyHandle $easy)
|
546 |
+
{
|
547 |
+
if (isset($easy->options['on_headers'])) {
|
548 |
+
$onHeaders = $easy->options['on_headers'];
|
549 |
+
|
550 |
+
if (!is_callable($onHeaders)) {
|
551 |
+
throw new \InvalidArgumentException('on_headers must be callable');
|
552 |
+
}
|
553 |
+
} else {
|
554 |
+
$onHeaders = null;
|
555 |
+
}
|
556 |
+
|
557 |
+
return function ($ch, $h) use (
|
558 |
+
$onHeaders,
|
559 |
+
$easy,
|
560 |
+
&$startingResponse
|
561 |
+
) {
|
562 |
+
$value = trim($h);
|
563 |
+
if ($value === '') {
|
564 |
+
$startingResponse = true;
|
565 |
+
$easy->createResponse();
|
566 |
+
if ($onHeaders !== null) {
|
567 |
+
try {
|
568 |
+
$onHeaders($easy->response);
|
569 |
+
} catch (\Exception $e) {
|
570 |
+
// Associate the exception with the handle and trigger
|
571 |
+
// a curl header write error by returning 0.
|
572 |
+
$easy->onHeadersException = $e;
|
573 |
+
return -1;
|
574 |
+
}
|
575 |
+
}
|
576 |
+
} elseif ($startingResponse) {
|
577 |
+
$startingResponse = false;
|
578 |
+
$easy->headers = [$value];
|
579 |
+
} else {
|
580 |
+
$easy->headers[] = $value;
|
581 |
+
}
|
582 |
+
return strlen($h);
|
583 |
+
};
|
584 |
+
}
|
585 |
+
}
|
vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php
CHANGED
@@ -1,205 +1,219 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp\Handler;
|
3 |
-
|
4 |
-
use GuzzleHttp\
|
5 |
-
use GuzzleHttp\Promise
|
6 |
-
use GuzzleHttp\
|
7 |
-
use Psr\Http\Message\RequestInterface;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Returns an asynchronous response using curl_multi_* functions.
|
11 |
-
*
|
12 |
-
* When using the CurlMultiHandler, custom curl options can be specified as an
|
13 |
-
* associative array of curl option constants mapping to values in the
|
14 |
-
* **curl** key of the provided request options.
|
15 |
-
*
|
16 |
-
* @property resource $_mh Internal use only. Lazy loaded multi-handle.
|
17 |
-
*/
|
18 |
-
class CurlMultiHandler
|
19 |
-
{
|
20 |
-
/** @var CurlFactoryInterface */
|
21 |
-
private $factory;
|
22 |
-
private $selectTimeout;
|
23 |
-
private $active;
|
24 |
-
private $handles = [];
|
25 |
-
private $delays = [];
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
*
|
30 |
-
*
|
31 |
-
* -
|
32 |
-
*
|
33 |
-
*
|
34 |
-
*
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
//
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
$
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
)
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
+
|
4 |
+
use GuzzleHttp\Exception\InvalidArgumentException;
|
5 |
+
use GuzzleHttp\Promise as P;
|
6 |
+
use GuzzleHttp\Promise\Promise;
|
7 |
+
use Psr\Http\Message\RequestInterface;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Returns an asynchronous response using curl_multi_* functions.
|
11 |
+
*
|
12 |
+
* When using the CurlMultiHandler, custom curl options can be specified as an
|
13 |
+
* associative array of curl option constants mapping to values in the
|
14 |
+
* **curl** key of the provided request options.
|
15 |
+
*
|
16 |
+
* @property resource $_mh Internal use only. Lazy loaded multi-handle.
|
17 |
+
*/
|
18 |
+
class CurlMultiHandler
|
19 |
+
{
|
20 |
+
/** @var CurlFactoryInterface */
|
21 |
+
private $factory;
|
22 |
+
private $selectTimeout;
|
23 |
+
private $active;
|
24 |
+
private $handles = [];
|
25 |
+
private $delays = [];
|
26 |
+
private $options = [];
|
27 |
+
|
28 |
+
/**
|
29 |
+
* This handler accepts the following options:
|
30 |
+
*
|
31 |
+
* - handle_factory: An optional factory used to create curl handles
|
32 |
+
* - select_timeout: Optional timeout (in seconds) to block before timing
|
33 |
+
* out while selecting curl handles. Defaults to 1 second.
|
34 |
+
* - options: An associative array of CURLMOPT_* options and
|
35 |
+
* corresponding values for curl_multi_setopt()
|
36 |
+
*
|
37 |
+
* @param array $options
|
38 |
+
*/
|
39 |
+
public function __construct(array $options = [])
|
40 |
+
{
|
41 |
+
$this->factory = isset($options['handle_factory'])
|
42 |
+
? $options['handle_factory'] : new CurlFactory(50);
|
43 |
+
|
44 |
+
if (isset($options['select_timeout'])) {
|
45 |
+
$this->selectTimeout = $options['select_timeout'];
|
46 |
+
} elseif ($selectTimeout = getenv('GUZZLE_CURL_SELECT_TIMEOUT')) {
|
47 |
+
$this->selectTimeout = $selectTimeout;
|
48 |
+
} else {
|
49 |
+
$this->selectTimeout = 1;
|
50 |
+
}
|
51 |
+
|
52 |
+
$this->options = isset($options['options']) ? $options['options'] : [];
|
53 |
+
}
|
54 |
+
|
55 |
+
public function __get($name)
|
56 |
+
{
|
57 |
+
if ($name === '_mh') {
|
58 |
+
$this->_mh = curl_multi_init();
|
59 |
+
|
60 |
+
foreach ($this->options as $option => $value) {
|
61 |
+
// A warning is raised in case of a wrong option.
|
62 |
+
curl_multi_setopt($this->_mh, $option, $value);
|
63 |
+
}
|
64 |
+
|
65 |
+
// Further calls to _mh will return the value directly, without entering the
|
66 |
+
// __get() method at all.
|
67 |
+
return $this->_mh;
|
68 |
+
}
|
69 |
+
|
70 |
+
throw new \BadMethodCallException();
|
71 |
+
}
|
72 |
+
|
73 |
+
public function __destruct()
|
74 |
+
{
|
75 |
+
if (isset($this->_mh)) {
|
76 |
+
curl_multi_close($this->_mh);
|
77 |
+
unset($this->_mh);
|
78 |
+
}
|
79 |
+
}
|
80 |
+
|
81 |
+
public function __invoke(RequestInterface $request, array $options)
|
82 |
+
{
|
83 |
+
$easy = $this->factory->create($request, $options);
|
84 |
+
$id = (int) $easy->handle;
|
85 |
+
|
86 |
+
$promise = new Promise(
|
87 |
+
[$this, 'execute'],
|
88 |
+
function () use ($id) {
|
89 |
+
return $this->cancel($id);
|
90 |
+
}
|
91 |
+
);
|
92 |
+
|
93 |
+
$this->addRequest(['easy' => $easy, 'deferred' => $promise]);
|
94 |
+
|
95 |
+
return $promise;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Ticks the curl event loop.
|
100 |
+
*/
|
101 |
+
public function tick()
|
102 |
+
{
|
103 |
+
// Add any delayed handles if needed.
|
104 |
+
if ($this->delays) {
|
105 |
+
$currentTime = \GuzzleHttp\_current_time();
|
106 |
+
foreach ($this->delays as $id => $delay) {
|
107 |
+
if ($currentTime >= $delay) {
|
108 |
+
unset($this->delays[$id]);
|
109 |
+
curl_multi_add_handle(
|
110 |
+
$this->_mh,
|
111 |
+
$this->handles[$id]['easy']->handle
|
112 |
+
);
|
113 |
+
}
|
114 |
+
}
|
115 |
+
}
|
116 |
+
|
117 |
+
// Step through the task queue which may add additional requests.
|
118 |
+
P\queue()->run();
|
119 |
+
|
120 |
+
if ($this->active &&
|
121 |
+
curl_multi_select($this->_mh, $this->selectTimeout) === -1
|
122 |
+
) {
|
123 |
+
// Perform a usleep if a select returns -1.
|
124 |
+
// See: https://bugs.php.net/bug.php?id=61141
|
125 |
+
usleep(250);
|
126 |
+
}
|
127 |
+
|
128 |
+
while (curl_multi_exec($this->_mh, $this->active) === CURLM_CALL_MULTI_PERFORM);
|
129 |
+
|
130 |
+
$this->processMessages();
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Runs until all outstanding connections have completed.
|
135 |
+
*/
|
136 |
+
public function execute()
|
137 |
+
{
|
138 |
+
$queue = P\queue();
|
139 |
+
|
140 |
+
while ($this->handles || !$queue->isEmpty()) {
|
141 |
+
// If there are no transfers, then sleep for the next delay
|
142 |
+
if (!$this->active && $this->delays) {
|
143 |
+
usleep($this->timeToNext());
|
144 |
+
}
|
145 |
+
$this->tick();
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
private function addRequest(array $entry)
|
150 |
+
{
|
151 |
+
$easy = $entry['easy'];
|
152 |
+
$id = (int) $easy->handle;
|
153 |
+
$this->handles[$id] = $entry;
|
154 |
+
if (empty($easy->options['delay'])) {
|
155 |
+
curl_multi_add_handle($this->_mh, $easy->handle);
|
156 |
+
} else {
|
157 |
+
$this->delays[$id] = \GuzzleHttp\_current_time() + ($easy->options['delay'] / 1000);
|
158 |
+
}
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Cancels a handle from sending and removes references to it.
|
163 |
+
*
|
164 |
+
* @param int $id Handle ID to cancel and remove.
|
165 |
+
*
|
166 |
+
* @return bool True on success, false on failure.
|
167 |
+
*/
|
168 |
+
private function cancel($id)
|
169 |
+
{
|
170 |
+
// Cannot cancel if it has been processed.
|
171 |
+
if (!isset($this->handles[$id])) {
|
172 |
+
return false;
|
173 |
+
}
|
174 |
+
|
175 |
+
$handle = $this->handles[$id]['easy']->handle;
|
176 |
+
unset($this->delays[$id], $this->handles[$id]);
|
177 |
+
curl_multi_remove_handle($this->_mh, $handle);
|
178 |
+
curl_close($handle);
|
179 |
+
|
180 |
+
return true;
|
181 |
+
}
|
182 |
+
|
183 |
+
private function processMessages()
|
184 |
+
{
|
185 |
+
while ($done = curl_multi_info_read($this->_mh)) {
|
186 |
+
$id = (int) $done['handle'];
|
187 |
+
curl_multi_remove_handle($this->_mh, $done['handle']);
|
188 |
+
|
189 |
+
if (!isset($this->handles[$id])) {
|
190 |
+
// Probably was cancelled.
|
191 |
+
continue;
|
192 |
+
}
|
193 |
+
|
194 |
+
$entry = $this->handles[$id];
|
195 |
+
unset($this->handles[$id], $this->delays[$id]);
|
196 |
+
$entry['easy']->errno = $done['result'];
|
197 |
+
$entry['deferred']->resolve(
|
198 |
+
CurlFactory::finish(
|
199 |
+
$this,
|
200 |
+
$entry['easy'],
|
201 |
+
$this->factory
|
202 |
+
)
|
203 |
+
);
|
204 |
+
}
|
205 |
+
}
|
206 |
+
|
207 |
+
private function timeToNext()
|
208 |
+
{
|
209 |
+
$currentTime = \GuzzleHttp\_current_time();
|
210 |
+
$nextTime = PHP_INT_MAX;
|
211 |
+
foreach ($this->delays as $time) {
|
212 |
+
if ($time < $nextTime) {
|
213 |
+
$nextTime = $time;
|
214 |
+
}
|
215 |
+
}
|
216 |
+
|
217 |
+
return max(0, $nextTime - $currentTime) * 1000000;
|
218 |
+
}
|
219 |
+
}
|
vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php
CHANGED
@@ -1,190 +1,195 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp\Handler;
|
3 |
-
|
4 |
-
use GuzzleHttp\Exception\RequestException;
|
5 |
-
use GuzzleHttp\HandlerStack;
|
6 |
-
use GuzzleHttp\Promise\PromiseInterface;
|
7 |
-
use GuzzleHttp\Promise\RejectedPromise;
|
8 |
-
use GuzzleHttp\TransferStats;
|
9 |
-
use Psr\Http\Message\RequestInterface;
|
10 |
-
use Psr\Http\Message\ResponseInterface;
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Handler that returns responses or throw exceptions from a queue.
|
14 |
-
*/
|
15 |
-
class MockHandler implements \Countable
|
16 |
-
{
|
17 |
-
private $queue = [];
|
18 |
-
private $lastRequest;
|
19 |
-
private $lastOptions;
|
20 |
-
private $onFulfilled;
|
21 |
-
private $onRejected;
|
22 |
-
|
23 |
-
/**
|
24 |
-
* Creates a new MockHandler that uses the default handler stack list of
|
25 |
-
* middlewares.
|
26 |
-
*
|
27 |
-
* @param array $queue Array of responses, callables, or exceptions.
|
28 |
-
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
29 |
-
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
30 |
-
*
|
31 |
-
* @return HandlerStack
|
32 |
-
*/
|
33 |
-
public static function createWithMiddleware(
|
34 |
-
array $queue = null,
|
35 |
-
callable $onFulfilled = null,
|
36 |
-
callable $onRejected = null
|
37 |
-
) {
|
38 |
-
return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
|
39 |
-
}
|
40 |
-
|
41 |
-
/**
|
42 |
-
* The passed in value must be an array of
|
43 |
-
* {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions,
|
44 |
-
* callables, or Promises.
|
45 |
-
*
|
46 |
-
* @param array $queue
|
47 |
-
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
48 |
-
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
49 |
-
*/
|
50 |
-
public function __construct(
|
51 |
-
array $queue = null,
|
52 |
-
callable $onFulfilled = null,
|
53 |
-
callable $onRejected = null
|
54 |
-
) {
|
55 |
-
$this->onFulfilled = $onFulfilled;
|
56 |
-
$this->onRejected = $onRejected;
|
57 |
-
|
58 |
-
if ($queue) {
|
59 |
-
call_user_func_array([$this, 'append'], $queue);
|
60 |
-
}
|
61 |
-
}
|
62 |
-
|
63 |
-
public function __invoke(RequestInterface $request, array $options)
|
64 |
-
{
|
65 |
-
if (!$this->queue) {
|
66 |
-
throw new \OutOfBoundsException('Mock queue is empty');
|
67 |
-
}
|
68 |
-
|
69 |
-
if (isset($options['delay'])) {
|
70 |
-
usleep($options['delay'] * 1000);
|
71 |
-
}
|
72 |
-
|
73 |
-
$this->lastRequest = $request;
|
74 |
-
$this->lastOptions = $options;
|
75 |
-
$response = array_shift($this->queue);
|
76 |
-
|
77 |
-
if (isset($options['on_headers'])) {
|
78 |
-
if (!is_callable($options['on_headers'])) {
|
79 |
-
throw new \InvalidArgumentException('on_headers must be callable');
|
80 |
-
}
|
81 |
-
try {
|
82 |
-
$options['on_headers']($response);
|
83 |
-
} catch (\Exception $e) {
|
84 |
-
$msg = 'An error was encountered during the on_headers event';
|
85 |
-
$response = new RequestException($msg, $request, $response, $e);
|
86 |
-
}
|
87 |
-
}
|
88 |
-
|
89 |
-
if (is_callable($response)) {
|
90 |
-
$response = call_user_func($response, $request, $options);
|
91 |
-
}
|
92 |
-
|
93 |
-
$response = $response instanceof \Exception
|
94 |
-
? \GuzzleHttp\Promise\rejection_for($response)
|
95 |
-
: \GuzzleHttp\Promise\promise_for($response);
|
96 |
-
|
97 |
-
return $response->then(
|
98 |
-
function ($value) use ($request, $options) {
|
99 |
-
$this->invokeStats($request, $options, $value);
|
100 |
-
if ($this->onFulfilled) {
|
101 |
-
call_user_func($this->onFulfilled, $value);
|
102 |
-
}
|
103 |
-
if (isset($options['sink'])) {
|
104 |
-
$contents = (string) $value->getBody();
|
105 |
-
$sink = $options['sink'];
|
106 |
-
|
107 |
-
if (is_resource($sink)) {
|
108 |
-
fwrite($sink, $contents);
|
109 |
-
} elseif (is_string($sink)) {
|
110 |
-
file_put_contents($sink, $contents);
|
111 |
-
} elseif ($sink instanceof \Psr\Http\Message\StreamInterface) {
|
112 |
-
$sink->write($contents);
|
113 |
-
}
|
114 |
-
}
|
115 |
-
|
116 |
-
return $value;
|
117 |
-
},
|
118 |
-
function ($reason) use ($request, $options) {
|
119 |
-
$this->invokeStats($request, $options, null, $reason);
|
120 |
-
if ($this->onRejected) {
|
121 |
-
call_user_func($this->onRejected, $reason);
|
122 |
-
}
|
123 |
-
return \GuzzleHttp\Promise\rejection_for($reason);
|
124 |
-
}
|
125 |
-
);
|
126 |
-
}
|
127 |
-
|
128 |
-
/**
|
129 |
-
* Adds one or more variadic requests, exceptions, callables, or promises
|
130 |
-
* to the queue.
|
131 |
-
*/
|
132 |
-
public function append()
|
133 |
-
{
|
134 |
-
foreach (func_get_args() as $value) {
|
135 |
-
if ($value instanceof ResponseInterface
|
136 |
-
|| $value instanceof \Exception
|
137 |
-
|| $value instanceof PromiseInterface
|
138 |
-
|| is_callable($value)
|
139 |
-
) {
|
140 |
-
$this->queue[] = $value;
|
141 |
-
} else {
|
142 |
-
throw new \InvalidArgumentException('Expected a response or '
|
143 |
-
. 'exception. Found ' . \GuzzleHttp\describe_type($value));
|
144 |
-
}
|
145 |
-
}
|
146 |
-
}
|
147 |
-
|
148 |
-
/**
|
149 |
-
* Get the last received request.
|
150 |
-
*
|
151 |
-
* @return RequestInterface
|
152 |
-
*/
|
153 |
-
public function getLastRequest()
|
154 |
-
{
|
155 |
-
return $this->lastRequest;
|
156 |
-
}
|
157 |
-
|
158 |
-
/**
|
159 |
-
* Get the last received request options.
|
160 |
-
*
|
161 |
-
* @return array
|
162 |
-
*/
|
163 |
-
public function getLastOptions()
|
164 |
-
{
|
165 |
-
return $this->lastOptions;
|
166 |
-
}
|
167 |
-
|
168 |
-
/**
|
169 |
-
* Returns the number of remaining items in the queue.
|
170 |
-
*
|
171 |
-
* @return int
|
172 |
-
*/
|
173 |
-
public function count()
|
174 |
-
{
|
175 |
-
return count($this->queue);
|
176 |
-
}
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
+
|
4 |
+
use GuzzleHttp\Exception\RequestException;
|
5 |
+
use GuzzleHttp\HandlerStack;
|
6 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
7 |
+
use GuzzleHttp\Promise\RejectedPromise;
|
8 |
+
use GuzzleHttp\TransferStats;
|
9 |
+
use Psr\Http\Message\RequestInterface;
|
10 |
+
use Psr\Http\Message\ResponseInterface;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Handler that returns responses or throw exceptions from a queue.
|
14 |
+
*/
|
15 |
+
class MockHandler implements \Countable
|
16 |
+
{
|
17 |
+
private $queue = [];
|
18 |
+
private $lastRequest;
|
19 |
+
private $lastOptions;
|
20 |
+
private $onFulfilled;
|
21 |
+
private $onRejected;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Creates a new MockHandler that uses the default handler stack list of
|
25 |
+
* middlewares.
|
26 |
+
*
|
27 |
+
* @param array $queue Array of responses, callables, or exceptions.
|
28 |
+
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
29 |
+
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
30 |
+
*
|
31 |
+
* @return HandlerStack
|
32 |
+
*/
|
33 |
+
public static function createWithMiddleware(
|
34 |
+
array $queue = null,
|
35 |
+
callable $onFulfilled = null,
|
36 |
+
callable $onRejected = null
|
37 |
+
) {
|
38 |
+
return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* The passed in value must be an array of
|
43 |
+
* {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions,
|
44 |
+
* callables, or Promises.
|
45 |
+
*
|
46 |
+
* @param array $queue
|
47 |
+
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
48 |
+
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
49 |
+
*/
|
50 |
+
public function __construct(
|
51 |
+
array $queue = null,
|
52 |
+
callable $onFulfilled = null,
|
53 |
+
callable $onRejected = null
|
54 |
+
) {
|
55 |
+
$this->onFulfilled = $onFulfilled;
|
56 |
+
$this->onRejected = $onRejected;
|
57 |
+
|
58 |
+
if ($queue) {
|
59 |
+
call_user_func_array([$this, 'append'], $queue);
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
+
public function __invoke(RequestInterface $request, array $options)
|
64 |
+
{
|
65 |
+
if (!$this->queue) {
|
66 |
+
throw new \OutOfBoundsException('Mock queue is empty');
|
67 |
+
}
|
68 |
+
|
69 |
+
if (isset($options['delay']) && is_numeric($options['delay'])) {
|
70 |
+
usleep($options['delay'] * 1000);
|
71 |
+
}
|
72 |
+
|
73 |
+
$this->lastRequest = $request;
|
74 |
+
$this->lastOptions = $options;
|
75 |
+
$response = array_shift($this->queue);
|
76 |
+
|
77 |
+
if (isset($options['on_headers'])) {
|
78 |
+
if (!is_callable($options['on_headers'])) {
|
79 |
+
throw new \InvalidArgumentException('on_headers must be callable');
|
80 |
+
}
|
81 |
+
try {
|
82 |
+
$options['on_headers']($response);
|
83 |
+
} catch (\Exception $e) {
|
84 |
+
$msg = 'An error was encountered during the on_headers event';
|
85 |
+
$response = new RequestException($msg, $request, $response, $e);
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
if (is_callable($response)) {
|
90 |
+
$response = call_user_func($response, $request, $options);
|
91 |
+
}
|
92 |
+
|
93 |
+
$response = $response instanceof \Exception
|
94 |
+
? \GuzzleHttp\Promise\rejection_for($response)
|
95 |
+
: \GuzzleHttp\Promise\promise_for($response);
|
96 |
+
|
97 |
+
return $response->then(
|
98 |
+
function ($value) use ($request, $options) {
|
99 |
+
$this->invokeStats($request, $options, $value);
|
100 |
+
if ($this->onFulfilled) {
|
101 |
+
call_user_func($this->onFulfilled, $value);
|
102 |
+
}
|
103 |
+
if (isset($options['sink'])) {
|
104 |
+
$contents = (string) $value->getBody();
|
105 |
+
$sink = $options['sink'];
|
106 |
+
|
107 |
+
if (is_resource($sink)) {
|
108 |
+
fwrite($sink, $contents);
|
109 |
+
} elseif (is_string($sink)) {
|
110 |
+
file_put_contents($sink, $contents);
|
111 |
+
} elseif ($sink instanceof \Psr\Http\Message\StreamInterface) {
|
112 |
+
$sink->write($contents);
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
return $value;
|
117 |
+
},
|
118 |
+
function ($reason) use ($request, $options) {
|
119 |
+
$this->invokeStats($request, $options, null, $reason);
|
120 |
+
if ($this->onRejected) {
|
121 |
+
call_user_func($this->onRejected, $reason);
|
122 |
+
}
|
123 |
+
return \GuzzleHttp\Promise\rejection_for($reason);
|
124 |
+
}
|
125 |
+
);
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Adds one or more variadic requests, exceptions, callables, or promises
|
130 |
+
* to the queue.
|
131 |
+
*/
|
132 |
+
public function append()
|
133 |
+
{
|
134 |
+
foreach (func_get_args() as $value) {
|
135 |
+
if ($value instanceof ResponseInterface
|
136 |
+
|| $value instanceof \Exception
|
137 |
+
|| $value instanceof PromiseInterface
|
138 |
+
|| is_callable($value)
|
139 |
+
) {
|
140 |
+
$this->queue[] = $value;
|
141 |
+
} else {
|
142 |
+
throw new \InvalidArgumentException('Expected a response or '
|
143 |
+
. 'exception. Found ' . \GuzzleHttp\describe_type($value));
|
144 |
+
}
|
145 |
+
}
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Get the last received request.
|
150 |
+
*
|
151 |
+
* @return RequestInterface
|
152 |
+
*/
|
153 |
+
public function getLastRequest()
|
154 |
+
{
|
155 |
+
return $this->lastRequest;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Get the last received request options.
|
160 |
+
*
|
161 |
+
* @return array
|
162 |
+
*/
|
163 |
+
public function getLastOptions()
|
164 |
+
{
|
165 |
+
return $this->lastOptions;
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Returns the number of remaining items in the queue.
|
170 |
+
*
|
171 |
+
* @return int
|
172 |
+
*/
|
173 |
+
public function count()
|
174 |
+
{
|
175 |
+
return count($this->queue);
|
176 |
+
}
|
177 |
+
|
178 |
+
public function reset()
|
179 |
+
{
|
180 |
+
$this->queue = [];
|
181 |
+
}
|
182 |
+
|
183 |
+
private function invokeStats(
|
184 |
+
RequestInterface $request,
|
185 |
+
array $options,
|
186 |
+
ResponseInterface $response = null,
|
187 |
+
$reason = null
|
188 |
+
) {
|
189 |
+
if (isset($options['on_stats'])) {
|
190 |
+
$transferTime = isset($options['transfer_time']) ? $options['transfer_time'] : 0;
|
191 |
+
$stats = new TransferStats($request, $response, $transferTime, $reason);
|
192 |
+
call_user_func($options['on_stats'], $stats);
|
193 |
+
}
|
194 |
+
}
|
195 |
+
}
|
vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php
CHANGED
@@ -1,544 +1,544 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp\Handler;
|
3 |
-
|
4 |
-
use GuzzleHttp\Exception\
|
5 |
-
use GuzzleHttp\Exception\
|
6 |
-
use GuzzleHttp\Promise\FulfilledPromise;
|
7 |
-
use GuzzleHttp\Promise\PromiseInterface;
|
8 |
-
use GuzzleHttp\Psr7;
|
9 |
-
use GuzzleHttp\TransferStats;
|
10 |
-
use Psr\Http\Message\RequestInterface;
|
11 |
-
use Psr\Http\Message\ResponseInterface;
|
12 |
-
use Psr\Http\Message\StreamInterface;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* HTTP handler that uses PHP's HTTP stream wrapper.
|
16 |
-
*/
|
17 |
-
class StreamHandler
|
18 |
-
{
|
19 |
-
private $lastHeaders = [];
|
20 |
-
|
21 |
-
/**
|
22 |
-
* Sends an HTTP request.
|
23 |
-
*
|
24 |
-
* @param RequestInterface $request Request to send.
|
25 |
-
* @param array $options Request transfer options.
|
26 |
-
*
|
27 |
-
* @return PromiseInterface
|
28 |
-
*/
|
29 |
-
public function __invoke(RequestInterface $request, array $options)
|
30 |
-
{
|
31 |
-
// Sleep if there is a delay specified.
|
32 |
-
if (isset($options['delay'])) {
|
33 |
-
usleep($options['delay'] * 1000);
|
34 |
-
}
|
35 |
-
|
36 |
-
$startTime = isset($options['on_stats']) ? \GuzzleHttp\_current_time() : null;
|
37 |
-
|
38 |
-
try {
|
39 |
-
// Does not support the expect header.
|
40 |
-
$request = $request->withoutHeader('Expect');
|
41 |
-
|
42 |
-
// Append a content-length header if body size is zero to match
|
43 |
-
// cURL's behavior.
|
44 |
-
if (0 === $request->getBody()->getSize()) {
|
45 |
-
$request = $request->withHeader('Content-Length', '0');
|
46 |
-
}
|
47 |
-
|
48 |
-
return $this->createResponse(
|
49 |
-
$request,
|
50 |
-
$options,
|
51 |
-
$this->createStream($request, $options),
|
52 |
-
$startTime
|
53 |
-
);
|
54 |
-
} catch (\InvalidArgumentException $e) {
|
55 |
-
throw $e;
|
56 |
-
} catch (\Exception $e) {
|
57 |
-
// Determine if the error was a networking error.
|
58 |
-
$message = $e->getMessage();
|
59 |
-
// This list can probably get more comprehensive.
|
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 |
-
}
|
67 |
-
$e = RequestException::wrapException($request, $e);
|
68 |
-
$this->invokeStats($options, $request, $startTime, null, $e);
|
69 |
-
|
70 |
-
return \GuzzleHttp\Promise\rejection_for($e);
|
71 |
-
}
|
72 |
-
}
|
73 |
-
|
74 |
-
private function invokeStats(
|
75 |
-
array $options,
|
76 |
-
RequestInterface $request,
|
77 |
-
$startTime,
|
78 |
-
ResponseInterface $response = null,
|
79 |
-
$error = null
|
80 |
-
) {
|
81 |
-
if (isset($options['on_stats'])) {
|
82 |
-
$stats = new TransferStats(
|
83 |
-
$request,
|
84 |
-
$response,
|
85 |
-
\GuzzleHttp\_current_time() - $startTime,
|
86 |
-
$error,
|
87 |
-
[]
|
88 |
-
);
|
89 |
-
call_user_func($options['on_stats'], $stats);
|
90 |
-
}
|
91 |
-
}
|
92 |
-
|
93 |
-
private function createResponse(
|
94 |
-
RequestInterface $request,
|
95 |
-
array $options,
|
96 |
-
$stream,
|
97 |
-
$startTime
|
98 |
-
) {
|
99 |
-
$hdrs = $this->lastHeaders;
|
100 |
-
$this->lastHeaders = [];
|
101 |
-
$parts = explode(' ', array_shift($hdrs), 3);
|
102 |
-
$ver = explode('/', $parts[0])[1];
|
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 |
-
|
110 |
-
if (strcasecmp('HEAD', $request->getMethod())) {
|
111 |
-
$sink = $this->createSink($stream, $options);
|
112 |
-
}
|
113 |
-
|
114 |
-
$response = new Psr7\Response($status, $headers, $sink, $ver, $reason);
|
115 |
-
|
116 |
-
if (isset($options['on_headers'])) {
|
117 |
-
try {
|
118 |
-
$options['on_headers']($response);
|
119 |
-
} catch (\Exception $e) {
|
120 |
-
$msg = 'An error was encountered during the on_headers event';
|
121 |
-
$ex = new RequestException($msg, $request, $response, $e);
|
122 |
-
return \GuzzleHttp\Promise\rejection_for($ex);
|
123 |
-
}
|
124 |
-
}
|
125 |
-
|
126 |
-
// Do not drain when the request is a HEAD request because they have
|
127 |
-
// no body.
|
128 |
-
if ($sink !== $stream) {
|
129 |
-
$this->drain(
|
130 |
-
$stream,
|
131 |
-
$sink,
|
132 |
-
$response->getHeaderLine('Content-Length')
|
133 |
-
);
|
134 |
-
}
|
135 |
-
|
136 |
-
$this->invokeStats($options, $request, $startTime, $response, null);
|
137 |
-
|
138 |
-
return new FulfilledPromise($response);
|
139 |
-
}
|
140 |
-
|
141 |
-
private function createSink(StreamInterface $stream, array $options)
|
142 |
-
{
|
143 |
-
if (!empty($options['stream'])) {
|
144 |
-
return $stream;
|
145 |
-
}
|
146 |
-
|
147 |
-
$sink = isset($options['sink'])
|
148 |
-
? $options['sink']
|
149 |
-
: fopen('php://temp', 'r+');
|
150 |
-
|
151 |
-
return is_string($sink)
|
152 |
-
? new Psr7\LazyOpenStream($sink, 'w+')
|
153 |
-
: Psr7\stream_for($sink);
|
154 |
-
}
|
155 |
-
|
156 |
-
private function checkDecode(array $options, array $headers, $stream)
|
157 |
-
{
|
158 |
-
// Automatically decode responses when instructed.
|
159 |
-
if (!empty($options['decode_content'])) {
|
160 |
-
$normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
|
161 |
-
if (isset($normalizedKeys['content-encoding'])) {
|
162 |
-
$encoding = $headers[$normalizedKeys['content-encoding']];
|
163 |
-
if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') {
|
164 |
-
$stream = new Psr7\InflateStream(
|
165 |
-
Psr7\stream_for($stream)
|
166 |
-
);
|
167 |
-
$headers['x-encoded-content-encoding']
|
168 |
-
= $headers[$normalizedKeys['content-encoding']];
|
169 |
-
// Remove content-encoding header
|
170 |
-
unset($headers[$normalizedKeys['content-encoding']]);
|
171 |
-
// Fix content-length header
|
172 |
-
if (isset($normalizedKeys['content-length'])) {
|
173 |
-
$headers['x-encoded-content-length']
|
174 |
-
= $headers[$normalizedKeys['content-length']];
|
175 |
-
|
176 |
-
$length = (int) $stream->getSize();
|
177 |
-
if ($length === 0) {
|
178 |
-
unset($headers[$normalizedKeys['content-length']]);
|
179 |
-
} else {
|
180 |
-
$headers[$normalizedKeys['content-length']] = [$length];
|
181 |
-
}
|
182 |
-
}
|
183 |
-
}
|
184 |
-
}
|
185 |
-
}
|
186 |
-
|
187 |
-
return [$stream, $headers];
|
188 |
-
}
|
189 |
-
|
190 |
-
/**
|
191 |
-
* Drains the source stream into the "sink" client option.
|
192 |
-
*
|
193 |
-
* @param StreamInterface $source
|
194 |
-
* @param StreamInterface $sink
|
195 |
-
* @param string $contentLength Header specifying the amount of
|
196 |
-
* data to read.
|
197 |
-
*
|
198 |
-
* @return StreamInterface
|
199 |
-
* @throws \RuntimeException when the sink option is invalid.
|
200 |
-
*/
|
201 |
-
private function drain(
|
202 |
-
StreamInterface $source,
|
203 |
-
StreamInterface $sink,
|
204 |
-
$contentLength
|
205 |
-
) {
|
206 |
-
// If a content-length header is provided, then stop reading once
|
207 |
-
// that number of bytes has been read. This can prevent infinitely
|
208 |
-
// reading from a stream when dealing with servers that do not honor
|
209 |
-
// Connection: Close headers.
|
210 |
-
Psr7\copy_to_stream(
|
211 |
-
$source,
|
212 |
-
$sink,
|
213 |
-
(strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1
|
214 |
-
);
|
215 |
-
|
216 |
-
$sink->seek(0);
|
217 |
-
$source->close();
|
218 |
-
|
219 |
-
return $sink;
|
220 |
-
}
|
221 |
-
|
222 |
-
/**
|
223 |
-
* Create a resource and check to ensure it was created successfully
|
224 |
-
*
|
225 |
-
* @param callable $callback Callable that returns stream resource
|
226 |
-
*
|
227 |
-
* @return resource
|
228 |
-
* @throws \RuntimeException on error
|
229 |
-
*/
|
230 |
-
private function createResource(callable $callback)
|
231 |
-
{
|
232 |
-
$errors = null;
|
233 |
-
set_error_handler(function ($_, $msg, $file, $line) use (&$errors) {
|
234 |
-
$errors[] = [
|
235 |
-
'message' => $msg,
|
236 |
-
'file' => $file,
|
237 |
-
'line' => $line
|
238 |
-
];
|
239 |
-
return true;
|
240 |
-
});
|
241 |
-
|
242 |
-
$resource = $callback();
|
243 |
-
restore_error_handler();
|
244 |
-
|
245 |
-
if (!$resource) {
|
246 |
-
$message = 'Error creating resource: ';
|
247 |
-
foreach ($errors as $err) {
|
248 |
-
foreach ($err as $key => $value) {
|
249 |
-
$message .= "[$key] $value" . PHP_EOL;
|
250 |
-
}
|
251 |
-
}
|
252 |
-
throw new \RuntimeException(trim($message));
|
253 |
-
}
|
254 |
-
|
255 |
-
return $resource;
|
256 |
-
}
|
257 |
-
|
258 |
-
private function createStream(RequestInterface $request, array $options)
|
259 |
-
{
|
260 |
-
static $methods;
|
261 |
-
if (!$methods) {
|
262 |
-
$methods = array_flip(get_class_methods(__CLASS__));
|
263 |
-
}
|
264 |
-
|
265 |
-
// HTTP/1.1 streams using the PHP stream wrapper require a
|
266 |
-
// Connection: close header
|
267 |
-
if ($request->getProtocolVersion() == '1.1'
|
268 |
-
&& !$request->hasHeader('Connection')
|
269 |
-
) {
|
270 |
-
$request = $request->withHeader('Connection', 'close');
|
271 |
-
}
|
272 |
-
|
273 |
-
// Ensure SSL is verified by default
|
274 |
-
if (!isset($options['verify'])) {
|
275 |
-
$options['verify'] = true;
|
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');
|
283 |
-
}
|
284 |
-
|
285 |
-
if (!empty($options)) {
|
286 |
-
foreach ($options as $key => $value) {
|
287 |
-
$method = "add_{$key}";
|
288 |
-
if (isset($methods[$method])) {
|
289 |
-
$this->{$method}($request, $context, $value, $params);
|
290 |
-
}
|
291 |
-
}
|
292 |
-
}
|
293 |
-
|
294 |
-
if (isset($options['stream_context'])) {
|
295 |
-
if (!is_array($options['stream_context'])) {
|
296 |
-
throw new \InvalidArgumentException('stream_context must be an array');
|
297 |
-
}
|
298 |
-
$context = array_replace_recursive(
|
299 |
-
$context,
|
300 |
-
$options['stream_context']
|
301 |
-
);
|
302 |
-
}
|
303 |
-
|
304 |
-
// Microsoft NTLM authentication only supported with curl handler
|
305 |
-
if (isset($options['auth'])
|
306 |
-
&& is_array($options['auth'])
|
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 |
-
|
313 |
-
$uri = $this->resolveHost($request, $options);
|
314 |
-
|
315 |
-
$context = $this->createResource(
|
316 |
-
function () use ($context, $params) {
|
317 |
-
return stream_context_create($context, $params);
|
318 |
-
}
|
319 |
-
);
|
320 |
-
|
321 |
-
return $this->createResource(
|
322 |
-
function () use ($uri, &$http_response_header, $context, $options) {
|
323 |
-
$resource = fopen((string) $uri, 'r', null, $context);
|
324 |
-
$this->lastHeaders = $http_response_header;
|
325 |
-
|
326 |
-
if (isset($options['read_timeout'])) {
|
327 |
-
$readTimeout = $options['read_timeout'];
|
328 |
-
$sec = (int) $readTimeout;
|
329 |
-
$usec = ($readTimeout - $sec) * 100000;
|
330 |
-
stream_set_timeout($resource, $sec, $usec);
|
331 |
-
}
|
332 |
-
|
333 |
-
return $resource;
|
334 |
-
}
|
335 |
-
);
|
336 |
-
}
|
337 |
-
|
338 |
-
private function resolveHost(RequestInterface $request, array $options)
|
339 |
-
{
|
340 |
-
$uri = $request->getUri();
|
341 |
-
|
342 |
-
if (isset($options['force_ip_resolve']) && !filter_var($uri->getHost(), FILTER_VALIDATE_IP)) {
|
343 |
-
if ('v4' === $options['force_ip_resolve']) {
|
344 |
-
$records = dns_get_record($uri->getHost(), DNS_A);
|
345 |
-
if (!isset($records[0]['ip'])) {
|
346 |
-
throw new ConnectException(
|
347 |
-
sprintf(
|
348 |
-
"Could not resolve IPv4 address for host '%s'",
|
349 |
-
$uri->getHost()
|
350 |
-
),
|
351 |
-
$request
|
352 |
-
);
|
353 |
-
}
|
354 |
-
$uri = $uri->withHost($records[0]['ip']);
|
355 |
-
} elseif ('v6' === $options['force_ip_resolve']) {
|
356 |
-
$records = dns_get_record($uri->getHost(), DNS_AAAA);
|
357 |
-
if (!isset($records[0]['ipv6'])) {
|
358 |
-
throw new ConnectException(
|
359 |
-
sprintf(
|
360 |
-
"Could not resolve IPv6 address for host '%s'",
|
361 |
-
$uri->getHost()
|
362 |
-
),
|
363 |
-
$request
|
364 |
-
);
|
365 |
-
}
|
366 |
-
$uri = $uri->withHost('[' . $records[0]['ipv6'] . ']');
|
367 |
-
}
|
368 |
-
}
|
369 |
-
|
370 |
-
return $uri;
|
371 |
-
}
|
372 |
-
|
373 |
-
private function getDefaultContext(RequestInterface $request)
|
374 |
-
{
|
375 |
-
$headers = '';
|
376 |
-
foreach ($request->getHeaders() as $name => $value) {
|
377 |
-
foreach ($value as $val) {
|
378 |
-
$headers .= "$name: $val\r\n";
|
379 |
-
}
|
380 |
-
}
|
381 |
-
|
382 |
-
$context = [
|
383 |
-
'http' => [
|
384 |
-
'method' => $request->getMethod(),
|
385 |
-
'header' => $headers,
|
386 |
-
'protocol_version' => $request->getProtocolVersion(),
|
387 |
-
'ignore_errors' => true,
|
388 |
-
'follow_location' => 0,
|
389 |
-
],
|
390 |
-
];
|
391 |
-
|
392 |
-
$body = (string) $request->getBody();
|
393 |
-
|
394 |
-
if (!empty($body)) {
|
395 |
-
$context['http']['content'] = $body;
|
396 |
-
// Prevent the HTTP handler from adding a Content-Type header.
|
397 |
-
if (!$request->hasHeader('Content-Type')) {
|
398 |
-
$context['http']['header'] .= "Content-Type:\r\n";
|
399 |
-
}
|
400 |
-
}
|
401 |
-
|
402 |
-
$context['http']['header'] = rtrim($context['http']['header']);
|
403 |
-
|
404 |
-
return $context;
|
405 |
-
}
|
406 |
-
|
407 |
-
private function add_proxy(RequestInterface $request, &$options, $value, &$params)
|
408 |
-
{
|
409 |
-
if (!is_array($value)) {
|
410 |
-
$options['http']['proxy'] = $value;
|
411 |
-
} else {
|
412 |
-
$scheme = $request->getUri()->getScheme();
|
413 |
-
if (isset($value[$scheme])) {
|
414 |
-
if (!isset($value['no'])
|
415 |
-
|| !\GuzzleHttp\is_host_in_noproxy(
|
416 |
-
$request->getUri()->getHost(),
|
417 |
-
$value['no']
|
418 |
-
)
|
419 |
-
) {
|
420 |
-
$options['http']['proxy'] = $value[$scheme];
|
421 |
-
}
|
422 |
-
}
|
423 |
-
}
|
424 |
-
}
|
425 |
-
|
426 |
-
private function add_timeout(RequestInterface $request, &$options, $value, &$params)
|
427 |
-
{
|
428 |
-
if ($value > 0) {
|
429 |
-
$options['http']['timeout'] = $value;
|
430 |
-
}
|
431 |
-
}
|
432 |
-
|
433 |
-
private function add_verify(RequestInterface $request, &$options, $value, &$params)
|
434 |
-
{
|
435 |
-
if ($value === true) {
|
436 |
-
// PHP 5.6 or greater will find the system cert by default. When
|
437 |
-
// < 5.6, use the Guzzle bundled cacert.
|
438 |
-
if (PHP_VERSION_ID < 50600) {
|
439 |
-
$options['ssl']['cafile'] = \GuzzleHttp\default_ca_bundle();
|
440 |
-
}
|
441 |
-
} elseif (is_string($value)) {
|
442 |
-
$options['ssl']['cafile'] = $value;
|
443 |
-
if (!file_exists($value)) {
|
444 |
-
throw new \RuntimeException("SSL CA bundle not found: $value");
|
445 |
-
}
|
446 |
-
} elseif ($value === false) {
|
447 |
-
$options['ssl']['verify_peer'] = false;
|
448 |
-
$options['ssl']['verify_peer_name'] = false;
|
449 |
-
return;
|
450 |
-
} else {
|
451 |
-
throw new \InvalidArgumentException('Invalid verify request option');
|
452 |
-
}
|
453 |
-
|
454 |
-
$options['ssl']['verify_peer'] = true;
|
455 |
-
$options['ssl']['verify_peer_name'] = true;
|
456 |
-
$options['ssl']['allow_self_signed'] = false;
|
457 |
-
}
|
458 |
-
|
459 |
-
private function add_cert(RequestInterface $request, &$options, $value, &$params)
|
460 |
-
{
|
461 |
-
if (is_array($value)) {
|
462 |
-
$options['ssl']['passphrase'] = $value[1];
|
463 |
-
$value = $value[0];
|
464 |
-
}
|
465 |
-
|
466 |
-
if (!file_exists($value)) {
|
467 |
-
throw new \RuntimeException("SSL certificate not found: {$value}");
|
468 |
-
}
|
469 |
-
|
470 |
-
$options['ssl']['local_cert'] = $value;
|
471 |
-
}
|
472 |
-
|
473 |
-
private function add_progress(RequestInterface $request, &$options, $value, &$params)
|
474 |
-
{
|
475 |
-
$this->addNotification(
|
476 |
-
$params,
|
477 |
-
function ($code, $a, $b, $c, $transferred, $total) use ($value) {
|
478 |
-
if ($code == STREAM_NOTIFY_PROGRESS) {
|
479 |
-
$value($total, $transferred, null, null);
|
480 |
-
}
|
481 |
-
}
|
482 |
-
);
|
483 |
-
}
|
484 |
-
|
485 |
-
private function add_debug(RequestInterface $request, &$options, $value, &$params)
|
486 |
-
{
|
487 |
-
if ($value === false) {
|
488 |
-
return;
|
489 |
-
}
|
490 |
-
|
491 |
-
static $map = [
|
492 |
-
STREAM_NOTIFY_CONNECT => 'CONNECT',
|
493 |
-
STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
|
494 |
-
STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
|
495 |
-
STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
|
496 |
-
STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
|
497 |
-
STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
|
498 |
-
STREAM_NOTIFY_PROGRESS => 'PROGRESS',
|
499 |
-
STREAM_NOTIFY_FAILURE => 'FAILURE',
|
500 |
-
STREAM_NOTIFY_COMPLETED => 'COMPLETED',
|
501 |
-
STREAM_NOTIFY_RESOLVE => 'RESOLVE',
|
502 |
-
];
|
503 |
-
static $args = ['severity', 'message', 'message_code',
|
504 |
-
'bytes_transferred', 'bytes_max'];
|
505 |
-
|
506 |
-
$value = \GuzzleHttp\debug_resource($value);
|
507 |
-
$ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');
|
508 |
-
$this->addNotification(
|
509 |
-
$params,
|
510 |
-
function () use ($ident, $value, $map, $args) {
|
511 |
-
$passed = func_get_args();
|
512 |
-
$code = array_shift($passed);
|
513 |
-
fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
|
514 |
-
foreach (array_filter($passed) as $i => $v) {
|
515 |
-
fwrite($value, $args[$i] . ': "' . $v . '" ');
|
516 |
-
}
|
517 |
-
fwrite($value, "\n");
|
518 |
-
}
|
519 |
-
);
|
520 |
-
}
|
521 |
-
|
522 |
-
private function addNotification(array &$params, callable $notify)
|
523 |
-
{
|
524 |
-
// Wrap the existing function if needed.
|
525 |
-
if (!isset($params['notification'])) {
|
526 |
-
$params['notification'] = $notify;
|
527 |
-
} else {
|
528 |
-
$params['notification'] = $this->callArray([
|
529 |
-
$params['notification'],
|
530 |
-
$notify
|
531 |
-
]);
|
532 |
-
}
|
533 |
-
}
|
534 |
-
|
535 |
-
private function callArray(array $functions)
|
536 |
-
{
|
537 |
-
return function () use ($functions) {
|
538 |
-
$args = func_get_args();
|
539 |
-
foreach ($functions as $fn) {
|
540 |
-
call_user_func_array($fn, $args);
|
541 |
-
}
|
542 |
-
};
|
543 |
-
}
|
544 |
-
}
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp\Handler;
|
3 |
+
|
4 |
+
use GuzzleHttp\Exception\ConnectException;
|
5 |
+
use GuzzleHttp\Exception\RequestException;
|
6 |
+
use GuzzleHttp\Promise\FulfilledPromise;
|
7 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
8 |
+
use GuzzleHttp\Psr7;
|
9 |
+
use GuzzleHttp\TransferStats;
|
10 |
+
use Psr\Http\Message\RequestInterface;
|
11 |
+
use Psr\Http\Message\ResponseInterface;
|
12 |
+
use Psr\Http\Message\StreamInterface;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* HTTP handler that uses PHP's HTTP stream wrapper.
|
16 |
+
*/
|
17 |
+
class StreamHandler
|
18 |
+
{
|
19 |
+
private $lastHeaders = [];
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Sends an HTTP request.
|
23 |
+
*
|
24 |
+
* @param RequestInterface $request Request to send.
|
25 |
+
* @param array $options Request transfer options.
|
26 |
+
*
|
27 |
+
* @return PromiseInterface
|
28 |
+
*/
|
29 |
+
public function __invoke(RequestInterface $request, array $options)
|
30 |
+
{
|
31 |
+
// Sleep if there is a delay specified.
|
32 |
+
if (isset($options['delay'])) {
|
33 |
+
usleep($options['delay'] * 1000);
|
34 |
+
}
|
35 |
+
|
36 |
+
$startTime = isset($options['on_stats']) ? \GuzzleHttp\_current_time() : null;
|
37 |
+
|
38 |
+
try {
|
39 |
+
// Does not support the expect header.
|
40 |
+
$request = $request->withoutHeader('Expect');
|
41 |
+
|
42 |
+
// Append a content-length header if body size is zero to match
|
43 |
+
// cURL's behavior.
|
44 |
+
if (0 === $request->getBody()->getSize()) {
|
45 |
+
$request = $request->withHeader('Content-Length', '0');
|
46 |
+
}
|
47 |
+
|
48 |
+
return $this->createResponse(
|
49 |
+
$request,
|
50 |
+
$options,
|
51 |
+
$this->createStream($request, $options),
|
52 |
+
$startTime
|
53 |
+
);
|
54 |
+
} catch (\InvalidArgumentException $e) {
|
55 |
+
throw $e;
|
56 |
+
} catch (\Exception $e) {
|
57 |
+
// Determine if the error was a networking error.
|
58 |
+
$message = $e->getMessage();
|
59 |
+
// This list can probably get more comprehensive.
|
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 |
+
}
|
67 |
+
$e = RequestException::wrapException($request, $e);
|
68 |
+
$this->invokeStats($options, $request, $startTime, null, $e);
|
69 |
+
|
70 |
+
return \GuzzleHttp\Promise\rejection_for($e);
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
private function invokeStats(
|
75 |
+
array $options,
|
76 |
+
RequestInterface $request,
|
77 |
+
$startTime,
|
78 |
+
ResponseInterface $response = null,
|
79 |
+
$error = null
|
80 |
+
) {
|
81 |
+
if (isset($options['on_stats'])) {
|
82 |
+
$stats = new TransferStats(
|
83 |
+
$request,
|
84 |
+
$response,
|
85 |
+
\GuzzleHttp\_current_time() - $startTime,
|
86 |
+
$error,
|
87 |
+
[]
|
88 |
+
);
|
89 |
+
call_user_func($options['on_stats'], $stats);
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
+
private function createResponse(
|
94 |
+
RequestInterface $request,
|
95 |
+
array $options,
|
96 |
+
$stream,
|
97 |
+
$startTime
|
98 |
+
) {
|
99 |
+
$hdrs = $this->lastHeaders;
|
100 |
+
$this->lastHeaders = [];
|
101 |
+
$parts = explode(' ', array_shift($hdrs), 3);
|
102 |
+
$ver = explode('/', $parts[0])[1];
|
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 |
+
|
110 |
+
if (strcasecmp('HEAD', $request->getMethod())) {
|
111 |
+
$sink = $this->createSink($stream, $options);
|
112 |
+
}
|
113 |
+
|
114 |
+
$response = new Psr7\Response($status, $headers, $sink, $ver, $reason);
|
115 |
+
|
116 |
+
if (isset($options['on_headers'])) {
|
117 |
+
try {
|
118 |
+
$options['on_headers']($response);
|
119 |
+
} catch (\Exception $e) {
|
120 |
+
$msg = 'An error was encountered during the on_headers event';
|
121 |
+
$ex = new RequestException($msg, $request, $response, $e);
|
122 |
+
return \GuzzleHttp\Promise\rejection_for($ex);
|
123 |
+
}
|
124 |
+
}
|
125 |
+
|
126 |
+
// Do not drain when the request is a HEAD request because they have
|
127 |
+
// no body.
|
128 |
+
if ($sink !== $stream) {
|
129 |
+
$this->drain(
|
130 |
+
$stream,
|
131 |
+
$sink,
|
132 |
+
$response->getHeaderLine('Content-Length')
|
133 |
+
);
|
134 |
+
}
|
135 |
+
|
136 |
+
$this->invokeStats($options, $request, $startTime, $response, null);
|
137 |
+
|
138 |
+
return new FulfilledPromise($response);
|
139 |
+
}
|
140 |
+
|
141 |
+
private function createSink(StreamInterface $stream, array $options)
|
142 |
+
{
|
143 |
+
if (!empty($options['stream'])) {
|
144 |
+
return $stream;
|
145 |
+
}
|
146 |
+
|
147 |
+
$sink = isset($options['sink'])
|
148 |
+
? $options['sink']
|
149 |
+
: fopen('php://temp', 'r+');
|
150 |
+
|
151 |
+
return is_string($sink)
|
152 |
+
? new Psr7\LazyOpenStream($sink, 'w+')
|
153 |
+
: Psr7\stream_for($sink);
|
154 |
+
}
|
155 |
+
|
156 |
+
private function checkDecode(array $options, array $headers, $stream)
|
157 |
+
{
|
158 |
+
// Automatically decode responses when instructed.
|
159 |
+
if (!empty($options['decode_content'])) {
|
160 |
+
$normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
|
161 |
+
if (isset($normalizedKeys['content-encoding'])) {
|
162 |
+
$encoding = $headers[$normalizedKeys['content-encoding']];
|
163 |
+
if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') {
|
164 |
+
$stream = new Psr7\InflateStream(
|
165 |
+
Psr7\stream_for($stream)
|
166 |
+
);
|
167 |
+
$headers['x-encoded-content-encoding']
|
168 |
+
= $headers[$normalizedKeys['content-encoding']];
|
169 |
+
// Remove content-encoding header
|
170 |
+
unset($headers[$normalizedKeys['content-encoding']]);
|
171 |
+
// Fix content-length header
|
172 |
+
if (isset($normalizedKeys['content-length'])) {
|
173 |
+
$headers['x-encoded-content-length']
|
174 |
+
= $headers[$normalizedKeys['content-length']];
|
175 |
+
|
176 |
+
$length = (int) $stream->getSize();
|
177 |
+
if ($length === 0) {
|
178 |
+
unset($headers[$normalizedKeys['content-length']]);
|
179 |
+
} else {
|
180 |
+
$headers[$normalizedKeys['content-length']] = [$length];
|
181 |
+
}
|
182 |
+
}
|
183 |
+
}
|
184 |
+
}
|
185 |
+
}
|
186 |
+
|
187 |
+
return [$stream, $headers];
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Drains the source stream into the "sink" client option.
|
192 |
+
*
|
193 |
+
* @param StreamInterface $source
|
194 |
+
* @param StreamInterface $sink
|
195 |
+
* @param string $contentLength Header specifying the amount of
|
196 |
+
* data to read.
|
197 |
+
*
|
198 |
+
* @return StreamInterface
|
199 |
+
* @throws \RuntimeException when the sink option is invalid.
|
200 |
+
*/
|
201 |
+
private function drain(
|
202 |
+
StreamInterface $source,
|
203 |
+
StreamInterface $sink,
|
204 |
+
$contentLength
|
205 |
+
) {
|
206 |
+
// If a content-length header is provided, then stop reading once
|
207 |
+
// that number of bytes has been read. This can prevent infinitely
|
208 |
+
// reading from a stream when dealing with servers that do not honor
|
209 |
+
// Connection: Close headers.
|
210 |
+
Psr7\copy_to_stream(
|
211 |
+
$source,
|
212 |
+
$sink,
|
213 |
+
(strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1
|
214 |
+
);
|
215 |
+
|
216 |
+
$sink->seek(0);
|
217 |
+
$source->close();
|
218 |
+
|
219 |
+
return $sink;
|
220 |
+
}
|
221 |
+
|
222 |
+
/**
|
223 |
+
* Create a resource and check to ensure it was created successfully
|
224 |
+
*
|
225 |
+
* @param callable $callback Callable that returns stream resource
|
226 |
+
*
|
227 |
+
* @return resource
|
228 |
+
* @throws \RuntimeException on error
|
229 |
+
*/
|
230 |
+
private function createResource(callable $callback)
|
231 |
+
{
|
232 |
+
$errors = null;
|
233 |
+
set_error_handler(function ($_, $msg, $file, $line) use (&$errors) {
|
234 |
+
$errors[] = [
|
235 |
+
'message' => $msg,
|
236 |
+
'file' => $file,
|
237 |
+
'line' => $line
|
238 |
+
];
|
239 |
+
return true;
|
240 |
+
});
|
241 |
+
|
242 |
+
$resource = $callback();
|
243 |
+
restore_error_handler();
|
244 |
+
|
245 |
+
if (!$resource) {
|
246 |
+
$message = 'Error creating resource: ';
|
247 |
+
foreach ($errors as $err) {
|
248 |
+
foreach ($err as $key => $value) {
|
249 |
+
$message .= "[$key] $value" . PHP_EOL;
|
250 |
+
}
|
251 |
+
}
|
252 |
+
throw new \RuntimeException(trim($message));
|
253 |
+
}
|
254 |
+
|
255 |
+
return $resource;
|
256 |
+
}
|
257 |
+
|
258 |
+
private function createStream(RequestInterface $request, array $options)
|
259 |
+
{
|
260 |
+
static $methods;
|
261 |
+
if (!$methods) {
|
262 |
+
$methods = array_flip(get_class_methods(__CLASS__));
|
263 |
+
}
|
264 |
+
|
265 |
+
// HTTP/1.1 streams using the PHP stream wrapper require a
|
266 |
+
// Connection: close header
|
267 |
+
if ($request->getProtocolVersion() == '1.1'
|
268 |
+
&& !$request->hasHeader('Connection')
|
269 |
+
) {
|
270 |
+
$request = $request->withHeader('Connection', 'close');
|
271 |
+
}
|
272 |
+
|
273 |
+
// Ensure SSL is verified by default
|
274 |
+
if (!isset($options['verify'])) {
|
275 |
+
$options['verify'] = true;
|
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');
|
283 |
+
}
|
284 |
+
|
285 |
+
if (!empty($options)) {
|
286 |
+
foreach ($options as $key => $value) {
|
287 |
+
$method = "add_{$key}";
|
288 |
+
if (isset($methods[$method])) {
|
289 |
+
$this->{$method}($request, $context, $value, $params);
|
290 |
+
}
|
291 |
+
}
|
292 |
+
}
|
293 |
+
|
294 |
+
if (isset($options['stream_context'])) {
|
295 |
+
if (!is_array($options['stream_context'])) {
|
296 |
+
throw new \InvalidArgumentException('stream_context must be an array');
|
297 |
+
}
|
298 |
+
$context = array_replace_recursive(
|
299 |
+
$context,
|
300 |
+
$options['stream_context']
|
301 |
+
);
|
302 |
+
}
|
303 |
+
|
304 |
+
// Microsoft NTLM authentication only supported with curl handler
|
305 |
+
if (isset($options['auth'])
|
306 |
+
&& is_array($options['auth'])
|
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 |
+
|
313 |
+
$uri = $this->resolveHost($request, $options);
|
314 |
+
|
315 |
+
$context = $this->createResource(
|
316 |
+
function () use ($context, $params) {
|
317 |
+
return stream_context_create($context, $params);
|
318 |
+
}
|
319 |
+
);
|
320 |
+
|
321 |
+
return $this->createResource(
|
322 |
+
function () use ($uri, &$http_response_header, $context, $options) {
|
323 |
+
$resource = fopen((string) $uri, 'r', null, $context);
|
324 |
+
$this->lastHeaders = $http_response_header;
|
325 |
+
|
326 |
+
if (isset($options['read_timeout'])) {
|
327 |
+
$readTimeout = $options['read_timeout'];
|
328 |
+
$sec = (int) $readTimeout;
|
329 |
+
$usec = ($readTimeout - $sec) * 100000;
|
330 |
+
stream_set_timeout($resource, $sec, $usec);
|
331 |
+
}
|
332 |
+
|
333 |
+
return $resource;
|
334 |
+
}
|
335 |
+
);
|
336 |
+
}
|
337 |
+
|
338 |
+
private function resolveHost(RequestInterface $request, array $options)
|
339 |
+
{
|
340 |
+
$uri = $request->getUri();
|
341 |
+
|
342 |
+
if (isset($options['force_ip_resolve']) && !filter_var($uri->getHost(), FILTER_VALIDATE_IP)) {
|
343 |
+
if ('v4' === $options['force_ip_resolve']) {
|
344 |
+
$records = dns_get_record($uri->getHost(), DNS_A);
|
345 |
+
if (!isset($records[0]['ip'])) {
|
346 |
+
throw new ConnectException(
|
347 |
+
sprintf(
|
348 |
+
"Could not resolve IPv4 address for host '%s'",
|
349 |
+
$uri->getHost()
|
350 |
+
),
|
351 |
+
$request
|
352 |
+
);
|
353 |
+
}
|
354 |
+
$uri = $uri->withHost($records[0]['ip']);
|
355 |
+
} elseif ('v6' === $options['force_ip_resolve']) {
|
356 |
+
$records = dns_get_record($uri->getHost(), DNS_AAAA);
|
357 |
+
if (!isset($records[0]['ipv6'])) {
|
358 |
+
throw new ConnectException(
|
359 |
+
sprintf(
|
360 |
+
"Could not resolve IPv6 address for host '%s'",
|
361 |
+
$uri->getHost()
|
362 |
+
),
|
363 |
+
$request
|
364 |
+
);
|
365 |
+
}
|
366 |
+
$uri = $uri->withHost('[' . $records[0]['ipv6'] . ']');
|
367 |
+
}
|
368 |
+
}
|
369 |
+
|
370 |
+
return $uri;
|
371 |
+
}
|
372 |
+
|
373 |
+
private function getDefaultContext(RequestInterface $request)
|
374 |
+
{
|
375 |
+
$headers = '';
|
376 |
+
foreach ($request->getHeaders() as $name => $value) {
|
377 |
+
foreach ($value as $val) {
|
378 |
+
$headers .= "$name: $val\r\n";
|
379 |
+
}
|
380 |
+
}
|
381 |
+
|
382 |
+
$context = [
|
383 |
+
'http' => [
|
384 |
+
'method' => $request->getMethod(),
|
385 |
+
'header' => $headers,
|
386 |
+
'protocol_version' => $request->getProtocolVersion(),
|
387 |
+
'ignore_errors' => true,
|
388 |
+
'follow_location' => 0,
|
389 |
+
],
|
390 |
+
];
|
391 |
+
|
392 |
+
$body = (string) $request->getBody();
|
393 |
+
|
394 |
+
if (!empty($body)) {
|
395 |
+
$context['http']['content'] = $body;
|
396 |
+
// Prevent the HTTP handler from adding a Content-Type header.
|
397 |
+
if (!$request->hasHeader('Content-Type')) {
|
398 |
+
$context['http']['header'] .= "Content-Type:\r\n";
|
399 |
+
}
|
400 |
+
}
|
401 |
+
|
402 |
+
$context['http']['header'] = rtrim($context['http']['header']);
|
403 |
+
|
404 |
+
return $context;
|
405 |
+
}
|
406 |
+
|
407 |
+
private function add_proxy(RequestInterface $request, &$options, $value, &$params)
|
408 |
+
{
|
409 |
+
if (!is_array($value)) {
|
410 |
+
$options['http']['proxy'] = $value;
|
411 |
+
} else {
|
412 |
+
$scheme = $request->getUri()->getScheme();
|
413 |
+
if (isset($value[$scheme])) {
|
414 |
+
if (!isset($value['no'])
|
415 |
+
|| !\GuzzleHttp\is_host_in_noproxy(
|
416 |
+
$request->getUri()->getHost(),
|
417 |
+
$value['no']
|
418 |
+
)
|
419 |
+
) {
|
420 |
+
$options['http']['proxy'] = $value[$scheme];
|
421 |
+
}
|
422 |
+
}
|
423 |
+
}
|
424 |
+
}
|
425 |
+
|
426 |
+
private function add_timeout(RequestInterface $request, &$options, $value, &$params)
|
427 |
+
{
|
428 |
+
if ($value > 0) {
|
429 |
+
$options['http']['timeout'] = $value;
|
430 |
+
}
|
431 |
+
}
|
432 |
+
|
433 |
+
private function add_verify(RequestInterface $request, &$options, $value, &$params)
|
434 |
+
{
|
435 |
+
if ($value === true) {
|
436 |
+
// PHP 5.6 or greater will find the system cert by default. When
|
437 |
+
// < 5.6, use the Guzzle bundled cacert.
|
438 |
+
if (PHP_VERSION_ID < 50600) {
|
439 |
+
$options['ssl']['cafile'] = \GuzzleHttp\default_ca_bundle();
|
440 |
+
}
|
441 |
+
} elseif (is_string($value)) {
|
442 |
+
$options['ssl']['cafile'] = $value;
|
443 |
+
if (!file_exists($value)) {
|
444 |
+
throw new \RuntimeException("SSL CA bundle not found: $value");
|
445 |
+
}
|
446 |
+
} elseif ($value === false) {
|
447 |
+
$options['ssl']['verify_peer'] = false;
|
448 |
+
$options['ssl']['verify_peer_name'] = false;
|
449 |
+
return;
|
450 |
+
} else {
|
451 |
+
throw new \InvalidArgumentException('Invalid verify request option');
|
452 |
+
}
|
453 |
+
|
454 |
+
$options['ssl']['verify_peer'] = true;
|
455 |
+
$options['ssl']['verify_peer_name'] = true;
|
456 |
+
$options['ssl']['allow_self_signed'] = false;
|
457 |
+
}
|
458 |
+
|
459 |
+
private function add_cert(RequestInterface $request, &$options, $value, &$params)
|
460 |
+
{
|
461 |
+
if (is_array($value)) {
|
462 |
+
$options['ssl']['passphrase'] = $value[1];
|
463 |
+
$value = $value[0];
|
464 |
+
}
|
465 |
+
|
466 |
+
if (!file_exists($value)) {
|
467 |
+
throw new \RuntimeException("SSL certificate not found: {$value}");
|
468 |
+
}
|
469 |
+
|
470 |
+
$options['ssl']['local_cert'] = $value;
|
471 |
+
}
|
472 |
+
|
473 |
+
private function add_progress(RequestInterface $request, &$options, $value, &$params)
|
474 |
+
{
|
475 |
+
$this->addNotification(
|
476 |
+
$params,
|
477 |
+
function ($code, $a, $b, $c, $transferred, $total) use ($value) {
|
478 |
+
if ($code == STREAM_NOTIFY_PROGRESS) {
|
479 |
+
$value($total, $transferred, null, null);
|
480 |
+
}
|
481 |
+
}
|
482 |
+
);
|
483 |
+
}
|
484 |
+
|
485 |
+
private function add_debug(RequestInterface $request, &$options, $value, &$params)
|
486 |
+
{
|
487 |
+
if ($value === false) {
|
488 |
+
return;
|
489 |
+
}
|
490 |
+
|
491 |
+
static $map = [
|
492 |
+
STREAM_NOTIFY_CONNECT => 'CONNECT',
|
493 |
+
STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
|
494 |
+
STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
|
495 |
+
STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
|
496 |
+
STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
|
497 |
+
STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
|
498 |
+
STREAM_NOTIFY_PROGRESS => 'PROGRESS',
|
499 |
+
STREAM_NOTIFY_FAILURE => 'FAILURE',
|
500 |
+
STREAM_NOTIFY_COMPLETED => 'COMPLETED',
|
501 |
+
STREAM_NOTIFY_RESOLVE => 'RESOLVE',
|
502 |
+
];
|
503 |
+
static $args = ['severity', 'message', 'message_code',
|
504 |
+
'bytes_transferred', 'bytes_max'];
|
505 |
+
|
506 |
+
$value = \GuzzleHttp\debug_resource($value);
|
507 |
+
$ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');
|
508 |
+
$this->addNotification(
|
509 |
+
$params,
|
510 |
+
function () use ($ident, $value, $map, $args) {
|
511 |
+
$passed = func_get_args();
|
512 |
+
$code = array_shift($passed);
|
513 |
+
fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
|
514 |
+
foreach (array_filter($passed) as $i => $v) {
|
515 |
+
fwrite($value, $args[$i] . ': "' . $v . '" ');
|
516 |
+
}
|
517 |
+
fwrite($value, "\n");
|
518 |
+
}
|
519 |
+
);
|
520 |
+
}
|
521 |
+
|
522 |
+
private function addNotification(array &$params, callable $notify)
|
523 |
+
{
|
524 |
+
// Wrap the existing function if needed.
|
525 |
+
if (!isset($params['notification'])) {
|
526 |
+
$params['notification'] = $notify;
|
527 |
+
} else {
|
528 |
+
$params['notification'] = $this->callArray([
|
529 |
+
$params['notification'],
|
530 |
+
$notify
|
531 |
+
]);
|
532 |
+
}
|
533 |
+
}
|
534 |
+
|
535 |
+
private function callArray(array $functions)
|
536 |
+
{
|
537 |
+
return function () use ($functions) {
|
538 |
+
$args = func_get_args();
|
539 |
+
foreach ($functions as $fn) {
|
540 |
+
call_user_func_array($fn, $args);
|
541 |
+
}
|
542 |
+
};
|
543 |
+
}
|
544 |
+
}
|
vendor/guzzlehttp/guzzle/src/HandlerStack.php
CHANGED
@@ -1,273 +1,277 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp;
|
3 |
-
|
4 |
-
use
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
*
|
25 |
-
*
|
26 |
-
*
|
27 |
-
*
|
28 |
-
*
|
29 |
-
*
|
30 |
-
*
|
31 |
-
*
|
32 |
-
*
|
33 |
-
*
|
34 |
-
*
|
35 |
-
*
|
36 |
-
*
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
$stack
|
43 |
-
$stack->push(Middleware::
|
44 |
-
$stack->push(Middleware::
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
*
|
61 |
-
*
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
$
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
$
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
$
|
94 |
-
}
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
*
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
*
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
}
|
201 |
-
|
202 |
-
$this->
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
*
|
229 |
-
*
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
*
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
if (
|
266 |
-
return
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
}
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
use Psr\Http\Message\ResponseInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Creates a composed Guzzle handler function by stacking middlewares on top of
|
10 |
+
* an HTTP handler function.
|
11 |
+
*/
|
12 |
+
class HandlerStack
|
13 |
+
{
|
14 |
+
/** @var callable|null */
|
15 |
+
private $handler;
|
16 |
+
|
17 |
+
/** @var array */
|
18 |
+
private $stack = [];
|
19 |
+
|
20 |
+
/** @var callable|null */
|
21 |
+
private $cached;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Creates a default handler stack that can be used by clients.
|
25 |
+
*
|
26 |
+
* The returned handler will wrap the provided handler or use the most
|
27 |
+
* appropriate default handler for your system. The returned HandlerStack has
|
28 |
+
* support for cookies, redirects, HTTP error exceptions, and preparing a body
|
29 |
+
* before sending.
|
30 |
+
*
|
31 |
+
* The returned handler stack can be passed to a client in the "handler"
|
32 |
+
* option.
|
33 |
+
*
|
34 |
+
* @param callable $handler HTTP handler function to use with the stack. If no
|
35 |
+
* handler is provided, the best handler for your
|
36 |
+
* system will be utilized.
|
37 |
+
*
|
38 |
+
* @return HandlerStack
|
39 |
+
*/
|
40 |
+
public static function create(callable $handler = null)
|
41 |
+
{
|
42 |
+
$stack = new self($handler ?: choose_handler());
|
43 |
+
$stack->push(Middleware::httpErrors(), 'http_errors');
|
44 |
+
$stack->push(Middleware::redirect(), 'allow_redirects');
|
45 |
+
$stack->push(Middleware::cookies(), 'cookies');
|
46 |
+
$stack->push(Middleware::prepareBody(), 'prepare_body');
|
47 |
+
|
48 |
+
return $stack;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @param callable $handler Underlying HTTP handler.
|
53 |
+
*/
|
54 |
+
public function __construct(callable $handler = null)
|
55 |
+
{
|
56 |
+
$this->handler = $handler;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Invokes the handler stack as a composed handler
|
61 |
+
*
|
62 |
+
* @param RequestInterface $request
|
63 |
+
* @param array $options
|
64 |
+
*
|
65 |
+
* @return ResponseInterface|PromiseInterface
|
66 |
+
*/
|
67 |
+
public function __invoke(RequestInterface $request, array $options)
|
68 |
+
{
|
69 |
+
$handler = $this->resolve();
|
70 |
+
|
71 |
+
return $handler($request, $options);
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Dumps a string representation of the stack.
|
76 |
+
*
|
77 |
+
* @return string
|
78 |
+
*/
|
79 |
+
public function __toString()
|
80 |
+
{
|
81 |
+
$depth = 0;
|
82 |
+
$stack = [];
|
83 |
+
if ($this->handler) {
|
84 |
+
$stack[] = "0) Handler: " . $this->debugCallable($this->handler);
|
85 |
+
}
|
86 |
+
|
87 |
+
$result = '';
|
88 |
+
foreach (array_reverse($this->stack) as $tuple) {
|
89 |
+
$depth++;
|
90 |
+
$str = "{$depth}) Name: '{$tuple[1]}', ";
|
91 |
+
$str .= "Function: " . $this->debugCallable($tuple[0]);
|
92 |
+
$result = "> {$str}\n{$result}";
|
93 |
+
$stack[] = $str;
|
94 |
+
}
|
95 |
+
|
96 |
+
foreach (array_keys($stack) as $k) {
|
97 |
+
$result .= "< {$stack[$k]}\n";
|
98 |
+
}
|
99 |
+
|
100 |
+
return $result;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Set the HTTP handler that actually returns a promise.
|
105 |
+
*
|
106 |
+
* @param callable $handler Accepts a request and array of options and
|
107 |
+
* returns a Promise.
|
108 |
+
*/
|
109 |
+
public function setHandler(callable $handler)
|
110 |
+
{
|
111 |
+
$this->handler = $handler;
|
112 |
+
$this->cached = null;
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Returns true if the builder has a handler.
|
117 |
+
*
|
118 |
+
* @return bool
|
119 |
+
*/
|
120 |
+
public function hasHandler()
|
121 |
+
{
|
122 |
+
return (bool) $this->handler;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Unshift a middleware to the bottom of the stack.
|
127 |
+
*
|
128 |
+
* @param callable $middleware Middleware function
|
129 |
+
* @param string $name Name to register for this middleware.
|
130 |
+
*/
|
131 |
+
public function unshift(callable $middleware, $name = null)
|
132 |
+
{
|
133 |
+
array_unshift($this->stack, [$middleware, $name]);
|
134 |
+
$this->cached = null;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Push a middleware to the top of the stack.
|
139 |
+
*
|
140 |
+
* @param callable $middleware Middleware function
|
141 |
+
* @param string $name Name to register for this middleware.
|
142 |
+
*/
|
143 |
+
public function push(callable $middleware, $name = '')
|
144 |
+
{
|
145 |
+
$this->stack[] = [$middleware, $name];
|
146 |
+
$this->cached = null;
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Add a middleware before another middleware by name.
|
151 |
+
*
|
152 |
+
* @param string $findName Middleware to find
|
153 |
+
* @param callable $middleware Middleware function
|
154 |
+
* @param string $withName Name to register for this middleware.
|
155 |
+
*/
|
156 |
+
public function before($findName, callable $middleware, $withName = '')
|
157 |
+
{
|
158 |
+
$this->splice($findName, $withName, $middleware, true);
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Add a middleware after another middleware by name.
|
163 |
+
*
|
164 |
+
* @param string $findName Middleware to find
|
165 |
+
* @param callable $middleware Middleware function
|
166 |
+
* @param string $withName Name to register for this middleware.
|
167 |
+
*/
|
168 |
+
public function after($findName, callable $middleware, $withName = '')
|
169 |
+
{
|
170 |
+
$this->splice($findName, $withName, $middleware, false);
|
171 |
+
}
|
172 |
+
|
173 |
+
/**
|
174 |
+
* Remove a middleware by instance or name from the stack.
|
175 |
+
*
|
176 |
+
* @param callable|string $remove Middleware to remove by instance or name.
|
177 |
+
*/
|
178 |
+
public function remove($remove)
|
179 |
+
{
|
180 |
+
$this->cached = null;
|
181 |
+
$idx = is_callable($remove) ? 0 : 1;
|
182 |
+
$this->stack = array_values(array_filter(
|
183 |
+
$this->stack,
|
184 |
+
function ($tuple) use ($idx, $remove) {
|
185 |
+
return $tuple[$idx] !== $remove;
|
186 |
+
}
|
187 |
+
));
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Compose the middleware and handler into a single callable function.
|
192 |
+
*
|
193 |
+
* @return callable
|
194 |
+
*/
|
195 |
+
public function resolve()
|
196 |
+
{
|
197 |
+
if (!$this->cached) {
|
198 |
+
if (!($prev = $this->handler)) {
|
199 |
+
throw new \LogicException('No handler has been specified');
|
200 |
+
}
|
201 |
+
|
202 |
+
foreach (array_reverse($this->stack) as $fn) {
|
203 |
+
$prev = $fn[0]($prev);
|
204 |
+
}
|
205 |
+
|
206 |
+
$this->cached = $prev;
|
207 |
+
}
|
208 |
+
|
209 |
+
return $this->cached;
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* @param string $name
|
214 |
+
* @return int
|
215 |
+
*/
|
216 |
+
private function findByName($name)
|
217 |
+
{
|
218 |
+
foreach ($this->stack as $k => $v) {
|
219 |
+
if ($v[1] === $name) {
|
220 |
+
return $k;
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
throw new \InvalidArgumentException("Middleware not found: $name");
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Splices a function into the middleware list at a specific position.
|
229 |
+
*
|
230 |
+
* @param string $findName
|
231 |
+
* @param string $withName
|
232 |
+
* @param callable $middleware
|
233 |
+
* @param bool $before
|
234 |
+
*/
|
235 |
+
private function splice($findName, $withName, callable $middleware, $before)
|
236 |
+
{
|
237 |
+
$this->cached = null;
|
238 |
+
$idx = $this->findByName($findName);
|
239 |
+
$tuple = [$middleware, $withName];
|
240 |
+
|
241 |
+
if ($before) {
|
242 |
+
if ($idx === 0) {
|
243 |
+
array_unshift($this->stack, $tuple);
|
244 |
+
} else {
|
245 |
+
$replacement = [$tuple, $this->stack[$idx]];
|
246 |
+
array_splice($this->stack, $idx, 1, $replacement);
|
247 |
+
}
|
248 |
+
} elseif ($idx === count($this->stack) - 1) {
|
249 |
+
$this->stack[] = $tuple;
|
250 |
+
} else {
|
251 |
+
$replacement = [$this->stack[$idx], $tuple];
|
252 |
+
array_splice($this->stack, $idx, 1, $replacement);
|
253 |
+
}
|
254 |
+
}
|
255 |
+
|
256 |
+
/**
|
257 |
+
* Provides a debug string for a given callable.
|
258 |
+
*
|
259 |
+
* @param array|callable $fn Function to write as a string.
|
260 |
+
*
|
261 |
+
* @return string
|
262 |
+
*/
|
263 |
+
private function debugCallable($fn)
|
264 |
+
{
|
265 |
+
if (is_string($fn)) {
|
266 |
+
return "callable({$fn})";
|
267 |
+
}
|
268 |
+
|
269 |
+
if (is_array($fn)) {
|
270 |
+
return is_string($fn[0])
|
271 |
+
? "callable({$fn[0]}::{$fn[1]})"
|
272 |
+
: "callable(['" . get_class($fn[0]) . "', '{$fn[1]}'])";
|
273 |
+
}
|
274 |
+
|
275 |
+
return 'callable(' . spl_object_hash($fn) . ')';
|
276 |
+
}
|
277 |
+
}
|
vendor/guzzlehttp/guzzle/src/MessageFormatter.php
CHANGED
@@ -1,180 +1,185 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp;
|
3 |
-
|
4 |
-
use Psr\Http\Message\MessageInterface;
|
5 |
-
use Psr\Http\Message\RequestInterface;
|
6 |
-
use Psr\Http\Message\ResponseInterface;
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Formats log messages using variable substitutions for requests, responses,
|
10 |
-
* and other transactional data.
|
11 |
-
*
|
12 |
-
* The following variable substitutions are supported:
|
13 |
-
*
|
14 |
-
* - {request}: Full HTTP request message
|
15 |
-
* - {response}: Full HTTP response message
|
16 |
-
* - {ts}: ISO 8601 date in GMT
|
17 |
-
* - {date_iso_8601} ISO 8601 date in GMT
|
18 |
-
* - {date_common_log} Apache common log date using the configured timezone.
|
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
|
25 |
-
* - {code}: Status code of the response (if available)
|
26 |
-
* - {phrase}: Reason phrase of the response (if available)
|
27 |
-
* - {error}: Any error messages (if available)
|
28 |
-
* - {req_header_*}: Replace `*` with the lowercased name of a request header to add to the message
|
29 |
-
* - {res_header_*}: Replace `*` with the lowercased name of a response header to add to the message
|
30 |
-
* - {req_headers}: Request headers
|
31 |
-
* - {res_headers}: Response headers
|
32 |
-
* - {req_body}: Request body
|
33 |
-
* - {res_body}: Response body
|
34 |
-
*/
|
35 |
-
class MessageFormatter
|
36 |
-
{
|
37 |
-
/**
|
38 |
-
* Apache Common Log Format.
|
39 |
-
* @link http://httpd.apache.org/docs/2.4/logs.html#common
|
40 |
-
* @var string
|
41 |
-
*/
|
42 |
-
const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
|
43 |
-
const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
|
44 |
-
const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
|
45 |
-
|
46 |
-
/** @var string Template used to format log messages */
|
47 |
-
private $template;
|
48 |
-
|
49 |
-
/**
|
50 |
-
* @param string $template Log message template
|
51 |
-
*/
|
52 |
-
public function __construct($template = self::CLF)
|
53 |
-
{
|
54 |
-
$this->template = $template ?: self::CLF;
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Returns a formatted message string.
|
59 |
-
*
|
60 |
-
* @param RequestInterface $request Request that was sent
|
61 |
-
* @param ResponseInterface $response Response that was received
|
62 |
-
* @param \Exception $error Exception that was received
|
63 |
-
*
|
64 |
-
* @return string
|
65 |
-
*/
|
66 |
-
public function format(
|
67 |
-
RequestInterface $request,
|
68 |
-
ResponseInterface $response = null,
|
69 |
-
\Exception $error = null
|
70 |
-
) {
|
71 |
-
$cache = [];
|
72 |
-
|
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 |
-
}
|
79 |
-
|
80 |
-
$result = '';
|
81 |
-
switch ($matches[1]) {
|
82 |
-
case 'request':
|
83 |
-
$result = Psr7\str($request);
|
84 |
-
break;
|
85 |
-
case 'response':
|
86 |
-
$result = $response ? Psr7\str($response) : '';
|
87 |
-
break;
|
88 |
-
case 'req_headers':
|
89 |
-
$result = trim($request->getMethod()
|
90 |
-
. ' ' . $request->getRequestTarget())
|
91 |
-
. ' HTTP/' . $request->getProtocolVersion() . "\r\n"
|
92 |
-
. $this->headers($request);
|
93 |
-
break;
|
94 |
-
case 'res_headers':
|
95 |
-
$result = $response ?
|
96 |
-
sprintf(
|
97 |
-
'HTTP/%s %d %s',
|
98 |
-
$response->getProtocolVersion(),
|
99 |
-
$response->getStatusCode(),
|
100 |
-
$response->getReasonPhrase()
|
101 |
-
) . "\r\n" . $this->headers($response)
|
102 |
-
: 'NULL';
|
103 |
-
break;
|
104 |
-
case 'req_body':
|
105 |
-
$result = $request->getBody();
|
106 |
-
break;
|
107 |
-
case 'res_body':
|
108 |
-
$result = $response ? $response->getBody() : 'NULL';
|
109 |
-
break;
|
110 |
-
case 'ts':
|
111 |
-
case 'date_iso_8601':
|
112 |
-
$result = gmdate('c');
|
113 |
-
break;
|
114 |
-
case 'date_common_log':
|
115 |
-
$result = date('d/M/Y:H:i:s O');
|
116 |
-
break;
|
117 |
-
case 'method':
|
118 |
-
$result = $request->getMethod();
|
119 |
-
break;
|
120 |
-
case 'version':
|
121 |
-
$result = $request->getProtocolVersion();
|
122 |
-
break;
|
123 |
-
case 'uri':
|
124 |
-
case 'url':
|
125 |
-
$result = $request->getUri();
|
126 |
-
break;
|
127 |
-
case 'target':
|
128 |
-
$result = $request->getRequestTarget();
|
129 |
-
break;
|
130 |
-
case 'req_version':
|
131 |
-
$result = $request->getProtocolVersion();
|
132 |
-
break;
|
133 |
-
case 'res_version':
|
134 |
-
$result = $response
|
135 |
-
? $response->getProtocolVersion()
|
136 |
-
: 'NULL';
|
137 |
-
break;
|
138 |
-
case 'host':
|
139 |
-
$result = $request->getHeaderLine('Host');
|
140 |
-
break;
|
141 |
-
case 'hostname':
|
142 |
-
$result = gethostname();
|
143 |
-
break;
|
144 |
-
case 'code':
|
145 |
-
$result = $response ? $response->getStatusCode() : 'NULL';
|
146 |
-
break;
|
147 |
-
case 'phrase':
|
148 |
-
$result = $response ? $response->getReasonPhrase() : 'NULL';
|
149 |
-
break;
|
150 |
-
case 'error':
|
151 |
-
$result = $error ? $error->getMessage() : 'NULL';
|
152 |
-
break;
|
153 |
-
default:
|
154 |
-
// handle prefixed dynamic headers
|
155 |
-
if (strpos($matches[1], 'req_header_') === 0) {
|
156 |
-
$result = $request->getHeaderLine(substr($matches[1], 11));
|
157 |
-
} elseif (strpos($matches[1], 'res_header_') === 0) {
|
158 |
-
$result = $response
|
159 |
-
? $response->getHeaderLine(substr($matches[1], 11))
|
160 |
-
: 'NULL';
|
161 |
-
}
|
162 |
-
}
|
163 |
-
|
164 |
-
$cache[$matches[1]] = $result;
|
165 |
-
return $result;
|
166 |
-
},
|
167 |
-
$this->template
|
168 |
-
);
|
169 |
-
}
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use Psr\Http\Message\MessageInterface;
|
5 |
+
use Psr\Http\Message\RequestInterface;
|
6 |
+
use Psr\Http\Message\ResponseInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Formats log messages using variable substitutions for requests, responses,
|
10 |
+
* and other transactional data.
|
11 |
+
*
|
12 |
+
* The following variable substitutions are supported:
|
13 |
+
*
|
14 |
+
* - {request}: Full HTTP request message
|
15 |
+
* - {response}: Full HTTP response message
|
16 |
+
* - {ts}: ISO 8601 date in GMT
|
17 |
+
* - {date_iso_8601} ISO 8601 date in GMT
|
18 |
+
* - {date_common_log} Apache common log date using the configured timezone.
|
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
|
25 |
+
* - {code}: Status code of the response (if available)
|
26 |
+
* - {phrase}: Reason phrase of the response (if available)
|
27 |
+
* - {error}: Any error messages (if available)
|
28 |
+
* - {req_header_*}: Replace `*` with the lowercased name of a request header to add to the message
|
29 |
+
* - {res_header_*}: Replace `*` with the lowercased name of a response header to add to the message
|
30 |
+
* - {req_headers}: Request headers
|
31 |
+
* - {res_headers}: Response headers
|
32 |
+
* - {req_body}: Request body
|
33 |
+
* - {res_body}: Response body
|
34 |
+
*/
|
35 |
+
class MessageFormatter
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Apache Common Log Format.
|
39 |
+
* @link http://httpd.apache.org/docs/2.4/logs.html#common
|
40 |
+
* @var string
|
41 |
+
*/
|
42 |
+
const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
|
43 |
+
const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
|
44 |
+
const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
|
45 |
+
|
46 |
+
/** @var string Template used to format log messages */
|
47 |
+
private $template;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @param string $template Log message template
|
51 |
+
*/
|
52 |
+
public function __construct($template = self::CLF)
|
53 |
+
{
|
54 |
+
$this->template = $template ?: self::CLF;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Returns a formatted message string.
|
59 |
+
*
|
60 |
+
* @param RequestInterface $request Request that was sent
|
61 |
+
* @param ResponseInterface $response Response that was received
|
62 |
+
* @param \Exception $error Exception that was received
|
63 |
+
*
|
64 |
+
* @return string
|
65 |
+
*/
|
66 |
+
public function format(
|
67 |
+
RequestInterface $request,
|
68 |
+
ResponseInterface $response = null,
|
69 |
+
\Exception $error = null
|
70 |
+
) {
|
71 |
+
$cache = [];
|
72 |
+
|
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 |
+
}
|
79 |
+
|
80 |
+
$result = '';
|
81 |
+
switch ($matches[1]) {
|
82 |
+
case 'request':
|
83 |
+
$result = Psr7\str($request);
|
84 |
+
break;
|
85 |
+
case 'response':
|
86 |
+
$result = $response ? Psr7\str($response) : '';
|
87 |
+
break;
|
88 |
+
case 'req_headers':
|
89 |
+
$result = trim($request->getMethod()
|
90 |
+
. ' ' . $request->getRequestTarget())
|
91 |
+
. ' HTTP/' . $request->getProtocolVersion() . "\r\n"
|
92 |
+
. $this->headers($request);
|
93 |
+
break;
|
94 |
+
case 'res_headers':
|
95 |
+
$result = $response ?
|
96 |
+
sprintf(
|
97 |
+
'HTTP/%s %d %s',
|
98 |
+
$response->getProtocolVersion(),
|
99 |
+
$response->getStatusCode(),
|
100 |
+
$response->getReasonPhrase()
|
101 |
+
) . "\r\n" . $this->headers($response)
|
102 |
+
: 'NULL';
|
103 |
+
break;
|
104 |
+
case 'req_body':
|
105 |
+
$result = $request->getBody();
|
106 |
+
break;
|
107 |
+
case 'res_body':
|
108 |
+
$result = $response ? $response->getBody() : 'NULL';
|
109 |
+
break;
|
110 |
+
case 'ts':
|
111 |
+
case 'date_iso_8601':
|
112 |
+
$result = gmdate('c');
|
113 |
+
break;
|
114 |
+
case 'date_common_log':
|
115 |
+
$result = date('d/M/Y:H:i:s O');
|
116 |
+
break;
|
117 |
+
case 'method':
|
118 |
+
$result = $request->getMethod();
|
119 |
+
break;
|
120 |
+
case 'version':
|
121 |
+
$result = $request->getProtocolVersion();
|
122 |
+
break;
|
123 |
+
case 'uri':
|
124 |
+
case 'url':
|
125 |
+
$result = $request->getUri();
|
126 |
+
break;
|
127 |
+
case 'target':
|
128 |
+
$result = $request->getRequestTarget();
|
129 |
+
break;
|
130 |
+
case 'req_version':
|
131 |
+
$result = $request->getProtocolVersion();
|
132 |
+
break;
|
133 |
+
case 'res_version':
|
134 |
+
$result = $response
|
135 |
+
? $response->getProtocolVersion()
|
136 |
+
: 'NULL';
|
137 |
+
break;
|
138 |
+
case 'host':
|
139 |
+
$result = $request->getHeaderLine('Host');
|
140 |
+
break;
|
141 |
+
case 'hostname':
|
142 |
+
$result = gethostname();
|
143 |
+
break;
|
144 |
+
case 'code':
|
145 |
+
$result = $response ? $response->getStatusCode() : 'NULL';
|
146 |
+
break;
|
147 |
+
case 'phrase':
|
148 |
+
$result = $response ? $response->getReasonPhrase() : 'NULL';
|
149 |
+
break;
|
150 |
+
case 'error':
|
151 |
+
$result = $error ? $error->getMessage() : 'NULL';
|
152 |
+
break;
|
153 |
+
default:
|
154 |
+
// handle prefixed dynamic headers
|
155 |
+
if (strpos($matches[1], 'req_header_') === 0) {
|
156 |
+
$result = $request->getHeaderLine(substr($matches[1], 11));
|
157 |
+
} elseif (strpos($matches[1], 'res_header_') === 0) {
|
158 |
+
$result = $response
|
159 |
+
? $response->getHeaderLine(substr($matches[1], 11))
|
160 |
+
: 'NULL';
|
161 |
+
}
|
162 |
+
}
|
163 |
+
|
164 |
+
$cache[$matches[1]] = $result;
|
165 |
+
return $result;
|
166 |
+
},
|
167 |
+
$this->template
|
168 |
+
);
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Get headers from message as string
|
173 |
+
*
|
174 |
+
* @return string
|
175 |
+
*/
|
176 |
+
private function headers(MessageInterface $message)
|
177 |
+
{
|
178 |
+
$result = '';
|
179 |
+
foreach ($message->getHeaders() as $name => $values) {
|
180 |
+
$result .= $name . ': ' . implode(', ', $values) . "\r\n";
|
181 |
+
}
|
182 |
+
|
183 |
+
return trim($result);
|
184 |
+
}
|
185 |
+
}
|
vendor/guzzlehttp/guzzle/src/Pool.php
CHANGED
@@ -1,123 +1,132 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp;
|
3 |
-
|
4 |
-
use GuzzleHttp\Promise\
|
5 |
-
use
|
6 |
-
use
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Sends an iterator of requests concurrently using a capped pool size.
|
10 |
-
*
|
11 |
-
* The pool will read from an iterator until it is cancelled or until the
|
12 |
-
* iterator is consumed. When a request is yielded, the request is sent after
|
13 |
-
* applying the "request_options" request options (if provided in the ctor).
|
14 |
-
*
|
15 |
-
* When a function is yielded by the iterator, the function is provided the
|
16 |
-
* "request_options" array that should be merged on top of any existing
|
17 |
-
* options, and the function MUST then return a wait-able promise.
|
18 |
-
*/
|
19 |
-
class Pool implements PromisorInterface
|
20 |
-
{
|
21 |
-
/** @var EachPromise */
|
22 |
-
private $each;
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @param ClientInterface $client Client used to send the requests.
|
26 |
-
* @param array|\Iterator $requests Requests or functions that return
|
27 |
-
* requests to send concurrently.
|
28 |
-
* @param array $config Associative array of options
|
29 |
-
* - concurrency: (int) Maximum number of requests to send concurrently
|
30 |
-
* - options: Array of request options to apply to each request.
|
31 |
-
* - fulfilled: (callable) Function to invoke when a request completes.
|
32 |
-
* - rejected: (callable) Function to invoke when a request is rejected.
|
33 |
-
*/
|
34 |
-
public function __construct(
|
35 |
-
ClientInterface $client,
|
36 |
-
$requests,
|
37 |
-
array $config = []
|
38 |
-
) {
|
39 |
-
// Backwards compatibility.
|
40 |
-
if (isset($config['pool_size'])) {
|
41 |
-
$config['concurrency'] = $config['pool_size'];
|
42 |
-
} elseif (!isset($config['concurrency'])) {
|
43 |
-
$config['concurrency'] = 25;
|
44 |
-
}
|
45 |
-
|
46 |
-
if (isset($config['options'])) {
|
47 |
-
$opts = $config['options'];
|
48 |
-
unset($config['options']);
|
49 |
-
} else {
|
50 |
-
$opts = [];
|
51 |
-
}
|
52 |
-
|
53 |
-
$iterable = \GuzzleHttp\Promise\iter_for($requests);
|
54 |
-
$requests = function () use ($iterable, $client, $opts) {
|
55 |
-
foreach ($iterable as $key => $rfn) {
|
56 |
-
if ($rfn instanceof RequestInterface) {
|
57 |
-
yield $key => $client->sendAsync($rfn, $opts);
|
58 |
-
} elseif (is_callable($rfn)) {
|
59 |
-
yield $key => $rfn($opts);
|
60 |
-
} else {
|
61 |
-
throw new \InvalidArgumentException('Each value yielded by '
|
62 |
-
. 'the iterator must be a Psr7\Http\Message\RequestInterface '
|
63 |
-
. 'or a callable that returns a promise that fulfills '
|
64 |
-
. 'with a Psr7\Message\Http\ResponseInterface object.');
|
65 |
-
}
|
66 |
-
}
|
67 |
-
};
|
68 |
-
|
69 |
-
$this->each = new EachPromise($requests(), $config);
|
70 |
-
}
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
*
|
83 |
-
*
|
84 |
-
*
|
85 |
-
*
|
86 |
-
*
|
87 |
-
*
|
88 |
-
*
|
89 |
-
*
|
90 |
-
* @
|
91 |
-
*
|
92 |
-
*
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
$
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
$
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use GuzzleHttp\Promise\EachPromise;
|
5 |
+
use GuzzleHttp\Promise\PromisorInterface;
|
6 |
+
use Psr\Http\Message\RequestInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Sends an iterator of requests concurrently using a capped pool size.
|
10 |
+
*
|
11 |
+
* The pool will read from an iterator until it is cancelled or until the
|
12 |
+
* iterator is consumed. When a request is yielded, the request is sent after
|
13 |
+
* applying the "request_options" request options (if provided in the ctor).
|
14 |
+
*
|
15 |
+
* When a function is yielded by the iterator, the function is provided the
|
16 |
+
* "request_options" array that should be merged on top of any existing
|
17 |
+
* options, and the function MUST then return a wait-able promise.
|
18 |
+
*/
|
19 |
+
class Pool implements PromisorInterface
|
20 |
+
{
|
21 |
+
/** @var EachPromise */
|
22 |
+
private $each;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @param ClientInterface $client Client used to send the requests.
|
26 |
+
* @param array|\Iterator $requests Requests or functions that return
|
27 |
+
* requests to send concurrently.
|
28 |
+
* @param array $config Associative array of options
|
29 |
+
* - concurrency: (int) Maximum number of requests to send concurrently
|
30 |
+
* - options: Array of request options to apply to each request.
|
31 |
+
* - fulfilled: (callable) Function to invoke when a request completes.
|
32 |
+
* - rejected: (callable) Function to invoke when a request is rejected.
|
33 |
+
*/
|
34 |
+
public function __construct(
|
35 |
+
ClientInterface $client,
|
36 |
+
$requests,
|
37 |
+
array $config = []
|
38 |
+
) {
|
39 |
+
// Backwards compatibility.
|
40 |
+
if (isset($config['pool_size'])) {
|
41 |
+
$config['concurrency'] = $config['pool_size'];
|
42 |
+
} elseif (!isset($config['concurrency'])) {
|
43 |
+
$config['concurrency'] = 25;
|
44 |
+
}
|
45 |
+
|
46 |
+
if (isset($config['options'])) {
|
47 |
+
$opts = $config['options'];
|
48 |
+
unset($config['options']);
|
49 |
+
} else {
|
50 |
+
$opts = [];
|
51 |
+
}
|
52 |
+
|
53 |
+
$iterable = \GuzzleHttp\Promise\iter_for($requests);
|
54 |
+
$requests = function () use ($iterable, $client, $opts) {
|
55 |
+
foreach ($iterable as $key => $rfn) {
|
56 |
+
if ($rfn instanceof RequestInterface) {
|
57 |
+
yield $key => $client->sendAsync($rfn, $opts);
|
58 |
+
} elseif (is_callable($rfn)) {
|
59 |
+
yield $key => $rfn($opts);
|
60 |
+
} else {
|
61 |
+
throw new \InvalidArgumentException('Each value yielded by '
|
62 |
+
. 'the iterator must be a Psr7\Http\Message\RequestInterface '
|
63 |
+
. 'or a callable that returns a promise that fulfills '
|
64 |
+
. 'with a Psr7\Message\Http\ResponseInterface object.');
|
65 |
+
}
|
66 |
+
}
|
67 |
+
};
|
68 |
+
|
69 |
+
$this->each = new EachPromise($requests(), $config);
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Get promise
|
74 |
+
* @return GuzzleHttp\Promise\Promise
|
75 |
+
*/
|
76 |
+
public function promise()
|
77 |
+
{
|
78 |
+
return $this->each->promise();
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Sends multiple requests concurrently and returns an array of responses
|
83 |
+
* and exceptions that uses the same ordering as the provided requests.
|
84 |
+
*
|
85 |
+
* IMPORTANT: This method keeps every request and response in memory, and
|
86 |
+
* as such, is NOT recommended when sending a large number or an
|
87 |
+
* indeterminate number of requests concurrently.
|
88 |
+
*
|
89 |
+
* @param ClientInterface $client Client used to send the requests
|
90 |
+
* @param array|\Iterator $requests Requests to send concurrently.
|
91 |
+
* @param array $options Passes through the options available in
|
92 |
+
* {@see GuzzleHttp\Pool::__construct}
|
93 |
+
*
|
94 |
+
* @return array Returns an array containing the response or an exception
|
95 |
+
* in the same order that the requests were sent.
|
96 |
+
* @throws \InvalidArgumentException if the event format is incorrect.
|
97 |
+
*/
|
98 |
+
public static function batch(
|
99 |
+
ClientInterface $client,
|
100 |
+
$requests,
|
101 |
+
array $options = []
|
102 |
+
) {
|
103 |
+
$res = [];
|
104 |
+
self::cmpCallback($options, 'fulfilled', $res);
|
105 |
+
self::cmpCallback($options, 'rejected', $res);
|
106 |
+
$pool = new static($client, $requests, $options);
|
107 |
+
$pool->promise()->wait();
|
108 |
+
ksort($res);
|
109 |
+
|
110 |
+
return $res;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Execute callback(s)
|
115 |
+
*
|
116 |
+
* @return void
|
117 |
+
*/
|
118 |
+
private static function cmpCallback(array &$options, $name, array &$results)
|
119 |
+
{
|
120 |
+
if (!isset($options[$name])) {
|
121 |
+
$options[$name] = function ($v, $k) use (&$results) {
|
122 |
+
$results[$k] = $v;
|
123 |
+
};
|
124 |
+
} else {
|
125 |
+
$currentFn = $options[$name];
|
126 |
+
$options[$name] = function ($v, $k) use (&$results, $currentFn) {
|
127 |
+
$currentFn($v, $k);
|
128 |
+
$results[$k] = $v;
|
129 |
+
};
|
130 |
+
}
|
131 |
+
}
|
132 |
+
}
|
vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php
CHANGED
@@ -1,106 +1,111 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp;
|
3 |
-
|
4 |
-
use GuzzleHttp\Promise\PromiseInterface;
|
5 |
-
use GuzzleHttp\Psr7;
|
6 |
-
use Psr\Http\Message\RequestInterface;
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Prepares requests that contain a body, adding the Content-Length,
|
10 |
-
* Content-Type, and Expect headers.
|
11 |
-
*/
|
12 |
-
class PrepareBodyMiddleware
|
13 |
-
{
|
14 |
-
/** @var callable */
|
15 |
-
private $nextHandler;
|
16 |
-
|
17 |
-
/**
|
18 |
-
* @param callable $nextHandler Next handler to invoke.
|
19 |
-
*/
|
20 |
-
public function __construct(callable $nextHandler)
|
21 |
-
{
|
22 |
-
$this->nextHandler = $nextHandler;
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @param RequestInterface $request
|
27 |
-
* @param array $options
|
28 |
-
*
|
29 |
-
* @return PromiseInterface
|
30 |
-
*/
|
31 |
-
public function __invoke(RequestInterface $request, array $options)
|
32 |
-
{
|
33 |
-
$fn = $this->nextHandler;
|
34 |
-
|
35 |
-
// Don't do anything if the request has no body.
|
36 |
-
if ($request->getBody()->getSize() === 0) {
|
37 |
-
return $fn($request, $options);
|
38 |
-
}
|
39 |
-
|
40 |
-
$modify = [];
|
41 |
-
|
42 |
-
// Add a default content-type if possible.
|
43 |
-
if (!$request->hasHeader('Content-Type')) {
|
44 |
-
if ($uri = $request->getBody()->getMetadata('uri')) {
|
45 |
-
if ($type = Psr7\mimetype_from_filename($uri)) {
|
46 |
-
$modify['set_headers']['Content-Type'] = $type;
|
47 |
-
}
|
48 |
-
}
|
49 |
-
}
|
50 |
-
|
51 |
-
// Add a default content-length or transfer-encoding header.
|
52 |
-
if (!$request->hasHeader('Content-Length')
|
53 |
-
&& !$request->hasHeader('Transfer-Encoding')
|
54 |
-
) {
|
55 |
-
$size = $request->getBody()->getSize();
|
56 |
-
if ($size !== null) {
|
57 |
-
$modify['set_headers']['Content-Length'] = $size;
|
58 |
-
} else {
|
59 |
-
$modify['set_headers']['Transfer-Encoding'] = 'chunked';
|
60 |
-
}
|
61 |
-
}
|
62 |
-
|
63 |
-
// Add the expect header if needed.
|
64 |
-
$this->addExpectHeader($request, $options, $modify);
|
65 |
-
|
66 |
-
return $fn(Psr7\modify_request($request, $modify), $options);
|
67 |
-
}
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
//
|
87 |
-
if ($expect ===
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
}
|
96 |
-
|
97 |
-
//
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
5 |
+
use GuzzleHttp\Psr7;
|
6 |
+
use Psr\Http\Message\RequestInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Prepares requests that contain a body, adding the Content-Length,
|
10 |
+
* Content-Type, and Expect headers.
|
11 |
+
*/
|
12 |
+
class PrepareBodyMiddleware
|
13 |
+
{
|
14 |
+
/** @var callable */
|
15 |
+
private $nextHandler;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param callable $nextHandler Next handler to invoke.
|
19 |
+
*/
|
20 |
+
public function __construct(callable $nextHandler)
|
21 |
+
{
|
22 |
+
$this->nextHandler = $nextHandler;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @param RequestInterface $request
|
27 |
+
* @param array $options
|
28 |
+
*
|
29 |
+
* @return PromiseInterface
|
30 |
+
*/
|
31 |
+
public function __invoke(RequestInterface $request, array $options)
|
32 |
+
{
|
33 |
+
$fn = $this->nextHandler;
|
34 |
+
|
35 |
+
// Don't do anything if the request has no body.
|
36 |
+
if ($request->getBody()->getSize() === 0) {
|
37 |
+
return $fn($request, $options);
|
38 |
+
}
|
39 |
+
|
40 |
+
$modify = [];
|
41 |
+
|
42 |
+
// Add a default content-type if possible.
|
43 |
+
if (!$request->hasHeader('Content-Type')) {
|
44 |
+
if ($uri = $request->getBody()->getMetadata('uri')) {
|
45 |
+
if ($type = Psr7\mimetype_from_filename($uri)) {
|
46 |
+
$modify['set_headers']['Content-Type'] = $type;
|
47 |
+
}
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
// Add a default content-length or transfer-encoding header.
|
52 |
+
if (!$request->hasHeader('Content-Length')
|
53 |
+
&& !$request->hasHeader('Transfer-Encoding')
|
54 |
+
) {
|
55 |
+
$size = $request->getBody()->getSize();
|
56 |
+
if ($size !== null) {
|
57 |
+
$modify['set_headers']['Content-Length'] = $size;
|
58 |
+
} else {
|
59 |
+
$modify['set_headers']['Transfer-Encoding'] = 'chunked';
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
+
// Add the expect header if needed.
|
64 |
+
$this->addExpectHeader($request, $options, $modify);
|
65 |
+
|
66 |
+
return $fn(Psr7\modify_request($request, $modify), $options);
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Add expect header
|
71 |
+
*
|
72 |
+
* @return void
|
73 |
+
*/
|
74 |
+
private function addExpectHeader(
|
75 |
+
RequestInterface $request,
|
76 |
+
array $options,
|
77 |
+
array &$modify
|
78 |
+
) {
|
79 |
+
// Determine if the Expect header should be used
|
80 |
+
if ($request->hasHeader('Expect')) {
|
81 |
+
return;
|
82 |
+
}
|
83 |
+
|
84 |
+
$expect = isset($options['expect']) ? $options['expect'] : null;
|
85 |
+
|
86 |
+
// Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0
|
87 |
+
if ($expect === false || $request->getProtocolVersion() < 1.1) {
|
88 |
+
return;
|
89 |
+
}
|
90 |
+
|
91 |
+
// The expect header is unconditionally enabled
|
92 |
+
if ($expect === true) {
|
93 |
+
$modify['set_headers']['Expect'] = '100-Continue';
|
94 |
+
return;
|
95 |
+
}
|
96 |
+
|
97 |
+
// By default, send the expect header when the payload is > 1mb
|
98 |
+
if ($expect === null) {
|
99 |
+
$expect = 1048576;
|
100 |
+
}
|
101 |
+
|
102 |
+
// Always add if the body cannot be rewound, the size cannot be
|
103 |
+
// determined, or the size is greater than the cutoff threshold
|
104 |
+
$body = $request->getBody();
|
105 |
+
$size = $body->getSize();
|
106 |
+
|
107 |
+
if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {
|
108 |
+
$modify['set_headers']['Expect'] = '100-Continue';
|
109 |
+
}
|
110 |
+
}
|
111 |
+
}
|
vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php
CHANGED
@@ -1,237 +1,249 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp;
|
3 |
-
|
4 |
-
use GuzzleHttp\Exception\BadResponseException;
|
5 |
-
use GuzzleHttp\Exception\TooManyRedirectsException;
|
6 |
-
use GuzzleHttp\Promise\PromiseInterface;
|
7 |
-
use GuzzleHttp\Psr7;
|
8 |
-
use Psr\Http\Message\RequestInterface;
|
9 |
-
use Psr\Http\Message\ResponseInterface;
|
10 |
-
use Psr\Http\Message\UriInterface;
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Request redirect middleware.
|
14 |
-
*
|
15 |
-
* Apply this middleware like other middleware using
|
16 |
-
* {@see GuzzleHttp\Middleware::redirect()}.
|
17 |
-
*/
|
18 |
-
class RedirectMiddleware
|
19 |
-
{
|
20 |
-
const HISTORY_HEADER = 'X-Guzzle-Redirect-History';
|
21 |
-
|
22 |
-
const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History';
|
23 |
-
|
24 |
-
public static $defaultSettings = [
|
25 |
-
'max' => 5,
|
26 |
-
'protocols' => ['http', 'https'],
|
27 |
-
'strict' => false,
|
28 |
-
'referer' => false,
|
29 |
-
'track_redirects' => false,
|
30 |
-
];
|
31 |
-
|
32 |
-
/** @var callable */
|
33 |
-
private $nextHandler;
|
34 |
-
|
35 |
-
/**
|
36 |
-
* @param callable $nextHandler Next handler to invoke.
|
37 |
-
*/
|
38 |
-
public function __construct(callable $nextHandler)
|
39 |
-
{
|
40 |
-
$this->nextHandler = $nextHandler;
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* @param RequestInterface $request
|
45 |
-
* @param array $options
|
46 |
-
*
|
47 |
-
* @return PromiseInterface
|
48 |
-
*/
|
49 |
-
public function __invoke(RequestInterface $request, array $options)
|
50 |
-
{
|
51 |
-
$fn = $this->nextHandler;
|
52 |
-
|
53 |
-
if (empty($options['allow_redirects'])) {
|
54 |
-
return $fn($request, $options);
|
55 |
-
}
|
56 |
-
|
57 |
-
if ($options['allow_redirects'] === true) {
|
58 |
-
$options['allow_redirects'] = self::$defaultSettings;
|
59 |
-
} elseif (!is_array($options['allow_redirects'])) {
|
60 |
-
throw new \InvalidArgumentException('allow_redirects must be true, false, or array');
|
61 |
-
} else {
|
62 |
-
// Merge the default settings with the provided settings
|
63 |
-
$options['allow_redirects'] += self::$defaultSettings;
|
64 |
-
}
|
65 |
-
|
66 |
-
if (empty($options['allow_redirects']['max'])) {
|
67 |
-
return $fn($request, $options);
|
68 |
-
}
|
69 |
-
|
70 |
-
return $fn($request, $options)
|
71 |
-
->then(function (ResponseInterface $response) use ($request, $options) {
|
72 |
-
return $this->checkRedirect($request, $options, $response);
|
73 |
-
});
|
74 |
-
}
|
75 |
-
|
76 |
-
/**
|
77 |
-
* @param RequestInterface $request
|
78 |
-
* @param array $options
|
79 |
-
* @param ResponseInterface
|
80 |
-
*
|
81 |
-
* @return ResponseInterface|PromiseInterface
|
82 |
-
*/
|
83 |
-
public function checkRedirect(
|
84 |
-
RequestInterface $request,
|
85 |
-
array $options,
|
86 |
-
ResponseInterface $response
|
87 |
-
) {
|
88 |
-
if (substr($response->getStatusCode(), 0, 1) != '3'
|
89 |
-
|| !$response->hasHeader('Location')
|
90 |
-
) {
|
91 |
-
return $response;
|
92 |
-
}
|
93 |
-
|
94 |
-
$this->guardMax($request, $options);
|
95 |
-
$nextRequest = $this->modifyRequest($request, $options, $response);
|
96 |
-
|
97 |
-
if (isset($options['allow_redirects']['on_redirect'])) {
|
98 |
-
call_user_func(
|
99 |
-
$options['allow_redirects']['on_redirect'],
|
100 |
-
$request,
|
101 |
-
$response,
|
102 |
-
$nextRequest->getUri()
|
103 |
-
);
|
104 |
-
}
|
105 |
-
|
106 |
-
/** @var PromiseInterface|ResponseInterface $promise */
|
107 |
-
$promise = $this($nextRequest, $options);
|
108 |
-
|
109 |
-
// Add headers to be able to track history of redirects.
|
110 |
-
if (!empty($options['allow_redirects']['track_redirects'])) {
|
111 |
-
return $this->withTracking(
|
112 |
-
$promise,
|
113 |
-
(string) $nextRequest->getUri(),
|
114 |
-
$response->getStatusCode()
|
115 |
-
);
|
116 |
-
}
|
117 |
-
|
118 |
-
return $promise;
|
119 |
-
}
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
//
|
185 |
-
|
186 |
-
if ($
|
187 |
-
&&
|
188 |
-
) {
|
189 |
-
$
|
190 |
-
$modify['
|
191 |
-
}
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
if
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use GuzzleHttp\Exception\BadResponseException;
|
5 |
+
use GuzzleHttp\Exception\TooManyRedirectsException;
|
6 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
7 |
+
use GuzzleHttp\Psr7;
|
8 |
+
use Psr\Http\Message\RequestInterface;
|
9 |
+
use Psr\Http\Message\ResponseInterface;
|
10 |
+
use Psr\Http\Message\UriInterface;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Request redirect middleware.
|
14 |
+
*
|
15 |
+
* Apply this middleware like other middleware using
|
16 |
+
* {@see GuzzleHttp\Middleware::redirect()}.
|
17 |
+
*/
|
18 |
+
class RedirectMiddleware
|
19 |
+
{
|
20 |
+
const HISTORY_HEADER = 'X-Guzzle-Redirect-History';
|
21 |
+
|
22 |
+
const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History';
|
23 |
+
|
24 |
+
public static $defaultSettings = [
|
25 |
+
'max' => 5,
|
26 |
+
'protocols' => ['http', 'https'],
|
27 |
+
'strict' => false,
|
28 |
+
'referer' => false,
|
29 |
+
'track_redirects' => false,
|
30 |
+
];
|
31 |
+
|
32 |
+
/** @var callable */
|
33 |
+
private $nextHandler;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @param callable $nextHandler Next handler to invoke.
|
37 |
+
*/
|
38 |
+
public function __construct(callable $nextHandler)
|
39 |
+
{
|
40 |
+
$this->nextHandler = $nextHandler;
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* @param RequestInterface $request
|
45 |
+
* @param array $options
|
46 |
+
*
|
47 |
+
* @return PromiseInterface
|
48 |
+
*/
|
49 |
+
public function __invoke(RequestInterface $request, array $options)
|
50 |
+
{
|
51 |
+
$fn = $this->nextHandler;
|
52 |
+
|
53 |
+
if (empty($options['allow_redirects'])) {
|
54 |
+
return $fn($request, $options);
|
55 |
+
}
|
56 |
+
|
57 |
+
if ($options['allow_redirects'] === true) {
|
58 |
+
$options['allow_redirects'] = self::$defaultSettings;
|
59 |
+
} elseif (!is_array($options['allow_redirects'])) {
|
60 |
+
throw new \InvalidArgumentException('allow_redirects must be true, false, or array');
|
61 |
+
} else {
|
62 |
+
// Merge the default settings with the provided settings
|
63 |
+
$options['allow_redirects'] += self::$defaultSettings;
|
64 |
+
}
|
65 |
+
|
66 |
+
if (empty($options['allow_redirects']['max'])) {
|
67 |
+
return $fn($request, $options);
|
68 |
+
}
|
69 |
+
|
70 |
+
return $fn($request, $options)
|
71 |
+
->then(function (ResponseInterface $response) use ($request, $options) {
|
72 |
+
return $this->checkRedirect($request, $options, $response);
|
73 |
+
});
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* @param RequestInterface $request
|
78 |
+
* @param array $options
|
79 |
+
* @param ResponseInterface $response
|
80 |
+
*
|
81 |
+
* @return ResponseInterface|PromiseInterface
|
82 |
+
*/
|
83 |
+
public function checkRedirect(
|
84 |
+
RequestInterface $request,
|
85 |
+
array $options,
|
86 |
+
ResponseInterface $response
|
87 |
+
) {
|
88 |
+
if (substr($response->getStatusCode(), 0, 1) != '3'
|
89 |
+
|| !$response->hasHeader('Location')
|
90 |
+
) {
|
91 |
+
return $response;
|
92 |
+
}
|
93 |
+
|
94 |
+
$this->guardMax($request, $options);
|
95 |
+
$nextRequest = $this->modifyRequest($request, $options, $response);
|
96 |
+
|
97 |
+
if (isset($options['allow_redirects']['on_redirect'])) {
|
98 |
+
call_user_func(
|
99 |
+
$options['allow_redirects']['on_redirect'],
|
100 |
+
$request,
|
101 |
+
$response,
|
102 |
+
$nextRequest->getUri()
|
103 |
+
);
|
104 |
+
}
|
105 |
+
|
106 |
+
/** @var PromiseInterface|ResponseInterface $promise */
|
107 |
+
$promise = $this($nextRequest, $options);
|
108 |
+
|
109 |
+
// Add headers to be able to track history of redirects.
|
110 |
+
if (!empty($options['allow_redirects']['track_redirects'])) {
|
111 |
+
return $this->withTracking(
|
112 |
+
$promise,
|
113 |
+
(string) $nextRequest->getUri(),
|
114 |
+
$response->getStatusCode()
|
115 |
+
);
|
116 |
+
}
|
117 |
+
|
118 |
+
return $promise;
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Enable tracking on promise.
|
123 |
+
*
|
124 |
+
* @return PromiseInterface
|
125 |
+
*/
|
126 |
+
private function withTracking(PromiseInterface $promise, $uri, $statusCode)
|
127 |
+
{
|
128 |
+
return $promise->then(
|
129 |
+
function (ResponseInterface $response) use ($uri, $statusCode) {
|
130 |
+
// Note that we are pushing to the front of the list as this
|
131 |
+
// would be an earlier response than what is currently present
|
132 |
+
// in the history header.
|
133 |
+
$historyHeader = $response->getHeader(self::HISTORY_HEADER);
|
134 |
+
$statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER);
|
135 |
+
array_unshift($historyHeader, $uri);
|
136 |
+
array_unshift($statusHeader, $statusCode);
|
137 |
+
return $response->withHeader(self::HISTORY_HEADER, $historyHeader)
|
138 |
+
->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader);
|
139 |
+
}
|
140 |
+
);
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Check for too many redirects
|
145 |
+
*
|
146 |
+
* @return void
|
147 |
+
*
|
148 |
+
* @throws TooManyRedirectsException Too many redirects.
|
149 |
+
*/
|
150 |
+
private function guardMax(RequestInterface $request, array &$options)
|
151 |
+
{
|
152 |
+
$current = isset($options['__redirect_count'])
|
153 |
+
? $options['__redirect_count']
|
154 |
+
: 0;
|
155 |
+
$options['__redirect_count'] = $current + 1;
|
156 |
+
$max = $options['allow_redirects']['max'];
|
157 |
+
|
158 |
+
if ($options['__redirect_count'] > $max) {
|
159 |
+
throw new TooManyRedirectsException(
|
160 |
+
"Will not follow more than {$max} redirects",
|
161 |
+
$request
|
162 |
+
);
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* @param RequestInterface $request
|
168 |
+
* @param array $options
|
169 |
+
* @param ResponseInterface $response
|
170 |
+
*
|
171 |
+
* @return RequestInterface
|
172 |
+
*/
|
173 |
+
public function modifyRequest(
|
174 |
+
RequestInterface $request,
|
175 |
+
array $options,
|
176 |
+
ResponseInterface $response
|
177 |
+
) {
|
178 |
+
// Request modifications to apply.
|
179 |
+
$modify = [];
|
180 |
+
$protocols = $options['allow_redirects']['protocols'];
|
181 |
+
|
182 |
+
// Use a GET request if this is an entity enclosing request and we are
|
183 |
+
// not forcing RFC compliance, but rather emulating what all browsers
|
184 |
+
// would do.
|
185 |
+
$statusCode = $response->getStatusCode();
|
186 |
+
if ($statusCode == 303 ||
|
187 |
+
($statusCode <= 302 && !$options['allow_redirects']['strict'])
|
188 |
+
) {
|
189 |
+
$modify['method'] = 'GET';
|
190 |
+
$modify['body'] = '';
|
191 |
+
}
|
192 |
+
|
193 |
+
$modify['uri'] = $this->redirectUri($request, $response, $protocols);
|
194 |
+
Psr7\rewind_body($request);
|
195 |
+
|
196 |
+
// Add the Referer header if it is told to do so and only
|
197 |
+
// add the header if we are not redirecting from https to http.
|
198 |
+
if ($options['allow_redirects']['referer']
|
199 |
+
&& $modify['uri']->getScheme() === $request->getUri()->getScheme()
|
200 |
+
) {
|
201 |
+
$uri = $request->getUri()->withUserInfo('');
|
202 |
+
$modify['set_headers']['Referer'] = (string) $uri;
|
203 |
+
} else {
|
204 |
+
$modify['remove_headers'][] = 'Referer';
|
205 |
+
}
|
206 |
+
|
207 |
+
// Remove Authorization header if host is different.
|
208 |
+
if ($request->getUri()->getHost() !== $modify['uri']->getHost()) {
|
209 |
+
$modify['remove_headers'][] = 'Authorization';
|
210 |
+
}
|
211 |
+
|
212 |
+
return Psr7\modify_request($request, $modify);
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Set the appropriate URL on the request based on the location header
|
217 |
+
*
|
218 |
+
* @param RequestInterface $request
|
219 |
+
* @param ResponseInterface $response
|
220 |
+
* @param array $protocols
|
221 |
+
*
|
222 |
+
* @return UriInterface
|
223 |
+
*/
|
224 |
+
private function redirectUri(
|
225 |
+
RequestInterface $request,
|
226 |
+
ResponseInterface $response,
|
227 |
+
array $protocols
|
228 |
+
) {
|
229 |
+
$location = Psr7\UriResolver::resolve(
|
230 |
+
$request->getUri(),
|
231 |
+
new Psr7\Uri($response->getHeaderLine('Location'))
|
232 |
+
);
|
233 |
+
|
234 |
+
// Ensure that the redirect URI is allowed based on the protocols.
|
235 |
+
if (!in_array($location->getScheme(), $protocols)) {
|
236 |
+
throw new BadResponseException(
|
237 |
+
sprintf(
|
238 |
+
'Redirect URI, %s, does not use one of the allowed redirect protocols: %s',
|
239 |
+
$location,
|
240 |
+
implode(', ', $protocols)
|
241 |
+
),
|
242 |
+
$request,
|
243 |
+
$response
|
244 |
+
);
|
245 |
+
}
|
246 |
+
|
247 |
+
return $location;
|
248 |
+
}
|
249 |
+
}
|
vendor/guzzlehttp/guzzle/src/RequestOptions.php
CHANGED
@@ -1,255 +1,263 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp;
|
3 |
-
|
4 |
-
/**
|
5 |
-
* This class contains a list of built-in Guzzle request options.
|
6 |
-
*
|
7 |
-
* More documentation for each option can be found at http://guzzlephp.org/.
|
8 |
-
*
|
9 |
-
* @link http://docs.guzzlephp.org/en/v6/request-options.html
|
10 |
-
*/
|
11 |
-
final class RequestOptions
|
12 |
-
{
|
13 |
-
/**
|
14 |
-
* allow_redirects: (bool|array) Controls redirect behavior. Pass false
|
15 |
-
* to disable redirects, pass true to enable redirects, pass an
|
16 |
-
* associative to provide custom redirect settings. Defaults to "false".
|
17 |
-
* This option only works if your handler has the RedirectMiddleware. When
|
18 |
-
* passing an associative array, you can provide the following key value
|
19 |
-
* pairs:
|
20 |
-
*
|
21 |
-
* - max: (int, default=5) maximum number of allowed redirects.
|
22 |
-
* - strict: (bool, default=false) Set to true to use strict redirects
|
23 |
-
* meaning redirect POST requests with POST requests vs. doing what most
|
24 |
-
* browsers do which is redirect POST requests with GET requests
|
25 |
-
* - referer: (bool, default=false) Set to true to enable the Referer
|
26 |
-
* header.
|
27 |
-
* - protocols: (array, default=['http', 'https']) Allowed redirect
|
28 |
-
* protocols.
|
29 |
-
* - on_redirect: (callable) PHP callable that is invoked when a redirect
|
30 |
-
* is encountered. The callable is invoked with the request, the redirect
|
31 |
-
* response that was received, and the effective URI. Any return value
|
32 |
-
* from the on_redirect function is ignored.
|
33 |
-
*/
|
34 |
-
const ALLOW_REDIRECTS = 'allow_redirects';
|
35 |
-
|
36 |
-
/**
|
37 |
-
* auth: (array) Pass an array of HTTP authentication parameters to use
|
38 |
-
* with the request. The array must contain the username in index [0],
|
39 |
-
* the password in index [1], and you can optionally provide a built-in
|
40 |
-
* authentication type in index [2]. Pass null to disable authentication
|
41 |
-
* for a request.
|
42 |
-
*/
|
43 |
-
const AUTH = 'auth';
|
44 |
-
|
45 |
-
/**
|
46 |
-
* body: (resource|string|null|int|float|StreamInterface|callable|\Iterator)
|
47 |
-
* Body to send in the request.
|
48 |
-
*/
|
49 |
-
const BODY = 'body';
|
50 |
-
|
51 |
-
/**
|
52 |
-
* cert: (string|array) Set to a string to specify the path to a file
|
53 |
-
* containing a PEM formatted SSL client side certificate. If a password
|
54 |
-
* is required, then set cert to an array containing the path to the PEM
|
55 |
-
* file in the first array element followed by the certificate password
|
56 |
-
* in the second array element.
|
57 |
-
*/
|
58 |
-
const CERT = 'cert';
|
59 |
-
|
60 |
-
/**
|
61 |
-
* cookies: (bool|GuzzleHttp\Cookie\CookieJarInterface, default=false)
|
62 |
-
* Specifies whether or not cookies are used in a request or what cookie
|
63 |
-
* jar to use or what cookies to send. This option only works if your
|
64 |
-
* handler has the `cookie` middleware. Valid values are `false` and
|
65 |
-
* an instance of {@see GuzzleHttp\Cookie\CookieJarInterface}.
|
66 |
-
*/
|
67 |
-
const COOKIES = 'cookies';
|
68 |
-
|
69 |
-
/**
|
70 |
-
* connect_timeout: (float, default=0) Float describing the number of
|
71 |
-
* seconds to wait while trying to connect to a server. Use 0 to wait
|
72 |
-
* indefinitely (the default behavior).
|
73 |
-
*/
|
74 |
-
const CONNECT_TIMEOUT = 'connect_timeout';
|
75 |
-
|
76 |
-
/**
|
77 |
-
* debug: (bool|resource) Set to true or set to a PHP stream returned by
|
78 |
-
* fopen() enable debug output with the HTTP handler used to send a
|
79 |
-
* request.
|
80 |
-
*/
|
81 |
-
const DEBUG = 'debug';
|
82 |
-
|
83 |
-
/**
|
84 |
-
* decode_content: (bool, default=true) Specify whether or not
|
85 |
-
* Content-Encoding responses (gzip, deflate, etc.) are automatically
|
86 |
-
* decoded.
|
87 |
-
*/
|
88 |
-
const DECODE_CONTENT = 'decode_content';
|
89 |
-
|
90 |
-
/**
|
91 |
-
* delay: (int) The amount of time to delay before sending in milliseconds.
|
92 |
-
*/
|
93 |
-
const DELAY = 'delay';
|
94 |
-
|
95 |
-
/**
|
96 |
-
* expect: (bool|integer) Controls the behavior of the
|
97 |
-
* "Expect: 100-Continue" header.
|
98 |
-
*
|
99 |
-
* Set to `true` to enable the "Expect: 100-Continue" header for all
|
100 |
-
* requests that sends a body. Set to `false` to disable the
|
101 |
-
* "Expect: 100-Continue" header for all requests. Set to a number so that
|
102 |
-
* the size of the payload must be greater than the number in order to send
|
103 |
-
* the Expect header. Setting to a number will send the Expect header for
|
104 |
-
* all requests in which the size of the payload cannot be determined or
|
105 |
-
* where the body is not rewindable.
|
106 |
-
*
|
107 |
-
* By default, Guzzle will add the "Expect: 100-Continue" header when the
|
108 |
-
* size of the body of a request is greater than 1 MB and a request is
|
109 |
-
* using HTTP/1.1.
|
110 |
-
*/
|
111 |
-
const EXPECT = 'expect';
|
112 |
-
|
113 |
-
/**
|
114 |
-
* form_params: (array) Associative array of form field names to values
|
115 |
-
* where each value is a string or array of strings. Sets the Content-Type
|
116 |
-
* header to application/x-www-form-urlencoded when no Content-Type header
|
117 |
-
* is already present.
|
118 |
-
*/
|
119 |
-
const FORM_PARAMS = 'form_params';
|
120 |
-
|
121 |
-
/**
|
122 |
-
* headers: (array) Associative array of HTTP headers. Each value MUST be
|
123 |
-
* a string or array of strings.
|
124 |
-
*/
|
125 |
-
const HEADERS = 'headers';
|
126 |
-
|
127 |
-
/**
|
128 |
-
* http_errors: (bool, default=true) Set to false to disable exceptions
|
129 |
-
* when a non- successful HTTP response is received. By default,
|
130 |
-
* exceptions will be thrown for 4xx and 5xx responses. This option only
|
131 |
-
* works if your handler has the `httpErrors` middleware.
|
132 |
-
*/
|
133 |
-
const HTTP_ERRORS = 'http_errors';
|
134 |
-
|
135 |
-
/**
|
136 |
-
*
|
137 |
-
*
|
138 |
-
*
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
*
|
145 |
-
*
|
146 |
-
*
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
*
|
155 |
-
*
|
156 |
-
*
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
*
|
163 |
-
*
|
164 |
-
*
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
*
|
173 |
-
*
|
174 |
-
*
|
175 |
-
*
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
*
|
182 |
-
*
|
183 |
-
*
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
*
|
190 |
-
*
|
191 |
-
*
|
192 |
-
*/
|
193 |
-
const
|
194 |
-
|
195 |
-
/**
|
196 |
-
*
|
197 |
-
*
|
198 |
-
* string
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
*
|
205 |
-
*
|
206 |
-
*
|
207 |
-
*/
|
208 |
-
const
|
209 |
-
|
210 |
-
/**
|
211 |
-
*
|
212 |
-
*
|
213 |
-
*
|
214 |
-
*
|
215 |
-
*/
|
216 |
-
const
|
217 |
-
|
218 |
-
/**
|
219 |
-
*
|
220 |
-
*
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
*
|
228 |
-
*
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
*
|
236 |
-
*
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* This class contains a list of built-in Guzzle request options.
|
6 |
+
*
|
7 |
+
* More documentation for each option can be found at http://guzzlephp.org/.
|
8 |
+
*
|
9 |
+
* @link http://docs.guzzlephp.org/en/v6/request-options.html
|
10 |
+
*/
|
11 |
+
final class RequestOptions
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* allow_redirects: (bool|array) Controls redirect behavior. Pass false
|
15 |
+
* to disable redirects, pass true to enable redirects, pass an
|
16 |
+
* associative to provide custom redirect settings. Defaults to "false".
|
17 |
+
* This option only works if your handler has the RedirectMiddleware. When
|
18 |
+
* passing an associative array, you can provide the following key value
|
19 |
+
* pairs:
|
20 |
+
*
|
21 |
+
* - max: (int, default=5) maximum number of allowed redirects.
|
22 |
+
* - strict: (bool, default=false) Set to true to use strict redirects
|
23 |
+
* meaning redirect POST requests with POST requests vs. doing what most
|
24 |
+
* browsers do which is redirect POST requests with GET requests
|
25 |
+
* - referer: (bool, default=false) Set to true to enable the Referer
|
26 |
+
* header.
|
27 |
+
* - protocols: (array, default=['http', 'https']) Allowed redirect
|
28 |
+
* protocols.
|
29 |
+
* - on_redirect: (callable) PHP callable that is invoked when a redirect
|
30 |
+
* is encountered. The callable is invoked with the request, the redirect
|
31 |
+
* response that was received, and the effective URI. Any return value
|
32 |
+
* from the on_redirect function is ignored.
|
33 |
+
*/
|
34 |
+
const ALLOW_REDIRECTS = 'allow_redirects';
|
35 |
+
|
36 |
+
/**
|
37 |
+
* auth: (array) Pass an array of HTTP authentication parameters to use
|
38 |
+
* with the request. The array must contain the username in index [0],
|
39 |
+
* the password in index [1], and you can optionally provide a built-in
|
40 |
+
* authentication type in index [2]. Pass null to disable authentication
|
41 |
+
* for a request.
|
42 |
+
*/
|
43 |
+
const AUTH = 'auth';
|
44 |
+
|
45 |
+
/**
|
46 |
+
* body: (resource|string|null|int|float|StreamInterface|callable|\Iterator)
|
47 |
+
* Body to send in the request.
|
48 |
+
*/
|
49 |
+
const BODY = 'body';
|
50 |
+
|
51 |
+
/**
|
52 |
+
* cert: (string|array) Set to a string to specify the path to a file
|
53 |
+
* containing a PEM formatted SSL client side certificate. If a password
|
54 |
+
* is required, then set cert to an array containing the path to the PEM
|
55 |
+
* file in the first array element followed by the certificate password
|
56 |
+
* in the second array element.
|
57 |
+
*/
|
58 |
+
const CERT = 'cert';
|
59 |
+
|
60 |
+
/**
|
61 |
+
* cookies: (bool|GuzzleHttp\Cookie\CookieJarInterface, default=false)
|
62 |
+
* Specifies whether or not cookies are used in a request or what cookie
|
63 |
+
* jar to use or what cookies to send. This option only works if your
|
64 |
+
* handler has the `cookie` middleware. Valid values are `false` and
|
65 |
+
* an instance of {@see GuzzleHttp\Cookie\CookieJarInterface}.
|
66 |
+
*/
|
67 |
+
const COOKIES = 'cookies';
|
68 |
+
|
69 |
+
/**
|
70 |
+
* connect_timeout: (float, default=0) Float describing the number of
|
71 |
+
* seconds to wait while trying to connect to a server. Use 0 to wait
|
72 |
+
* indefinitely (the default behavior).
|
73 |
+
*/
|
74 |
+
const CONNECT_TIMEOUT = 'connect_timeout';
|
75 |
+
|
76 |
+
/**
|
77 |
+
* debug: (bool|resource) Set to true or set to a PHP stream returned by
|
78 |
+
* fopen() enable debug output with the HTTP handler used to send a
|
79 |
+
* request.
|
80 |
+
*/
|
81 |
+
const DEBUG = 'debug';
|
82 |
+
|
83 |
+
/**
|
84 |
+
* decode_content: (bool, default=true) Specify whether or not
|
85 |
+
* Content-Encoding responses (gzip, deflate, etc.) are automatically
|
86 |
+
* decoded.
|
87 |
+
*/
|
88 |
+
const DECODE_CONTENT = 'decode_content';
|
89 |
+
|
90 |
+
/**
|
91 |
+
* delay: (int) The amount of time to delay before sending in milliseconds.
|
92 |
+
*/
|
93 |
+
const DELAY = 'delay';
|
94 |
+
|
95 |
+
/**
|
96 |
+
* expect: (bool|integer) Controls the behavior of the
|
97 |
+
* "Expect: 100-Continue" header.
|
98 |
+
*
|
99 |
+
* Set to `true` to enable the "Expect: 100-Continue" header for all
|
100 |
+
* requests that sends a body. Set to `false` to disable the
|
101 |
+
* "Expect: 100-Continue" header for all requests. Set to a number so that
|
102 |
+
* the size of the payload must be greater than the number in order to send
|
103 |
+
* the Expect header. Setting to a number will send the Expect header for
|
104 |
+
* all requests in which the size of the payload cannot be determined or
|
105 |
+
* where the body is not rewindable.
|
106 |
+
*
|
107 |
+
* By default, Guzzle will add the "Expect: 100-Continue" header when the
|
108 |
+
* size of the body of a request is greater than 1 MB and a request is
|
109 |
+
* using HTTP/1.1.
|
110 |
+
*/
|
111 |
+
const EXPECT = 'expect';
|
112 |
+
|
113 |
+
/**
|
114 |
+
* form_params: (array) Associative array of form field names to values
|
115 |
+
* where each value is a string or array of strings. Sets the Content-Type
|
116 |
+
* header to application/x-www-form-urlencoded when no Content-Type header
|
117 |
+
* is already present.
|
118 |
+
*/
|
119 |
+
const FORM_PARAMS = 'form_params';
|
120 |
+
|
121 |
+
/**
|
122 |
+
* headers: (array) Associative array of HTTP headers. Each value MUST be
|
123 |
+
* a string or array of strings.
|
124 |
+
*/
|
125 |
+
const HEADERS = 'headers';
|
126 |
+
|
127 |
+
/**
|
128 |
+
* http_errors: (bool, default=true) Set to false to disable exceptions
|
129 |
+
* when a non- successful HTTP response is received. By default,
|
130 |
+
* exceptions will be thrown for 4xx and 5xx responses. This option only
|
131 |
+
* works if your handler has the `httpErrors` middleware.
|
132 |
+
*/
|
133 |
+
const HTTP_ERRORS = 'http_errors';
|
134 |
+
|
135 |
+
/**
|
136 |
+
* idn: (bool|int, default=true) A combination of IDNA_* constants for
|
137 |
+
* idn_to_ascii() PHP's function (see "options" parameter). Set to false to
|
138 |
+
* disable IDN support completely, or to true to use the default
|
139 |
+
* configuration (IDNA_DEFAULT constant).
|
140 |
+
*/
|
141 |
+
const IDN_CONVERSION = 'idn_conversion';
|
142 |
+
|
143 |
+
/**
|
144 |
+
* json: (mixed) Adds JSON data to a request. The provided value is JSON
|
145 |
+
* encoded and a Content-Type header of application/json will be added to
|
146 |
+
* the request if no Content-Type header is already present.
|
147 |
+
*/
|
148 |
+
const JSON = 'json';
|
149 |
+
|
150 |
+
/**
|
151 |
+
* multipart: (array) Array of associative arrays, each containing a
|
152 |
+
* required "name" key mapping to the form field, name, a required
|
153 |
+
* "contents" key mapping to a StreamInterface|resource|string, an
|
154 |
+
* optional "headers" associative array of custom headers, and an
|
155 |
+
* optional "filename" key mapping to a string to send as the filename in
|
156 |
+
* the part. If no "filename" key is present, then no "filename" attribute
|
157 |
+
* will be added to the part.
|
158 |
+
*/
|
159 |
+
const MULTIPART = 'multipart';
|
160 |
+
|
161 |
+
/**
|
162 |
+
* on_headers: (callable) A callable that is invoked when the HTTP headers
|
163 |
+
* of the response have been received but the body has not yet begun to
|
164 |
+
* download.
|
165 |
+
*/
|
166 |
+
const ON_HEADERS = 'on_headers';
|
167 |
+
|
168 |
+
/**
|
169 |
+
* on_stats: (callable) allows you to get access to transfer statistics of
|
170 |
+
* a request and access the lower level transfer details of the handler
|
171 |
+
* associated with your client. ``on_stats`` is a callable that is invoked
|
172 |
+
* when a handler has finished sending a request. The callback is invoked
|
173 |
+
* with transfer statistics about the request, the response received, or
|
174 |
+
* the error encountered. Included in the data is the total amount of time
|
175 |
+
* taken to send the request.
|
176 |
+
*/
|
177 |
+
const ON_STATS = 'on_stats';
|
178 |
+
|
179 |
+
/**
|
180 |
+
* progress: (callable) Defines a function to invoke when transfer
|
181 |
+
* progress is made. The function accepts the following positional
|
182 |
+
* arguments: the total number of bytes expected to be downloaded, the
|
183 |
+
* number of bytes downloaded so far, the number of bytes expected to be
|
184 |
+
* uploaded, the number of bytes uploaded so far.
|
185 |
+
*/
|
186 |
+
const PROGRESS = 'progress';
|
187 |
+
|
188 |
+
/**
|
189 |
+
* proxy: (string|array) Pass a string to specify an HTTP proxy, or an
|
190 |
+
* array to specify different proxies for different protocols (where the
|
191 |
+
* key is the protocol and the value is a proxy string).
|
192 |
+
*/
|
193 |
+
const PROXY = 'proxy';
|
194 |
+
|
195 |
+
/**
|
196 |
+
* query: (array|string) Associative array of query string values to add
|
197 |
+
* to the request. This option uses PHP's http_build_query() to create
|
198 |
+
* the string representation. Pass a string value if you need more
|
199 |
+
* control than what this method provides
|
200 |
+
*/
|
201 |
+
const QUERY = 'query';
|
202 |
+
|
203 |
+
/**
|
204 |
+
* sink: (resource|string|StreamInterface) Where the data of the
|
205 |
+
* response is written to. Defaults to a PHP temp stream. Providing a
|
206 |
+
* string will write data to a file by the given name.
|
207 |
+
*/
|
208 |
+
const SINK = 'sink';
|
209 |
+
|
210 |
+
/**
|
211 |
+
* synchronous: (bool) Set to true to inform HTTP handlers that you intend
|
212 |
+
* on waiting on the response. This can be useful for optimizations. Note
|
213 |
+
* that a promise is still returned if you are using one of the async
|
214 |
+
* client methods.
|
215 |
+
*/
|
216 |
+
const SYNCHRONOUS = 'synchronous';
|
217 |
+
|
218 |
+
/**
|
219 |
+
* ssl_key: (array|string) Specify the path to a file containing a private
|
220 |
+
* SSL key in PEM format. If a password is required, then set to an array
|
221 |
+
* containing the path to the SSL key in the first array element followed
|
222 |
+
* by the password required for the certificate in the second element.
|
223 |
+
*/
|
224 |
+
const SSL_KEY = 'ssl_key';
|
225 |
+
|
226 |
+
/**
|
227 |
+
* stream: Set to true to attempt to stream a response rather than
|
228 |
+
* download it all up-front.
|
229 |
+
*/
|
230 |
+
const STREAM = 'stream';
|
231 |
+
|
232 |
+
/**
|
233 |
+
* verify: (bool|string, default=true) Describes the SSL certificate
|
234 |
+
* verification behavior of a request. Set to true to enable SSL
|
235 |
+
* certificate verification using the system CA bundle when available
|
236 |
+
* (the default). Set to false to disable certificate verification (this
|
237 |
+
* is insecure!). Set to a string to provide the path to a CA bundle on
|
238 |
+
* disk to enable verification using a custom certificate.
|
239 |
+
*/
|
240 |
+
const VERIFY = 'verify';
|
241 |
+
|
242 |
+
/**
|
243 |
+
* timeout: (float, default=0) Float describing the timeout of the
|
244 |
+
* request in seconds. Use 0 to wait indefinitely (the default behavior).
|
245 |
+
*/
|
246 |
+
const TIMEOUT = 'timeout';
|
247 |
+
|
248 |
+
/**
|
249 |
+
* read_timeout: (float, default=default_socket_timeout ini setting) Float describing
|
250 |
+
* the body read timeout, for stream requests.
|
251 |
+
*/
|
252 |
+
const READ_TIMEOUT = 'read_timeout';
|
253 |
+
|
254 |
+
/**
|
255 |
+
* version: (float) Specifies the HTTP protocol version to attempt to use.
|
256 |
+
*/
|
257 |
+
const VERSION = 'version';
|
258 |
+
|
259 |
+
/**
|
260 |
+
* force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol
|
261 |
+
*/
|
262 |
+
const FORCE_IP_RESOLVE = 'force_ip_resolve';
|
263 |
+
}
|
vendor/guzzlehttp/guzzle/src/RetryMiddleware.php
CHANGED
@@ -1,115 +1,128 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp;
|
3 |
-
|
4 |
-
use GuzzleHttp\Promise\PromiseInterface;
|
5 |
-
use GuzzleHttp\Promise\RejectedPromise;
|
6 |
-
use GuzzleHttp\Psr7;
|
7 |
-
use Psr\Http\Message\RequestInterface;
|
8 |
-
use Psr\Http\Message\ResponseInterface;
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Middleware that retries requests based on the boolean result of
|
12 |
-
* invoking the provided "decider" function.
|
13 |
-
*/
|
14 |
-
class RetryMiddleware
|
15 |
-
{
|
16 |
-
/** @var callable */
|
17 |
-
private $nextHandler;
|
18 |
-
|
19 |
-
/** @var callable */
|
20 |
-
private $decider;
|
21 |
-
|
22 |
-
/** @var callable */
|
23 |
-
private $delay;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @param callable $decider Function that accepts the number of retries,
|
27 |
-
* a request, [response], and [exception] and
|
28 |
-
* returns true if the request is to be
|
29 |
-
* retried.
|
30 |
-
* @param callable $nextHandler Next handler to invoke.
|
31 |
-
* @param callable $delay Function that accepts the number of retries
|
32 |
-
* and [response] and returns the number of
|
33 |
-
* milliseconds to delay.
|
34 |
-
*/
|
35 |
-
public function __construct(
|
36 |
-
callable $decider,
|
37 |
-
callable $nextHandler,
|
38 |
-
callable $delay = null
|
39 |
-
) {
|
40 |
-
$this->decider = $decider;
|
41 |
-
$this->nextHandler = $nextHandler;
|
42 |
-
$this->delay = $delay ?: __CLASS__ . '::exponentialDelay';
|
43 |
-
}
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Default exponential backoff delay function.
|
47 |
-
*
|
48 |
-
* @param int $retries
|
49 |
-
*
|
50 |
-
* @return int
|
51 |
-
*/
|
52 |
-
public static function exponentialDelay($retries)
|
53 |
-
{
|
54 |
-
return (int) pow(2, $retries - 1);
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* @param RequestInterface $request
|
59 |
-
* @param array $options
|
60 |
-
*
|
61 |
-
* @return PromiseInterface
|
62 |
-
*/
|
63 |
-
public function __invoke(RequestInterface $request, array $options)
|
64 |
-
{
|
65 |
-
if (!isset($options['retries'])) {
|
66 |
-
$options['retries'] = 0;
|
67 |
-
}
|
68 |
-
|
69 |
-
$fn = $this->nextHandler;
|
70 |
-
return $fn($request, $options)
|
71 |
-
->then(
|
72 |
-
$this->onFulfilled($request, $options),
|
73 |
-
$this->onRejected($request, $options)
|
74 |
-
);
|
75 |
-
}
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use GuzzleHttp\Promise\PromiseInterface;
|
5 |
+
use GuzzleHttp\Promise\RejectedPromise;
|
6 |
+
use GuzzleHttp\Psr7;
|
7 |
+
use Psr\Http\Message\RequestInterface;
|
8 |
+
use Psr\Http\Message\ResponseInterface;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Middleware that retries requests based on the boolean result of
|
12 |
+
* invoking the provided "decider" function.
|
13 |
+
*/
|
14 |
+
class RetryMiddleware
|
15 |
+
{
|
16 |
+
/** @var callable */
|
17 |
+
private $nextHandler;
|
18 |
+
|
19 |
+
/** @var callable */
|
20 |
+
private $decider;
|
21 |
+
|
22 |
+
/** @var callable */
|
23 |
+
private $delay;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @param callable $decider Function that accepts the number of retries,
|
27 |
+
* a request, [response], and [exception] and
|
28 |
+
* returns true if the request is to be
|
29 |
+
* retried.
|
30 |
+
* @param callable $nextHandler Next handler to invoke.
|
31 |
+
* @param callable $delay Function that accepts the number of retries
|
32 |
+
* and [response] and returns the number of
|
33 |
+
* milliseconds to delay.
|
34 |
+
*/
|
35 |
+
public function __construct(
|
36 |
+
callable $decider,
|
37 |
+
callable $nextHandler,
|
38 |
+
callable $delay = null
|
39 |
+
) {
|
40 |
+
$this->decider = $decider;
|
41 |
+
$this->nextHandler = $nextHandler;
|
42 |
+
$this->delay = $delay ?: __CLASS__ . '::exponentialDelay';
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Default exponential backoff delay function.
|
47 |
+
*
|
48 |
+
* @param int $retries
|
49 |
+
*
|
50 |
+
* @return int milliseconds.
|
51 |
+
*/
|
52 |
+
public static function exponentialDelay($retries)
|
53 |
+
{
|
54 |
+
return (int) pow(2, $retries - 1) * 1000;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @param RequestInterface $request
|
59 |
+
* @param array $options
|
60 |
+
*
|
61 |
+
* @return PromiseInterface
|
62 |
+
*/
|
63 |
+
public function __invoke(RequestInterface $request, array $options)
|
64 |
+
{
|
65 |
+
if (!isset($options['retries'])) {
|
66 |
+
$options['retries'] = 0;
|
67 |
+
}
|
68 |
+
|
69 |
+
$fn = $this->nextHandler;
|
70 |
+
return $fn($request, $options)
|
71 |
+
->then(
|
72 |
+
$this->onFulfilled($request, $options),
|
73 |
+
$this->onRejected($request, $options)
|
74 |
+
);
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Execute fulfilled closure
|
79 |
+
*
|
80 |
+
* @return mixed
|
81 |
+
*/
|
82 |
+
private function onFulfilled(RequestInterface $req, array $options)
|
83 |
+
{
|
84 |
+
return function ($value) use ($req, $options) {
|
85 |
+
if (!call_user_func(
|
86 |
+
$this->decider,
|
87 |
+
$options['retries'],
|
88 |
+
$req,
|
89 |
+
$value,
|
90 |
+
null
|
91 |
+
)) {
|
92 |
+
return $value;
|
93 |
+
}
|
94 |
+
return $this->doRetry($req, $options, $value);
|
95 |
+
};
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Execute rejected closure
|
100 |
+
*
|
101 |
+
* @return callable
|
102 |
+
*/
|
103 |
+
private function onRejected(RequestInterface $req, array $options)
|
104 |
+
{
|
105 |
+
return function ($reason) use ($req, $options) {
|
106 |
+
if (!call_user_func(
|
107 |
+
$this->decider,
|
108 |
+
$options['retries'],
|
109 |
+
$req,
|
110 |
+
null,
|
111 |
+
$reason
|
112 |
+
)) {
|
113 |
+
return \GuzzleHttp\Promise\rejection_for($reason);
|
114 |
+
}
|
115 |
+
return $this->doRetry($req, $options);
|
116 |
+
};
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* @return self
|
121 |
+
*/
|
122 |
+
private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null)
|
123 |
+
{
|
124 |
+
$options['delay'] = call_user_func($this->delay, ++$options['retries'], $response);
|
125 |
+
|
126 |
+
return $this($request, $options);
|
127 |
+
}
|
128 |
+
}
|
vendor/guzzlehttp/guzzle/src/TransferStats.php
CHANGED
@@ -1,126 +1,126 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp;
|
3 |
-
|
4 |
-
use Psr\Http\Message\RequestInterface;
|
5 |
-
use Psr\Http\Message\ResponseInterface;
|
6 |
-
use Psr\Http\Message\UriInterface;
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Represents data at the point after it was transferred either successfully
|
10 |
-
* or after a network error.
|
11 |
-
*/
|
12 |
-
final class TransferStats
|
13 |
-
{
|
14 |
-
private $request;
|
15 |
-
private $response;
|
16 |
-
private $transferTime;
|
17 |
-
private $handlerStats;
|
18 |
-
private $handlerErrorData;
|
19 |
-
|
20 |
-
/**
|
21 |
-
* @param RequestInterface
|
22 |
-
* @param ResponseInterface $response Response received (if any)
|
23 |
-
* @param float|null
|
24 |
-
* @param mixed
|
25 |
-
* @param array
|
26 |
-
*/
|
27 |
-
public function __construct(
|
28 |
-
RequestInterface $request,
|
29 |
-
ResponseInterface $response = null,
|
30 |
-
$transferTime = null,
|
31 |
-
$handlerErrorData = null,
|
32 |
-
$handlerStats = []
|
33 |
-
) {
|
34 |
-
$this->request = $request;
|
35 |
-
$this->response = $response;
|
36 |
-
$this->transferTime = $transferTime;
|
37 |
-
$this->handlerErrorData = $handlerErrorData;
|
38 |
-
$this->handlerStats = $handlerStats;
|
39 |
-
}
|
40 |
-
|
41 |
-
/**
|
42 |
-
* @return RequestInterface
|
43 |
-
*/
|
44 |
-
public function getRequest()
|
45 |
-
{
|
46 |
-
return $this->request;
|
47 |
-
}
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Returns the response that was received (if any).
|
51 |
-
*
|
52 |
-
* @return ResponseInterface|null
|
53 |
-
*/
|
54 |
-
public function getResponse()
|
55 |
-
{
|
56 |
-
return $this->response;
|
57 |
-
}
|
58 |
-
|
59 |
-
/**
|
60 |
-
* Returns true if a response was received.
|
61 |
-
*
|
62 |
-
* @return bool
|
63 |
-
*/
|
64 |
-
public function hasResponse()
|
65 |
-
{
|
66 |
-
return $this->response !== null;
|
67 |
-
}
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Gets handler specific error data.
|
71 |
-
*
|
72 |
-
* This might be an exception, a integer representing an error code, or
|
73 |
-
* anything else. Relying on this value assumes that you know what handler
|
74 |
-
* you are using.
|
75 |
-
*
|
76 |
-
* @return mixed
|
77 |
-
*/
|
78 |
-
public function getHandlerErrorData()
|
79 |
-
{
|
80 |
-
return $this->handlerErrorData;
|
81 |
-
}
|
82 |
-
|
83 |
-
/**
|
84 |
-
* Get the effective URI the request was sent to.
|
85 |
-
*
|
86 |
-
* @return UriInterface
|
87 |
-
*/
|
88 |
-
public function getEffectiveUri()
|
89 |
-
{
|
90 |
-
return $this->request->getUri();
|
91 |
-
}
|
92 |
-
|
93 |
-
/**
|
94 |
-
* Get the estimated time the request was being transferred by the handler.
|
95 |
-
*
|
96 |
-
* @return float Time in seconds.
|
97 |
-
*/
|
98 |
-
public function getTransferTime()
|
99 |
-
{
|
100 |
-
return $this->transferTime;
|
101 |
-
}
|
102 |
-
|
103 |
-
/**
|
104 |
-
* Gets an array of all of the handler specific transfer data.
|
105 |
-
*
|
106 |
-
* @return array
|
107 |
-
*/
|
108 |
-
public function getHandlerStats()
|
109 |
-
{
|
110 |
-
return $this->handlerStats;
|
111 |
-
}
|
112 |
-
|
113 |
-
/**
|
114 |
-
* Get a specific handler statistic from the handler by name.
|
115 |
-
*
|
116 |
-
* @param string $stat Handler specific transfer stat to retrieve.
|
117 |
-
*
|
118 |
-
* @return mixed|null
|
119 |
-
*/
|
120 |
-
public function getHandlerStat($stat)
|
121 |
-
{
|
122 |
-
return isset($this->handlerStats[$stat])
|
123 |
-
? $this->handlerStats[$stat]
|
124 |
-
: null;
|
125 |
-
}
|
126 |
-
}
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use Psr\Http\Message\RequestInterface;
|
5 |
+
use Psr\Http\Message\ResponseInterface;
|
6 |
+
use Psr\Http\Message\UriInterface;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Represents data at the point after it was transferred either successfully
|
10 |
+
* or after a network error.
|
11 |
+
*/
|
12 |
+
final class TransferStats
|
13 |
+
{
|
14 |
+
private $request;
|
15 |
+
private $response;
|
16 |
+
private $transferTime;
|
17 |
+
private $handlerStats;
|
18 |
+
private $handlerErrorData;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @param RequestInterface $request Request that was sent.
|
22 |
+
* @param ResponseInterface|null $response Response received (if any)
|
23 |
+
* @param float|null $transferTime Total handler transfer time.
|
24 |
+
* @param mixed $handlerErrorData Handler error data.
|
25 |
+
* @param array $handlerStats Handler specific stats.
|
26 |
+
*/
|
27 |
+
public function __construct(
|
28 |
+
RequestInterface $request,
|
29 |
+
ResponseInterface $response = null,
|
30 |
+
$transferTime = null,
|
31 |
+
$handlerErrorData = null,
|
32 |
+
$handlerStats = []
|
33 |
+
) {
|
34 |
+
$this->request = $request;
|
35 |
+
$this->response = $response;
|
36 |
+
$this->transferTime = $transferTime;
|
37 |
+
$this->handlerErrorData = $handlerErrorData;
|
38 |
+
$this->handlerStats = $handlerStats;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* @return RequestInterface
|
43 |
+
*/
|
44 |
+
public function getRequest()
|
45 |
+
{
|
46 |
+
return $this->request;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Returns the response that was received (if any).
|
51 |
+
*
|
52 |
+
* @return ResponseInterface|null
|
53 |
+
*/
|
54 |
+
public function getResponse()
|
55 |
+
{
|
56 |
+
return $this->response;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Returns true if a response was received.
|
61 |
+
*
|
62 |
+
* @return bool
|
63 |
+
*/
|
64 |
+
public function hasResponse()
|
65 |
+
{
|
66 |
+
return $this->response !== null;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Gets handler specific error data.
|
71 |
+
*
|
72 |
+
* This might be an exception, a integer representing an error code, or
|
73 |
+
* anything else. Relying on this value assumes that you know what handler
|
74 |
+
* you are using.
|
75 |
+
*
|
76 |
+
* @return mixed
|
77 |
+
*/
|
78 |
+
public function getHandlerErrorData()
|
79 |
+
{
|
80 |
+
return $this->handlerErrorData;
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Get the effective URI the request was sent to.
|
85 |
+
*
|
86 |
+
* @return UriInterface
|
87 |
+
*/
|
88 |
+
public function getEffectiveUri()
|
89 |
+
{
|
90 |
+
return $this->request->getUri();
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Get the estimated time the request was being transferred by the handler.
|
95 |
+
*
|
96 |
+
* @return float|null Time in seconds.
|
97 |
+
*/
|
98 |
+
public function getTransferTime()
|
99 |
+
{
|
100 |
+
return $this->transferTime;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Gets an array of all of the handler specific transfer data.
|
105 |
+
*
|
106 |
+
* @return array
|
107 |
+
*/
|
108 |
+
public function getHandlerStats()
|
109 |
+
{
|
110 |
+
return $this->handlerStats;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Get a specific handler statistic from the handler by name.
|
115 |
+
*
|
116 |
+
* @param string $stat Handler specific transfer stat to retrieve.
|
117 |
+
*
|
118 |
+
* @return mixed|null
|
119 |
+
*/
|
120 |
+
public function getHandlerStat($stat)
|
121 |
+
{
|
122 |
+
return isset($this->handlerStats[$stat])
|
123 |
+
? $this->handlerStats[$stat]
|
124 |
+
: null;
|
125 |
+
}
|
126 |
+
}
|
vendor/guzzlehttp/guzzle/src/functions.php
CHANGED
@@ -1,346 +1,346 @@
|
|
1 |
-
<?php
|
2 |
-
namespace GuzzleHttp;
|
3 |
-
|
4 |
-
use GuzzleHttp\Handler\CurlHandler;
|
5 |
-
use GuzzleHttp\Handler\CurlMultiHandler;
|
6 |
-
use GuzzleHttp\Handler\Proxy;
|
7 |
-
use GuzzleHttp\Handler\StreamHandler;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Expands a URI template
|
11 |
-
*
|
12 |
-
* @param string $template URI template
|
13 |
-
* @param array $variables Template variables
|
14 |
-
*
|
15 |
-
* @return string
|
16 |
-
*/
|
17 |
-
function uri_template($template, array $variables)
|
18 |
-
{
|
19 |
-
if (extension_loaded('uri_template')) {
|
20 |
-
// @codeCoverageIgnoreStart
|
21 |
-
return \uri_template($template, $variables);
|
22 |
-
// @codeCoverageIgnoreEnd
|
23 |
-
}
|
24 |
-
|
25 |
-
static $uriTemplate;
|
26 |
-
if (!$uriTemplate) {
|
27 |
-
$uriTemplate = new UriTemplate();
|
28 |
-
}
|
29 |
-
|
30 |
-
return $uriTemplate->expand($template, $variables);
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Debug function used to describe the provided value type and class.
|
35 |
-
*
|
36 |
-
* @param mixed $input
|
37 |
-
*
|
38 |
-
* @return string Returns a string containing the type of the variable and
|
39 |
-
* if a class is provided, the class name.
|
40 |
-
*/
|
41 |
-
function describe_type($input)
|
42 |
-
{
|
43 |
-
switch (gettype($input)) {
|
44 |
-
case 'object':
|
45 |
-
return 'object(' . get_class($input) . ')';
|
46 |
-
case 'array':
|
47 |
-
return 'array(' . count($input) . ')';
|
48 |
-
default:
|
49 |
-
ob_start();
|
50 |
-
var_dump($input);
|
51 |
-
// normalize float vs double
|
52 |
-
return str_replace('double(', 'float(', rtrim(ob_get_clean()));
|
53 |
-
}
|
54 |
-
}
|
55 |
-
|
56 |
-
/**
|
57 |
-
* Parses an array of header lines into an associative array of headers.
|
58 |
-
*
|
59 |
-
* @param
|
60 |
-
* format: "Name: Value"
|
61 |
-
* @return array
|
62 |
-
*/
|
63 |
-
function headers_from_lines($lines)
|
64 |
-
{
|
65 |
-
$headers = [];
|
66 |
-
|
67 |
-
foreach ($lines as $line) {
|
68 |
-
$parts = explode(':', $line, 2);
|
69 |
-
$headers[trim($parts[0])][] = isset($parts[1])
|
70 |
-
? trim($parts[1])
|
71 |
-
: null;
|
72 |
-
}
|
73 |
-
|
74 |
-
return $headers;
|
75 |
-
}
|
76 |
-
|
77 |
-
/**
|
78 |
-
* Returns a debug stream based on the provided variable.
|
79 |
-
*
|
80 |
-
* @param mixed $value Optional value
|
81 |
-
*
|
82 |
-
* @return resource
|
83 |
-
*/
|
84 |
-
function debug_resource($value = null)
|
85 |
-
{
|
86 |
-
if (is_resource($value)) {
|
87 |
-
return $value;
|
88 |
-
} elseif (defined('STDOUT')) {
|
89 |
-
return STDOUT;
|
90 |
-
}
|
91 |
-
|
92 |
-
return fopen('php://output', 'w');
|
93 |
-
}
|
94 |
-
|
95 |
-
/**
|
96 |
-
* Chooses and creates a default handler to use based on the environment.
|
97 |
-
*
|
98 |
-
* The returned handler is not wrapped by any default middlewares.
|
99 |
-
*
|
100 |
-
* @throws \RuntimeException if no viable Handler is available.
|
101 |
-
* @return callable Returns the best handler for the given system.
|
102 |
-
*/
|
103 |
-
function choose_handler()
|
104 |
-
{
|
105 |
-
$handler = null;
|
106 |
-
if (function_exists('curl_multi_exec') && function_exists('curl_exec')) {
|
107 |
-
$handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());
|
108 |
-
} elseif (function_exists('curl_exec')) {
|
109 |
-
$handler = new CurlHandler();
|
110 |
-
} elseif (function_exists('curl_multi_exec')) {
|
111 |
-
$handler = new CurlMultiHandler();
|
112 |
-
}
|
113 |
-
|
114 |
-
if (ini_get('allow_url_fopen')) {
|
115 |
-
$handler = $handler
|
116 |
-
? Proxy::wrapStreaming($handler, new StreamHandler())
|
117 |
-
: new StreamHandler();
|
118 |
-
} elseif (!$handler) {
|
119 |
-
throw new \RuntimeException('GuzzleHttp requires cURL, the '
|
120 |
-
. 'allow_url_fopen ini setting, or a custom HTTP handler.');
|
121 |
-
}
|
122 |
-
|
123 |
-
return $handler;
|
124 |
-
}
|
125 |
-
|
126 |
-
/**
|
127 |
-
* Get the default User-Agent string to use with Guzzle
|
128 |
-
*
|
129 |
-
* @return string
|
130 |
-
*/
|
131 |
-
function default_user_agent()
|
132 |
-
{
|
133 |
-
static $defaultAgent = '';
|
134 |
-
|
135 |
-
if (!$defaultAgent) {
|
136 |
-
$defaultAgent = 'GuzzleHttp/' . Client::VERSION;
|
137 |
-
if (extension_loaded('curl') && function_exists('curl_version')) {
|
138 |
-
$defaultAgent .= ' curl/' . \curl_version()['version'];
|
139 |
-
}
|
140 |
-
$defaultAgent .= ' PHP/' . PHP_VERSION;
|
141 |
-
}
|
142 |
-
|
143 |
-
return $defaultAgent;
|
144 |
-
}
|
145 |
-
|
146 |
-
/**
|
147 |
-
* Returns the default cacert bundle for the current system.
|
148 |
-
*
|
149 |
-
* First, the openssl.cafile and curl.cainfo php.ini settings are checked.
|
150 |
-
* If those settings are not configured, then the common locations for
|
151 |
-
* bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X
|
152 |
-
* and Windows are checked. If any of these file locations are found on
|
153 |
-
* disk, they will be utilized.
|
154 |
-
*
|
155 |
-
* Note: the result of this function is cached for subsequent calls.
|
156 |
-
*
|
157 |
-
* @return string
|
158 |
-
* @throws \RuntimeException if no bundle can be found.
|
159 |
-
*/
|
160 |
-
function default_ca_bundle()
|
161 |
-
{
|
162 |
-
static $cached = null;
|
163 |
-
static $cafiles = [
|
164 |
-
// Red Hat, CentOS, Fedora (provided by the ca-certificates package)
|
165 |
-
'/etc/pki/tls/certs/ca-bundle.crt',
|
166 |
-
// Ubuntu, Debian (provided by the ca-certificates package)
|
167 |
-
'/etc/ssl/certs/ca-certificates.crt',
|
168 |
-
// FreeBSD (provided by the ca_root_nss package)
|
169 |
-
'/usr/local/share/certs/ca-root-nss.crt',
|
170 |
-
// SLES 12 (provided by the ca-certificates package)
|
171 |
-
'/var/lib/ca-certificates/ca-bundle.pem',
|
172 |
-
// OS X provided by homebrew (using the default path)
|
173 |
-
'/usr/local/etc/openssl/cert.pem',
|
174 |
-
// Google app engine
|
175 |
-
'/etc/ca-certificates.crt',
|
176 |
-
// Windows?
|
177 |
-
'C:\\windows\\system32\\curl-ca-bundle.crt',
|
178 |
-
'C:\\windows\\curl-ca-bundle.crt',
|
179 |
-
];
|
180 |
-
|
181 |
-
if ($cached) {
|
182 |
-
return $cached;
|
183 |
-
}
|
184 |
-
|
185 |
-
if ($ca = ini_get('openssl.cafile')) {
|
186 |
-
return $cached = $ca;
|
187 |
-
}
|
188 |
-
|
189 |
-
if ($ca = ini_get('curl.cainfo')) {
|
190 |
-
return $cached = $ca;
|
191 |
-
}
|
192 |
-
|
193 |
-
foreach ($cafiles as $filename) {
|
194 |
-
if (file_exists($filename)) {
|
195 |
-
return $cached = $filename;
|
196 |
-
}
|
197 |
-
}
|
198 |
-
|
199 |
-
throw new \RuntimeException(
|
200 |
-
<<< EOT
|
201 |
-
No system CA bundle could be found in any of the the common system locations.
|
202 |
-
PHP versions earlier than 5.6 are not properly configured to use the system's
|
203 |
-
CA bundle by default. In order to verify peer certificates, you will need to
|
204 |
-
supply the path on disk to a certificate bundle to the 'verify' request
|
205 |
-
option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not
|
206 |
-
need a specific certificate bundle, then Mozilla provides a commonly used CA
|
207 |
-
bundle which can be downloaded here (provided by the maintainer of cURL):
|
208 |
-
https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once
|
209 |
-
you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP
|
210 |
-
ini setting to point to the path to the file, allowing you to omit the 'verify'
|
211 |
-
request option. See http://curl.haxx.se/docs/sslcerts.html for more
|
212 |
-
information.
|
213 |
-
EOT
|
214 |
-
);
|
215 |
-
}
|
216 |
-
|
217 |
-
/**
|
218 |
-
* Creates an associative array of lowercase header names to the actual
|
219 |
-
* header casing.
|
220 |
-
*
|
221 |
-
* @param array $headers
|
222 |
-
*
|
223 |
-
* @return array
|
224 |
-
*/
|
225 |
-
function normalize_header_keys(array $headers)
|
226 |
-
{
|
227 |
-
$result = [];
|
228 |
-
foreach (array_keys($headers) as $key) {
|
229 |
-
$result[strtolower($key)] = $key;
|
230 |
-
}
|
231 |
-
|
232 |
-
return $result;
|
233 |
-
}
|
234 |
-
|
235 |
-
/**
|
236 |
-
* Returns true if the provided host matches any of the no proxy areas.
|
237 |
-
*
|
238 |
-
* This method will strip a port from the host if it is present. Each pattern
|
239 |
-
* can be matched with an exact match (e.g., "foo.com" == "foo.com") or a
|
240 |
-
* partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" ==
|
241 |
-
* "baz.foo.com", but ".foo.com" != "foo.com").
|
242 |
-
*
|
243 |
-
* Areas are matched in the following cases:
|
244 |
-
* 1. "*" (without quotes) always matches any hosts.
|
245 |
-
* 2. An exact match.
|
246 |
-
* 3. The area starts with "." and the area is the last part of the host. e.g.
|
247 |
-
* '.mit.edu' will match any host that ends with '.mit.edu'.
|
248 |
-
*
|
249 |
-
* @param string $host Host to check against the patterns.
|
250 |
-
* @param array $noProxyArray An array of host patterns.
|
251 |
-
*
|
252 |
-
* @return bool
|
253 |
-
*/
|
254 |
-
function is_host_in_noproxy($host, array $noProxyArray)
|
255 |
-
{
|
256 |
-
if (strlen($host) === 0) {
|
257 |
-
throw new \InvalidArgumentException('Empty host provided');
|
258 |
-
}
|
259 |
-
|
260 |
-
// Strip port if present.
|
261 |
-
if (strpos($host, ':')) {
|
262 |
-
$host = explode($host, ':', 2)[0];
|
263 |
-
}
|
264 |
-
|
265 |
-
foreach ($noProxyArray as $area) {
|
266 |
-
// Always match on wildcards.
|
267 |
-
if ($area === '*') {
|
268 |
-
return true;
|
269 |
-
} elseif (empty($area)) {
|
270 |
-
// Don't match on empty values.
|
271 |
-
continue;
|
272 |
-
} elseif ($area === $host) {
|
273 |
-
// Exact matches.
|
274 |
-
return true;
|
275 |
-
} else {
|
276 |
-
// Special match if the area when prefixed with ".". Remove any
|
277 |
-
// existing leading "." and add a new leading ".".
|
278 |
-
$area = '.' . ltrim($area, '.');
|
279 |
-
if (substr($host, -(strlen($area))) === $area) {
|
280 |
-
return true;
|
281 |
-
}
|
282 |
-
}
|
283 |
-
}
|
284 |
-
|
285 |
-
return false;
|
286 |
-
}
|
287 |
-
|
288 |
-
/**
|
289 |
-
* Wrapper for json_decode that throws when an error occurs.
|
290 |
-
*
|
291 |
-
* @param string $json JSON data to parse
|
292 |
-
* @param bool $assoc When true, returned objects will be converted
|
293 |
-
* into associative arrays.
|
294 |
-
* @param int $depth User specified recursion depth.
|
295 |
-
* @param int $options Bitmask of JSON decode options.
|
296 |
-
*
|
297 |
-
* @return mixed
|
298 |
-
* @throws Exception\InvalidArgumentException if the JSON cannot be decoded.
|
299 |
-
* @link http://www.php.net/manual/en/function.json-decode.php
|
300 |
-
*/
|
301 |
-
function json_decode($json, $assoc = false, $depth = 512, $options = 0)
|
302 |
-
{
|
303 |
-
$data = \json_decode($json, $assoc, $depth, $options);
|
304 |
-
if (JSON_ERROR_NONE !== json_last_error()) {
|
305 |
-
throw new Exception\InvalidArgumentException(
|
306 |
-
'json_decode error: ' . json_last_error_msg()
|
307 |
-
);
|
308 |
-
}
|
309 |
-
|
310 |
-
return $data;
|
311 |
-
}
|
312 |
-
|
313 |
-
/**
|
314 |
-
* Wrapper for JSON encoding that throws when an error occurs.
|
315 |
-
*
|
316 |
-
* @param mixed $value The value being encoded
|
317 |
-
* @param int $options JSON encode option bitmask
|
318 |
-
* @param int $depth Set the maximum depth. Must be greater than zero.
|
319 |
-
*
|
320 |
-
* @return string
|
321 |
-
* @throws Exception\InvalidArgumentException if the JSON cannot be encoded.
|
322 |
-
* @link http://www.php.net/manual/en/function.json-encode.php
|
323 |
-
*/
|
324 |
-
function json_encode($value, $options = 0, $depth = 512)
|
325 |
-
{
|
326 |
-
$json = \json_encode($value, $options, $depth);
|
327 |
-
if (JSON_ERROR_NONE !== json_last_error()) {
|
328 |
-
throw new Exception\InvalidArgumentException(
|
329 |
-
'json_encode error: ' . json_last_error_msg()
|
330 |
-
);
|
331 |
-
}
|
332 |
-
|
333 |
-
return $json;
|
334 |
-
}
|
335 |
-
|
336 |
-
/**
|
337 |
-
* Wrapper for the hrtime() or microtime() functions
|
338 |
-
* (depending on the PHP version, one of the two is used)
|
339 |
-
*
|
340 |
-
* @return float|mixed UNIX timestamp
|
341 |
-
* @internal
|
342 |
-
*/
|
343 |
-
function _current_time()
|
344 |
-
{
|
345 |
-
return function_exists('hrtime') ? hrtime(true) / 1e9 : microtime(true);
|
346 |
-
}
|
1 |
+
<?php
|
2 |
+
namespace GuzzleHttp;
|
3 |
+
|
4 |
+
use GuzzleHttp\Handler\CurlHandler;
|
5 |
+
use GuzzleHttp\Handler\CurlMultiHandler;
|
6 |
+
use GuzzleHttp\Handler\Proxy;
|
7 |
+
use GuzzleHttp\Handler\StreamHandler;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Expands a URI template
|
11 |
+
*
|
12 |
+
* @param string $template URI template
|
13 |
+
* @param array $variables Template variables
|
14 |
+
*
|
15 |
+
* @return string
|
16 |
+
*/
|
17 |
+
function uri_template($template, array $variables)
|
18 |
+
{
|
19 |
+
if (extension_loaded('uri_template')) {
|
20 |
+
// @codeCoverageIgnoreStart
|
21 |
+
return \uri_template($template, $variables);
|
22 |
+
// @codeCoverageIgnoreEnd
|
23 |
+
}
|
24 |
+
|
25 |
+
static $uriTemplate;
|
26 |
+
if (!$uriTemplate) {
|
27 |
+
$uriTemplate = new UriTemplate();
|
28 |
+
}
|
29 |
+
|
30 |
+
return $uriTemplate->expand($template, $variables);
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Debug function used to describe the provided value type and class.
|
35 |
+
*
|
36 |
+
* @param mixed $input
|
37 |
+
*
|
38 |
+
* @return string Returns a string containing the type of the variable and
|
39 |
+
* if a class is provided, the class name.
|
40 |
+
*/
|
41 |
+
function describe_type($input)
|
42 |
+
{
|
43 |
+
switch (gettype($input)) {
|
44 |
+
case 'object':
|
45 |
+
return 'object(' . get_class($input) . ')';
|
46 |
+
case 'array':
|
47 |
+
return 'array(' . count($input) . ')';
|
48 |
+
default:
|
49 |
+
ob_start();
|
50 |
+
var_dump($input);
|
51 |
+
// normalize float vs double
|
52 |
+
return str_replace('double(', 'float(', rtrim(ob_get_clean()));
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Parses an array of header lines into an associative array of headers.
|
58 |
+
*
|
59 |
+
* @param iterable $lines Header lines array of strings in the following
|
60 |
+
* format: "Name: Value"
|
61 |
+
* @return array
|
62 |
+
*/
|
63 |
+
function headers_from_lines($lines)
|
64 |
+
{
|
65 |
+
$headers = [];
|
66 |
+
|
67 |
+
foreach ($lines as $line) {
|
68 |
+
$parts = explode(':', $line, 2);
|
69 |
+
$headers[trim($parts[0])][] = isset($parts[1])
|
70 |
+
? trim($parts[1])
|
71 |
+
: null;
|
72 |
+
}
|
73 |
+
|
74 |
+
return $headers;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Returns a debug stream based on the provided variable.
|
79 |
+
*
|
80 |
+
* @param mixed $value Optional value
|
81 |
+
*
|
82 |
+
* @return resource
|
83 |
+
*/
|
84 |
+
function debug_resource($value = null)
|
85 |
+
{
|
86 |
+
if (is_resource($value)) {
|
87 |
+
return $value;
|
88 |
+
} elseif (defined('STDOUT')) {
|
89 |
+
return STDOUT;
|
90 |
+
}
|
91 |
+
|
92 |
+
return fopen('php://output', 'w');
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Chooses and creates a default handler to use based on the environment.
|
97 |
+
*
|
98 |
+
* The returned handler is not wrapped by any default middlewares.
|
99 |
+
*
|
100 |
+
* @throws \RuntimeException if no viable Handler is available.
|
101 |
+
* @return callable Returns the best handler for the given system.
|
102 |
+
*/
|
103 |
+
function choose_handler()
|
104 |
+
{
|
105 |
+
$handler = null;
|
106 |
+
if (function_exists('curl_multi_exec') && function_exists('curl_exec')) {
|
107 |
+
$handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());
|
108 |
+
} elseif (function_exists('curl_exec')) {
|
109 |
+
$handler = new CurlHandler();
|
110 |
+
} elseif (function_exists('curl_multi_exec')) {
|
111 |
+
$handler = new CurlMultiHandler();
|
112 |
+
}
|
113 |
+
|
114 |
+
if (ini_get('allow_url_fopen')) {
|
115 |
+
$handler = $handler
|
116 |
+
? Proxy::wrapStreaming($handler, new StreamHandler())
|
117 |
+
: new StreamHandler();
|
118 |
+
} elseif (!$handler) {
|
119 |
+
throw new \RuntimeException('GuzzleHttp requires cURL, the '
|
120 |
+
. 'allow_url_fopen ini setting, or a custom HTTP handler.');
|
121 |
+
}
|
122 |
+
|
123 |
+
return $handler;
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Get the default User-Agent string to use with Guzzle
|
128 |
+
*
|
129 |
+
* @return string
|
130 |
+
*/
|
131 |
+
function default_user_agent()
|
132 |
+
{
|
133 |
+
static $defaultAgent = '';
|
134 |
+
|
135 |
+
if (!$defaultAgent) {
|
136 |
+
$defaultAgent = 'GuzzleHttp/' . Client::VERSION;
|
137 |
+
if (extension_loaded('curl') && function_exists('curl_version')) {
|
138 |
+
$defaultAgent .= ' curl/' . \curl_version()['version'];
|
139 |
+
}
|
140 |
+
$defaultAgent .= ' PHP/' . PHP_VERSION;
|
141 |
+
}
|
142 |
+
|
143 |
+
return $defaultAgent;
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Returns the default cacert bundle for the current system.
|
148 |
+
*
|
149 |
+
* First, the openssl.cafile and curl.cainfo php.ini settings are checked.
|
150 |
+
* If those settings are not configured, then the common locations for
|
151 |
+
* bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X
|
152 |
+
* and Windows are checked. If any of these file locations are found on
|
153 |
+
* disk, they will be utilized.
|
154 |
+
*
|
155 |
+
* Note: the result of this function is cached for subsequent calls.
|
156 |
+
*
|
157 |
+
* @return string
|
158 |
+
* @throws \RuntimeException if no bundle can be found.
|
159 |
+
*/
|
160 |
+
function default_ca_bundle()
|
161 |
+
{
|
162 |
+
static $cached = null;
|
163 |
+
static $cafiles = [
|
164 |
+
// Red Hat, CentOS, Fedora (provided by the ca-certificates package)
|
165 |
+
'/etc/pki/tls/certs/ca-bundle.crt',
|
166 |
+
// Ubuntu, Debian (provided by the ca-certificates package)
|
167 |
+
'/etc/ssl/certs/ca-certificates.crt',
|
168 |
+
// FreeBSD (provided by the ca_root_nss package)
|
169 |
+
'/usr/local/share/certs/ca-root-nss.crt',
|
170 |
+
// SLES 12 (provided by the ca-certificates package)
|
171 |
+
'/var/lib/ca-certificates/ca-bundle.pem',
|
172 |
+
// OS X provided by homebrew (using the default path)
|
173 |
+
'/usr/local/etc/openssl/cert.pem',
|
174 |
+
// Google app engine
|
175 |
+
'/etc/ca-certificates.crt',
|
176 |
+
// Windows?
|
177 |
+
'C:\\windows\\system32\\curl-ca-bundle.crt',
|
178 |
+
'C:\\windows\\curl-ca-bundle.crt',
|
179 |
+
];
|
180 |
+
|
181 |
+
if ($cached) {
|
182 |
+
return $cached;
|
183 |
+
}
|
184 |
+
|
185 |
+
if ($ca = ini_get('openssl.cafile')) {
|
186 |
+
return $cached = $ca;
|
187 |
+
}
|
188 |
+
|
189 |
+
if ($ca = ini_get('curl.cainfo')) {
|
190 |
+
return $cached = $ca;
|
191 |
+
}
|
192 |
+
|
193 |
+
foreach ($cafiles as $filename) {
|
194 |
+
if (file_exists($filename)) {
|
195 |
+
return $cached = $filename;
|
196 |
+
}
|
197 |
+
}
|
198 |
+
|
199 |
+
throw new \RuntimeException(
|
200 |
+
<<< EOT
|
201 |
+
No system CA bundle could be found in any of the the common system locations.
|
202 |
+
PHP versions earlier than 5.6 are not properly configured to use the system's
|
203 |
+
CA bundle by default. In order to verify peer certificates, you will need to
|
204 |
+
supply the path on disk to a certificate bundle to the 'verify' request
|
205 |
+
option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not
|
206 |
+
need a specific certificate bundle, then Mozilla provides a commonly used CA
|
207 |
+
bundle which can be downloaded here (provided by the maintainer of cURL):
|
208 |
+
https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once
|
209 |
+
you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP
|
210 |
+
ini setting to point to the path to the file, allowing you to omit the 'verify'
|
211 |
+
request option. See http://curl.haxx.se/docs/sslcerts.html for more
|
212 |
+
information.
|
213 |
+
EOT
|
214 |
+
);
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Creates an associative array of lowercase header names to the actual
|
219 |
+
* header casing.
|
220 |
+
*
|
221 |
+
* @param array $headers
|
222 |
+
*
|
223 |
+
* @return array
|
224 |
+
*/
|
225 |
+
function normalize_header_keys(array $headers)
|
226 |
+
{
|
227 |
+
$result = [];
|
228 |
+
foreach (array_keys($headers) as $key) {
|
229 |
+
$result[strtolower($key)] = $key;
|
230 |
+
}
|
231 |
+
|
232 |
+
return $result;
|
233 |
+
}
|
234 |
+
|
235 |
+
/**
|
236 |
+
* Returns true if the provided host matches any of the no proxy areas.
|
237 |
+
*
|
238 |
+
* This method will strip a port from the host if it is present. Each pattern
|
239 |
+
* can be matched with an exact match (e.g., "foo.com" == "foo.com") or a
|
240 |
+
* partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" ==
|
241 |
+
* "baz.foo.com", but ".foo.com" != "foo.com").
|
242 |
+
*
|
243 |
+
* Areas are matched in the following cases:
|
244 |
+
* 1. "*" (without quotes) always matches any hosts.
|
245 |
+
* 2. An exact match.
|
246 |
+
* 3. The area starts with "." and the area is the last part of the host. e.g.
|
247 |
+
* '.mit.edu' will match any host that ends with '.mit.edu'.
|
248 |
+
*
|
249 |
+
* @param string $host Host to check against the patterns.
|
250 |
+
* @param array $noProxyArray An array of host patterns.
|
251 |
+
*
|
252 |
+
* @return bool
|
253 |
+
*/
|
254 |
+
function is_host_in_noproxy($host, array $noProxyArray)
|
255 |
+
{
|
256 |
+
if (strlen($host) === 0) {
|
257 |
+
throw new \InvalidArgumentException('Empty host provided');
|
258 |
+
}
|
259 |
+
|
260 |
+
// Strip port if present.
|
261 |
+
if (strpos($host, ':')) {
|
262 |
+
$host = explode($host, ':', 2)[0];
|
263 |
+
}
|
264 |
+
|
265 |
+
foreach ($noProxyArray as $area) {
|
266 |
+
// Always match on wildcards.
|
267 |
+
if ($area === '*') {
|
268 |
+
return true;
|
269 |
+
} elseif (empty($area)) {
|
270 |
+
// Don't match on empty values.
|
271 |
+
continue;
|
272 |
+
} elseif ($area === $host) {
|
273 |
+
// Exact matches.
|
274 |
+
return true;
|
275 |
+
} else {
|
276 |
+
// Special match if the area when prefixed with ".". Remove any
|
277 |
+
// existing leading "." and add a new leading ".".
|
278 |
+
$area = '.' . ltrim($area, '.');
|
279 |
+
if (substr($host, -(strlen($area))) === $area) {
|
280 |
+
return true;
|
281 |
+
}
|
282 |
+
}
|
283 |
+
}
|
284 |
+
|
285 |
+
return false;
|
286 |
+
}
|
287 |
+
|
288 |
+
/**
|
289 |
+
* Wrapper for json_decode that throws when an error occurs.
|
290 |
+
*
|
291 |
+
* @param string $json JSON data to parse
|
292 |
+
* @param bool $assoc When true, returned objects will be converted
|
293 |
+
* into associative arrays.
|
294 |
+
* @param int $depth User specified recursion depth.
|
295 |
+
* @param int $options Bitmask of JSON decode options.
|
296 |
+
*
|
297 |
+
* @return mixed
|
298 |
+
* @throws Exception\InvalidArgumentException if the JSON cannot be decoded.
|
299 |
+
* @link http://www.php.net/manual/en/function.json-decode.php
|
300 |
+
*/
|
301 |
+
function json_decode($json, $assoc = false, $depth = 512, $options = 0)
|
302 |
+
{
|
303 |
+
$data = \json_decode($json, $assoc, $depth, $options);
|
304 |
+
if (JSON_ERROR_NONE !== json_last_error()) {
|
305 |
+
throw new Exception\InvalidArgumentException(
|
306 |
+
'json_decode error: ' . json_last_error_msg()
|
307 |
+
);
|
308 |
+
}
|
309 |
+
|
310 |
+
return $data;
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Wrapper for JSON encoding that throws when an error occurs.
|
315 |
+
*
|
316 |
+
* @param mixed $value The value being encoded
|
317 |
+
* @param int $options JSON encode option bitmask
|
318 |
+
* @param int $depth Set the maximum depth. Must be greater than zero.
|
319 |
+
*
|
320 |
+
* @return string
|
321 |
+
* @throws Exception\InvalidArgumentException if the JSON cannot be encoded.
|
322 |
+
* @link http://www.php.net/manual/en/function.json-encode.php
|
323 |
+
*/
|
324 |
+
function json_encode($value, $options = 0, $depth = 512)
|
325 |
+
{
|
326 |
+
$json = \json_encode($value, $options, $depth);
|
327 |
+
if (JSON_ERROR_NONE !== json_last_error()) {
|
328 |
+
throw new Exception\InvalidArgumentException(
|
329 |
+
'json_encode error: ' . json_last_error_msg()
|
330 |
+
);
|
331 |
+
}
|
332 |
+
|
333 |
+
return $json;
|
334 |
+
}
|
335 |
+
|
336 |
+
/**
|
337 |
+
* Wrapper for the hrtime() or microtime() functions
|
338 |
+
* (depending on the PHP version, one of the two is used)
|
339 |
+
*
|
340 |
+
* @return float|mixed UNIX timestamp
|
341 |
+
* @internal
|
342 |
+
*/
|
343 |
+
function _current_time()
|
344 |
+
{
|
345 |
+
return function_exists('hrtime') ? hrtime(true) / 1e9 : microtime(true);
|
346 |
+
}
|
vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php
CHANGED
@@ -11,6 +11,8 @@
|
|
11 |
|
12 |
namespace Monolog\Formatter;
|
13 |
|
|
|
|
|
14 |
/**
|
15 |
* Class FluentdFormatter
|
16 |
*
|
@@ -71,7 +73,7 @@ class FluentdFormatter implements FormatterInterface
|
|
71 |
$message['level_name'] = $record['level_name'];
|
72 |
}
|
73 |
|
74 |
-
return
|
75 |
}
|
76 |
|
77 |
public function formatBatch(array $records)
|
11 |
|
12 |
namespace Monolog\Formatter;
|
13 |
|
14 |
+
use Monolog\Utils;
|
15 |
+
|
16 |
/**
|
17 |
* Class FluentdFormatter
|
18 |
*
|
73 |
$message['level_name'] = $record['level_name'];
|
74 |
}
|
75 |
|
76 |
+
return Utils::jsonEncode(array($tag, $record['datetime']->getTimestamp(), $message));
|
77 |
}
|
78 |
|
79 |
public function formatBatch(array $records)
|
vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php
CHANGED
@@ -11,6 +11,7 @@
|
|
11 |
namespace Monolog\Formatter;
|
12 |
|
13 |
use Monolog\Logger;
|
|
|
14 |
|
15 |
/**
|
16 |
* Formats incoming records into an HTML table
|
@@ -133,9 +134,9 @@ class HtmlFormatter extends NormalizerFormatter
|
|
133 |
|
134 |
$data = $this->normalize($data);
|
135 |
if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
|
136 |
-
return
|
137 |
}
|
138 |
|
139 |
-
return str_replace('\\/', '/',
|
140 |
}
|
141 |
}
|
11 |
namespace Monolog\Formatter;
|
12 |
|
13 |
use Monolog\Logger;
|
14 |
+
use Monolog\Utils;
|
15 |
|
16 |
/**
|
17 |
* Formats incoming records into an HTML table
|
134 |
|
135 |
$data = $this->normalize($data);
|
136 |
if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
|
137 |
+
return Utils::jsonEncode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE, true);
|
138 |
}
|
139 |
|
140 |
+
return str_replace('\\/', '/', Utils::jsonEncode($data, null, true));
|
141 |
}
|
142 |
}
|
vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php
CHANGED
@@ -145,7 +145,7 @@ class JsonFormatter extends NormalizerFormatter
|
|
145 |
return 'Over 9 levels deep, aborting normalization';
|
146 |
}
|
147 |
|
148 |
-
if (is_array($data)
|
149 |
$normalized = array();
|
150 |
|
151 |
$count = 1;
|
@@ -186,7 +186,7 @@ class JsonFormatter extends NormalizerFormatter
|
|
186 |
$data = array(
|
187 |
'class' => Utils::getClass($e),
|
188 |
'message' => $e->getMessage(),
|
189 |
-
'code' => $e->getCode(),
|
190 |
'file' => $e->getFile().':'.$e->getLine(),
|
191 |
);
|
192 |
|
145 |
return 'Over 9 levels deep, aborting normalization';
|
146 |
}
|
147 |
|
148 |
+
if (is_array($data)) {
|
149 |
$normalized = array();
|
150 |
|
151 |
$count = 1;
|
186 |
$data = array(
|
187 |
'class' => Utils::getClass($e),
|
188 |
'message' => $e->getMessage(),
|
189 |
+
'code' => (int) $e->getCode(),
|
190 |
'file' => $e->getFile().':'.$e->getLine(),
|
191 |
);
|
192 |
|
vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php
CHANGED
@@ -163,7 +163,7 @@ class LineFormatter extends NormalizerFormatter
|
|
163 |
return $this->toJson($data, true);
|
164 |
}
|
165 |
|
166 |
-
return str_replace('\\/', '/',
|
167 |
}
|
168 |
|
169 |
protected function replaceNewlines($str)
|
163 |
return $this->toJson($data, true);
|
164 |
}
|
165 |
|
166 |
+
return str_replace('\\/', '/', $this->toJson($data, true));
|
167 |
}
|
168 |
|
169 |
protected function replaceNewlines($str)
|
vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php
CHANGED
@@ -87,7 +87,7 @@ class MongoDBFormatter implements FormatterInterface
|
|
87 |
$formattedException = array(
|
88 |
'class' => Utils::getClass($exception),
|
89 |
'message' => $exception->getMessage(),
|
90 |
-
'code' => $exception->getCode(),
|
91 |
'file' => $exception->getFile() . ':' . $exception->getLine(),
|
92 |
);
|
93 |
|
87 |
$formattedException = array(
|
88 |
'class' => Utils::getClass($exception),
|
89 |
'message' => $exception->getMessage(),
|
90 |
+
'code' => (int) $exception->getCode(),
|
91 |
'file' => $exception->getFile() . ':' . $exception->getLine(),
|
92 |
);
|
93 |
|
vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php
CHANGED
@@ -129,7 +129,7 @@ class NormalizerFormatter implements FormatterInterface
|
|
129 |
$data = array(
|
130 |
'class' => Utils::getClass($e),
|
131 |
'message' => $e->getMessage(),
|
132 |
-
'code' => $e->getCode(),
|
133 |
'file' => $e->getFile().':'.$e->getLine(),
|
134 |
);
|
135 |
|
@@ -142,8 +142,8 @@ class NormalizerFormatter implements FormatterInterface
|
|
142 |
$data['faultactor'] = $e->faultactor;
|
143 |
}
|
144 |
|
145 |
-
if (isset($e->detail)) {
|
146 |
-
$data['detail'] = $e->detail;
|
147 |
}
|
148 |
}
|
149 |
|
@@ -171,127 +171,6 @@ class NormalizerFormatter implements FormatterInterface
|
|
171 |
*/
|
172 |
protected function toJson($data, $ignoreErrors = false)
|
173 |
{
|
174 |
-
|
175 |
-
if ($ignoreErrors) {
|
176 |
-
return @$this->jsonEncode($data);
|
177 |
-
}
|
178 |
-
|
179 |
-
$json = $this->jsonEncode($data);
|
180 |
-
|
181 |
-
if ($json === false) {
|
182 |
-
$json = $this->handleJsonError(json_last_error(), $data);
|
183 |
-
}
|
184 |
-
|
185 |
-
return $json;
|
186 |
-
}
|
187 |
-
|
188 |
-
/**
|
189 |
-
* @param mixed $data
|
190 |
-
* @return string JSON encoded data or null on failure
|
191 |
-
*/
|
192 |
-
private function jsonEncode($data)
|
193 |
-
{
|
194 |
-
if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
|
195 |
-
return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
196 |
-
}
|
197 |
-
|
198 |
-
return json_encode($data);
|
199 |
-
}
|
200 |
-
|
201 |
-
/**
|
202 |
-
* Handle a json_encode failure.
|
203 |
-
*
|
204 |
-
* If the failure is due to invalid string encoding, try to clean the
|
205 |
-
* input and encode again. If the second encoding attempt fails, the
|
206 |
-
* inital error is not encoding related or the input can't be cleaned then
|
207 |
-
* raise a descriptive exception.
|
208 |
-
*
|
209 |
-
* @param int $code return code of json_last_error function
|
210 |
-
* @param mixed $data data that was meant to be encoded
|
211 |
-
* @throws \RuntimeException if failure can't be corrected
|
212 |
-
* @return string JSON encoded data after error correction
|
213 |
-
*/
|
214 |
-
private function handleJsonError($code, $data)
|
215 |
-
{
|
216 |
-
if ($code !== JSON_ERROR_UTF8) {
|
217 |
-
$this->throwEncodeError($code, $data);
|
218 |
-
}
|
219 |
-
|
220 |
-
if (is_string($data)) {
|
221 |
-
$this->detectAndCleanUtf8($data);
|
222 |
-
} elseif (is_array($data)) {
|
223 |
-
array_walk_recursive($data, array($this, 'detectAndCleanUtf8'));
|
224 |
-
} else {
|
225 |
-
$this->throwEncodeError($code, $data);
|
226 |
-
}
|
227 |
-
|
228 |
-
$json = $this->jsonEncode($data);
|
229 |
-
|
230 |
-
if ($json === false) {
|
231 |
-
$this->throwEncodeError(json_last_error(), $data);
|
232 |
-
}
|
233 |
-
|
234 |
-
return $json;
|
235 |
-
}
|
236 |
-
|
237 |
-
/**
|
238 |
-
* Throws an exception according to a given code with a customized message
|
239 |
-
*
|
240 |
-
* @param int $code return code of json_last_error function
|
241 |
-
* @param mixed $data data that was meant to be encoded
|
242 |
-
* @throws \RuntimeException
|
243 |
-
*/
|
244 |
-
private function throwEncodeError($code, $data)
|
245 |
-
{
|
246 |
-
switch ($code) {
|
247 |
-
case JSON_ERROR_DEPTH:
|
248 |
-
$msg = 'Maximum stack depth exceeded';
|
249 |
-
break;
|
250 |
-
case JSON_ERROR_STATE_MISMATCH:
|
251 |
-
$msg = 'Underflow or the modes mismatch';
|
252 |
-
break;
|
253 |
-
case JSON_ERROR_CTRL_CHAR:
|
254 |
-
$msg = 'Unexpected control character found';
|
255 |
-
break;
|
256 |
-
case JSON_ERROR_UTF8:
|
257 |
-
$msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
|
258 |
-
break;
|
259 |
-
default:
|
260 |
-
$msg = 'Unknown error';
|
261 |
-
}
|
262 |
-
|
263 |
-
throw new \RuntimeException('JSON encoding failed: '.$msg.'. Encoding: '.var_export($data, true));
|
264 |
-
}
|
265 |
-
|
266 |
-
/**
|
267 |
-
* Detect invalid UTF-8 string characters and convert to valid UTF-8.
|
268 |
-
*
|
269 |
-
* Valid UTF-8 input will be left unmodified, but strings containing
|
270 |
-
* invalid UTF-8 codepoints will be reencoded as UTF-8 with an assumed
|
271 |
-
* original encoding of ISO-8859-15. This conversion may result in
|
272 |
-
* incorrect output if the actual encoding was not ISO-8859-15, but it
|
273 |
-
* will be clean UTF-8 output and will not rely on expensive and fragile
|
274 |
-
* detection algorithms.
|
275 |
-
*
|
276 |
-
* Function converts the input in place in the passed variable so that it
|
277 |
-
* can be used as a callback for array_walk_recursive.
|
278 |
-
*
|
279 |
-
* @param mixed &$data Input to check and convert if needed
|
280 |
-
* @private
|
281 |
-
*/
|
282 |
-
public function detectAndCleanUtf8(&$data)
|
283 |
-
{
|
284 |
-
if (is_string($data) && !preg_match('//u', $data)) {
|
285 |
-
$data = preg_replace_callback(
|
286 |
-
'/[\x80-\xFF]+/',
|
287 |
-
function ($m) { return utf8_encode($m[0]); },
|
288 |
-
$data
|
289 |
-
);
|
290 |
-
$data = str_replace(
|
291 |
-
array('¤', '¦', '¨', '´', '¸', '¼', '½', '¾'),
|
292 |
-
array('€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'),
|
293 |
-
$data
|
294 |
-
);
|
295 |
-
}
|
296 |
}
|
297 |
}
|
129 |
$data = array(
|
130 |
'class' => Utils::getClass($e),
|
131 |
'message' => $e->getMessage(),
|
132 |
+
'code' => (int) $e->getCode(),
|
133 |
'file' => $e->getFile().':'.$e->getLine(),
|
134 |
);
|
135 |
|
142 |
$data['faultactor'] = $e->faultactor;
|
143 |
}
|
144 |
|
145 |
+
if (isset($e->detail) && (is_string($e->detail) || is_object($e->detail) || is_array($e->detail))) {
|
146 |
+
$data['detail'] = is_string($e->detail) ? $e->detail : reset($e->detail);
|
147 |
}
|
148 |
}
|
149 |
|
171 |
*/
|
172 |
protected function toJson($data, $ignoreErrors = false)
|
173 |
{
|
174 |
+
return Utils::jsonEncode($data, null, $ignoreErrors);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
}
|
176 |
}
|
vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php
CHANGED
@@ -164,21 +164,22 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
|
|
164 |
|
165 |
private static function handleStyles($formatted)
|
166 |
{
|
167 |
-
$args = array(
|
168 |
$format = '%c' . $formatted;
|
169 |
preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
|
170 |
|
171 |
foreach (array_reverse($matches) as $match) {
|
172 |
-
$args[] = static::quote(static::handleCustomStyles($match[2][0], $match[1][0]));
|
173 |
$args[] = '"font-weight: normal"';
|
|
|
174 |
|
175 |
$pos = $match[0][1];
|
176 |
$format = substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . substr($format, $pos + strlen($match[0][0]));
|
177 |
}
|
178 |
|
179 |
-
|
|
|
180 |
|
181 |
-
return $args;
|
182 |
}
|
183 |
|
184 |
private static function handleCustomStyles($style, $string)
|
164 |
|
165 |
private static function handleStyles($formatted)
|
166 |
{
|
167 |
+
$args = array();
|
168 |
$format = '%c' . $formatted;
|
169 |
preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
|
170 |
|
171 |
foreach (array_reverse($matches) as $match) {
|
|
|
172 |
$args[] = '"font-weight: normal"';
|
173 |
+
$args[] = static::quote(static::handleCustomStyles($match[2][0], $match[1][0]));
|
174 |
|
175 |
$pos = $match[0][1];
|
176 |
$format = substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . substr($format, $pos + strlen($match[0][0]));
|
177 |
}
|
178 |
|
179 |
+
$args[] = static::quote('font-weight: normal');
|
180 |
+
$args[] = static::quote($format);
|
181 |
|
182 |
+
return array_reverse($args);
|
183 |
}
|
184 |
|
185 |
private static function handleCustomStyles($style, $string)
|
vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php
CHANGED
@@ -13,6 +13,7 @@ namespace Monolog\Handler;
|
|
13 |
|
14 |
use Monolog\Logger;
|
15 |
use Monolog\ResettableInterface;
|
|
|
16 |
|
17 |
/**
|
18 |
* Buffers all records until closing the handler and then pass them as batch.
|
@@ -126,4 +127,22 @@ class BufferHandler extends AbstractHandler
|
|
126 |
$this->handler->reset();
|
127 |
}
|
128 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
}
|
13 |
|
14 |
use Monolog\Logger;
|
15 |
use Monolog\ResettableInterface;
|
16 |
+
use Monolog\Formatter\FormatterInterface;
|
17 |
|
18 |
/**
|
19 |
* Buffers all records until closing the handler and then pass them as batch.
|
127 |
$this->handler->reset();
|
128 |
}
|
129 |
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* {@inheritdoc}
|
133 |
+
*/
|
134 |
+
public function setFormatter(FormatterInterface $formatter)
|
135 |
+
{
|
136 |
+
$this->handler->setFormatter($formatter);
|
137 |
+
|
138 |
+
return $this;
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* {@inheritdoc}
|
143 |
+
*/
|
144 |
+
public function getFormatter()
|
145 |
+
{
|
146 |
+
return $this->handler->getFormatter();
|
147 |
+
}
|
148 |
}
|
vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php
CHANGED
@@ -13,6 +13,7 @@ namespace Monolog\Handler;
|
|
13 |
|
14 |
use Monolog\Formatter\ChromePHPFormatter;
|
15 |
use Monolog\Logger;
|
|
|
16 |
|
17 |
/**
|
18 |
* Handler sending logs to the ChromePHP extension (http://www.chromephp.com/)
|
@@ -134,7 +135,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
|
|
134 |
self::$json['request_uri'] = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
|
135 |
}
|
136 |
|
137 |
-
$json =
|
138 |
$data = base64_encode(utf8_encode($json));
|
139 |
if (strlen($data) > 3 * 1024) {
|
140 |
self::$overflowed = true;
|
@@ -149,7 +150,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
|
|
149 |
'extra' => array(),
|
150 |
);
|
151 |
self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record);
|
152 |
-
$json =
|
153 |
$data = base64_encode(utf8_encode($json));
|
154 |
}
|
155 |
|
13 |
|
14 |
use Monolog\Formatter\ChromePHPFormatter;
|
15 |
use Monolog\Logger;
|
16 |
+
use Monolog\Utils;
|
17 |
|
18 |
/**
|
19 |
* Handler sending logs to the ChromePHP extension (http://www.chromephp.com/)
|
135 |
self::$json['request_uri'] = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
|
136 |
}
|
137 |
|
138 |
+
$json = Utils::jsonEncode(self::$json, null, true);
|
139 |
$data = base64_encode(utf8_encode($json));
|
140 |
if (strlen($data) > 3 * 1024) {
|
141 |
self::$overflowed = true;
|
150 |
'extra' => array(),
|
151 |
);
|
152 |
self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record);
|
153 |
+
$json = Utils::jsonEncode(self::$json, null, true);
|
154 |
$data = base64_encode(utf8_encode($json));
|
155 |
}
|
156 |
|
vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php
CHANGED
@@ -12,6 +12,7 @@
|
|
12 |
namespace Monolog\Handler;
|
13 |
|
14 |
use Monolog\Logger;
|
|
|
15 |
|
16 |
/**
|
17 |
* Logs to Cube.
|
@@ -119,9 +120,9 @@ class CubeHandler extends AbstractProcessingHandler
|
|
119 |
$data['data']['level'] = $record['level'];
|
120 |
|
121 |
if ($this->scheme === 'http') {
|
122 |
-
$this->writeHttp(
|
123 |
} else {
|
124 |
-
$this->writeUdp(
|
125 |
}
|
126 |
}
|
127 |
|
12 |
namespace Monolog\Handler;
|
13 |
|
14 |
use Monolog\Logger;
|
15 |
+
use Monolog\Utils;
|
16 |
|
17 |
/**
|
18 |
* Logs to Cube.
|
120 |
$data['data']['level'] = $record['level'];
|
121 |
|
122 |
if ($this->scheme === 'http') {
|
123 |
+
$this->writeHttp(Utils::jsonEncode($data));
|
124 |
} else {
|
125 |
+
$this->writeUdp(Utils::jsonEncode($data));
|
126 |
}
|
127 |
}
|
128 |
|
vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php
CHANGED
@@ -12,6 +12,7 @@
|
|
12 |
namespace Monolog\Handler;
|
13 |
|
14 |
use Monolog\Logger;
|
|
|
15 |
|
16 |
/**
|
17 |
* Simple handler wrapper that filters records based on a list of levels
|
@@ -45,7 +46,7 @@ class FilterHandler extends AbstractHandler
|
|
45 |
protected $bubble;
|
46 |
|
47 |
/**
|
48 |
-
* @param callable|HandlerInterface $handler Handler or factory callable($record, $
|
49 |
* @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided
|
50 |
* @param int $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array
|
51 |
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
@@ -104,21 +105,13 @@ class FilterHandler extends AbstractHandler
|
|
104 |
return false;
|
105 |
}
|
106 |
|
107 |
-
// The same logic as in FingersCrossedHandler
|
108 |
-
if (!$this->handler instanceof HandlerInterface) {
|
109 |
-
$this->handler = call_user_func($this->handler, $record, $this);
|
110 |
-
if (!$this->handler instanceof HandlerInterface) {
|
111 |
-
throw new \RuntimeException("The factory callable should return a HandlerInterface");
|
112 |
-
}
|
113 |
-
}
|
114 |
-
|
115 |
if ($this->processors) {
|
116 |
foreach ($this->processors as $processor) {
|
117 |
$record = call_user_func($processor, $record);
|
118 |
}
|
119 |
}
|
120 |
|
121 |
-
$this->
|
122 |
|
123 |
return false === $this->bubble;
|
124 |
}
|
@@ -135,6 +128,43 @@ class FilterHandler extends AbstractHandler
|
|
135 |
}
|
136 |
}
|
137 |
|
138 |
-
$this->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
}
|
140 |
}
|
12 |
namespace Monolog\Handler;
|
13 |
|
14 |
use Monolog\Logger;
|
15 |
+
use Monolog\Formatter\FormatterInterface;
|
16 |
|
17 |
/**
|
18 |
* Simple handler wrapper that filters records based on a list of levels
|
46 |
protected $bubble;
|
47 |
|
48 |
/**
|
49 |
+
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $filterHandler).
|
50 |
* @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided
|
51 |
* @param int $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array
|
52 |
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
105 |
return false;
|
106 |
}
|
107 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
if ($this->processors) {
|
109 |
foreach ($this->processors as $processor) {
|
110 |
$record = call_user_func($processor, $record);
|
111 |
}
|
112 |
}
|
113 |
|
114 |
+
$this->getHandler($record)->handle($record);
|
115 |
|
116 |
return false === $this->bubble;
|
117 |
}
|
128 |
}
|
129 |
}
|
130 |
|
131 |
+
$this->getHandler($filtered[count($filtered) - 1])->handleBatch($filtered);
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Return the nested handler
|
136 |
+
*
|
137 |
+
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
|
138 |
+
*
|
139 |
+
* @return HandlerInterface
|
140 |
+
*/
|
141 |
+
public function getHandler(array $record = null)
|
142 |
+
{
|
143 |
+
if (!$this->handler instanceof HandlerInterface) {
|
144 |
+
$this->handler = call_user_func($this->handler, $record, $this);
|
145 |
+
if (!$this->handler instanceof HandlerInterface) {
|
146 |
+
throw new \RuntimeException("The factory callable should return a HandlerInterface");
|
147 |
+
}
|
148 |
+
}
|
149 |
+
|
150 |
+
return $this->handler;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* {@inheritdoc}
|
155 |
+
*/
|
156 |
+
public function setFormatter(FormatterInterface $formatter)
|
157 |
+
{
|
158 |
+
$this->getHandler()->setFormatter($formatter);
|
159 |
+
|
160 |
+
return $this;
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* {@inheritdoc}
|
165 |
+
*/
|
166 |
+
public function getFormatter()
|
167 |
+
{
|
168 |
+
return $this->getHandler()->getFormatter();
|
169 |
}
|
170 |
}
|
vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php
CHANGED
@@ -15,6 +15,7 @@ use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
|
|
15 |
use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
|
16 |
use Monolog\Logger;
|
17 |
use Monolog\ResettableInterface;
|
|
|
18 |
|
19 |
/**
|
20 |
* Buffers all records until a certain level is reached
|
@@ -39,7 +40,7 @@ class FingersCrossedHandler extends AbstractHandler
|
|
39 |
protected $passthruLevel;
|
40 |
|
41 |
/**
|
42 |
-
* @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler).
|
43 |
* @param int|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action
|
44 |
* @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
|
45 |
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
@@ -88,15 +89,7 @@ class FingersCrossedHandler extends AbstractHandler
|
|
88 |
if ($this->stopBuffering) {
|
89 |
$this->buffering = false;
|
90 |
}
|
91 |
-
|
92 |
-
$record = end($this->buffer) ?: null;
|
93 |
-
|
94 |
-
$this->handler = call_user_func($this->handler, $record, $this);
|
95 |
-
if (!$this->handler instanceof HandlerInterface) {
|
96 |
-
throw new \RuntimeException("The factory callable should return a HandlerInterface");
|
97 |
-
}
|
98 |
-
}
|
99 |
-
$this->handler->handleBatch($this->buffer);
|
100 |
$this->buffer = array();
|
101 |
}
|
102 |
|
@@ -120,7 +113,7 @@ class FingersCrossedHandler extends AbstractHandler
|
|
120 |
$this->activate();
|
121 |
}
|
122 |
} else {
|
123 |
-
$this->
|
124 |
}
|
125 |
|
126 |
return false === $this->bubble;
|
@@ -140,8 +133,8 @@ class FingersCrossedHandler extends AbstractHandler
|
|
140 |
|
141 |
parent::reset();
|
142 |
|
143 |
-
if ($this->
|
144 |
-
$this->
|
145 |
}
|
146 |
}
|
147 |
|
@@ -167,11 +160,48 @@ class FingersCrossedHandler extends AbstractHandler
|
|
167 |
return $record['level'] >= $level;
|
168 |
});
|
169 |
if (count($this->buffer) > 0) {
|
170 |
-
$this->
|
171 |
}
|
172 |
}
|
173 |
|
174 |
$this->buffer = array();
|
175 |
$this->buffering = true;
|
176 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
}
|
15 |
use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
|
16 |
use Monolog\Logger;
|
17 |
use Monolog\ResettableInterface;
|
18 |
+
use Monolog\Formatter\FormatterInterface;
|
19 |
|
20 |
/**
|
21 |
* Buffers all records until a certain level is reached
|
40 |
protected $passthruLevel;
|
41 |
|
42 |
/**
|
43 |
+
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $fingersCrossedHandler).
|
44 |
* @param int|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action
|
45 |
* @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
|
46 |
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
89 |
if ($this->stopBuffering) {
|
90 |
$this->buffering = false;
|
91 |
}
|
92 |
+
$this->getHandler(end($this->buffer) ?: null)->handleBatch($this->buffer);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
$this->buffer = array();
|
94 |
}
|
95 |
|
113 |
$this->activate();
|
114 |
}
|
115 |
} else {
|
116 |
+
$this->getHandler($record)->handle($record);
|
117 |
}
|
118 |
|
119 |
return false === $this->bubble;
|
133 |
|
134 |
parent::reset();
|
135 |
|
136 |
+
if ($this->getHandler() instanceof ResettableInterface) {
|
137 |
+
$this->getHandler()->reset();
|
138 |
}
|
139 |
}
|
140 |
|
160 |
return $record['level'] >= $level;
|
161 |
});
|
162 |
if (count($this->buffer) > 0) {
|
163 |
+
$this->getHandler(end($this->buffer) ?: null)->handleBatch($this->buffer);
|
164 |
}
|
165 |
}
|
166 |
|
167 |
$this->buffer = array();
|
168 |
$this->buffering = true;
|
169 |
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Return the nested handler
|
173 |
+
*
|
174 |
+
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
|
175 |
+
*
|
176 |
+
* @return HandlerInterface
|
177 |
+
*/
|
178 |
+
public function getHandler(array $record = null)
|
179 |
+
{
|
180 |
+
if (!$this->handler instanceof HandlerInterface) {
|
181 |
+
$this->handler = call_user_func($this->handler, $record, $this);
|
182 |
+
if (!$this->handler instanceof HandlerInterface) {
|
183 |
+
throw new \RuntimeException("The factory callable should return a HandlerInterface");
|
184 |
+
}
|
185 |
+
}
|
186 |
+
|
187 |
+
return $this->handler;
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* {@inheritdoc}
|
192 |
+
*/
|
193 |
+
public function setFormatter(FormatterInterface $formatter)
|
194 |
+
{
|
195 |
+
$this->getHandler()->setFormatter($formatter);
|
196 |
+
|
197 |
+
return $this;
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* {@inheritdoc}
|
202 |
+
*/
|
203 |
+
public function getFormatter()
|
204 |
+
{
|
205 |
+
return $this->getHandler()->getFormatter();
|
206 |
+
}
|
207 |
}
|
vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php
CHANGED
@@ -12,6 +12,7 @@
|
|
12 |
namespace Monolog\Handler;
|
13 |
|
14 |
use Monolog\Logger;
|
|
|
15 |
use Monolog\Formatter\FlowdockFormatter;
|
16 |
use Monolog\Formatter\FormatterInterface;
|
17 |
|
@@ -105,7 +106,7 @@ class FlowdockHandler extends SocketHandler
|
|
105 |
*/
|
106 |
private function buildContent($record)
|
107 |
{
|
108 |
-
return
|
109 |
}
|
110 |
|
111 |
/**
|
12 |
namespace Monolog\Handler;
|
13 |
|
14 |
use Monolog\Logger;
|
15 |
+
use Monolog\Utils;
|
16 |
use Monolog\Formatter\FlowdockFormatter;
|
17 |
use Monolog\Formatter\FormatterInterface;
|
18 |
|
106 |
*/
|
107 |
private function buildContent($record)
|
108 |
{
|
109 |
+
return Utils::jsonEncode($record['formatted']['flowdock']);
|
110 |
}
|
111 |
|
112 |
/**
|
vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php
CHANGED
@@ -12,6 +12,7 @@
|
|
12 |
namespace Monolog\Handler;
|
13 |
|
14 |
use Monolog\Logger;
|
|
|
15 |
|
16 |
/**
|
17 |
* IFTTTHandler uses cURL to trigger IFTTT Maker actions
|
@@ -53,7 +54,7 @@ class IFTTTHandler extends AbstractProcessingHandler
|
|
53 |
"value2" => $record["level_name"],
|
54 |
"value3" => $record["message"],
|
55 |
);
|
56 |
-
$postString =
|
57 |
|
58 |
$ch = curl_init();
|
59 |
curl_setopt($ch, CURLOPT_URL, "https://maker.ifttt.com/trigger/" . $this->eventName . "/with/key/" . $this->secretKey);
|
12 |
namespace Monolog\Handler;
|
13 |
|
14 |
use Monolog\Logger;
|
15 |
+
use Monolog\Utils;
|
16 |
|
17 |
/**
|
18 |
* IFTTTHandler uses cURL to trigger IFTTT Maker actions
|
54 |
"value2" => $record["level_name"],
|
55 |
"value3" => $record["message"],
|
56 |
);
|
57 |
+
$postString = Utils::jsonEncode($postData);
|
58 |
|
59 |
$ch = curl_init();
|
60 |
curl_setopt($ch, CURLOPT_URL, "https://maker.ifttt.com/trigger/" . $this->eventName . "/with/key/" . $this->secretKey);
|
vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php
CHANGED
@@ -12,6 +12,7 @@
|
|
12 |
namespace Monolog\Handler;
|
13 |
|
14 |
use Monolog\Logger;
|
|
|
15 |
use Monolog\Formatter\NormalizerFormatter;
|
16 |
|
17 |
/**
|
@@ -190,7 +191,7 @@ class NewRelicHandler extends AbstractProcessingHandler
|
|
190 |
if (null === $value || is_scalar($value)) {
|
191 |
newrelic_add_custom_parameter($key, $value);
|
192 |
} else {
|
193 |
-
newrelic_add_custom_parameter($key,
|
194 |
}
|
195 |
}
|
196 |
|
12 |
namespace Monolog\Handler;
|
13 |
|
14 |
use Monolog\Logger;
|
15 |
+
use Monolog\Utils;
|
16 |
use Monolog\Formatter\NormalizerFormatter;
|
17 |
|
18 |
/**
|
191 |
if (null === $value || is_scalar($value)) {
|
192 |
newrelic_add_custom_parameter($key, $value);
|
193 |
} else {
|
194 |
+
newrelic_add_custom_parameter($key, Utils::jsonEncode($value, null, true));
|
195 |
}
|
196 |
}
|
197 |
|
vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php
CHANGED
@@ -14,6 +14,7 @@ namespace Monolog\Handler;
|
|
14 |
use Exception;
|
15 |
use Monolog\Formatter\LineFormatter;
|
16 |
use Monolog\Logger;
|
|
|
17 |
use PhpConsole\Connector;
|
18 |
use PhpConsole\Handler;
|
19 |
use PhpConsole\Helper;
|
@@ -188,7 +189,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
|
|
188 |
$tags = $this->getRecordTags($record);
|
189 |
$message = $record['message'];
|
190 |
if ($record['context']) {
|
191 |
-
$message .= ' ' .
|
192 |
}
|
193 |
$this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']);
|
194 |
}
|
14 |
use Exception;
|
15 |
use Monolog\Formatter\LineFormatter;
|
16 |
use Monolog\Logger;
|
17 |
+
use Monolog\Utils;
|
18 |
use PhpConsole\Connector;
|
19 |
use PhpConsole\Handler;
|
20 |
use PhpConsole\Helper;
|
189 |
$tags = $this->getRecordTags($record);
|
190 |
$message = $record['message'];
|
191 |
if ($record['context']) {
|
192 |
+
$message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($record['context'])), null, true);
|
193 |
}
|
194 |
$this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']);
|
195 |
}
|
vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php
CHANGED
@@ -11,6 +11,8 @@
|
|
11 |
|
12 |
namespace Monolog\Handler;
|
13 |
|
|
|
|
|
14 |
/**
|
15 |
* Sampling handler
|
16 |
*
|
@@ -38,7 +40,7 @@ class SamplingHandler extends AbstractHandler
|
|
38 |
protected $factor;
|
39 |
|
40 |
/**
|
41 |
-
* @param callable|HandlerInterface $handler Handler or factory callable($record, $
|
42 |
* @param int $factor Sample factor
|
43 |
*/
|
44 |
public function __construct($handler, $factor)
|
@@ -54,29 +56,58 @@ class SamplingHandler extends AbstractHandler
|
|
54 |
|
55 |
public function isHandling(array $record)
|
56 |
{
|
57 |
-
return $this->
|
58 |
}
|
59 |
|
60 |
public function handle(array $record)
|
61 |
{
|
62 |
if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) {
|
63 |
-
// The same logic as in FingersCrossedHandler
|
64 |
-
if (!$this->handler instanceof HandlerInterface) {
|
65 |
-
$this->handler = call_user_func($this->handler, $record, $this);
|
66 |
-
if (!$this->handler instanceof HandlerInterface) {
|
67 |
-
throw new \RuntimeException("The factory callable should return a HandlerInterface");
|
68 |
-
}
|
69 |
-
}
|
70 |
-
|
71 |
if ($this->processors) {
|
72 |
foreach ($this->processors as $processor) {
|
73 |
$record = call_user_func($processor, $record);
|
74 |
}
|
75 |
}
|
76 |
|
77 |
-
$this->
|
78 |
}
|
79 |
|
80 |
return false === $this->bubble;
|
81 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
}
|
11 |
|
12 |
namespace Monolog\Handler;
|
13 |
|
14 |
+
use Monolog\Formatter\FormatterInterface;
|
15 |
+
|
16 |
/**
|
17 |
* Sampling handler
|
18 |
*
|
40 |
protected $factor;
|
41 |
|
42 |
/**
|
43 |
+
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $samplingHandler).
|
44 |
* @param int $factor Sample factor
|
45 |
*/
|
46 |
public function __construct($handler, $factor)
|
56 |
|
57 |
public function isHandling(array $record)
|
58 |
{
|
59 |
+
return $this->getHandler($record)->isHandling($record);
|
60 |
}
|
61 |
|
62 |
public function handle(array $record)
|
63 |
{
|
64 |
if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
if ($this->processors) {
|
66 |
foreach ($this->processors as $processor) {
|
67 |
$record = call_user_func($processor, $record);
|
68 |
}
|
69 |
}
|
70 |
|
71 |
+
$this->getHandler($record)->handle($record);
|
72 |
}
|
73 |
|
74 |
return false === $this->bubble;
|
75 |
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Return the nested handler
|
79 |
+
*
|
80 |
+
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
|
81 |
+
*
|
82 |
+
* @return HandlerInterface
|
83 |
+
*/
|
84 |
+
public function getHandler(array $record = null)
|
85 |
+
{
|
86 |
+
if (!$this->handler instanceof HandlerInterface) {
|
87 |
+
$this->handler = call_user_func($this->handler, $record, $this);
|
88 |
+
if (!$this->handler instanceof HandlerInterface) {
|
89 |
+
throw new \RuntimeException("The factory callable should return a HandlerInterface");
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
+
return $this->handler;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* {@inheritdoc}
|
98 |
+
*/
|
99 |
+
public function setFormatter(FormatterInterface $formatter)
|
100 |
+
{
|
101 |
+
$this->getHandler()->setFormatter($formatter);
|
102 |
+
|
103 |
+
return $this;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* {@inheritdoc}
|
108 |
+
*/
|
109 |
+
public function getFormatter()
|
110 |
+
{
|
111 |
+
return $this->getHandler()->getFormatter();
|
112 |
+
}
|
113 |
}
|
vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php
CHANGED
@@ -12,6 +12,7 @@
|
|
12 |
namespace Monolog\Handler\Slack;
|
13 |
|
14 |
use Monolog\Logger;
|
|
|
15 |
use Monolog\Formatter\NormalizerFormatter;
|
16 |
use Monolog\Formatter\FormatterInterface;
|
17 |
|
@@ -207,13 +208,17 @@ class SlackRecord
|
|
207 |
{
|
208 |
$normalized = $this->normalizerFormatter->format($fields);
|
209 |
$prettyPrintFlag = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 128;
|
|
|
|
|
|
|
|
|
210 |
|
211 |
$hasSecondDimension = count(array_filter($normalized, 'is_array'));
|
212 |
$hasNonNumericKeys = !count(array_filter(array_keys($normalized), 'is_numeric'));
|
213 |
|
214 |
return $hasSecondDimension || $hasNonNumericKeys
|
215 |
-
?
|
216 |
-
:
|
217 |
}
|
218 |
|
219 |
/**
|
12 |
namespace Monolog\Handler\Slack;
|
13 |
|
14 |
use Monolog\Logger;
|
15 |
+
use Monolog\Utils;
|
16 |
use Monolog\Formatter\NormalizerFormatter;
|
17 |
use Monolog\Formatter\FormatterInterface;
|
18 |
|
208 |
{
|
209 |
$normalized = $this->normalizerFormatter->format($fields);
|
210 |
$prettyPrintFlag = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 128;
|
211 |
+
$flags = 0;
|
212 |
+
if (PHP_VERSION_ID >= 50400) {
|
213 |
+
$flags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
|
214 |
+
}
|
215 |
|
216 |
$hasSecondDimension = count(array_filter($normalized, 'is_array'));
|
217 |
$hasNonNumericKeys = !count(array_filter(array_keys($normalized), 'is_numeric'));
|
218 |
|
219 |
return $hasSecondDimension || $hasNonNumericKeys
|
220 |
+
? Utils::jsonEncode($normalized, $prettyPrintFlag | $flags)
|
221 |
+
: Utils::jsonEncode($normalized, $flags);
|
222 |
}
|
223 |
|
224 |
/**
|
vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php
CHANGED
@@ -13,6 +13,7 @@ namespace Monolog\Handler;
|
|
13 |
|
14 |
use Monolog\Formatter\FormatterInterface;
|
15 |
use Monolog\Logger;
|
|
|
16 |
use Monolog\Handler\Slack\SlackRecord;
|
17 |
|
18 |
/**
|
@@ -118,7 +119,7 @@ class SlackHandler extends SocketHandler
|
|
118 |
$dataArray['token'] = $this->token;
|
119 |
|
120 |
if (!empty($dataArray['attachments'])) {
|
121 |
-
$dataArray['attachments'] =
|
122 |
}
|
123 |
|
124 |
return $dataArray;
|
13 |
|
14 |
use Monolog\Formatter\FormatterInterface;
|
15 |
use Monolog\Logger;
|
16 |
+
use Monolog\Utils;
|
17 |
use Monolog\Handler\Slack\SlackRecord;
|
18 |
|
19 |
/**
|
119 |
$dataArray['token'] = $this->token;
|
120 |
|
121 |
if (!empty($dataArray['attachments'])) {
|
122 |
+
$dataArray['attachments'] = Utils::jsonEncode($dataArray['attachments']);
|
123 |
}
|
124 |
|
125 |
return $dataArray;
|
vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php
CHANGED
@@ -13,6 +13,7 @@ namespace Monolog\Handler;
|
|
13 |
|
14 |
use Monolog\Formatter\FormatterInterface;
|
15 |
use Monolog\Logger;
|
|
|
16 |
use Monolog\Handler\Slack\SlackRecord;
|
17 |
|
18 |
/**
|
@@ -83,7 +84,7 @@ class SlackWebhookHandler extends AbstractProcessingHandler
|
|
83 |
protected function write(array $record)
|
84 |
{
|
85 |
$postData = $this->slackRecord->getSlackData($record);
|
86 |
-
$postString =
|
87 |
|
88 |
$ch = curl_init();
|
89 |
$options = array(
|
13 |
|
14 |
use Monolog\Formatter\FormatterInterface;
|
15 |
use Monolog\Logger;
|
16 |
+
use Monolog\Utils;
|
17 |
use Monolog\Handler\Slack\SlackRecord;
|
18 |
|
19 |
/**
|
84 |
protected function write(array $record)
|
85 |
{
|
86 |
$postData = $this->slackRecord->getSlackData($record);
|
87 |
+
$postString = Utils::jsonEncode($postData);
|
88 |
|
89 |
$ch = curl_init();
|
90 |
$options = array(
|
vendor/monolog/monolog/src/Monolog/Utils.php
CHANGED
@@ -22,4 +22,138 @@ class Utils
|
|
22 |
|
23 |
return 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class;
|
24 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
}
|
22 |
|
23 |
return 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class;
|
24 |
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Return the JSON representation of a value
|
28 |
+
*
|
29 |
+
* @param mixed $data
|
30 |
+
* @param int $encodeFlags flags to pass to json encode, defaults to JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
|
31 |
+
* @param bool $ignoreErrors whether to ignore encoding errors or to throw on error, when ignored and the encoding fails, "null" is returned which is valid json for null
|
32 |
+
* @throws \RuntimeException if encoding fails and errors are not ignored
|
33 |
+
* @return string
|
34 |
+
*/
|
35 |
+
public static function jsonEncode($data, $encodeFlags = null, $ignoreErrors = false)
|
36 |
+
{
|
37 |
+
if (null === $encodeFlags && version_compare(PHP_VERSION, '5.4.0', '>=')) {
|
38 |
+
$encodeFlags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
|
39 |
+
}
|
40 |
+
|
41 |
+
if ($ignoreErrors) {
|
42 |
+
$json = @json_encode($data, $encodeFlags);
|
43 |
+
if (false === $json) {
|
44 |
+
return 'null';
|
45 |
+
}
|
46 |
+
|
47 |
+
return $json;
|
48 |
+
}
|
49 |
+
|
50 |
+
$json = json_encode($data, $encodeFlags);
|
51 |
+
if (false === $json) {
|
52 |
+
$json = self::handleJsonError(json_last_error(), $data);
|
53 |
+
}
|
54 |
+
|
55 |
+
return $json;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Handle a json_encode failure.
|
60 |
+
*
|
61 |
+
* If the failure is due to invalid string encoding, try to clean the
|
62 |
+
* input and encode again. If the second encoding attempt fails, the
|
63 |
+
* inital error is not encoding related or the input can't be cleaned then
|
64 |
+
* raise a descriptive exception.
|
65 |
+
*
|
66 |
+
* @param int $code return code of json_last_error function
|
67 |
+
* @param mixed $data data that was meant to be encoded
|
68 |
+
* @param int $encodeFlags flags to pass to json encode, defaults to JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
|
69 |
+
* @throws \RuntimeException if failure can't be corrected
|
70 |
+
* @return string JSON encoded data after error correction
|
71 |
+
*/
|
72 |
+
public static function handleJsonError($code, $data, $encodeFlags = null)
|
73 |
+
{
|
74 |
+
if ($code !== JSON_ERROR_UTF8) {
|
75 |
+
self::throwEncodeError($code, $data);
|
76 |
+
}
|
77 |
+
|
78 |
+
if (is_string($data)) {
|
79 |
+
self::detectAndCleanUtf8($data);
|
80 |
+
} elseif (is_array($data)) {
|
81 |
+
array_walk_recursive($data, array('Monolog\Utils', 'detectAndCleanUtf8'));
|
82 |
+
} else {
|
83 |
+
self::throwEncodeError($code, $data);
|
84 |
+
}
|
85 |
+
|
86 |
+
if (null === $encodeFlags && version_compare(PHP_VERSION, '5.4.0', '>=')) {
|
87 |
+
$encodeFlags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
|
88 |
+
}
|
89 |
+
|
90 |
+
$json = json_encode($data, $encodeFlags);
|
91 |
+
|
92 |
+
if ($json === false) {
|
93 |
+
self::throwEncodeError(json_last_error(), $data);
|
94 |
+
}
|
95 |
+
|
96 |
+
return $json;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Throws an exception according to a given code with a customized message
|
101 |
+
*
|
102 |
+
* @param int $code return code of json_last_error function
|
103 |
+
* @param mixed $data data that was meant to be encoded
|
104 |
+
* @throws \RuntimeException
|
105 |
+
*/
|
106 |
+
private static function throwEncodeError($code, $data)
|
107 |
+
{
|
108 |
+
switch ($code) {
|
109 |
+
case JSON_ERROR_DEPTH:
|
110 |
+
$msg = 'Maximum stack depth exceeded';
|
111 |
+
break;
|
112 |
+
case JSON_ERROR_STATE_MISMATCH:
|
113 |
+
$msg = 'Underflow or the modes mismatch';
|
114 |
+
break;
|
115 |
+
case JSON_ERROR_CTRL_CHAR:
|
116 |
+
$msg = 'Unexpected control character found';
|
117 |
+
break;
|
118 |
+
case JSON_ERROR_UTF8:
|
119 |
+
$msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
|
120 |
+
break;
|
121 |
+
default:
|
122 |
+
$msg = 'Unknown error';
|
123 |
+
}
|
124 |
+
|
125 |
+
throw new \RuntimeException('JSON encoding failed: '.$msg.'. Encoding: '.var_export($data, true));
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Detect invalid UTF-8 string characters and convert to valid UTF-8.
|
130 |
+
*
|
131 |
+
* Valid UTF-8 input will be left unmodified, but strings containing
|
132 |
+
* invalid UTF-8 codepoints will be reencoded as UTF-8 with an assumed
|
133 |
+
* original encoding of ISO-8859-15. This conversion may result in
|
134 |
+
* incorrect output if the actual encoding was not ISO-8859-15, but it
|
135 |
+
* will be clean UTF-8 output and will not rely on expensive and fragile
|
136 |
+
* detection algorithms.
|
137 |
+
*
|
138 |
+
* Function converts the input in place in the passed variable so that it
|
139 |
+
* can be used as a callback for array_walk_recursive.
|
140 |
+
*
|
141 |
+
* @param mixed &$data Input to check and convert if needed
|
142 |
+
* @private
|
143 |
+
*/
|
144 |
+
public static function detectAndCleanUtf8(&$data)
|
145 |
+
{
|
146 |
+
if (is_string($data) && !preg_match('//u', $data)) {
|
147 |
+
$data = preg_replace_callback(
|
148 |
+
'/[\x80-\xFF]+/',
|
149 |
+
function ($m) { return utf8_encode($m[0]); },
|
150 |
+
$data
|
151 |
+
);
|
152 |
+
$data = str_replace(
|
153 |
+
array('¤', '¦', '¨', '´', '¸', '¼', '½', '¾'),
|
154 |
+
array('€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'),
|
155 |
+
$data
|
156 |
+
);
|
157 |
+
}
|
158 |
+
}
|
159 |
}
|
wp_mail_smtp.php
CHANGED
@@ -1,166 +1,167 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Plugin Name: WP Mail SMTP
|
4 |
-
* Version: 1.
|
5 |
-
* Plugin URI: https://wpmailsmtp.com/
|
6 |
-
* Description: Reconfigures the <code>wp_mail()</code> function to use Gmail/Mailgun/SendGrid/SMTP instead of the default <code>mail()</code> and creates an options page to manage the settings.
|
7 |
-
* Author: WPForms
|
8 |
-
* Author URI: https://wpforms.com/
|
9 |
-
* Network: false
|
10 |
-
* Text Domain: wp-mail-smtp
|
11 |
-
* Domain Path: /assets/languages
|
12 |
-
*/
|
13 |
-
|
14 |
-
/**
|
15 |
-
* @author WPForms
|
16 |
-
* @copyright WPForms, 2007-19, All Rights Reserved
|
17 |
-
* This code is released under the GPL licence version 3 or later, available here
|
18 |
-
* https://www.gnu.org/licenses/gpl.txt
|
19 |
-
*/
|
20 |
-
|
21 |
-
/**
|
22 |
-
* Setting options in wp-config.php
|
23 |
-
*
|
24 |
-
* Specifically aimed at WP Multisite users, you can set the options for this plugin as
|
25 |
-
* constants in wp-config.php. Copy the code below into wp-config.php and tweak settings.
|
26 |
-
* Values from constants are NOT stripslash()'ed.
|
27 |
-
*
|
28 |
-
* When enabled, make sure to comment out (at the beginning of the line using //) those constants that you do not need,
|
29 |
-
* or remove them completely, so they won't interfere with plugin settings.
|
30 |
-
*/
|
31 |
-
|
32 |
-
/*
|
33 |
-
define( 'WPMS_ON', true ); // True turns on the whole constants support and usage, false turns it off.
|
34 |
-
|
35 |
-
define( 'WPMS_DO_NOT_SEND', true ); // Or false, in that case constant is ignored.
|
36 |
-
|
37 |
-
define( 'WPMS_MAIL_FROM', 'mail@example.com' );
|
38 |
-
define( 'WPMS_MAIL_FROM_FORCE', true ); // True turns it on, false turns it off.
|
39 |
-
define( 'WPMS_MAIL_FROM_NAME', 'From Name' );
|
40 |
-
define( 'WPMS_MAIL_FROM_NAME_FORCE', true ); // True turns it on, false turns it off.
|
41 |
-
define( 'WPMS_MAILER', 'sendinblue' ); // Possible values: 'mail', 'sendinblue', 'mailgun', 'sendgrid', 'gmail', 'smtp'.
|
42 |
-
define( 'WPMS_SET_RETURN_PATH', true ); // Sets $phpmailer->Sender if true, relevant only for Other SMTP mailer.
|
43 |
-
|
44 |
-
// Recommended
|
45 |
-
define( '
|
46 |
-
|
47 |
-
|
48 |
-
define( '
|
49 |
-
define( '
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
define( '
|
55 |
-
|
56 |
-
|
57 |
-
define( '
|
58 |
-
define( '
|
59 |
-
define( '
|
60 |
-
define( '
|
61 |
-
define( '
|
62 |
-
define( '
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
*
|
68 |
-
*
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
*
|
76 |
-
*
|
77 |
-
*
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
*
|
94 |
-
*
|
95 |
-
*
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
*
|
126 |
-
*
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
}
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
*
|
154 |
-
*
|
155 |
-
*
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Plugin Name: WP Mail SMTP
|
4 |
+
* Version: 1.8.0
|
5 |
+
* Plugin URI: https://wpmailsmtp.com/
|
6 |
+
* Description: Reconfigures the <code>wp_mail()</code> function to use Gmail/Mailgun/SendGrid/SMTP instead of the default <code>mail()</code> and creates an options page to manage the settings.
|
7 |
+
* Author: WPForms
|
8 |
+
* Author URI: https://wpforms.com/
|
9 |
+
* Network: false
|
10 |
+
* Text Domain: wp-mail-smtp
|
11 |
+
* Domain Path: /assets/languages
|
12 |
+
*/
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @author WPForms
|
16 |
+
* @copyright WPForms, 2007-19, All Rights Reserved
|
17 |
+
* This code is released under the GPL licence version 3 or later, available here
|
18 |
+
* https://www.gnu.org/licenses/gpl.txt
|
19 |
+
*/
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Setting options in wp-config.php
|
23 |
+
*
|
24 |
+
* Specifically aimed at WP Multisite users, you can set the options for this plugin as
|
25 |
+
* constants in wp-config.php. Copy the code below into wp-config.php and tweak settings.
|
26 |
+
* Values from constants are NOT stripslash()'ed.
|
27 |
+
*
|
28 |
+
* When enabled, make sure to comment out (at the beginning of the line using //) those constants that you do not need,
|
29 |
+
* or remove them completely, so they won't interfere with plugin settings.
|
30 |
+
*/
|
31 |
+
|
32 |
+
/*
|
33 |
+
define( 'WPMS_ON', true ); // True turns on the whole constants support and usage, false turns it off.
|
34 |
+
|
35 |
+
define( 'WPMS_DO_NOT_SEND', true ); // Or false, in that case constant is ignored.
|
36 |
+
|
37 |
+
define( 'WPMS_MAIL_FROM', 'mail@example.com' );
|
38 |
+
define( 'WPMS_MAIL_FROM_FORCE', true ); // True turns it on, false turns it off.
|
39 |
+
define( 'WPMS_MAIL_FROM_NAME', 'From Name' );
|
40 |
+
define( 'WPMS_MAIL_FROM_NAME_FORCE', true ); // True turns it on, false turns it off.
|
41 |
+
define( 'WPMS_MAILER', 'sendinblue' ); // Possible values: 'mail', 'sendinblue', 'mailgun', 'sendgrid', 'gmail', 'smtp'.
|
42 |
+
define( 'WPMS_SET_RETURN_PATH', true ); // Sets $phpmailer->Sender if true, relevant only for Other SMTP mailer.
|
43 |
+
|
44 |
+
// Recommended mailers.
|
45 |
+
define( 'WPMS_PEPIPOST_API_KEY', '' );
|
46 |
+
define( 'WPMS_SENDINBLUE_API_KEY', '' );
|
47 |
+
|
48 |
+
define( 'WPMS_MAILGUN_API_KEY', '' );
|
49 |
+
define( 'WPMS_MAILGUN_DOMAIN', '' );
|
50 |
+
define( 'WPMS_MAILGUN_REGION', 'US' ); // or 'EU' for Europe.
|
51 |
+
|
52 |
+
define( 'WPMS_SENDGRID_API_KEY', '' );
|
53 |
+
|
54 |
+
define( 'WPMS_GMAIL_CLIENT_ID', '' );
|
55 |
+
define( 'WPMS_GMAIL_CLIENT_SECRET', '' );
|
56 |
+
|
57 |
+
define( 'WPMS_SMTP_HOST', 'localhost' ); // The SMTP mail host.
|
58 |
+
define( 'WPMS_SMTP_PORT', 25 ); // The SMTP server port number.
|
59 |
+
define( 'WPMS_SSL', '' ); // Possible values '', 'ssl', 'tls' - note TLS is not STARTTLS.
|
60 |
+
define( 'WPMS_SMTP_AUTH', true ); // True turns it on, false turns it off.
|
61 |
+
define( 'WPMS_SMTP_USER', 'username' ); // SMTP authentication username, only used if WPMS_SMTP_AUTH is true.
|
62 |
+
define( 'WPMS_SMTP_PASS', 'password' ); // SMTP authentication password, only used if WPMS_SMTP_AUTH is true.
|
63 |
+
define( 'WPMS_SMTP_AUTOTLS', true ); // True turns it on, false turns it off.
|
64 |
+
*/
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Don't allow multiple versions of 1.5.x (Lite and Pro) and above to be active.
|
68 |
+
*
|
69 |
+
* @since 1.5.0
|
70 |
+
*/
|
71 |
+
if ( function_exists( 'wp_mail_smtp' ) ) {
|
72 |
+
|
73 |
+
if ( ! function_exists( 'wp_mail_smtp_deactivate' ) ) {
|
74 |
+
/**
|
75 |
+
* Deactivate if plugin already activated.
|
76 |
+
* Needed when transitioning from 1.5+ Lite to Pro.
|
77 |
+
*
|
78 |
+
* @since 1.5.0
|
79 |
+
*/
|
80 |
+
function wp_mail_smtp_deactivate() {
|
81 |
+
|
82 |
+
deactivate_plugins( plugin_basename( __FILE__ ) );
|
83 |
+
}
|
84 |
+
}
|
85 |
+
add_action( 'admin_init', 'wp_mail_smtp_deactivate' );
|
86 |
+
|
87 |
+
// Do not process the plugin code further.
|
88 |
+
return;
|
89 |
+
}
|
90 |
+
|
91 |
+
if ( ! function_exists( 'wp_mail_smtp_check_pro_loading_allowed' ) ) {
|
92 |
+
/**
|
93 |
+
* Don't allow 1.4.x and below to break when 1.5+ Pro is activated.
|
94 |
+
* This will stop the current plugin from loading and display a message in admin area.
|
95 |
+
*
|
96 |
+
* @since 1.5.0
|
97 |
+
*/
|
98 |
+
function wp_mail_smtp_check_pro_loading_allowed() {
|
99 |
+
|
100 |
+
// Check for pro without using wp_mail_smtp()->is_pro(), because at this point it's too early.
|
101 |
+
if ( ! is_readable( rtrim( plugin_dir_path( __FILE__ ), '/\\' ) . '/src/Pro/Pro.php' ) ) {
|
102 |
+
// Currently, not a pro version of the plugin is loaded.
|
103 |
+
return false;
|
104 |
+
}
|
105 |
+
|
106 |
+
if ( ! function_exists( 'is_plugin_active' ) ) {
|
107 |
+
require_once ABSPATH . '/wp-admin/includes/plugin.php';
|
108 |
+
}
|
109 |
+
|
110 |
+
// Search for old plugin name.
|
111 |
+
if ( is_plugin_active( 'wp-mail-smtp/wp_mail_smtp.php' ) ) {
|
112 |
+
// As Pro is loaded and Lite too - deactivate *silently* itself not to break older SMTP plugin.
|
113 |
+
deactivate_plugins( plugin_basename( __FILE__ ) );
|
114 |
+
|
115 |
+
add_action( 'admin_notices', 'wp_mail_smtp_lite_deactivation_notice' );
|
116 |
+
|
117 |
+
return true;
|
118 |
+
}
|
119 |
+
|
120 |
+
return false;
|
121 |
+
}
|
122 |
+
|
123 |
+
if ( ! function_exists( 'wp_mail_smtp_lite_deactivation_notice' ) ) {
|
124 |
+
/**
|
125 |
+
* Display the notice after deactivation.
|
126 |
+
*
|
127 |
+
* @since 1.5.0
|
128 |
+
*/
|
129 |
+
function wp_mail_smtp_lite_deactivation_notice() {
|
130 |
+
|
131 |
+
echo '<div class="notice notice-warning"><p>' . esc_html__( 'Please deactivate the free version of the WP Mail SMTP plugin before activating WP Mail SMTP Pro.', 'wp-mail-smtp' ) . '</p></div>';
|
132 |
+
|
133 |
+
if ( isset( $_GET['activate'] ) ) { // phpcs:ignore
|
134 |
+
unset( $_GET['activate'] ); // phpcs:ignore
|
135 |
+
}
|
136 |
+
}
|
137 |
+
}
|
138 |
+
|
139 |
+
// Stop the plugin loading.
|
140 |
+
if ( wp_mail_smtp_check_pro_loading_allowed() === true ) {
|
141 |
+
return;
|
142 |
+
}
|
143 |
+
}
|
144 |
+
|
145 |
+
if ( ! defined( 'WPMS_PLUGIN_VER' ) ) {
|
146 |
+
define( 'WPMS_PLUGIN_VER', '1.8.0' );
|
147 |
+
}
|
148 |
+
if ( ! defined( 'WPMS_PHP_VER' ) ) {
|
149 |
+
define( 'WPMS_PHP_VER', '5.3.6' );
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Newer PHP version 5.3+ will be handled a lot differently,
|
154 |
+
* with better code and newer logic.
|
155 |
+
*
|
156 |
+
* @since 1.0.0
|
157 |
+
*/
|
158 |
+
if ( version_compare( phpversion(), WPMS_PHP_VER, '>=' ) ) {
|
159 |
+
require_once dirname( __FILE__ ) . '/wp-mail-smtp.php';
|
160 |
+
|
161 |
+
return;
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* PHP 5.2 only.
|
166 |
+
*/
|
167 |
+
require_once dirname( __FILE__ ) . '/wp-mail-smtp-0.11.2.php';
|