WP Mail SMTP by WPForms - Version 1.0.0

Version Description

  • 2017-12-12 =
  • Added: Automatic migration tool to move options from older storage format to a new one.
  • Added: Added Gmail & G Suite email provider integration - without your email and password.
  • Added: Added SendGrid email provider integration - using the API key only.
  • Added: Added Mailgun email provider integration - using the API key and configured domain only.
  • 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.
  • Changed: The new look of the admin area.
  • Changed: SMTP password field now has "password" type.
  • Changed: SMTP password field does not display real password at all when using constants in wp-config.php to define it.
  • Changed: Escape properly all translations.
  • Changed: More helpful test email content (with a mailer name).
Download this release

Release Info

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

Code changes from version 0.11.2 to 1.0.0

Files changed (228) hide show
  1. assets/css/smtp-admin.min.css +3 -0
  2. assets/images/gmail.png +0 -0
  3. assets/images/logo.png +0 -0
  4. assets/images/mailgun.png +0 -0
  5. assets/images/pepipost.png +0 -0
  6. assets/images/php.png +0 -0
  7. assets/images/sendgrid.png +0 -0
  8. assets/images/smtp.png +0 -0
  9. assets/js/smtp-admin.js +36 -0
  10. assets/js/smtp-admin.min.js +1 -0
  11. class-wpms-am-notification.php +9 -27
  12. languages/wp-mail-smtp.pot +315 -47
  13. readme.txt +108 -43
  14. src/AM_Notification.php +452 -0
  15. src/Admin/Area.php +450 -0
  16. src/Admin/PageAbstract.php +66 -0
  17. src/Admin/PageInterface.php +45 -0
  18. src/Admin/Pages/Auth.php +56 -0
  19. src/Admin/Pages/Misc.php +99 -0
  20. src/Admin/Pages/Settings.php +236 -0
  21. src/Admin/Pages/Test.php +208 -0
  22. src/Core.php +213 -0
  23. src/MailCatcher.php +66 -0
  24. src/Migration.php +245 -0
  25. src/Options.php +469 -0
  26. src/Processor.php +169 -0
  27. src/Providers/AuthAbstract.php +22 -0
  28. src/Providers/AuthInterface.php +19 -0
  29. src/Providers/Gmail/Auth.php +299 -0
  30. src/Providers/Gmail/Mailer.php +173 -0
  31. src/Providers/Gmail/Options.php +131 -0
  32. src/Providers/Loader.php +178 -0
  33. src/Providers/Mail/Options.php +42 -0
  34. src/Providers/MailerAbstract.php +346 -0
  35. src/Providers/MailerInterface.php +139 -0
  36. src/Providers/Mailgun/Mailer.php +299 -0
  37. src/Providers/Mailgun/Options.php +106 -0
  38. src/Providers/OptionAbstract.php +291 -0
  39. src/Providers/OptionInterface.php +64 -0
  40. src/Providers/Pepipost/Options.php +29 -0
  41. src/Providers/SMTP/Options.php +45 -0
  42. src/Providers/Sendgrid/Mailer.php +294 -0
  43. src/Providers/Sendgrid/Options.php +89 -0
  44. src/WP.php +140 -0
  45. vendor/autoload.php +7 -0
  46. vendor/composer/ClassLoader.php +413 -0
  47. vendor/composer/LICENSE +21 -0
  48. vendor/composer/autoload_classmap.php +11 -0
  49. vendor/composer/autoload_files.php +27 -0
  50. vendor/composer/autoload_namespaces.php +11 -0
  51. vendor/composer/autoload_psr4.php +20 -0
  52. vendor/composer/autoload_real.php +70 -0
  53. vendor/composer/autoload_static.php +138 -0
  54. vendor/google/apiclient-services/LICENSE +203 -0
  55. vendor/google/apiclient-services/src/Google/Service/Gmail.php +1136 -0
  56. vendor/google/apiclient-services/src/Google/Service/Gmail/AutoForwarding.php +48 -0
  57. vendor/google/apiclient-services/src/Google/Service/Gmail/BatchDeleteMessagesRequest.php +31 -0
  58. vendor/google/apiclient-services/src/Google/Service/Gmail/BatchModifyMessagesRequest.php +49 -0
  59. vendor/google/apiclient-services/src/Google/Service/Gmail/Draft.php +46 -0
  60. vendor/google/apiclient-services/src/Google/Service/Gmail/Filter.php +62 -0
  61. vendor/google/apiclient-services/src/Google/Service/Gmail/FilterAction.php +49 -0
  62. vendor/google/apiclient-services/src/Google/Service/Gmail/FilterCriteria.php +102 -0
  63. vendor/google/apiclient-services/src/Google/Service/Gmail/ForwardingAddress.php +39 -0
  64. vendor/google/apiclient-services/src/Google/Service/Gmail/History.php +111 -0
  65. vendor/google/apiclient-services/src/Google/Service/Gmail/HistoryLabelAdded.php +47 -0
  66. vendor/google/apiclient-services/src/Google/Service/Gmail/HistoryLabelRemoved.php +47 -0
  67. vendor/google/apiclient-services/src/Google/Service/Gmail/HistoryMessageAdded.php +37 -0
  68. vendor/google/apiclient-services/src/Google/Service/Gmail/HistoryMessageDeleted.php +37 -0
  69. vendor/google/apiclient-services/src/Google/Service/Gmail/ImapSettings.php +57 -0
  70. vendor/google/apiclient-services/src/Google/Service/Gmail/Label.php +102 -0
  71. vendor/google/apiclient-services/src/Google/Service/Gmail/ListDraftsResponse.php +56 -0
  72. vendor/google/apiclient-services/src/Google/Service/Gmail/ListFiltersResponse.php +38 -0
  73. vendor/google/apiclient-services/src/Google/Service/Gmail/ListForwardingAddressesResponse.php +38 -0
  74. vendor/google/apiclient-services/src/Google/Service/Gmail/ListHistoryResponse.php +56 -0
  75. vendor/google/apiclient-services/src/Google/Service/Gmail/ListLabelsResponse.php +38 -0
  76. vendor/google/apiclient-services/src/Google/Service/Gmail/ListMessagesResponse.php +56 -0
  77. vendor/google/apiclient-services/src/Google/Service/Gmail/ListSendAsResponse.php +38 -0
  78. vendor/google/apiclient-services/src/Google/Service/Gmail/ListSmimeInfoResponse.php +38 -0
  79. vendor/google/apiclient-services/src/Google/Service/Gmail/ListThreadsResponse.php +56 -0
  80. vendor/google/apiclient-services/src/Google/Service/Gmail/Message.php +110 -0
  81. vendor/google/apiclient-services/src/Google/Service/Gmail/MessagePart.php +97 -0
  82. vendor/google/apiclient-services/src/Google/Service/Gmail/MessagePartBody.php +48 -0
  83. vendor/google/apiclient-services/src/Google/Service/Gmail/MessagePartHeader.php +39 -0
  84. vendor/google/apiclient-services/src/Google/Service/Gmail/ModifyMessageRequest.php +40 -0
  85. vendor/google/apiclient-services/src/Google/Service/Gmail/ModifyThreadRequest.php +40 -0
  86. vendor/google/apiclient-services/src/Google/Service/Gmail/PopSettings.php +39 -0
  87. vendor/google/apiclient-services/src/Google/Service/Gmail/Profile.php +57 -0
  88. vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/Users.php +71 -0
  89. vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersDrafts.php +130 -0
  90. vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersHistory.php +61 -0
  91. vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersLabels.php +120 -0
  92. vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersMessages.php +229 -0
  93. vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersMessagesAttachments.php +44 -0
  94. vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettings.php +149 -0
  95. vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsFilters.php +86 -0
  96. vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsForwardingAddresses.php +97 -0
  97. vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsSendAs.php +162 -0
  98. vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsSendAsSmimeInfo.php +115 -0
  99. vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersThreads.php +135 -0
  100. vendor/google/apiclient-services/src/Google/Service/Gmail/SendAs.php +109 -0
  101. vendor/google/apiclient-services/src/Google/Service/Gmail/SmimeInfo.php +84 -0
  102. vendor/google/apiclient-services/src/Google/Service/Gmail/SmtpMsa.php +66 -0
  103. vendor/google/apiclient-services/src/Google/Service/Gmail/Thread.php +65 -0
  104. vendor/google/apiclient-services/src/Google/Service/Gmail/VacationSettings.php +93 -0
  105. vendor/google/apiclient-services/src/Google/Service/Gmail/WatchRequest.php +49 -0
  106. vendor/google/apiclient-services/src/Google/Service/Gmail/WatchResponse.php +39 -0
  107. vendor/google/apiclient/LICENSE +203 -0
  108. vendor/google/apiclient/src/Google/AccessToken/Revoke.php +78 -0
  109. vendor/google/apiclient/src/Google/AccessToken/Verify.php +272 -0
  110. vendor/google/apiclient/src/Google/AuthHandler/AuthHandlerFactory.php +42 -0
  111. vendor/google/apiclient/src/Google/AuthHandler/Guzzle5AuthHandler.php +99 -0
  112. vendor/google/apiclient/src/Google/AuthHandler/Guzzle6AuthHandler.php +106 -0
  113. vendor/google/apiclient/src/Google/Client.php +1118 -0
  114. vendor/google/apiclient/src/Google/Collection.php +100 -0
  115. vendor/google/apiclient/src/Google/Exception.php +20 -0
  116. vendor/google/apiclient/src/Google/Http/Batch.php +249 -0
  117. vendor/google/apiclient/src/Google/Http/MediaFileUpload.php +351 -0
  118. vendor/google/apiclient/src/Google/Http/REST.php +182 -0
  119. vendor/google/apiclient/src/Google/Model.php +317 -0
  120. vendor/google/apiclient/src/Google/Service.php +56 -0
  121. vendor/google/apiclient/src/Google/Service/Exception.php +68 -0
  122. vendor/google/apiclient/src/Google/Service/Resource.php +296 -0
  123. vendor/google/apiclient/src/Google/Task/Exception.php +20 -0
  124. vendor/google/apiclient/src/Google/Task/Retryable.php +24 -0
  125. vendor/google/apiclient/src/Google/Task/Runner.php +281 -0
  126. vendor/google/apiclient/src/Google/Utils/UriTemplate.php +333 -0
  127. vendor/google/apiclient/src/Google/autoload.php +21 -0
  128. vendor/google/auth/COPYING +202 -0
  129. vendor/google/auth/LICENSE +203 -0
  130. vendor/google/auth/autoload.php +34 -0
  131. vendor/google/auth/src/ApplicationDefaultCredentials.php +173 -0
  132. vendor/google/auth/src/Cache/InvalidArgumentException.php +24 -0
  133. vendor/google/auth/src/Cache/Item.php +185 -0
  134. vendor/google/auth/src/Cache/MemoryCacheItemPool.php +154 -0
  135. vendor/google/auth/src/CacheTrait.php +83 -0
  136. vendor/google/auth/src/Credentials/AppIdentityCredentials.php +159 -0
  137. vendor/google/auth/src/Credentials/GCECredentials.php +219 -0
  138. vendor/google/auth/src/Credentials/IAMCredentials.php +89 -0
  139. vendor/google/auth/src/Credentials/ServiceAccountCredentials.php +177 -0
  140. vendor/google/auth/src/Credentials/ServiceAccountJwtAccessCredentials.php +131 -0
  141. vendor/google/auth/src/Credentials/UserRefreshCredentials.php +110 -0
  142. vendor/google/auth/src/CredentialsLoader.php +210 -0
  143. vendor/google/auth/src/FetchAuthTokenCache.php +108 -0
  144. vendor/google/auth/src/FetchAuthTokenInterface.php +55 -0
  145. vendor/google/auth/src/HttpHandler/Guzzle5HttpHandler.php +68 -0
  146. vendor/google/auth/src/HttpHandler/Guzzle6HttpHandler.php +36 -0
  147. vendor/google/auth/src/HttpHandler/HttpHandlerFactory.php +47 -0
  148. vendor/google/auth/src/Middleware/AuthTokenMiddleware.php +126 -0
  149. vendor/google/auth/src/Middleware/ScopedAccessTokenMiddleware.php +175 -0
  150. vendor/google/auth/src/Middleware/SimpleMiddleware.php +93 -0
  151. vendor/google/auth/src/OAuth2.php +1335 -0
  152. vendor/google/auth/src/Subscriber/AuthTokenSubscriber.php +118 -0
  153. vendor/google/auth/src/Subscriber/ScopedAccessTokenSubscriber.php +177 -0
  154. vendor/google/auth/src/Subscriber/SimpleSubscriber.php +90 -0
  155. vendor/guzzlehttp/guzzle/LICENSE +19 -0
  156. vendor/guzzlehttp/guzzle/src/Client.php +414 -0
  157. vendor/guzzlehttp/guzzle/src/ClientInterface.php +84 -0
  158. vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php +314 -0
  159. vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php +84 -0
  160. vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php +90 -0
  161. vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php +71 -0
  162. vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php +404 -0
  163. vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php +27 -0
  164. vendor/guzzlehttp/guzzle/src/Exception/ClientException.php +7 -0
  165. vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php +37 -0
  166. vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php +4 -0
  167. vendor/guzzlehttp/guzzle/src/Exception/RequestException.php +217 -0
  168. vendor/guzzlehttp/guzzle/src/Exception/SeekException.php +27 -0
  169. vendor/guzzlehttp/guzzle/src/Exception/ServerException.php +7 -0
  170. vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php +4 -0
  171. vendor/guzzlehttp/guzzle/src/Exception/TransferException.php +4 -0
  172. vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php +559 -0
  173. vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php +27 -0
  174. vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php +45 -0
  175. vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php +197 -0
  176. vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php +92 -0
  177. vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php +189 -0
  178. vendor/guzzlehttp/guzzle/src/Handler/Proxy.php +55 -0
  179. vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php +533 -0
  180. vendor/guzzlehttp/guzzle/src/HandlerStack.php +273 -0
  181. vendor/guzzlehttp/guzzle/src/MessageFormatter.php +182 -0
  182. vendor/guzzlehttp/guzzle/src/Middleware.php +254 -0
  183. vendor/guzzlehttp/guzzle/src/Pool.php +123 -0
  184. vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php +106 -0
  185. vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php +237 -0
  186. vendor/guzzlehttp/guzzle/src/RequestOptions.php +255 -0
  187. vendor/guzzlehttp/guzzle/src/RetryMiddleware.php +112 -0
  188. vendor/guzzlehttp/guzzle/src/TransferStats.php +126 -0
  189. vendor/guzzlehttp/guzzle/src/UriTemplate.php +241 -0
  190. vendor/guzzlehttp/guzzle/src/functions.php +331 -0
  191. vendor/guzzlehttp/guzzle/src/functions_include.php +6 -0
  192. vendor/guzzlehttp/promises/LICENSE +19 -0
  193. vendor/guzzlehttp/promises/src/AggregateException.php +16 -0
  194. vendor/guzzlehttp/promises/src/CancellationException.php +9 -0
  195. vendor/guzzlehttp/promises/src/Coroutine.php +151 -0
  196. vendor/guzzlehttp/promises/src/EachPromise.php +229 -0
  197. vendor/guzzlehttp/promises/src/FulfilledPromise.php +82 -0
  198. vendor/guzzlehttp/promises/src/Promise.php +280 -0
  199. vendor/guzzlehttp/promises/src/PromiseInterface.php +93 -0
  200. vendor/guzzlehttp/promises/src/PromisorInterface.php +15 -0
  201. vendor/guzzlehttp/promises/src/RejectedPromise.php +87 -0
  202. vendor/guzzlehttp/promises/src/RejectionException.php +47 -0
  203. vendor/guzzlehttp/promises/src/TaskQueue.php +66 -0
  204. vendor/guzzlehttp/promises/src/TaskQueueInterface.php +25 -0
  205. vendor/guzzlehttp/promises/src/functions.php +457 -0
  206. vendor/guzzlehttp/promises/src/functions_include.php +6 -0
  207. vendor/guzzlehttp/psr7/LICENSE +19 -0
  208. vendor/guzzlehttp/psr7/src/AppendStream.php +233 -0
  209. vendor/guzzlehttp/psr7/src/BufferStream.php +137 -0
  210. vendor/guzzlehttp/psr7/src/CachingStream.php +138 -0
  211. vendor/guzzlehttp/psr7/src/DroppingStream.php +42 -0
  212. vendor/guzzlehttp/psr7/src/FnStream.php +149 -0
  213. vendor/guzzlehttp/psr7/src/InflateStream.php +52 -0
  214. vendor/guzzlehttp/psr7/src/LazyOpenStream.php +39 -0
  215. vendor/guzzlehttp/psr7/src/LimitStream.php +155 -0
  216. vendor/guzzlehttp/psr7/src/MessageTrait.php +183 -0
  217. vendor/guzzlehttp/psr7/src/MultipartStream.php +153 -0
  218. vendor/guzzlehttp/psr7/src/NoSeekStream.php +22 -0
  219. vendor/guzzlehttp/psr7/src/PumpStream.php +165 -0
  220. vendor/guzzlehttp/psr7/src/Request.php +142 -0
  221. vendor/guzzlehttp/psr7/src/Response.php +132 -0
  222. vendor/guzzlehttp/psr7/src/ServerRequest.php +358 -0
  223. vendor/guzzlehttp/psr7/src/Stream.php +257 -0
  224. vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php +149 -0
  225. vendor/guzzlehttp/psr7/src/StreamWrapper.php +121 -0
  226. vendor/guzzlehttp/psr7/src/UploadedFile.php +316 -0
  227. vendor/guzzlehttp/psr7/src/Uri.php +702 -0
  228. vendor/guzzlehttp/psr7/src/UriNormalizer.php +55 -0
assets/css/smtp-admin.min.css ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ #wpcontent{padding-left:0 !important;position:relative}@media (max-width: 320px){#wpcontent{padding-top:46px}}@media (max-width: 320px){#wpbody{padding-top:0}}#wp-mail-smtp-header{background-color:#f1f3f7;border-top:3px solid #FF982D;padding:20px}#wp-mail-smtp-header img{display:block;margin:0;max-width:242px}@media (max-width: 768px){#wp-mail-smtp-header img{max-width:200px}}#wp-mail-smtp{margin:0}#wp-mail-smtp .wp-mail-smtp-page-title{background-color:#fff;font-size:14px;margin:0 0 20px 0;padding:0 20px}#wp-mail-smtp .wp-mail-smtp-page-title a{border-bottom:2px solid #fff;box-shadow:none;color:#666;display:inline-block;margin-right:30px;padding:20px 0 18px 0;text-decoration:none}#wp-mail-smtp .wp-mail-smtp-page-title a.active{border-bottom:2px solid #FF982D}#wp-mail-smtp .wp-mail-smtp-page-title a:hover{border-color:#999}#wp-mail-smtp .wp-mail-smtp-page{padding:0 20px}#wp-mail-smtp .wp-mail-smtp-page *,#wp-mail-smtp .wp-mail-smtp-page *::before,#wp-mail-smtp .wp-mail-smtp-page *::after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-clear:before{content:" ";display:table}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-clear:after{clear:both;content:" ";display:table}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row{border-bottom:1px solid #e4e4e4;padding:30px 0;font-size:14px;line-height:1.3}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row:first-of-type{padding-top:10px !important}@media (max-width: 767px){#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row{padding:20px 0}}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.inactive{display:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.section-heading{padding:20px 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.section-heading.no-desc h2,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.section-heading.no-desc h4{margin:0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.section-heading .wp-mail-smtp-setting-field{margin:0;max-width:1000px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox input[type=checkbox]{float:left;margin:1px 0 0 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox input[type=checkbox]+label{margin:0 0 0 8px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox .desc{margin:0 0 0 30px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox input[type=checkbox]+label+.desc{margin:8px 0 0 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-text .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-password .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-number .wp-mail-smtp-setting-label,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-email .wp-mail-smtp-setting-label{padding-top:8px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-select .wp-mail-smtp-setting-label{padding-top:8px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-radio .wp-mail-smtp-setting-field input[type=radio]{margin:-3px 10px 0 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-radio .wp-mail-smtp-setting-field label{margin-right:30px;display:inline-block}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field label{vertical-align:middle;display:inline-block}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field label:hover .wp-mail-smtp-setting-toggle-switch{background-color:#999}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]{display:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:checked+.wp-mail-smtp-setting-toggle-switch{background-color:#83c11f}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:checked+.wp-mail-smtp-setting-toggle-switch:before{-webkit-transform:translateX(19px);-ms-transform:translateX(19px);transform:translateX(19px)}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:checked+.wp-mail-smtp-setting-toggle-switch+.wp-mail-smtp-setting-toggle-checked-label{display:inline-block}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field input[type=checkbox]:checked+.wp-mail-smtp-setting-toggle-switch+.wp-mail-smtp-setting-toggle-checked-label+.wp-mail-smtp-setting-toggle-unchecked-label{display:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-unchecked-label,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-checked-label{text-transform:uppercase;font-weight:700;font-size:13px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-checked-label{display:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-switch{position:relative;cursor:pointer;background-color:#ccc;border-radius:15px;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;vertical-align:middle;position:relative;display:inline-block;margin:0 5px 0 0;width:40px;height:20px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-checkbox-toggle .wp-mail-smtp-setting-field .wp-mail-smtp-setting-toggle-switch:before{position:absolute;content:"";height:14px;width:14px;left:3px;top:3px;background-color:#fff;border-radius:50%;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer{padding-bottom:20px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer{display:inline-block;width:140px;margin-right:10px;margin-bottom:10px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer:last-child{margin-right:0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer .wp-mail-smtp-mailer-image{background:#fff;text-align:center;border:2px solid #E5E5E5;border-radius:4px;height:76px;position:relative;margin-bottom:10px;cursor:pointer;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer .wp-mail-smtp-mailer-image img{display:block;position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);opacity:0.6;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer.active .wp-mail-smtp-mailer-image{border-color:#FF982D}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer.active .wp-mail-smtp-mailer-image img{opacity:1}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer:hover .wp-mail-smtp-mailer-image{border-color:#ccc}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row.wp-mail-smtp-setting-row-mailer .wp-mail-smtp-mailer:hover .wp-mail-smtp-mailer-image img{opacity:1}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row h2,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row h4{color:#444;font-size:20px;font-weight:700;margin:0 0 6px 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row h3{color:#444;font-size:24px;font-weight:600;margin:0 0 20px 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row p{margin:12px 0 0;font-size:14px;line-height:1.3}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row p:first-of-type{margin:8px 0 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row p.desc{font-style:italic;color:#666}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password]{background-color:#fff;border:1px solid #ddd;border-radius:3px;box-shadow:none;color:#333;display:inline-block;vertical-align:middle;padding:7px 12px;margin:0 10px 0 0;width:400px;min-height:35px}@media (max-width: 1023px){#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password]{width:300px}}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text][readonly],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email][readonly],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number][readonly],#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password][readonly]{background-color:#f9f9f9}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text].small-text,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email].small-text,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number].small-text,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password].small-text{width:75px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text]:focus,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email]:focus,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number]:focus,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password]:focus{border-color:#bbb}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=text]:disabled,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=email]:disabled,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=number]:disabled,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-row input[type=password]:disabled{opacity:0.6}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-label{display:block;float:left;width:200px;padding:0}@media (max-width: 767px){#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-label{float:none;width:100%;padding-bottom:15px}}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-label label{display:block;font-weight:600}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-field{display:block;margin:0 0 0 200px;max-width:800px}@media (max-width: 767px){#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-setting-field{margin:0}}#wp-mail-smtp .wp-mail-smtp-page p.wp-mail-smtp-submit{margin:0;padding:25px 0}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-mailer-options .wp-mail-smtp-mailer-option .wp-mail-smtp-setting-row.section-heading{padding:20px 0 !important}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-mailer-options .wp-mail-smtp-mailer-option blockquote{background:#E5E5E5;border-radius:4px;color:#666;font-size:14px;margin:20px 0;padding:15px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn{border:0;border-radius:3px;cursor:pointer;display:inline-block;margin:0;text-decoration:none;text-align:center;vertical-align:middle;white-space:nowrap;text-shadow:none;box-shadow:none;outline:none}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn .dashicons{font-size:16px;width:16px;height:16px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-block{display:block}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-md{font-size:13px;font-weight:600;padding:8px 12px;min-height:35px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-lg{font-size:16px;font-weight:600;padding:16px 28px}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-orange{background-color:#FF982D;border-color:#FF982D;color:#fff}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-orange:hover,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-orange:active,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-orange:focus{background-color:#f97f00;border-color:#f97f00}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-grey{background-color:#eee;border-color:#ccc;color:#666}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-grey:hover,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-grey:active,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-grey:focus{background-color:#d7d7d7;border-color:#ccc;color:#444}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-light-grey{background-color:#f5f5f5;border:1px solid #ccc;color:#666}#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-light-grey:hover,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-light-grey:active,#wp-mail-smtp .wp-mail-smtp-page .wp-mail-smtp-btn-light-grey:focus{background-color:#eee;color:#444}#wp-mail-smtp .wp-mail-smtp-page p{margin:0}#wp-mail-smtp .wp-mail-smtp-page .notice p{margin:0.5em 0}#wp-mail-smtp .wp-mail-smtp-page pre{white-space:pre-line}#wp-mail-smtp .wp-mail-smtp-page.active{display:block}
2
+
3
+ /*# sourceMappingURL=smtp-admin.min.css.map */
assets/images/gmail.png ADDED
Binary file
assets/images/logo.png ADDED
Binary file
assets/images/mailgun.png ADDED
Binary file
assets/images/pepipost.png ADDED
Binary file
assets/images/php.png ADDED
Binary file
assets/images/sendgrid.png ADDED
Binary file
assets/images/smtp.png ADDED
Binary file
assets/js/smtp-admin.js ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* globals jQuery */
2
+ jQuery( document ).ready( function ( $ ) {
3
+
4
+ $( '.wp-mail-smtp-mailer input' ).click( function () {
5
+ if ( $( this ).prop( 'disabled' ) ) {
6
+ return false;
7
+ }
8
+
9
+ // Deselect the current mailer.
10
+ $( '.wp-mail-smtp-mailer' ).removeClass( 'active' );
11
+ // Select the correct one.
12
+ $( this ).parents( '.wp-mail-smtp-mailer' ).addClass( 'active' );
13
+
14
+ $( '.wp-mail-smtp-mailer-option' ).addClass( 'hidden' ).removeClass( 'active' );
15
+ $( '.wp-mail-smtp-mailer-option-' + $( this ).val() ).addClass( 'active' ).removeClass( 'hidden' );
16
+ } );
17
+
18
+ $( '.wp-mail-smtp-mailer-image' ).click( function () {
19
+ $( this ).parents( '.wp-mail-smtp-mailer' ).find( 'input' ).trigger( 'click' );
20
+ } );
21
+
22
+ $( '.wp-mail-smtp-setting-copy' ).click( function ( e ) {
23
+ e.preventDefault();
24
+
25
+ var target = $( '#' + $( this ).data( 'source_id' ) ).get(0);
26
+
27
+ target.select();
28
+
29
+ document.execCommand( 'Copy' );
30
+ } );
31
+
32
+ $( '#wp-mail-smtp-setting-smtp-auth' ).change(function() {
33
+ $( '#wp-mail-smtp-setting-row-smtp-user, #wp-mail-smtp-setting-row-smtp-pass' ).toggleClass( 'inactive' );
34
+ });
35
+
36
+ } );
assets/js/smtp-admin.min.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery(document).ready(function(i){i(".wp-mail-smtp-mailer input").click(function(){if(i(this).prop("disabled"))return!1;i(".wp-mail-smtp-mailer").removeClass("active"),i(this).parents(".wp-mail-smtp-mailer").addClass("active"),i(".wp-mail-smtp-mailer-option").addClass("hidden").removeClass("active"),i(".wp-mail-smtp-mailer-option-"+i(this).val()).addClass("active").removeClass("hidden")}),i(".wp-mail-smtp-mailer-image").click(function(){i(this).parents(".wp-mail-smtp-mailer").find("input").trigger("click")}),i(".wp-mail-smtp-setting-copy").click(function(t){t.preventDefault();i("#"+i(this).data("source_id")).get(0).select(),document.execCommand("Copy")}),i("#wp-mail-smtp-setting-smtp-auth").change(function(){i("#wp-mail-smtp-setting-row-smtp-user, #wp-mail-smtp-setting-row-smtp-pass").toggleClass("inactive")})});
class-wpms-am-notification.php CHANGED
@@ -10,7 +10,7 @@
10
  * @author Benjamin Rojas
11
  * @license GPL-2.0+
12
  * @copyright Copyright (c) 2017, Retyp LLC
13
- * @version 1.0.0
14
  */
15
  class WPMS_AM_Notification {
16
  /**
@@ -41,24 +41,6 @@ class WPMS_AM_Notification {
41
  */
42
  public $plugin_version;
43
 
44
- /**
45
- * The list of installed plugins.
46
- *
47
- * @since 1.0.0
48
- *
49
- * @var array
50
- */
51
- public $plugin_list = array();
52
-
53
- /**
54
- * The list of installed themes.
55
- *
56
- * @since 1.0.0
57
- *
58
- * @var string
59
- */
60
- public $theme_list = array();
61
-
62
  /**
63
  * Flag if a notice has been registered.
64
  *
@@ -93,7 +75,9 @@ class WPMS_AM_Notification {
93
  */
94
  public function custom_post_type() {
95
  register_post_type( 'amn_' . $this->plugin, array(
96
- 'supports' => false,
 
 
97
  ) );
98
  }
99
 
@@ -111,7 +95,7 @@ class WPMS_AM_Notification {
111
 
112
  if ( $last_checked < strtotime( 'today midnight' ) ) {
113
  $plugin_notifications = $this->get_plugin_notifications( 1 );
114
- $notification_id = null;
115
 
116
  if ( ! empty( $plugin_notifications ) ) {
117
  // Unset it from the array.
@@ -123,7 +107,7 @@ class WPMS_AM_Notification {
123
  'body' => array(
124
  'slug' => $this->plugin,
125
  'version' => $this->plugin_version,
126
- 'last_notification' => $notification_id
127
  ),
128
  ) ) );
129
 
@@ -156,8 +140,6 @@ class WPMS_AM_Notification {
156
  update_post_meta( $new_notification_id, 'type', sanitize_text_field( trim( $data->type ) ) );
157
  update_post_meta( $new_notification_id, 'dismissable', (bool) $data->dismissible ? 1 : 0 );
158
  update_post_meta( $new_notification_id, 'location', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->location ) : json_encode( $data->location ) );
159
- update_post_meta( $new_notification_id, 'plugins', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->plugins ) : json_encode( $data->plugins ) );
160
- update_post_meta( $new_notification_id, 'theme', sanitize_text_field( trim( $data->theme ) ) );
161
  update_post_meta( $new_notification_id, 'version', sanitize_text_field( trim( $data->version ) ) );
162
  update_post_meta( $new_notification_id, 'viewed', 0 );
163
  update_post_meta( $new_notification_id, 'expiration', $data->expiration ? absint( $data->expiration ) : false );
@@ -188,8 +170,8 @@ class WPMS_AM_Notification {
188
  public function get_plugin_notifications( $limit = -1, $args = array() ) {
189
  return get_posts(
190
  array(
191
- 'showposts' => $limit,
192
- 'post_type' => 'amn_' . $this->plugin,
193
  ) + $args
194
  );
195
  }
@@ -343,7 +325,7 @@ class WPMS_AM_Notification {
343
  */
344
  public function get_plan_level() {
345
  // Prepare variables.
346
- $key = '';
347
  $level = '';
348
  $option = false;
349
  switch ( $this->plugin ) {
10
  * @author Benjamin Rojas
11
  * @license GPL-2.0+
12
  * @copyright Copyright (c) 2017, Retyp LLC
13
+ * @version 1.0.2
14
  */
15
  class WPMS_AM_Notification {
16
  /**
41
  */
42
  public $plugin_version;
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  /**
45
  * Flag if a notice has been registered.
46
  *
75
  */
76
  public function custom_post_type() {
77
  register_post_type( 'amn_' . $this->plugin, array(
78
+ 'label' => $this->plugin . ' Announcements',
79
+ 'can_export' => false,
80
+ 'supports' => false,
81
  ) );
82
  }
83
 
95
 
96
  if ( $last_checked < strtotime( 'today midnight' ) ) {
97
  $plugin_notifications = $this->get_plugin_notifications( 1 );
98
+ $notification_id = null;
99
 
100
  if ( ! empty( $plugin_notifications ) ) {
101
  // Unset it from the array.
107
  'body' => array(
108
  'slug' => $this->plugin,
109
  'version' => $this->plugin_version,
110
+ 'last_notification' => $notification_id,
111
  ),
112
  ) ) );
113
 
140
  update_post_meta( $new_notification_id, 'type', sanitize_text_field( trim( $data->type ) ) );
141
  update_post_meta( $new_notification_id, 'dismissable', (bool) $data->dismissible ? 1 : 0 );
142
  update_post_meta( $new_notification_id, 'location', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->location ) : json_encode( $data->location ) );
 
 
143
  update_post_meta( $new_notification_id, 'version', sanitize_text_field( trim( $data->version ) ) );
144
  update_post_meta( $new_notification_id, 'viewed', 0 );
145
  update_post_meta( $new_notification_id, 'expiration', $data->expiration ? absint( $data->expiration ) : false );
170
  public function get_plugin_notifications( $limit = -1, $args = array() ) {
171
  return get_posts(
172
  array(
173
+ 'posts_per_page' => $limit,
174
+ 'post_type' => 'amn_' . $this->plugin,
175
  ) + $args
176
  );
177
  }
325
  */
326
  public function get_plan_level() {
327
  // Prepare variables.
328
+ $key = '';
329
  $level = '';
330
  $option = false;
331
  switch ( $this->plugin ) {
languages/wp-mail-smtp.pot CHANGED
@@ -14,190 +14,458 @@ msgstr ""
14
  "X-Poedit-SourceCharset: UTF-8\n"
15
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
16
 
17
- #: wp_mail_smtp.php:239
18
  msgid "Test mail to %s"
19
  msgstr ""
20
 
21
- #: wp_mail_smtp.php:240
22
  msgid "This is a test email generated by the WP Mail SMTP WordPress plugin."
23
  msgstr ""
24
 
25
- #: wp_mail_smtp.php:256
26
  msgid "Test Message Sent"
27
  msgstr ""
28
 
29
- #: wp_mail_smtp.php:257
30
  msgid "The result was:"
31
  msgstr ""
32
 
33
- #: wp_mail_smtp.php:260
34
  msgid "The full debugging output is shown below:"
35
  msgstr ""
36
 
37
- #: wp_mail_smtp.php:263
38
  msgid "The SMTP debugging output is shown below:"
39
  msgstr ""
40
 
41
- #: wp_mail_smtp.php:230, wp_mail_smtp.php:604
42
  msgid "Send Test"
43
  msgstr ""
44
 
45
- #: wp_mail_smtp.php:275, wp_mail_smtp.php:640
46
  msgid "WP Mail SMTP Settings"
47
  msgstr ""
48
 
49
- #: wp_mail_smtp.php:284
50
  msgid "From Email"
51
  msgstr ""
52
 
53
- #: wp_mail_smtp.php:291
54
  msgid "You can specify the email address that emails should be sent from. If you leave this blank, the default email will be used."
55
  msgstr ""
56
 
57
- #: wp_mail_smtp.php:294
58
  msgid "<strong>Please Note:</strong> You appear to be using a version of WordPress prior to 2.3. Please ignore the From Name field and instead enter Name&lt;email@domain.com&gt; in this field."
59
  msgstr ""
60
 
61
- #: wp_mail_smtp.php:303
62
  msgid "From Name"
63
  msgstr ""
64
 
65
- #: wp_mail_smtp.php:309
66
  msgid "You can specify the name that emails should be sent from. If you leave this blank, the emails will be sent from WordPress."
67
  msgstr ""
68
 
69
- #: wp_mail_smtp.php:318, wp_mail_smtp.php:323
70
  msgid "Mailer"
71
  msgstr ""
72
 
73
- #: wp_mail_smtp.php:328
74
  msgid "Send all WordPress emails via SMTP."
75
  msgstr ""
76
 
77
- #: wp_mail_smtp.php:332
78
  msgid "Use the PHP mail() function to send emails."
79
  msgstr ""
80
 
81
- #: wp_mail_smtp.php:338
82
  msgid "Use Pepipost SMTP to send emails."
83
  msgstr ""
84
 
85
- #: wp_mail_smtp.php:344
86
  msgid "Looking for high inbox delivery? Try Pepipost with easy setup and free emails. Learn more %1$shere%2$s."
87
  msgstr ""
88
 
89
- #: wp_mail_smtp.php:359, wp_mail_smtp.php:364
90
  msgid "Return Path"
91
  msgstr ""
92
 
93
- #: wp_mail_smtp.php:369
94
  msgid "Set the return-path to match the From Email"
95
  msgstr ""
96
 
97
- #: wp_mail_smtp.php:373
98
  msgid "Return Path indicates where non-delivery receipts - or bounce messages - are to be sent."
99
  msgstr ""
100
 
101
- #: wp_mail_smtp.php:383, wp_mail_smtp.php:388
102
  msgid "Hide Announcements"
103
  msgstr ""
104
 
105
- #: wp_mail_smtp.php:393
106
  msgid "Check this if you would like to hide plugin announcements and update details."
107
  msgstr ""
108
 
109
- #: wp_mail_smtp.php:401, wp_mail_smtp.php:501, wp_mail_smtp.php:577
110
  msgid "Save Changes"
111
  msgstr ""
112
 
113
- #: wp_mail_smtp.php:406
114
  msgid "SMTP Options"
115
  msgstr ""
116
 
117
- #: wp_mail_smtp.php:408
118
  msgid "These options only apply if you have chosen to send mail by SMTP above."
119
  msgstr ""
120
 
121
- #: wp_mail_smtp.php:413
122
  msgid "SMTP Host"
123
  msgstr ""
124
 
125
- #: wp_mail_smtp.php:421, wp_mail_smtp.php:539
126
  msgid "SMTP Port"
127
  msgstr ""
128
 
129
- #: wp_mail_smtp.php:428, wp_mail_smtp.php:432, wp_mail_smtp.php:547, wp_mail_smtp.php:553
130
  msgid "Encryption"
131
  msgstr ""
132
 
133
- #: wp_mail_smtp.php:437, wp_mail_smtp.php:559
134
  msgid "No encryption."
135
  msgstr ""
136
 
137
- #: wp_mail_smtp.php:442, wp_mail_smtp.php:564
138
  msgid "Use SSL encryption."
139
  msgstr ""
140
 
141
- #: wp_mail_smtp.php:447, wp_mail_smtp.php:569
142
  msgid "Use TLS encryption."
143
  msgstr ""
144
 
145
- #: wp_mail_smtp.php:450
146
  msgid "TLS is not the same as STARTTLS. For most servers SSL is the recommended option."
147
  msgstr ""
148
 
149
- #: wp_mail_smtp.php:455, wp_mail_smtp.php:459
150
  msgid "Authentication"
151
  msgstr ""
152
 
153
- #: wp_mail_smtp.php:464
154
  msgid "No: Do not use SMTP authentication."
155
  msgstr ""
156
 
157
- #: wp_mail_smtp.php:469
158
  msgid "Yes: Use SMTP authentication."
159
  msgstr ""
160
 
161
- #: wp_mail_smtp.php:473
162
  msgid "If this is set to no, the values below are ignored."
163
  msgstr ""
164
 
165
- #: wp_mail_smtp.php:480, wp_mail_smtp.php:523
166
  msgid "Username"
167
  msgstr ""
168
 
169
- #: wp_mail_smtp.php:488, wp_mail_smtp.php:531
170
  msgid "Password"
171
  msgstr ""
172
 
173
- #: wp_mail_smtp.php:494
174
  msgid "This is in plain text because it must not be stored encrypted."
175
  msgstr ""
176
 
177
- #: wp_mail_smtp.php:508
178
  msgid "Pepipost SMTP Options"
179
  msgstr ""
180
 
181
- #: wp_mail_smtp.php:514
182
  msgid "You need to signup on %s to get the SMTP username/password."
183
  msgstr ""
184
 
185
- #: wp_mail_smtp.php:586
186
  msgid "Send a Test Email"
187
  msgstr ""
188
 
189
- #: wp_mail_smtp.php:594
190
  msgid "To"
191
  msgstr ""
192
 
193
- #: wp_mail_smtp.php:598
194
  msgid "Type an email address here and then click Send Test to generate a test email."
195
  msgstr ""
196
 
197
- #: wp_mail_smtp.php:640
198
  msgid "WP Mail SMTP"
199
  msgstr ""
200
 
201
- #: wp_mail_smtp.php:746
202
  msgid "Settings"
203
  msgstr ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  "X-Poedit-SourceCharset: UTF-8\n"
15
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
16
 
17
+ #: wp_mail_smtp.php:251
18
  msgid "Test mail to %s"
19
  msgstr ""
20
 
21
+ #: wp_mail_smtp.php:252
22
  msgid "This is a test email generated by the WP Mail SMTP WordPress plugin."
23
  msgstr ""
24
 
25
+ #: wp_mail_smtp.php:268
26
  msgid "Test Message Sent"
27
  msgstr ""
28
 
29
+ #: wp_mail_smtp.php:269
30
  msgid "The result was:"
31
  msgstr ""
32
 
33
+ #: wp_mail_smtp.php:272
34
  msgid "The full debugging output is shown below:"
35
  msgstr ""
36
 
37
+ #: wp_mail_smtp.php:275
38
  msgid "The SMTP debugging output is shown below:"
39
  msgstr ""
40
 
41
+ #: wp_mail_smtp.php:242, wp_mail_smtp.php:616
42
  msgid "Send Test"
43
  msgstr ""
44
 
45
+ #: wp_mail_smtp.php:287, wp_mail_smtp.php:652
46
  msgid "WP Mail SMTP Settings"
47
  msgstr ""
48
 
49
+ #: wp_mail_smtp.php:296, src/Admin/Pages/Settings.php:57
50
  msgid "From Email"
51
  msgstr ""
52
 
53
+ #: wp_mail_smtp.php:303
54
  msgid "You can specify the email address that emails should be sent from. If you leave this blank, the default email will be used."
55
  msgstr ""
56
 
57
+ #: wp_mail_smtp.php:306
58
  msgid "<strong>Please Note:</strong> You appear to be using a version of WordPress prior to 2.3. Please ignore the From Name field and instead enter Name&lt;email@domain.com&gt; in this field."
59
  msgstr ""
60
 
61
+ #: wp_mail_smtp.php:315, src/Admin/Pages/Settings.php:84
62
  msgid "From Name"
63
  msgstr ""
64
 
65
+ #: wp_mail_smtp.php:321
66
  msgid "You can specify the name that emails should be sent from. If you leave this blank, the emails will be sent from WordPress."
67
  msgstr ""
68
 
69
+ #: wp_mail_smtp.php:330, wp_mail_smtp.php:335, src/Admin/Pages/Settings.php:108
70
  msgid "Mailer"
71
  msgstr ""
72
 
73
+ #: wp_mail_smtp.php:340
74
  msgid "Send all WordPress emails via SMTP."
75
  msgstr ""
76
 
77
+ #: wp_mail_smtp.php:344
78
  msgid "Use the PHP mail() function to send emails."
79
  msgstr ""
80
 
81
+ #: wp_mail_smtp.php:350
82
  msgid "Use Pepipost SMTP to send emails."
83
  msgstr ""
84
 
85
+ #: wp_mail_smtp.php:356
86
  msgid "Looking for high inbox delivery? Try Pepipost with easy setup and free emails. Learn more %1$shere%2$s."
87
  msgstr ""
88
 
89
+ #: wp_mail_smtp.php:371, wp_mail_smtp.php:376, src/Admin/Pages/Settings.php:141
90
  msgid "Return Path"
91
  msgstr ""
92
 
93
+ #: wp_mail_smtp.php:381, src/Admin/Pages/Settings.php:149
94
  msgid "Set the return-path to match the From Email"
95
  msgstr ""
96
 
97
+ #: wp_mail_smtp.php:385, src/Admin/Pages/Settings.php:151
98
  msgid "Return Path indicates where non-delivery receipts - or bounce messages - are to be sent."
99
  msgstr ""
100
 
101
+ #: wp_mail_smtp.php:395, wp_mail_smtp.php:400, src/Admin/Pages/Misc.php:55
102
  msgid "Hide Announcements"
103
  msgstr ""
104
 
105
+ #: wp_mail_smtp.php:405, src/Admin/Pages/Misc.php:62
106
  msgid "Check this if you would like to hide plugin announcements and update details."
107
  msgstr ""
108
 
109
+ #: wp_mail_smtp.php:413, wp_mail_smtp.php:513, wp_mail_smtp.php:589
110
  msgid "Save Changes"
111
  msgstr ""
112
 
113
+ #: wp_mail_smtp.php:418
114
  msgid "SMTP Options"
115
  msgstr ""
116
 
117
+ #: wp_mail_smtp.php:420
118
  msgid "These options only apply if you have chosen to send mail by SMTP above."
119
  msgstr ""
120
 
121
+ #: wp_mail_smtp.php:425, src/Providers/OptionAbstract.php:126
122
  msgid "SMTP Host"
123
  msgstr ""
124
 
125
+ #: wp_mail_smtp.php:433, wp_mail_smtp.php:551, src/Providers/OptionAbstract.php:140
126
  msgid "SMTP Port"
127
  msgstr ""
128
 
129
+ #: wp_mail_smtp.php:440, wp_mail_smtp.php:444, wp_mail_smtp.php:559, wp_mail_smtp.php:565, src/Providers/OptionAbstract.php:154
130
  msgid "Encryption"
131
  msgstr ""
132
 
133
+ #: wp_mail_smtp.php:449, wp_mail_smtp.php:571
134
  msgid "No encryption."
135
  msgstr ""
136
 
137
+ #: wp_mail_smtp.php:454, wp_mail_smtp.php:576
138
  msgid "Use SSL encryption."
139
  msgstr ""
140
 
141
+ #: wp_mail_smtp.php:459, wp_mail_smtp.php:581
142
  msgid "Use TLS encryption."
143
  msgstr ""
144
 
145
+ #: wp_mail_smtp.php:462, src/Providers/OptionAbstract.php:186
146
  msgid "TLS is not the same as STARTTLS. For most servers SSL is the recommended option."
147
  msgstr ""
148
 
149
+ #: wp_mail_smtp.php:467, wp_mail_smtp.php:471, src/Providers/OptionAbstract.php:195
150
  msgid "Authentication"
151
  msgstr ""
152
 
153
+ #: wp_mail_smtp.php:476
154
  msgid "No: Do not use SMTP authentication."
155
  msgstr ""
156
 
157
+ #: wp_mail_smtp.php:481
158
  msgid "Yes: Use SMTP authentication."
159
  msgstr ""
160
 
161
+ #: wp_mail_smtp.php:485
162
  msgid "If this is set to no, the values below are ignored."
163
  msgstr ""
164
 
165
+ #: wp_mail_smtp.php:492, wp_mail_smtp.php:535
166
  msgid "Username"
167
  msgstr ""
168
 
169
+ #: wp_mail_smtp.php:500, wp_mail_smtp.php:543
170
  msgid "Password"
171
  msgstr ""
172
 
173
+ #: wp_mail_smtp.php:506
174
  msgid "This is in plain text because it must not be stored encrypted."
175
  msgstr ""
176
 
177
+ #: wp_mail_smtp.php:520
178
  msgid "Pepipost SMTP Options"
179
  msgstr ""
180
 
181
+ #: wp_mail_smtp.php:526
182
  msgid "You need to signup on %s to get the SMTP username/password."
183
  msgstr ""
184
 
185
+ #: wp_mail_smtp.php:598, src/Admin/Pages/Test.php:48
186
  msgid "Send a Test Email"
187
  msgstr ""
188
 
189
+ #: wp_mail_smtp.php:606
190
  msgid "To"
191
  msgstr ""
192
 
193
+ #: wp_mail_smtp.php:610
194
  msgid "Type an email address here and then click Send Test to generate a test email."
195
  msgstr ""
196
 
197
+ #: wp_mail_smtp.php:652, src/Admin/Area.php:127
198
  msgid "WP Mail SMTP"
199
  msgstr ""
200
 
201
+ #: wp_mail_smtp.php:758, src/Admin/Area.php:363, src/Admin/Pages/Settings.php:25
202
  msgid "Settings"
203
  msgstr ""
204
+
205
+ #: src/Admin/Area.php:88
206
+ msgid "There was an error while processing the authentication request: %s. Please try again."
207
+ msgstr ""
208
+
209
+ #: src/Admin/Area.php:95
210
+ msgid "There was an error while processing the authentication request. Please try again."
211
+ msgstr ""
212
+
213
+ #: src/Admin/Area.php:102
214
+ msgid "There was an error while processing the authentication request. Please make sure that you have Client ID and Client Secret both valid and saved."
215
+ msgstr ""
216
+
217
+ #: src/Admin/Area.php:111
218
+ msgid "You have successfully linked the current site with you Google API project. Now you can start sending emails through Google."
219
+ msgstr ""
220
+
221
+ #: src/Admin/Area.php:126
222
+ msgid "WP Mail SMTP Options"
223
+ msgstr ""
224
+
225
+ #: src/Admin/Area.php:199
226
+ msgid "Please rate <strong>WP Mail SMTP</strong> <a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">&#9733;&#9733;&#9733;&#9733;&#9733;</a> on <a href=\"%2$s\" target=\"_blank\">WordPress.org</a> to help us spread the word. Thank you from the WP Mail SMTP team!"
227
+ msgstr ""
228
+
229
+ #: src/Providers/OptionAbstract.php:164
230
+ msgid "None"
231
+ msgstr ""
232
+
233
+ #: src/Providers/OptionAbstract.php:173
234
+ msgid "SSL"
235
+ msgstr ""
236
+
237
+ #: src/Providers/OptionAbstract.php:182
238
+ msgid "TLS"
239
+ msgstr ""
240
+
241
+ #: src/Providers/OptionAbstract.php:205
242
+ msgid "On"
243
+ msgstr ""
244
+
245
+ #: src/Providers/OptionAbstract.php:206
246
+ msgid "Off"
247
+ msgstr ""
248
+
249
+ #: src/Providers/OptionAbstract.php:214
250
+ msgid "SMTP Username"
251
+ msgstr ""
252
+
253
+ #: src/Providers/OptionAbstract.php:228
254
+ msgid "SMTP Password"
255
+ msgstr ""
256
+
257
+ #: src/Providers/OptionAbstract.php:242
258
+ msgid "The password is stored in plain text. We highly recommend you setup your password in your WordPress configuration file for improved security; to do this add the lines below to your %s file."
259
+ msgstr ""
260
+
261
+ #: src/Providers/OptionAbstract.php:279
262
+ msgid "%1$s requires PHP %2$s to work and does not support your current PHP version %3$s. Please contact your host and request a PHP upgrade to the latest one."
263
+ msgstr ""
264
+
265
+ #: src/Providers/OptionAbstract.php:286
266
+ msgid "Meanwhile you can switch to the \"Other SMTP\" Mailer option."
267
+ msgstr ""
268
+
269
+ #: src/Admin/Pages/Misc.php:24
270
+ msgid "Misc"
271
+ msgstr ""
272
+
273
+ #: src/Admin/Pages/Misc.php:48
274
+ msgid "General"
275
+ msgstr ""
276
+
277
+ #: src/Admin/Pages/Misc.php:67, src/Admin/Pages/Settings.php:182
278
+ msgid "Save Settings"
279
+ msgstr ""
280
+
281
+ #: src/Admin/Pages/Misc.php:95, src/Admin/Pages/Settings.php:232
282
+ msgid "Settings were successfully saved."
283
+ msgstr ""
284
+
285
+ #: src/Admin/Pages/Settings.php:50
286
+ msgid "Mail"
287
+ msgstr ""
288
+
289
+ #: src/Admin/Pages/Settings.php:66
290
+ msgid "You can specify the email address that emails should be sent from."
291
+ msgstr ""
292
+
293
+ #: src/Admin/Pages/Settings.php:70
294
+ msgid "If you leave this blank, the default one will be used: %s."
295
+ msgstr ""
296
+
297
+ #: src/Admin/Pages/Settings.php:76
298
+ msgid "Please note if you are sending using an email provider (Gmail, Yahoo, Hotmail, Outlook.com, etc) this setting should be your email address for that account."
299
+ msgstr ""
300
+
301
+ #: src/Admin/Pages/Settings.php:93
302
+ msgid "You can specify the name that emails should be sent from."
303
+ msgstr ""
304
+
305
+ #: src/Admin/Pages/Settings.php:97
306
+ msgid "If you leave this blank, the emails will be sent from %s."
307
+ msgstr ""
308
+
309
+ #: src/Admin/Pages/Settings.php:152
310
+ msgid "If unchecked bounce messages may be lost."
311
+ msgstr ""
312
+
313
+ #: src/Admin/Pages/Test.php:26
314
+ msgid "Email Test"
315
+ msgstr ""
316
+
317
+ #: src/Admin/Pages/Test.php:55
318
+ msgid "Send To"
319
+ msgstr ""
320
+
321
+ #: src/Admin/Pages/Test.php:60
322
+ msgid "Type an email address here and then click a button below to generate a test email."
323
+ msgstr ""
324
+
325
+ #: src/Admin/Pages/Test.php:66
326
+ msgid "Send Email"
327
+ msgstr ""
328
+
329
+ #: src/Admin/Pages/Test.php:86
330
+ msgid "Test failed. Please use a valid email address and try to resend the test email."
331
+ msgstr ""
332
+
333
+ #: src/Admin/Pages/Test.php:110
334
+ msgid "Test email to %s"
335
+ msgstr ""
336
+
337
+ #: src/Admin/Pages/Test.php:113
338
+ msgid "This email was sent by %s mailer, and generated by the WP Mail SMTP WordPress plugin."
339
+ msgstr ""
340
+
341
+ #: src/Admin/Pages/Test.php:126
342
+ msgid "Your email was sent successfully!"
343
+ msgstr ""
344
+
345
+ #: src/Admin/Pages/Test.php:133
346
+ msgid "There was a problem while sending a test email."
347
+ msgstr ""
348
+
349
+ #: src/Admin/Pages/Test.php:134
350
+ msgid "The related debugging output is shown below:"
351
+ msgstr ""
352
+
353
+ #: src/Providers/Gmail/Options.php:25
354
+ msgid "Gmail"
355
+ msgstr ""
356
+
357
+ #: src/Providers/Gmail/Options.php:29
358
+ msgid "Send emails using your Gmail or G Suite (formerly Google Apps) account, all while keeping your login credentials safe. Other Google SMTP methods require enabling less secure apps in your account and entering your password. However, this integration uses the Google API to improve email delivery issues while keeping your site secure.<br><br>Read our %1$sGmail documentation%2$s to learn how to configure Gmail or G Suite."
359
+ msgstr ""
360
+
361
+ #: src/Providers/Gmail/Options.php:63
362
+ msgid "Client ID"
363
+ msgstr ""
364
+
365
+ #: src/Providers/Gmail/Options.php:77
366
+ msgid "Client Secret"
367
+ msgstr ""
368
+
369
+ #: src/Providers/Gmail/Options.php:91
370
+ msgid "Authorized redirect URI"
371
+ msgstr ""
372
+
373
+ #: src/Providers/Gmail/Options.php:99
374
+ msgid "Copy URL to clipboard"
375
+ msgstr ""
376
+
377
+ #: src/Providers/Gmail/Options.php:104
378
+ msgid "This is the path on your site that you will be redirected to after you have authenticated with Google."
379
+ msgstr ""
380
+
381
+ #: src/Providers/Gmail/Options.php:106
382
+ msgid "You need to copy this URL into \"Authorized redirect URIs\" field for you web application on Google APIs site for your project there."
383
+ msgstr ""
384
+
385
+ #: src/Providers/Gmail/Options.php:116
386
+ msgid "Authorize"
387
+ msgstr ""
388
+
389
+ #: src/Providers/Gmail/Options.php:120
390
+ msgid "Allow plugin to send emails using your Google account"
391
+ msgstr ""
392
+
393
+ #: src/Providers/Gmail/Options.php:123
394
+ msgid "Click the button above to confirm authorization."
395
+ msgstr ""
396
+
397
+ #: src/Providers/Mail/Options.php:25
398
+ msgid "Default (none)"
399
+ msgstr ""
400
+
401
+ #: src/Providers/Mail/Options.php:37
402
+ msgid "You currently have the native WordPress option selected. Please select any other Mailer option above to continue the setup."
403
+ msgstr ""
404
+
405
+ #: src/Providers/Mailgun/Options.php:25
406
+ msgid "Mailgun"
407
+ msgstr ""
408
+
409
+ #: src/Providers/Mailgun/Options.php:29
410
+ msgid "%1$sMailgun%2$s is one of the leading transactional email services trusted by over 10,000 website and application developers. They provide users 10,000 free emails per month.<br><br>Read our %3$sMailgun documentation%4$s to learn how to configure Mailgun and improve your email deliverability."
411
+ msgstr ""
412
+
413
+ #: src/Providers/Mailgun/Options.php:57
414
+ msgid "Private API Key"
415
+ msgstr ""
416
+
417
+ #: src/Providers/Mailgun/Options.php:69
418
+ msgid "Follow this link to get an API Key from Mailgun: %s."
419
+ msgstr ""
420
+
421
+ #: src/Providers/Mailgun/Options.php:71
422
+ msgid "Get a Private API Key"
423
+ msgstr ""
424
+
425
+ #: src/Providers/Mailgun/Options.php:82
426
+ msgid "Domain Name"
427
+ msgstr ""
428
+
429
+ #: src/Providers/Mailgun/Options.php:94
430
+ msgid "Follow this link to get a Domain Name from Mailgun: %s."
431
+ msgstr ""
432
+
433
+ #: src/Providers/Mailgun/Options.php:96
434
+ msgid "Get a Domain Name"
435
+ msgstr ""
436
+
437
+ #: src/Providers/Pepipost/Options.php:25
438
+ msgid "Pepipost"
439
+ msgstr ""
440
+
441
+ #: src/Providers/Sendgrid/Options.php:25
442
+ msgid "SendGrid"
443
+ msgstr ""
444
+
445
+ #: src/Providers/Sendgrid/Options.php:29
446
+ msgid "%1$sSendGrid%2$s is one of the leading transactional email services, sending over 35 billion emails every month. They provide users 100 free emails per month.<br><br>Read our %3$sSendGrid documentation%4$s to learn how to set up SendGrid and improve your email deliverability."
447
+ msgstr ""
448
+
449
+ #: src/Providers/Sendgrid/Options.php:57
450
+ msgid "API Key"
451
+ msgstr ""
452
+
453
+ #: src/Providers/Sendgrid/Options.php:69
454
+ msgid "Follow this link to get an API Key from SendGrid: %s."
455
+ msgstr ""
456
+
457
+ #: src/Providers/Sendgrid/Options.php:71
458
+ msgid "Create API Key"
459
+ msgstr ""
460
+
461
+ #: src/Providers/Sendgrid/Options.php:79
462
+ msgid "To send emails you will need only a %s access level for this API key."
463
+ msgstr ""
464
+
465
+ #: src/Providers/SMTP/Options.php:25
466
+ msgid "Other SMTP"
467
+ msgstr ""
468
+
469
+ #: src/Providers/SMTP/Options.php:29
470
+ msgid "Use the SMTP details provided by your hosting provider or email service.<br><br>To see recommended settings for the popular services as well as troubleshooting tips, check out our %1$sSMTP documentation%2$s."
471
+ msgstr ""
readme.txt CHANGED
@@ -1,36 +1,93 @@
1
  === WP Mail SMTP by WPForms ===
2
- Contributors: wpforms, smub, jaredatch, slaFFik
3
- Donate link: https://wpforms.com/
4
- Tags: mail, smtp, wp_mail, mailer, phpmailer
5
- Requires at least: 2.7
6
  Tested up to: 4.9
7
  Stable tag: trunk
 
8
 
9
  The most popular WordPress SMTP and PHP Mailer plugin. Trusted by over 700k sites.
10
 
11
  == Description ==
12
 
13
- This plugin reconfigures the wp_mail() function to use SMTP instead of mail() and creates an options page that allows you to specify various options.
14
 
15
- You can set the following options:
16
 
17
- * Specify the from name and email address for outgoing email.
18
- * Choose to send mail by SMTP or PHP's mail() function.
19
- * Specify an SMTP host (defaults to localhost).
20
- * Specify an SMTP port (defaults to 25).
21
- * Choose SSL / TLS encryption (not the same as STARTTLS).
22
- * Choose to use SMTP authentication or not (defaults to not).
23
- * Specify an SMTP username and password.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
- WP Mail SMTP plugin works with all major email services such as Gmail, Yahoo, Outlook, Microsoft Live, and any other email sending service that offers SMTP.
26
 
27
- = Why WP Mail SMTP =
28
 
29
- The goal of WP Mail SMTP plugin is to help fix the common "WordPress not sending an email issue".
30
 
31
- Often times an email sent out by your WordPress site either lands in the spam folder or get completely rejected by popular email providers.
32
 
33
- SMTP (Simple Mail Transfer Protocol) is the industry standard for sending emails. WP Mail SMTP helps you use proper authentication which increases email deliverability.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  = Credits =
36
 
@@ -40,11 +97,9 @@ You can try the <a href="https://wordpress.org/plugins/wpforms-lite/" rel="frien
40
 
41
  = What's Next =
42
 
43
- If you like this plugin, then consider checking out our other projects:
44
 
45
  * <a href="http://optinmonster.com/" rel="friend" title="OptinMonster">OptinMonster</a> - Get More Email Subscribers
46
- * <a href="http://soliloquywp.com/" rel="friend" title="Soliloquy">Soliloquy</a> - Best WordPress Slider Plugin
47
- * <a href="http://enviragallery.com/" rel="friend" title="Envira Gallery">Envira Gallery</a> - Best WordPress Gallery Plugin
48
  * <a href="https://www.monsterinsights.com/" rel="friend" title="MonsterInsights">MonsterInsights</a> - Best Google Analytics Plugin for WordPress
49
 
50
  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>.
@@ -54,28 +109,24 @@ Visit <a href="http://www.wpbeginner.com/" rel="friend" title="WPBeginner">WPBeg
54
  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>)
55
  2. Activate WP Mail SMTP by WPForms.
56
  3. Navigate to the Settings area of WP Mail SMTP in the WordPress admin.
57
- 4. Want to support us? Consider trying <a href="https://wpforms.com/?utm_source=wprepo&utm_medium=link&utm_campaign=liteversion" rel="friend" title="WPForms">WPForms Pro</a> - the best WordPress contact form plugin!
 
58
 
59
  == Frequently Asked Questions ==
60
 
61
- = My plugin still sends mail via the mail() function =
 
 
62
 
63
- If other plugins you're using are not coded to use the wp_mail() function but instead call PHP's mail() function directly, they will bypass the settings of this plugin. Normally, you can edit the other plugins and simply replace the `mail(` calls with `wp_mail(` (just adding wp_ in front) and this will work. I've tested this on a couple of plugins and it works, but it may not work on all plugins.
64
 
65
- = Will this plugin work with WordPress versions less than 2.7? =
66
 
67
- No. WordPress 2.7 changed the way options were updated, so the options page will only work on 2.7 or later.
68
 
69
- = Can I use this plugin to send email via Gmail / Google Apps =
70
 
71
- Yes. Use these settings:
72
- Mailer: SMTP
73
- SMTP Host: smtp.gmail.com
74
- SMTP Port: 465
75
- Encryption: SSL
76
- Authentication: Yes
77
- Username: your full gmail address
78
- Password: your mail password
79
 
80
  = Can you add feature x, y or z to the plugin? =
81
 
@@ -86,21 +137,35 @@ By all means please contact us to discuss features or options you'd like to see
86
 
87
  == Screenshots ==
88
 
89
- 1. Advanced Email Options
90
- 2. SMTP Options
91
- 3. Pepipost SMTP Options
92
- 4. Send a Test Email
 
 
93
 
94
  == Changelog ==
95
 
96
- = [0.11.2] - 2017-11-28 =
97
- * Added: Setting to hide annoucement feed.
 
 
 
 
 
 
 
 
 
 
 
 
98
  * Changed: Announcement feed data.
99
 
100
- = [0.11.1] - 2017-10-30 =
101
  * Fixed: Older PHP compatibility fix.
102
 
103
- = [0.11] - 2017-10-30 =
104
  * Added: Helper description to Return Path option.
105
  * Added: Filter `wp_mail_smtp_admin_test_email_smtp_debug` to increase the debug message verbosity.
106
  * Added: PHP 5.2 notice.
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: 3.6
 
5
  Tested up to: 4.9
6
  Stable tag: trunk
7
+ Requires PHP: 5.3
8
 
9
  The most popular WordPress SMTP and PHP Mailer plugin. Trusted by over 700k sites.
10
 
11
  == Description ==
12
 
13
+ = WordPress Mail SMTP Plugin =
14
 
15
+ Having problems with your WordPress site not sending emails? You're not alone. Over 700,000 websites use WP Mail SMTP to fix their email deliverability issues.
16
 
17
+ WP Mail SMTP fixes your email deliverability by reconfiguring the wp_mail() PHP function to use a proper SMTP provider.
18
+
19
+ = What is SMTP? =
20
+
21
+ SMTP (Simple Mail Transfer Protocol) is an industry standard for sending emails. SMTP helps increase email deliverability by using proper authentication.
22
+
23
+ Popular email clients like Gmail, Yahoo, Outlook, etc are constantly improving their services to reduce email spam. One of the things their spam tools look for is whether an email is originating from the location it claims to be originating from.
24
+
25
+ If the proper authentication isn't there, then the emails either go in your SPAM folder or worst not get delivered at all.
26
+
27
+ 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>.
28
+
29
+ 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.
30
+
31
+ The combination of two causes your WordPress emails to not get delivered.
32
+
33
+ = How does WP Mail SMTP work? =
34
+
35
+ WP Mail SMTP plugin allows you to easily reconfigure the wp_mail() function to use a trusted SMTP provider.
36
+
37
+ This helps you fix all WordPress not sending email issues.
38
+
39
+ WP Mail SMTP plugin includes four different SMTP setup options:
40
+
41
+ 1. Mailgun SMTP
42
+ 2. SendGrid SMTP
43
+ 3. Gmail SMTP
44
+ 4. All Other SMTP
45
+
46
+ For all options, you can specify the "from name" and "email address" for outgoing emails.
47
+
48
+ 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.
49
+
50
+ = Mailgun SMTP =
51
 
52
+ 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.
53
 
54
+ 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.
55
 
56
+ Read our <a href="https://wpforms.com/how-to-send-wordpress-emails-with-mailgun/" rel="friend">Mailgun documentation</a> for more details.
57
 
58
+ = Gmail SMTP =
59
 
60
+ 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.
61
+
62
+ 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.
63
+
64
+ Unlike other Gmail SMTP plugins, our Gmail SMTP option uses OAuth to authenticate your Google account, keeping your login information 100% secure.
65
+
66
+ Read our <a href="https://wpforms.com/how-to-securely-send-wordpress-emails-using-gmail-smtp/" rel="friend">Gmail documentation</a> for more details.
67
+
68
+ = SendGrid SMTP =
69
+
70
+ 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.
71
+
72
+ Read our <a href="https://wpforms.com/fix-wordpress-email-notifications-with-sendgrid/" rel="friend">SendGrid documentation</a> for more details.
73
+
74
+ = Other SMTP =
75
+
76
+ 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.
77
+
78
+ You can set the following options:
79
+
80
+ * Specify an SMTP host.
81
+ * Specify an SMTP port.
82
+ * Choose SSL / TLS encryption.
83
+ * Choose to use SMTP authentication or not.
84
+ * Specify an SMTP username and password.
85
+
86
+ WP Mail SMTP also gives you the option to insert your password in your wp-config.php file, so it's not visible in your WordPress settings.
87
+
88
+ To see recommended settings for the popular services as well as troubleshooting tips, check out our <a href="https://wpforms.com/docs/how-to-set-up-smtp-using-the-wp-mail-smtp-plugin/" rel="friend">SMTP documentation</a>.
89
+
90
+ We hope that you find WP Mail SMTP plugin helpful.
91
 
92
  = Credits =
93
 
97
 
98
  = What's Next =
99
 
100
+ If you like this plugin, then please consider checking out our other popular plugins:
101
 
102
  * <a href="http://optinmonster.com/" rel="friend" title="OptinMonster">OptinMonster</a> - Get More Email Subscribers
 
 
103
  * <a href="https://www.monsterinsights.com/" rel="friend" title="MonsterInsights">MonsterInsights</a> - Best Google Analytics Plugin for WordPress
104
 
105
  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>.
109
  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>)
110
  2. Activate WP Mail SMTP by WPForms.
111
  3. Navigate to the Settings area of WP Mail SMTP in the WordPress admin.
112
+ 4. Choose your SMTP option (Mailgun SMTP, SendGrid SMTP, Gmail SMTP, or Other SMTP) and follow the instructions to set it up.
113
+ 5. Want to support us? Consider trying <a href="https://wpforms.com/?utm_source=wprepo&utm_medium=link&utm_campaign=liteversion" rel="friend" title="WPForms">WPForms Pro</a> - the best WordPress contact form plugin!
114
 
115
  == Frequently Asked Questions ==
116
 
117
+ = Can I use this plugin to send email via Gmail, G Suite, Outlook.com, Office 365, Hotmail, Yahoo, or AOL SMTP? =
118
+
119
+ Yes! We have extensive documentation that covers setting up SMTP most popular email services.
120
 
121
+ <a href="How to Set Up WordPress SMTP Using WP Mail SMTP by WPForms" rel="friend">Read our docs</a> to see the correct SMTP settings for each service.
122
 
123
+ = Help! I need support or have an issue. =
124
 
125
+ Please read <a href="https://wordpress.org/support/topic/wp-mail-smtp-support-policy/">our support policy</a> for more information.
126
 
127
+ = I found a bug, now what? =
128
 
129
+ 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.
 
 
 
 
 
 
 
130
 
131
  = Can you add feature x, y or z to the plugin? =
132
 
137
 
138
  == Screenshots ==
139
 
140
+ 1. WP Mail SMTP Settings page
141
+ 2. Gmail / G Suite settings
142
+ 3. Mailgun settings
143
+ 4. SendGrid settings
144
+ 5. SMTP settings
145
+ 6. Send a Test Email
146
 
147
  == Changelog ==
148
 
149
+ = 1.0.0 - 2017-12-12 =
150
+ * Added: Automatic migration tool to move options from older storage format to a new one.
151
+ * Added: Added Gmail & G Suite email provider integration - without your email and password.
152
+ * Added: Added SendGrid email provider integration - using the API key only.
153
+ * Added: Added Mailgun email provider integration - using the API key and configured domain only.
154
+ * 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.
155
+ * Changed: The new look of the admin area.
156
+ * Changed: SMTP password field now has "password" type.
157
+ * Changed: SMTP password field does not display real password at all when using constants in `wp-config.php` to define it.
158
+ * Changed: Escape properly all translations.
159
+ * Changed: More helpful test email content (with a mailer name).
160
+
161
+ = 0.11.2 - 2017-11-28 =
162
+ * Added: Setting to hide announcement feed.
163
  * Changed: Announcement feed data.
164
 
165
+ = 0.11.1 - 2017-10-30 =
166
  * Fixed: Older PHP compatibility fix.
167
 
168
+ = 0.11 - 2017-10-30 =
169
  * Added: Helper description to Return Path option.
170
  * Added: Filter `wp_mail_smtp_admin_test_email_smtp_debug` to increase the debug message verbosity.
171
  * Added: PHP 5.2 notice.
src/AM_Notification.php ADDED
@@ -0,0 +1,452 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP;
4
+
5
+ /**
6
+ * Awesome Motive Notifications
7
+ *
8
+ * This creates a custom post type (if it doesn't exist) and calls the API to
9
+ * retrieve notifications for this product.
10
+ *
11
+ * @package AwesomeMotive
12
+ * @author Benjamin Rojas
13
+ * @license GPL-2.0+
14
+ * @copyright Copyright (c) 2017, Retyp LLC
15
+ * @version 1.0.2
16
+ */
17
+ class AM_Notification {
18
+ /**
19
+ * The api url we are calling.
20
+ *
21
+ * @since 1.0.0
22
+ *
23
+ * @var string
24
+ */
25
+ public $api_url = 'https://api.awesomemotive.com/v1/notification/';
26
+
27
+ /**
28
+ * A unique slug for this plugin.
29
+ * (Not the WordPress plugin slug)
30
+ *
31
+ * @since 1.0.0
32
+ *
33
+ * @var string
34
+ */
35
+ public $plugin;
36
+
37
+ /**
38
+ * The current plugin version.
39
+ *
40
+ * @since 1.0.0
41
+ *
42
+ * @var string
43
+ */
44
+ public $plugin_version;
45
+
46
+ /**
47
+ * Flag if a notice has been registered.
48
+ *
49
+ * @since 1.0.0
50
+ *
51
+ * @var bool
52
+ */
53
+ public static $registered = false;
54
+
55
+ /**
56
+ * Construct.
57
+ *
58
+ * @since 1.0.0
59
+ *
60
+ * @param string $plugin The plugin slug.
61
+ * @param mixed $version The version of the plugin.
62
+ */
63
+ public function __construct( $plugin = '', $version = 0 ) {
64
+ $this->plugin = $plugin;
65
+ $this->plugin_version = $version;
66
+
67
+ add_action( 'init', array( $this, 'custom_post_type' ) );
68
+ add_action( 'admin_init', array( $this, 'get_remote_notifications' ), 100 );
69
+ add_action( 'admin_notices', array( $this, 'display_notifications' ) );
70
+ add_action( 'wp_ajax_am_notification_dismiss', array( $this, 'dismiss_notification' ) );
71
+ }
72
+
73
+ /**
74
+ * Registers a custom post type.
75
+ *
76
+ * @since 1.0.0
77
+ */
78
+ public function custom_post_type() {
79
+ register_post_type( 'amn_' . $this->plugin, array(
80
+ 'label' => $this->plugin . ' Announcements',
81
+ 'can_export' => false,
82
+ 'supports' => false,
83
+ ) );
84
+ }
85
+
86
+ /**
87
+ * Retrieve the remote notifications if the time has expired.
88
+ *
89
+ * @since 1.0.0
90
+ */
91
+ public function get_remote_notifications() {
92
+ if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
93
+ return;
94
+ }
95
+
96
+ $last_checked = get_option( '_amn_' . $this->plugin . '_last_checked', strtotime( '-1 week' ) );
97
+
98
+ if ( $last_checked < strtotime( 'today midnight' ) ) {
99
+ $plugin_notifications = $this->get_plugin_notifications( 1 );
100
+ $notification_id = null;
101
+
102
+ if ( ! empty( $plugin_notifications ) ) {
103
+ // Unset it from the array.
104
+ $notification = $plugin_notifications[0];
105
+ $notification_id = get_post_meta( $notification->ID, 'notification_id', true );
106
+ }
107
+
108
+ $response = wp_remote_retrieve_body( wp_remote_post( $this->api_url, array(
109
+ 'body' => array(
110
+ 'slug' => $this->plugin,
111
+ 'version' => $this->plugin_version,
112
+ 'last_notification' => $notification_id,
113
+ ),
114
+ ) ) );
115
+
116
+ $data = json_decode( $response );
117
+
118
+ if ( ! empty( $data->id ) ) {
119
+ $notifications = array();
120
+
121
+ foreach ( (array) $data->slugs as $slug ) {
122
+ $notifications = array_merge(
123
+ $notifications,
124
+ (array) get_posts(
125
+ array(
126
+ 'post_type' => 'amn_' . $slug,
127
+ 'post_status' => 'all',
128
+ 'meta_key' => 'notification_id',
129
+ 'meta_value' => $data->id,
130
+ )
131
+ )
132
+ );
133
+ }
134
+
135
+ if ( empty( $notifications ) ) {
136
+ $new_notification_id = wp_insert_post( array(
137
+ 'post_content' => wp_kses_post( $data->content ),
138
+ 'post_type' => 'amn_' . $this->plugin,
139
+ ) );
140
+
141
+ update_post_meta( $new_notification_id, 'notification_id', absint( $data->id ) );
142
+ update_post_meta( $new_notification_id, 'type', sanitize_text_field( trim( $data->type ) ) );
143
+ update_post_meta( $new_notification_id, 'dismissable', (bool) $data->dismissible ? 1 : 0 );
144
+ update_post_meta( $new_notification_id, 'location', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->location ) : json_encode( $data->location ) );
145
+ update_post_meta( $new_notification_id, 'version', sanitize_text_field( trim( $data->version ) ) );
146
+ update_post_meta( $new_notification_id, 'viewed', 0 );
147
+ update_post_meta( $new_notification_id, 'expiration', $data->expiration ? absint( $data->expiration ) : false );
148
+ update_post_meta( $new_notification_id, 'plans', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->plans ) : json_encode( $data->plans ) );
149
+ }
150
+ }
151
+
152
+ // Possibly revoke notifications.
153
+ if ( ! empty( $data->revoked ) ) {
154
+ $this->revoke_notifications( $data->revoked );
155
+ }
156
+
157
+ // Set the option now so we can't run this again until after 24 hours.
158
+ update_option( '_amn_' . $this->plugin . '_last_checked', strtotime( 'today midnight' ) );
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Get local plugin notifications that have already been set.
164
+ *
165
+ * @since 1.0.0
166
+ *
167
+ * @param integer $limit Set the limit for how many posts to retrieve.
168
+ * @param array $args Any top-level arguments to add to the array.
169
+ *
170
+ * @return WP_Post[] WP_Post that match the query.
171
+ */
172
+ public function get_plugin_notifications( $limit = -1, $args = array() ) {
173
+ return get_posts(
174
+ array(
175
+ 'posts_per_page' => $limit,
176
+ 'post_type' => 'amn_' . $this->plugin,
177
+ ) + $args
178
+ );
179
+ }
180
+
181
+ /**
182
+ * Display any notifications that should be displayed.
183
+ *
184
+ * @since 1.0.0
185
+ */
186
+ public function display_notifications() {
187
+ if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
188
+ return;
189
+ }
190
+
191
+ $plugin_notifications = $this->get_plugin_notifications( -1, array(
192
+ 'post_status' => 'all',
193
+ 'meta_key' => 'viewed',
194
+ 'meta_value' => '0',
195
+ ) );
196
+
197
+ $plugin_notifications = $this->validate_notifications( $plugin_notifications );
198
+
199
+ if ( ! empty( $plugin_notifications ) && ! self::$registered ) {
200
+ foreach ( $plugin_notifications as $notification ) {
201
+ $dismissable = get_post_meta( $notification->ID, 'dismissable', true );
202
+ $type = get_post_meta( $notification->ID, 'type', true );
203
+ ?>
204
+ <div class="am-notification am-notification-<?php echo $notification->ID; ?> notice notice-<?php echo $type; ?><?php echo $dismissable ? ' is-dismissible' : ''; ?>">
205
+ <?php echo $notification->post_content; ?>
206
+ </div>
207
+ <script type="text/javascript">
208
+ jQuery(document).ready(function ($) {
209
+ $(document).on('click', '.am-notification-<?php echo $notification->ID; ?> button.notice-dismiss', function (event) {
210
+ $.post(ajaxurl, {
211
+ action: 'am_notification_dismiss',
212
+ notification_id: '<?php echo $notification->ID; ?>'
213
+ });
214
+ });
215
+ });
216
+ </script>
217
+ <?php
218
+ }
219
+
220
+ self::$registered = true;
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Validate the notifications before displaying them.
226
+ *
227
+ * @since 1.0.0
228
+ *
229
+ * @param array $plugin_notifications An array of plugin notifications.
230
+ *
231
+ * @return array A filtered array of plugin notifications.
232
+ */
233
+ public function validate_notifications( $plugin_notifications ) {
234
+ global $pagenow;
235
+
236
+ foreach ( $plugin_notifications as $key => $notification ) {
237
+ // Location validation.
238
+ $location = (array) json_decode( get_post_meta( $notification->ID, 'location', true ) );
239
+ $continue = false;
240
+ if ( ! in_array( 'everywhere', $location, true ) ) {
241
+ if ( in_array( 'index.php', $location, true ) && 'index.php' === $pagenow ) {
242
+ $continue = true;
243
+ }
244
+
245
+ if ( in_array( 'plugins.php', $location, true ) && 'plugins.php' === $pagenow ) {
246
+ $continue = true;
247
+ }
248
+
249
+ if ( ! $continue ) {
250
+ unset( $plugin_notifications[ $key ] );
251
+ }
252
+ }
253
+
254
+ // Plugin validation (OR conditional).
255
+ $plugins = (array) json_decode( get_post_meta( $notification->ID, 'plugins', true ) );
256
+ $continue = false;
257
+ if ( ! empty( $plugins ) ) {
258
+ foreach ( $plugins as $plugin ) {
259
+ if ( is_plugin_active( $plugin ) ) {
260
+ $continue = true;
261
+ }
262
+ }
263
+
264
+ if ( ! $continue ) {
265
+ unset( $plugin_notifications[ $key ] );
266
+ }
267
+ }
268
+
269
+ // Theme validation.
270
+ $theme = get_post_meta( $notification->ID, 'theme', true );
271
+ $continue = (string) wp_get_theme() === $theme;
272
+
273
+ if ( ! empty( $theme ) && ! $continue ) {
274
+ unset( $plugin_notifications[ $key ] );
275
+ }
276
+
277
+ // Version validation.
278
+ $version = get_post_meta( $notification->ID, 'version', true );
279
+ $continue = false;
280
+ if ( ! empty( $version ) ) {
281
+ if ( version_compare( $this->plugin_version, $version, '<=' ) ) {
282
+ $continue = true;
283
+ }
284
+
285
+ if ( ! $continue ) {
286
+ unset( $plugin_notifications[ $key ] );
287
+ }
288
+ }
289
+
290
+ // Expiration validation.
291
+ $expiration = get_post_meta( $notification->ID, 'expiration', true );
292
+ $continue = false;
293
+ if ( ! empty( $expiration ) ) {
294
+ if ( $expiration > time() ) {
295
+ $continue = true;
296
+ }
297
+
298
+ if ( ! $continue ) {
299
+ unset( $plugin_notifications[ $key ] );
300
+ }
301
+ }
302
+
303
+ // Plan validation.
304
+ $plans = (array) json_decode( get_post_meta( $notification->ID, 'plans', true ) );
305
+ $continue = false;
306
+ if ( ! empty( $plans ) ) {
307
+ $level = $this->get_plan_level();
308
+ if ( in_array( $level, $plans, true ) ) {
309
+ $continue = true;
310
+ }
311
+
312
+ if ( ! $continue ) {
313
+ unset( $plugin_notifications[ $key ] );
314
+ }
315
+ }
316
+ }
317
+
318
+ return $plugin_notifications;
319
+ }
320
+
321
+ /**
322
+ * Grab the current plan level.
323
+ *
324
+ * @since 1.0.0
325
+ *
326
+ * @return string The current plan level.
327
+ */
328
+ public function get_plan_level() {
329
+ // Prepare variables.
330
+ $key = '';
331
+ $level = '';
332
+ $option = false;
333
+ switch ( $this->plugin ) {
334
+ case 'wpforms' :
335
+ $option = get_option( 'wpforms_license' );
336
+ $key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
337
+ $level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
338
+
339
+ // Possibly check for a constant.
340
+ if ( empty( $key ) && defined( 'WPFORMS_LICENSE_KEY' ) ) {
341
+ $key = WPFORMS_LICENSE_KEY;
342
+ }
343
+ break;
344
+ case 'mi' :
345
+ $option = get_option( 'monsterinsights_license' );
346
+ $key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
347
+ $level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
348
+
349
+ // Possibly check for a constant.
350
+ if ( empty( $key ) && defined( 'MONSTERINSIGHTS_LICENSE_KEY' ) && is_string( MONSTERINSIGHTS_LICENSE_KEY ) && strlen( MONSTERINSIGHTS_LICENSE_KEY ) > 10 ) {
351
+ $key = MONSTERINSIGHTS_LICENSE_KEY;
352
+ }
353
+ break;
354
+ case 'sol' :
355
+ $option = get_option( 'soliloquy' );
356
+ $key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
357
+ $level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
358
+
359
+ // Possibly check for a constant.
360
+ if ( empty( $key ) && defined( 'SOLILOQUY_LICENSE_KEY' ) ) {
361
+ $key = SOLILOQUY_LICENSE_KEY;
362
+ }
363
+ break;
364
+ case 'envira' :
365
+ $option = get_option( 'envira_gallery' );
366
+ $key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
367
+ $level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
368
+
369
+ // Possibly check for a constant.
370
+ if ( empty( $key ) && defined( 'ENVIRA_LICENSE_KEY' ) ) {
371
+ $key = ENVIRA_LICENSE_KEY;
372
+ }
373
+ break;
374
+ case 'om' :
375
+ $option = get_option( 'optin_monster_api' );
376
+ $key = is_array( $option ) && isset( $option['api']['apikey'] ) ? $option['api']['apikey'] : '';
377
+
378
+ // Possibly check for a constant.
379
+ if ( empty( $key ) && defined( 'OPTINMONSTER_REST_API_LICENSE_KEY' ) ) {
380
+ $key = OPTINMONSTER_REST_API_LICENSE_KEY;
381
+ }
382
+
383
+ // If the key is still empty, check for the old legacy key.
384
+ if ( empty( $key ) ) {
385
+ $key = is_array( $option ) && isset( $option['api']['key'] ) ? $option['api']['key'] : '';
386
+ }
387
+ break;
388
+ }
389
+
390
+ // Possibly set the level to 'none' if the key is empty and no level has been set.
391
+ if ( empty( $key ) && empty( $level ) ) {
392
+ $level = 'none';
393
+ }
394
+
395
+ // Normalize the level.
396
+ switch ( $level ) {
397
+ case 'bronze' :
398
+ case 'personal' :
399
+ $level = 'basic';
400
+ break;
401
+ case 'silver' :
402
+ case 'multi' :
403
+ $level = 'plus';
404
+ break;
405
+ case 'gold' :
406
+ case 'developer' :
407
+ $level = 'pro';
408
+ break;
409
+ case 'platinum' :
410
+ case 'master' :
411
+ $level = 'ultimate';
412
+ break;
413
+ }
414
+
415
+ // Return the plan level.
416
+ return $level;
417
+ }
418
+
419
+ /**
420
+ * Dismiss the notification via AJAX.
421
+ *
422
+ * @since 1.0.0
423
+ */
424
+ public function dismiss_notification() {
425
+ if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
426
+ die;
427
+ }
428
+
429
+ $notification_id = intval( $_POST['notification_id'] );
430
+ update_post_meta( $notification_id, 'viewed', 1 );
431
+ die;
432
+ }
433
+
434
+ /**
435
+ * Revokes notifications.
436
+ *
437
+ * @since 1.0.0
438
+ *
439
+ * @param array $ids An array of notification IDs to revoke.
440
+ */
441
+ public function revoke_notifications( $ids ) {
442
+ // Loop through each of the IDs and find the post that has it as meta.
443
+ foreach ( (array) $ids as $id ) {
444
+ $notifications = $this->get_plugin_notifications( -1, array( 'post_status' => 'all', 'meta_key' => 'notification_id', 'meta_value' => $id ) );
445
+ if ( $notifications ) {
446
+ foreach ( $notifications as $notification ) {
447
+ update_post_meta( $notification->ID, 'viewed', 1 );
448
+ }
449
+ }
450
+ }
451
+ }
452
+ }
src/Admin/Area.php ADDED
@@ -0,0 +1,450 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Admin;
4
+
5
+ use WPMailSMTP\WP;
6
+
7
+ /**
8
+ * Class Area registers and process all wp-admin display functionality.
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ class Area {
13
+
14
+ /**
15
+ * @var string Slug of the admin area page.
16
+ */
17
+ const SLUG = 'wp-mail-smtp';
18
+
19
+ /**
20
+ * @var string Admin page unique hook.
21
+ */
22
+ public $hook;
23
+
24
+ /**
25
+ * @var PageAbstract[]
26
+ */
27
+ private $pages;
28
+
29
+ /**
30
+ * Area constructor.
31
+ *
32
+ * @since 1.0.0
33
+ */
34
+ public function __construct() {
35
+ $this->hooks();
36
+ }
37
+
38
+ /**
39
+ * Assign all hooks to proper places.
40
+ *
41
+ * @since 1.0.0
42
+ */
43
+ protected function hooks() {
44
+
45
+ // Add the Settings link to a plugin on Plugins page.
46
+ add_filter( 'plugin_action_links', array( $this, 'add_plugin_action_link' ), 10, 2 );
47
+
48
+ // Add the options page.
49
+ add_action( 'admin_menu', array( $this, 'add_admin_options_page' ) );
50
+
51
+ // Admin footer text.
52
+ add_filter( 'admin_footer_text', array( $this, 'get_admin_footer' ), 1, 2 );
53
+
54
+ // Enqueue admin area scripts and styles.
55
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
56
+
57
+ // Process the admin page forms actions.
58
+ add_action( 'admin_init', array( $this, 'process_actions' ) );
59
+
60
+ // Display custom notices based on the error/success codes.
61
+ add_action( 'admin_init', array( $this, 'display_custom_auth_notices' ) );
62
+
63
+ // Outputs the plugin admin header.
64
+ add_action( 'in_admin_header', array( $this, 'display_admin_header' ), 100 );
65
+
66
+ // Hide all unrelated to the plugin notices on the plugin admin pages.
67
+ add_action( 'admin_print_scripts', array( $this, 'hide_unrelated_notices' ) );
68
+ }
69
+
70
+ /**
71
+ * Display custom notices based on the error/success codes.
72
+ *
73
+ * @since 1.0.0
74
+ */
75
+ public function display_custom_auth_notices() {
76
+
77
+ $error = isset( $_GET['error'] ) ? $_GET['error'] : '';
78
+ $success = isset( $_GET['success'] ) ? $_GET['success'] : '';
79
+
80
+ if ( empty( $error ) && empty( $success ) ) {
81
+ return;
82
+ }
83
+
84
+ switch ( $error ) {
85
+ case 'google_access_denied':
86
+ WP::add_admin_notice(
87
+ /* translators: %s - error code, returned by Google API. */
88
+ sprintf( esc_html__( 'There was an error while processing the authentication request: %s. Please try again.', 'wp-mail-smtp' ), '<code>' . $error . '</code>' ),
89
+ WP::ADMIN_NOTICE_ERROR
90
+ );
91
+ break;
92
+
93
+ case 'google_no_code_scope':
94
+ WP::add_admin_notice(
95
+ esc_html__( 'There was an error while processing the authentication request. Please try again.', 'wp-mail-smtp' ),
96
+ WP::ADMIN_NOTICE_ERROR
97
+ );
98
+ break;
99
+
100
+ case 'google_no_clients':
101
+ WP::add_admin_notice(
102
+ 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' ),
103
+ WP::ADMIN_NOTICE_ERROR
104
+ );
105
+ break;
106
+ }
107
+
108
+ switch ( $success ) {
109
+ case 'google_site_linked':
110
+ WP::add_admin_notice(
111
+ esc_html__( 'You have successfully linked the current site with you Google API project. Now you can start sending emails through Google.', 'wp-mail-smtp' ),
112
+ WP::ADMIN_NOTICE_SUCCESS
113
+ );
114
+ break;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Add admin area menu item.
120
+ *
121
+ * @since 1.0.0
122
+ */
123
+ public function add_admin_options_page() {
124
+
125
+ $this->hook = add_options_page(
126
+ esc_html__( 'WP Mail SMTP Options', 'wp-mail-smtp' ),
127
+ esc_html__( 'WP Mail SMTP', 'wp-mail-smtp' ),
128
+ 'manage_options',
129
+ self::SLUG,
130
+ array( $this, 'display' )
131
+ );
132
+ }
133
+
134
+ /**
135
+ * Enqueue admin area scripts and styles.
136
+ *
137
+ * @since 1.0.0
138
+ *
139
+ * @param string $hook
140
+ */
141
+ public function enqueue_assets( $hook ) {
142
+
143
+ if ( $hook !== $this->hook ) {
144
+ return;
145
+ }
146
+
147
+ wp_enqueue_style(
148
+ 'wp-mail-smtp-admin',
149
+ wp_mail_smtp()->plugin_url . '/assets/css/smtp-admin.min.css',
150
+ false,
151
+ WPMS_PLUGIN_VER
152
+ );
153
+
154
+ wp_enqueue_script(
155
+ 'wp-mail-smtp-admin',
156
+ wp_mail_smtp()->plugin_url . '/assets/js/smtp-admin' . WP::asset_min() . '.js',
157
+ array( 'jquery' ),
158
+ WPMS_PLUGIN_VER
159
+ );
160
+ }
161
+
162
+ /**
163
+ * Outputs the plugin admin header.
164
+ *
165
+ * @since 1.0.0
166
+ */
167
+ public function display_admin_header() {
168
+
169
+ // Bail if we're not on a plugin page.
170
+ if ( ! $this->is_admin_page() ) {
171
+ return;
172
+ }
173
+ ?>
174
+
175
+ <div id="wp-mail-smtp-header">
176
+ <!--suppress HtmlUnknownTarget -->
177
+ <img class="wp-mail-smtp-header-logo" src="<?php echo wp_mail_smtp()->plugin_url; ?>/assets/images/logo.png" alt="WP Mail SMTP"/>
178
+ </div>
179
+
180
+ <?php
181
+ }
182
+
183
+ /**
184
+ * Display a text to ask users to review the plugin on WP.org.
185
+ *
186
+ * @since 1.0.0
187
+ *
188
+ * @param string $text
189
+ *
190
+ * @return string
191
+ */
192
+ public function get_admin_footer( $text ) {
193
+
194
+ if ( $this->is_admin_page() ) {
195
+ $url = 'https://wordpress.org/support/plugin/wp-mail-smtp/reviews/?filter=5#new-post';
196
+
197
+ $text = sprintf(
198
+ /* translators: %1$s - WP.org link; %2$s - same WP.org link. */
199
+ __( 'Please rate <strong>WP Mail SMTP</strong> <a href="%1$s" target="_blank" rel="noopener noreferrer">&#9733;&#9733;&#9733;&#9733;&#9733;</a> on <a href="%2$s" target="_blank">WordPress.org</a> to help us spread the word. Thank you from the WP Mail SMTP team!', 'wp-mail-smtp' ),
200
+ $url,
201
+ $url
202
+ );
203
+ }
204
+
205
+ return $text;
206
+ }
207
+
208
+ /**
209
+ * Display content of the admin area page.
210
+ *
211
+ * @since 1.0.0
212
+ */
213
+ public function display() {
214
+ ?>
215
+
216
+ <div class="wrap" id="wp-mail-smtp">
217
+
218
+ <div class="wp-mail-smtp-page-title">
219
+ <?php
220
+ foreach ( $this->get_pages() as $page_slug => $page ) :
221
+ $label = $page->get_label();
222
+ if ( empty( $label ) ) {
223
+ continue;
224
+ }
225
+ $class = $page_slug === $this->get_current_tab() ? 'class="active"' : '';
226
+ ?>
227
+
228
+ <a href="<?php echo $page->get_link(); ?>" <?php echo $class; ?>><?php echo $label; ?></a>
229
+
230
+ <?php endforeach; ?>
231
+ </div>
232
+
233
+ <div class="wp-mail-smtp-page wp-mail-smtp-tab-<?php echo $this->get_current_tab(); ?>">
234
+ <h1 class="screen-reader-text"><?php echo $this->get_current_tab_title(); ?></h1>
235
+
236
+ <?php $this->display_current_tab_content(); ?>
237
+ </div>
238
+
239
+ </div>
240
+
241
+ <?php
242
+ }
243
+
244
+ /**
245
+ * Get the current tab title.
246
+ *
247
+ * @since 1.0.0
248
+ */
249
+ public function display_current_tab_content() {
250
+
251
+ if ( ! array_key_exists( $this->get_current_tab(), $this->get_pages() ) ) {
252
+ return;
253
+ }
254
+
255
+ $this->pages[ $this->get_current_tab() ]->display();
256
+ }
257
+
258
+ /**
259
+ * Get the current admin area tab.
260
+ *
261
+ * @since 1.0.0
262
+ *
263
+ * @return string
264
+ */
265
+ protected function get_current_tab() {
266
+ return ! empty( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'settings';
267
+ }
268
+
269
+ /**
270
+ * Get the array of default registered tabs for plugin admin area.
271
+ *
272
+ * @since 1.0.0
273
+ *
274
+ * @return \WPMailSMTP\Admin\PageAbstract[]
275
+ */
276
+ public function get_pages() {
277
+
278
+ if ( empty( $this->pages ) ) {
279
+ $this->pages = array(
280
+ 'settings' => new Pages\Settings(),
281
+ 'test' => new Pages\Test(),
282
+ 'misc' => new Pages\Misc(),
283
+ 'auth' => new Pages\Auth(),
284
+ );
285
+ }
286
+
287
+ return apply_filters( 'wp_mail_smtp_admin_get_pages', $this->pages );
288
+ }
289
+
290
+ /**
291
+ * Get the current tab title.
292
+ *
293
+ * @since 1.0.0
294
+ *
295
+ * @return string
296
+ */
297
+ public function get_current_tab_title() {
298
+
299
+ if ( ! array_key_exists( $this->get_current_tab(), $this->get_pages() ) ) {
300
+ return '';
301
+ }
302
+
303
+ return $this->pages[ $this->get_current_tab() ]->get_title();
304
+ }
305
+
306
+ /**
307
+ * Check whether we are on an admin page.
308
+ *
309
+ * @since 1.0.0
310
+ *
311
+ * @return bool
312
+ */
313
+ protected function is_admin_page() {
314
+
315
+ $page = isset( $_GET['page'] ) ? $_GET['page'] : '';
316
+
317
+ return self::SLUG === $page;
318
+ }
319
+
320
+ /**
321
+ * All possible plugin forms manipulation will be done here.
322
+ *
323
+ * @since 1.0.0
324
+ */
325
+ public function process_actions() {
326
+
327
+ // Allow to process only own tabs.
328
+ if ( ! array_key_exists( $this->get_current_tab(), $this->get_pages() ) ) {
329
+ return;
330
+ }
331
+
332
+ // Process POST only if it exists.
333
+ if ( ! empty( $_POST ) ) {
334
+ if ( ! empty( $_POST['wp-mail-smtp'] ) ) {
335
+ $post = $_POST['wp-mail-smtp'];
336
+ } else {
337
+ $post = array();
338
+ }
339
+
340
+ $this->pages[ $this->get_current_tab() ]->process_post( $post );
341
+ }
342
+
343
+ // This won't do anything for most pages.
344
+ $this->pages[ $this->get_current_tab() ]->process_auth();
345
+ }
346
+
347
+ /**
348
+ * Add a link to Settings page of a plugin on Plugins page.
349
+ *
350
+ * @since 1.0.0
351
+ *
352
+ * @param array $links
353
+ * @param string $file
354
+ *
355
+ * @return mixed
356
+ */
357
+ public function add_plugin_action_link( $links, $file ) {
358
+
359
+ if ( strpos( $file, 'wp-mail-smtp' ) === false ) {
360
+ return $links;
361
+ }
362
+
363
+ $settings_link = '<a href="' . $this->get_admin_page_url() . '">' . esc_html__( 'Settings', 'wp-mail-smtp' ) . '</a>';
364
+
365
+ array_unshift( $links, $settings_link );
366
+
367
+ return $links;
368
+ }
369
+
370
+ /**
371
+ * Get plugin admin area page URL.
372
+ *
373
+ * @since 1.0.0
374
+ *
375
+ * @return string
376
+ */
377
+ public function get_admin_page_url() {
378
+ return add_query_arg(
379
+ 'page',
380
+ self::SLUG,
381
+ admin_url( 'options-general.php' )
382
+ );
383
+ }
384
+
385
+ /**
386
+ * Remove all non-WP Mail SMTP plugin notices from plugin pages.
387
+ *
388
+ * @since 1.0.0
389
+ */
390
+ public function hide_unrelated_notices() {
391
+
392
+ // Bail if we're not on a our screen or page.
393
+ if ( empty( $_REQUEST['page'] ) || strpos( $_REQUEST['page'], self::SLUG ) === false ) {
394
+ return;
395
+ }
396
+
397
+ global $wp_filter;
398
+
399
+ if ( ! empty( $wp_filter['user_admin_notices']->callbacks ) && is_array( $wp_filter['user_admin_notices']->callbacks ) ) {
400
+ foreach ( $wp_filter['user_admin_notices']->callbacks as $priority => $hooks ) {
401
+ foreach ( $hooks as $name => $arr ) {
402
+ if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
403
+ unset( $wp_filter['user_admin_notices']->callbacks[ $priority ][ $name ] );
404
+ continue;
405
+ }
406
+ if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
407
+ continue;
408
+ }
409
+ if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
410
+ unset( $wp_filter['user_admin_notices']->callbacks[ $priority ][ $name ] );
411
+ }
412
+ }
413
+ }
414
+ }
415
+
416
+ if ( ! empty( $wp_filter['admin_notices']->callbacks ) && is_array( $wp_filter['admin_notices']->callbacks ) ) {
417
+ foreach ( $wp_filter['admin_notices']->callbacks as $priority => $hooks ) {
418
+ foreach ( $hooks as $name => $arr ) {
419
+ if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
420
+ unset( $wp_filter['admin_notices']->callbacks[ $priority ][ $name ] );
421
+ continue;
422
+ }
423
+ if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
424
+ continue;
425
+ }
426
+ if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
427
+ unset( $wp_filter['admin_notices']->callbacks[ $priority ][ $name ] );
428
+ }
429
+ }
430
+ }
431
+ }
432
+
433
+ if ( ! empty( $wp_filter['all_admin_notices']->callbacks ) && is_array( $wp_filter['all_admin_notices']->callbacks ) ) {
434
+ foreach ( $wp_filter['all_admin_notices']->callbacks as $priority => $hooks ) {
435
+ foreach ( $hooks as $name => $arr ) {
436
+ if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
437
+ unset( $wp_filter['all_admin_notices']->callbacks[ $priority ][ $name ] );
438
+ continue;
439
+ }
440
+ if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
441
+ continue;
442
+ }
443
+ if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
444
+ unset( $wp_filter['all_admin_notices']->callbacks[ $priority ][ $name ] );
445
+ }
446
+ }
447
+ }
448
+ }
449
+ }
450
+ }
src/Admin/PageAbstract.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Admin;
4
+
5
+ /**
6
+ * Class PageAbstract.
7
+ *
8
+ * @since 1.0.0
9
+ */
10
+ abstract class PageAbstract implements PageInterface {
11
+
12
+ /**
13
+ * @var string Slug of a tab.
14
+ */
15
+ protected $slug;
16
+
17
+ /**
18
+ * @inheritdoc
19
+ */
20
+ public function get_link() {
21
+ return esc_url(
22
+ add_query_arg(
23
+ 'tab',
24
+ $this->slug,
25
+ admin_url( 'options-general.php?page=' . Area::SLUG )
26
+ )
27
+ );
28
+ }
29
+
30
+ /**
31
+ * Process tab form submission ($_POST ).
32
+ *
33
+ * @since 1.0.0
34
+ *
35
+ * @param array $data $_POST data specific for the plugin.
36
+ */
37
+ public function process_post( $data ) {
38
+ }
39
+
40
+ /**
41
+ * Process tab & mailer specific Auth actions.
42
+ *
43
+ * @since 1.0.0
44
+ */
45
+ public function process_auth() {
46
+ }
47
+
48
+ /**
49
+ * Print the nonce field for a specific tab.
50
+ *
51
+ * @since 1.0.0
52
+ */
53
+ public function wp_nonce_field() {
54
+ wp_nonce_field( Area::SLUG . '-' . $this->slug );
55
+ }
56
+
57
+ /**
58
+ * Make sure that a user was referred from plugin admin page.
59
+ * To avoid security problems.
60
+ *
61
+ * @since 1.0.0
62
+ */
63
+ public function check_admin_referer() {
64
+ check_admin_referer( Area::SLUG . '-' . $this->slug );
65
+ }
66
+ }
src/Admin/PageInterface.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Admin;
4
+
5
+ /**
6
+ * Class PageInterface defines what should be in each page class.
7
+ *
8
+ * @since 1.0.0
9
+ */
10
+ interface PageInterface {
11
+
12
+ /**
13
+ * URL to a tab.
14
+ *
15
+ * @since 1.0.0
16
+ *
17
+ * @return string
18
+ */
19
+ public function get_link();
20
+
21
+ /**
22
+ * Title of a tab.
23
+ *
24
+ * @since 1.0.0
25
+ *
26
+ * @return string
27
+ */
28
+ public function get_title();
29
+
30
+ /**
31
+ * Link label of a tab.
32
+ *
33
+ * @since 1.0.0
34
+ *
35
+ * @return string
36
+ */
37
+ public function get_label();
38
+
39
+ /**
40
+ * Tab content.
41
+ *
42
+ * @since 1.0.0
43
+ */
44
+ public function display();
45
+ }
src/Admin/Pages/Auth.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Admin\Pages;
4
+
5
+ use WPMailSMTP\Options;
6
+
7
+ /**
8
+ * Class Auth.
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ class Auth {
13
+
14
+ /**
15
+ * @var string Slug of a tab.
16
+ */
17
+ protected $slug = 'auth';
18
+
19
+ /**
20
+ * Launch mailer specific Auth logic.
21
+ *
22
+ * @since 1.0.0
23
+ */
24
+ public function process_auth() {
25
+
26
+ $auth = wp_mail_smtp()->get_providers()->get_auth( Options::init()->get( 'mail', 'mailer' ) );
27
+
28
+ $auth->process();
29
+ }
30
+
31
+ /**
32
+ * Return nothing, as we don't need this functionality.
33
+ *
34
+ * @since 1.0.0
35
+ */
36
+ public function get_label() {
37
+ return '';
38
+ }
39
+
40
+ /**
41
+ * Return nothing, as we don't need this functionality.
42
+ *
43
+ * @since 1.0.0
44
+ */
45
+ public function get_title() {
46
+ return '';
47
+ }
48
+
49
+ /**
50
+ * Do nothing, as we don't need this functionality.
51
+ *
52
+ * @since 1.0.0
53
+ */
54
+ public function display() {
55
+ }
56
+ }
src/Admin/Pages/Misc.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Admin\Pages;
4
+
5
+ use WPMailSMTP\Admin\PageAbstract;
6
+ use WPMailSMTP\Options;
7
+ use WPMailSMTP\WP;
8
+
9
+ /**
10
+ * Class Misc is part of Area, displays different plugin-related settings of the plugin (not related to emails).
11
+ *
12
+ * @since 1.0.0
13
+ */
14
+ class Misc extends PageAbstract {
15
+ /**
16
+ * @var string Slug of a tab.
17
+ */
18
+ protected $slug = 'misc';
19
+
20
+ /**
21
+ * @inheritdoc
22
+ */
23
+ public function get_label() {
24
+ return esc_html__( 'Misc', 'wp-mail-smtp' );
25
+ }
26
+
27
+ /**
28
+ * @inheritdoc
29
+ */
30
+ public function get_title() {
31
+ return $this->get_label();
32
+ }
33
+
34
+ /**
35
+ * @inheritdoc
36
+ */
37
+ public function display() {
38
+
39
+ $options = new Options();
40
+ ?>
41
+
42
+ <form method="POST" action="">
43
+ <?php $this->wp_nonce_field(); ?>
44
+
45
+ <!-- General Section Title -->
46
+ <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">
47
+ <div class="wp-mail-smtp-setting-field">
48
+ <h2><?php esc_html_e( 'General', 'wp-mail-smtp' ); ?></h2>
49
+ </div>
50
+ </div>
51
+
52
+ <!-- Hide Announcements -->
53
+ <div id="wp-mail-smtp-setting-row-am_notifications_hidden" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox wp-mail-smtp-clear">
54
+ <div class="wp-mail-smtp-setting-label">
55
+ <label for="wp-mail-smtp-setting-am_notifications_hidden"><?php esc_html_e( 'Hide Announcements', 'wp-mail-smtp' ); ?></label>
56
+ </div>
57
+ <div class="wp-mail-smtp-setting-field">
58
+ <input name="wp-mail-smtp[general][am_notifications_hidden]" type="checkbox"
59
+ value="true" <?php checked( true, $options->get( 'general', 'am_notifications_hidden' ) ); ?>
60
+ id="wp-mail-smtp-setting-am_notifications_hidden"
61
+ />
62
+ <label for="wp-mail-smtp-setting-am_notifications_hidden"><?php esc_html_e( 'Check this if you would like to hide plugin announcements and update details.', 'wp-mail-smtp' ); ?></label>
63
+ </div>
64
+ </div>
65
+
66
+ <p class="wp-mail-smtp-submit">
67
+ <button type="submit" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange"><?php esc_html_e( 'Save Settings', 'wp-mail-smtp' ); ?></button>
68
+ </p>
69
+
70
+ </form>
71
+
72
+ <?php
73
+ }
74
+
75
+ /**
76
+ * @inheritdoc
77
+ */
78
+ public function process_post( $data ) {
79
+
80
+ $this->check_admin_referer();
81
+
82
+ $options = new Options();
83
+
84
+ // Unchecked checkbox doesn't exist in $_POST, so we need to ensure we actually have it.
85
+ if ( empty( $data['general']['am_notifications_hidden'] ) ) {
86
+ $data['general']['am_notifications_hidden'] = false;
87
+ }
88
+
89
+ $to_save = array_merge( $options->get_all(), $data );
90
+
91
+ // All the sanitization is done there.
92
+ $options->set( $to_save );
93
+
94
+ WP::add_admin_notice(
95
+ esc_html__( 'Settings were successfully saved.', 'wp-mail-smtp' ),
96
+ WP::ADMIN_NOTICE_SUCCESS
97
+ );
98
+ }
99
+ }
src/Admin/Pages/Settings.php ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Admin\Pages;
4
+
5
+ use WPMailSMTP\Admin\PageAbstract;
6
+ use WPMailSMTP\Options;
7
+ use WPMailSMTP\WP;
8
+
9
+ /**
10
+ * Class Settings is part of Area, displays general settings of the plugin.
11
+ *
12
+ * @since 1.0.0
13
+ */
14
+ class Settings extends PageAbstract {
15
+
16
+ /**
17
+ * @var string Slug of a tab.
18
+ */
19
+ protected $slug = 'settings';
20
+
21
+ /**
22
+ * @inheritdoc
23
+ */
24
+ public function get_label() {
25
+ return esc_html__( 'Settings', 'wp-mail-smtp' );
26
+ }
27
+
28
+ /**
29
+ * @inheritdoc
30
+ */
31
+ public function get_title() {
32
+ return $this->get_label();
33
+ }
34
+
35
+ /**
36
+ * @inheritdoc
37
+ */
38
+ public function display() {
39
+
40
+ $options = new Options();
41
+ $mailer = $options->get( 'mail', 'mailer' );
42
+ ?>
43
+
44
+ <form method="POST" action="">
45
+ <?php $this->wp_nonce_field(); ?>
46
+
47
+ <!-- Mail Section Title -->
48
+ <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">
49
+ <div class="wp-mail-smtp-setting-field">
50
+ <h2><?php esc_html_e( 'Mail', 'wp-mail-smtp' ); ?></h2>
51
+ </div>
52
+ </div>
53
+
54
+ <!-- From Email -->
55
+ <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">
56
+ <div class="wp-mail-smtp-setting-label">
57
+ <label for="wp-mail-smtp-setting-from_email"><?php esc_html_e( 'From Email', 'wp-mail-smtp' ); ?></label>
58
+ </div>
59
+ <div class="wp-mail-smtp-setting-field">
60
+ <input name="wp-mail-smtp[mail][from_email]" type="email"
61
+ value="<?php echo esc_attr( $options->get( 'mail', 'from_email' ) ); ?>"
62
+ <?php echo $options->is_const_defined( 'mail', 'from_email' ) ? 'disabled' : ''; ?>
63
+ id="wp-mail-smtp-setting-from_email" spellcheck="false"
64
+ />
65
+ <p class="desc">
66
+ <?php esc_html_e( 'You can specify the email address that emails should be sent from.', 'wp-mail-smtp' ); ?><br/>
67
+ <?php
68
+ printf(
69
+ /* translators: %s - default email address. */
70
+ esc_html__( 'If you leave this blank, the default one will be used: %s.', 'wp-mail-smtp' ),
71
+ '<code>' . wp_mail_smtp()->get_processor()->get_default_email() . '</code>'
72
+ );
73
+ ?>
74
+ </p>
75
+ <p class="desc">
76
+ <?php esc_html_e( 'Please note if you are sending using an email provider (Gmail, Yahoo, Hotmail, Outlook.com, etc) this setting should be your email address for that account.', 'wp-mail-smtp' ); ?>
77
+ </p>
78
+ </div>
79
+ </div>
80
+
81
+ <!-- From Name -->
82
+ <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">
83
+ <div class="wp-mail-smtp-setting-label">
84
+ <label for="wp-mail-smtp-setting-from_name"><?php esc_html_e( 'From Name', 'wp-mail-smtp' ); ?></label>
85
+ </div>
86
+ <div class="wp-mail-smtp-setting-field">
87
+ <input name="wp-mail-smtp[mail][from_name]" type="text"
88
+ value="<?php echo esc_attr( $options->get( 'mail', 'from_name' ) ); ?>"
89
+ <?php echo $options->is_const_defined( 'mail', 'from_name' ) ? 'disabled' : ''; ?>
90
+ id="wp-mail-smtp-setting-from-name" spellcheck="false"
91
+ />
92
+ <p class="desc">
93
+ <?php esc_html_e( 'You can specify the name that emails should be sent from.', 'wp-mail-smtp' ); ?><br/>
94
+ <?php
95
+ printf(
96
+ /* translators: %s - WordPress. */
97
+ esc_html__( 'If you leave this blank, the emails will be sent from %s.', 'wp-mail-smtp' ),
98
+ '<code>WordPress</code>'
99
+ );
100
+ ?>
101
+ </p>
102
+ </div>
103
+ </div>
104
+
105
+ <!-- Mailer -->
106
+ <div id="wp-mail-smtp-setting-row-mailer" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-mailer wp-mail-smtp-clear">
107
+ <div class="wp-mail-smtp-setting-label">
108
+ <label for="wp-mail-smtp-setting-mailer"><?php esc_html_e( 'Mailer', 'wp-mail-smtp' ); ?></label>
109
+ </div>
110
+ <div class="wp-mail-smtp-setting-field">
111
+ <div class="wp-mail-smtp-mailers">
112
+
113
+ <?php foreach ( wp_mail_smtp()->get_providers()->get_options_all() as $provider ) : ?>
114
+
115
+ <div class="wp-mail-smtp-mailer <?php echo $mailer === $provider->get_slug() ? 'active' : ''; ?>">
116
+ <div class="wp-mail-smtp-mailer-image">
117
+ <img src="<?php echo esc_url( $provider->get_logo_url() ); ?>"
118
+ alt="<?php echo esc_attr( $provider->get_title() ); ?>">
119
+ </div>
120
+
121
+ <div class="wp-mail-smtp-mailer-text">
122
+ <input id="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>"
123
+ type="radio" name="wp-mail-smtp[mail][mailer]"
124
+ value="<?php echo esc_attr( $provider->get_slug() ); ?>"
125
+ <?php checked( $provider->get_slug(), $mailer ); ?>
126
+ <?php echo $options->is_const_defined( 'mail', 'mailer' ) ? 'disabled' : ''; ?>
127
+ />
128
+ <label for="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>"><?php echo $provider->get_title(); ?></label>
129
+ </div>
130
+ </div>
131
+
132
+ <?php endforeach; ?>
133
+
134
+ </div>
135
+ </div>
136
+ </div>
137
+
138
+ <!-- Return Path -->
139
+ <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">
140
+ <div class="wp-mail-smtp-setting-label">
141
+ <label for="wp-mail-smtp-setting-return_path"><?php esc_html_e( 'Return Path', 'wp-mail-smtp' ); ?></label>
142
+ </div>
143
+ <div class="wp-mail-smtp-setting-field">
144
+ <input name="wp-mail-smtp[mail][return_path]" type="checkbox"
145
+ value="true" <?php checked( true, $options->get( 'mail', 'return_path' ) ); ?>
146
+ <?php echo $options->is_const_defined( 'mail', 'return_path' ) ? 'disabled' : ''; ?>
147
+ id="wp-mail-smtp-setting-return_path"
148
+ />
149
+ <label for="wp-mail-smtp-setting-return_path"><?php esc_html_e( 'Set the return-path to match the From Email', 'wp-mail-smtp' ); ?></label></label>
150
+ <p class="desc">
151
+ <?php esc_html_e( 'Return Path indicates where non-delivery receipts - or bounce messages - are to be sent.', 'wp-mail-smtp' ); ?><br/>
152
+ <?php esc_html_e( 'If unchecked bounce messages may be lost.', 'wp-mail-smtp' ); ?>
153
+ </p>
154
+ </div>
155
+ </div>
156
+
157
+ <!-- Mailer Options -->
158
+ <div class="wp-mail-smtp-mailer-options">
159
+ <?php foreach ( wp_mail_smtp()->get_providers()->get_options_all() as $provider ) : ?>
160
+
161
+ <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'; ?>">
162
+
163
+ <!-- Mailer Option Title -->
164
+ <?php $provider_desc = $provider->get_description(); ?>
165
+ <div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading <?php empty( $provider_desc ) ? 'no-desc' : ''; ?>" id="wp-mail-smtp-setting-row-email-heading">
166
+ <div class="wp-mail-smtp-setting-field">
167
+ <h2><?php echo $provider->get_title(); ?></h2>
168
+ <?php if ( ! empty( $provider_desc ) ) : ?>
169
+ <p class="desc"><?php echo $provider_desc; ?></p>
170
+ <?php endif; ?>
171
+ </div>
172
+ </div>
173
+
174
+ <?php $provider->display_options(); ?>
175
+ </div>
176
+
177
+ <?php endforeach; ?>
178
+
179
+ </div>
180
+
181
+ <p class="wp-mail-smtp-submit">
182
+ <button type="submit" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange"><?php esc_html_e( 'Save Settings', 'wp-mail-smtp' ); ?></button>
183
+ </p>
184
+
185
+ </form>
186
+
187
+ <?php
188
+ }
189
+
190
+ /**
191
+ * @inheritdoc
192
+ */
193
+ public function process_post( $data ) {
194
+
195
+ $this->check_admin_referer();
196
+
197
+ $options = new Options();
198
+ $old_opt = $options->get_all();
199
+
200
+ $to_redirect = false;
201
+
202
+ // Old and new Gmail client id/secret values are different - we need to invalidate tokens and scroll to Auth button.
203
+ if (
204
+ $options->get( 'mail', 'mailer' ) === 'gmail' &&
205
+ (
206
+ $options->get( 'gmail', 'client_id' ) !== $data['gmail']['client_id'] ||
207
+ $options->get( 'gmail', 'client_secret' ) !== $data['gmail']['client_secret']
208
+ )
209
+ ) {
210
+ unset( $old_opt['gmail'] );
211
+
212
+ if (
213
+ ! empty( $data['gmail']['client_id'] ) &&
214
+ ! empty( $data['gmail']['client_secret'] )
215
+ ) {
216
+ $to_redirect = true;
217
+ }
218
+ }
219
+
220
+ // New gmail clients data will be added from new $data, except the old access/refresh_token.
221
+ $to_save = array_merge( $old_opt, $data );
222
+
223
+ // All the sanitization is done there.
224
+ $options->set( $to_save );
225
+
226
+ if ( $to_redirect ) {
227
+ wp_redirect( $_POST['_wp_http_referer'] . '#wp-mail-smtp-setting-row-gmail-authorize' );
228
+ exit;
229
+ }
230
+
231
+ WP::add_admin_notice(
232
+ esc_html__( 'Settings were successfully saved.', 'wp-mail-smtp' ),
233
+ WP::ADMIN_NOTICE_SUCCESS
234
+ );
235
+ }
236
+ }
src/Admin/Pages/Test.php ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Admin\Pages;
4
+
5
+ use WPMailSMTP\MailCatcher;
6
+ use WPMailSMTP\Options;
7
+ use WPMailSMTP\WP;
8
+ use WPMailSMTP\Admin\PageAbstract;
9
+
10
+ /**
11
+ * Class Test is part of Area, displays email testing page of the plugin.
12
+ *
13
+ * @since 1.0.0
14
+ */
15
+ class Test extends PageAbstract {
16
+
17
+ /**
18
+ * @var string Slug of a tab.
19
+ */
20
+ protected $slug = 'test';
21
+
22
+ /**
23
+ * @inheritdoc
24
+ */
25
+ public function get_label() {
26
+ return esc_html__( 'Email Test', 'wp-mail-smtp' );
27
+ }
28
+
29
+ /**
30
+ * @inheritdoc
31
+ */
32
+ public function get_title() {
33
+ return $this->get_label();
34
+ }
35
+
36
+ /**
37
+ * @inheritdoc
38
+ */
39
+ public function display() {
40
+ ?>
41
+
42
+ <form method="POST" action="">
43
+ <?php $this->wp_nonce_field(); ?>
44
+
45
+ <!-- Test Email Section Title -->
46
+ <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">
47
+ <div class="wp-mail-smtp-setting-field">
48
+ <h2><?php esc_html_e( 'Send a Test Email', 'wp-mail-smtp' ); ?></h2>
49
+ </div>
50
+ </div>
51
+
52
+ <!-- Test Email -->
53
+ <div id="wp-mail-smtp-setting-row-test_email" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-email wp-mail-smtp-clear">
54
+ <div class="wp-mail-smtp-setting-label">
55
+ <label for="wp-mail-smtp-setting-test_email"><?php esc_html_e( 'Send To', 'wp-mail-smtp' ); ?></label>
56
+ </div>
57
+ <div class="wp-mail-smtp-setting-field">
58
+ <input name="wp-mail-smtp[test_email]" type="email" id="wp-mail-smtp-setting-test_email" spellcheck="false" required />
59
+ <p class="desc">
60
+ <?php esc_html_e( 'Type an email address here and then click a button below to generate a test email.', 'wp-mail-smtp' ); ?>
61
+ </p>
62
+ </div>
63
+ </div>
64
+
65
+ <p class="wp-mail-smtp-submit">
66
+ <button type="submit" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange"><?php esc_html_e( 'Send Email', 'wp-mail-smtp' ); ?></button>
67
+ </p>
68
+ </form>
69
+
70
+ <?php
71
+ }
72
+
73
+ /**
74
+ * @inheritdoc
75
+ */
76
+ public function process_post( $data ) {
77
+
78
+ $this->check_admin_referer();
79
+
80
+ if ( isset( $data['test_email'] ) ) {
81
+ $data['test_email'] = filter_var( $data['test_email'], FILTER_VALIDATE_EMAIL );
82
+ }
83
+
84
+ if ( empty( $data['test_email'] ) ) {
85
+ WP::add_admin_notice(
86
+ esc_html__( 'Test failed. Please use a valid email address and try to resend the test email.', 'wp-mail-smtp' ),
87
+ WP::ADMIN_NOTICE_WARNING
88
+ );
89
+ return;
90
+ }
91
+
92
+ global $phpmailer;
93
+
94
+ // Make sure the PHPMailer class has been instantiated.
95
+ if ( ! is_object( $phpmailer ) || ! is_a( $phpmailer, 'PHPMailer' ) ) {
96
+ require_once ABSPATH . WPINC . '/class-phpmailer.php';
97
+ $phpmailer = new MailCatcher( true );
98
+ }
99
+
100
+ // Set SMTPDebug level, default is 2 (commands + data + connection status).
101
+ $phpmailer->SMTPDebug = apply_filters( 'wp_mail_smtp_admin_test_email_smtp_debug', 2 );
102
+
103
+ // Start output buffering to grab smtp debugging output.
104
+ ob_start();
105
+
106
+ // Send the test mail.
107
+ $result = wp_mail(
108
+ $data['test_email'],
109
+ /* translators: %s - email address a test email will be sent to. */
110
+ 'WP Mail SMTP: ' . sprintf( esc_html__( 'Test email to %s', 'wp-mail-smtp' ), $data['test_email'] ),
111
+ sprintf(
112
+ /* translators: %s - mailer name. */
113
+ esc_html__( 'This email was sent by %s mailer, and generated by the WP Mail SMTP WordPress plugin.', 'wp-mail-smtp' ),
114
+ wp_mail_smtp()->get_providers()->get_options( Options::init()->get( 'mail', 'mailer' ) )->get_title()
115
+ )
116
+ );
117
+
118
+ // Grab the smtp debugging output.
119
+ $smtp_debug = ob_get_clean();
120
+
121
+ /*
122
+ * Do the actual sending.
123
+ */
124
+ if ( $result ) {
125
+ WP::add_admin_notice(
126
+ esc_html__( 'Your email was sent successfully!', 'wp-mail-smtp' ),
127
+ WP::ADMIN_NOTICE_SUCCESS
128
+ );
129
+ } else {
130
+ $error = $this->get_debug_messages( $phpmailer, $smtp_debug );
131
+
132
+ WP::add_admin_notice(
133
+ '<p><strong>' . esc_html__( 'There was a problem while sending a test email.', 'wp-mail-smtp' ) . '</strong></p>' .
134
+ '<p>' . esc_html__( 'The related debugging output is shown below:', 'wp-mail-smtp' ) . '</p>' .
135
+ '<blockquote>' . $error . '</blockquote>',
136
+ WP::ADMIN_NOTICE_ERROR
137
+ );
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Prepare debug information, that will help users to identify the error.
143
+ *
144
+ * @param \PHPMailer $phpmailer
145
+ * @param string $smtp_debug
146
+ *
147
+ * @return string
148
+ */
149
+ protected function get_debug_messages( $phpmailer, $smtp_debug ) {
150
+
151
+ global $wp_version;
152
+
153
+ $errors = array();
154
+
155
+ $versions_text = '<h3>Versions</h3>';
156
+
157
+ $versions_text .= '<strong>WordPress:</strong> ' . $wp_version . '<br>';
158
+ $versions_text .= '<strong>PHP:</strong> ' . PHP_VERSION . '<br>';
159
+ $versions_text .= '<strong>WP Mail SMTP:</strong> ' . WPMS_PLUGIN_VER;
160
+
161
+ $errors[] = $versions_text;
162
+
163
+ $phpmailer_text = '<h3>PHPMailer</h3>';
164
+
165
+ $phpmailer_text .= '<strong>ErrorInfo:</strong> ' . make_clickable( $phpmailer->ErrorInfo ) . '<br>';
166
+ $phpmailer_text .= '<strong>Mailer:</strong> ' . $phpmailer->Mailer . '<br>';
167
+ $phpmailer_text .= '<strong>Host:</strong> ' . $phpmailer->Host . '<br>';
168
+ $phpmailer_text .= '<strong>Port:</strong> ' . $phpmailer->Port . '<br>';
169
+ $phpmailer_text .= '<strong>SMTPSecure:</strong> ' . $this->pvar( $phpmailer->SMTPSecure ) . '<br>';
170
+ $phpmailer_text .= '<strong>SMTPAutoTLS:</strong> ' . $this->pvar( $phpmailer->SMTPAutoTLS ) . '<br>';
171
+ $phpmailer_text .= '<strong>SMTPAuth:</strong> ' . $this->pvar( $phpmailer->SMTPAuth );
172
+ if ( ! empty( $phpmailer->SMTPOptions ) ) {
173
+ $phpmailer_text .= '<br><strong>SMTPOptions:</strong> ' . $this->pvar( $phpmailer->SMTPOptions );
174
+ }
175
+
176
+ $errors[] = $phpmailer_text;
177
+
178
+ if ( ! empty( $smtp_debug ) ) {
179
+ $errors[] = '<h3>SMTP Debug</h3>' . nl2br( $smtp_debug );
180
+ }
181
+
182
+ return implode( '</p><p>', $errors );
183
+ }
184
+
185
+ /**
186
+ * Get the proper variable content output to debug.
187
+ *
188
+ * @param mixed $var
189
+ *
190
+ * @return string
191
+ */
192
+ protected function pvar( $var = '' ) {
193
+
194
+ ob_start();
195
+
196
+ echo '<code>';
197
+
198
+ if ( is_bool( $var ) || empty( $var ) ) {
199
+ var_dump( $var );
200
+ } else {
201
+ print_r( $var );
202
+ }
203
+
204
+ echo '</code>';
205
+
206
+ return ob_get_clean();
207
+ }
208
+ }
src/Core.php ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP;
4
+
5
+ /**
6
+ * Class Core to handle all plugin initialization.
7
+ *
8
+ * @since 1.0.0
9
+ */
10
+ class Core {
11
+
12
+ /**
13
+ * Without trailing slash.
14
+ *
15
+ * @var string
16
+ */
17
+ public $plugin_url;
18
+ /**
19
+ * Without trailing slash.
20
+ *
21
+ * @var string
22
+ */
23
+ public $plugin_path;
24
+
25
+ /**
26
+ * Core constructor.
27
+ *
28
+ * @since 1.0.0
29
+ */
30
+ public function __construct() {
31
+
32
+ $this->plugin_url = rtrim( plugin_dir_url( __DIR__ ), '/\\' );
33
+ $this->plugin_path = rtrim( plugin_dir_path( __DIR__ ), '/\\' );
34
+
35
+ $this->hooks();
36
+ }
37
+
38
+ /**
39
+ * Assign all hooks to proper places.
40
+ *
41
+ * @since 1.0.0
42
+ */
43
+ public function hooks() {
44
+
45
+ // Activation hook.
46
+ add_action( 'activate_wp-mail-smtp/wp_mail_smtp.php', array( $this, 'activate' ) );
47
+
48
+ add_action( 'plugins_loaded', array( $this, 'get_processor' ) );
49
+ add_action( 'plugins_loaded', array( $this, 'replace_phpmailer' ) );
50
+ add_action( 'plugins_loaded', array( $this, 'init_notifications' ) );
51
+
52
+ add_action( 'admin_notices', array( '\WPMailSMTP\WP', 'display_admin_notices' ) );
53
+
54
+ add_action( 'init', array( $this, 'init' ) );
55
+ }
56
+
57
+ /**
58
+ * Initial plugin actions.
59
+ *
60
+ * @since 1.0.0
61
+ */
62
+ public function init() {
63
+
64
+ // Load translations just in case.
65
+ load_plugin_textdomain( 'wp-mail-smtp', false, wp_mail_smtp()->plugin_path . '/languages' );
66
+
67
+ /*
68
+ * Constantly check in admin area, that we don't need to upgrade DB.
69
+ * Do not wait for the `admin_init` hook, because some actions are already done
70
+ * on `plugins_loaded`, so migration has to be done before.
71
+ */
72
+ if ( WP::in_wp_admin() ) {
73
+ $this->get_migration();
74
+ $this->get_admin();
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Load the plugin core processor.
80
+ *
81
+ * @since 1.0.0
82
+ *
83
+ * @return Processor
84
+ */
85
+ public function get_processor() {
86
+
87
+ static $processor;
88
+
89
+ if ( ! isset( $processor ) ) {
90
+ $processor = apply_filters( 'wp_mail_smtp_core_get_processor', new Processor() );
91
+ }
92
+
93
+ return $processor;
94
+ }
95
+
96
+ /**
97
+ * Load the plugin admin area.
98
+ *
99
+ * @since 1.0.0
100
+ *
101
+ * @return Admin\Area
102
+ */
103
+ public function get_admin() {
104
+
105
+ static $admin;
106
+
107
+ if ( ! isset( $admin ) ) {
108
+ $admin = apply_filters( 'wp_mail_smtp_core_get_admin', new Admin\Area() );
109
+ }
110
+
111
+ return $admin;
112
+ }
113
+
114
+ /**
115
+ * Load the plugin providers loader.
116
+ *
117
+ * @since 1.0.0
118
+ *
119
+ * @return Providers\Loader
120
+ */
121
+ public function get_providers() {
122
+
123
+ static $providers;
124
+
125
+ if ( ! isset( $providers ) ) {
126
+ $providers = apply_filters( 'wp_mail_smtp_core_get_providers', new Providers\Loader() );
127
+ }
128
+
129
+ return $providers;
130
+ }
131
+
132
+ /**
133
+ * Load the plugin option migrator.
134
+ *
135
+ * @since 1.0.0
136
+ *
137
+ * @return Migration
138
+ */
139
+ public function get_migration() {
140
+
141
+ static $migration;
142
+
143
+ if ( ! isset( $migration ) ) {
144
+ $migration = apply_filters( 'wp_mail_smtp_core_get_migration', new Migration() );
145
+ }
146
+
147
+ return $migration;
148
+ }
149
+
150
+ /**
151
+ * Awesome Motive Notifications.
152
+ *
153
+ * @since 1.0.0
154
+ */
155
+ public function init_notifications() {
156
+
157
+ if ( Options::init()->get( 'general', 'am_notifications_hidden' ) ) {
158
+ return;
159
+ }
160
+
161
+ static $notification;
162
+
163
+ if ( ! isset( $notification ) ) {
164
+ $notification = new AM_Notification( 'smtp', WPMS_PLUGIN_VER );
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Init the \PHPMailer replacement.
170
+ *
171
+ * @since 1.0.0
172
+ *
173
+ * @return \WPMailSMTP\MailCatcher
174
+ */
175
+ public function replace_phpmailer() {
176
+ global $phpmailer;
177
+
178
+ return $this->replace_w_fake_phpmailer( $phpmailer );
179
+ }
180
+
181
+ /**
182
+ * Overwrite default PhpMailer with out MailCatcher.
183
+ *
184
+ * @since 1.0.0
185
+ *
186
+ * @param null $obj
187
+ *
188
+ * @return \WPMailSMTP\MailCatcher
189
+ */
190
+ protected function replace_w_fake_phpmailer( &$obj = null ) {
191
+
192
+ $obj = new MailCatcher();
193
+
194
+ return $obj;
195
+ }
196
+
197
+ /**
198
+ * What to do on plugin activation.
199
+ *
200
+ * @since 1.0.0
201
+ */
202
+ public function activate() {
203
+
204
+ $options['mail'] = array(
205
+ 'from_email' => get_option( 'admin_email' ),
206
+ 'from_name' => get_bloginfo( 'name' ),
207
+ 'mailer' => 'mail',
208
+ 'return_path' => false,
209
+ );
210
+
211
+ Options::init()->set( $options );
212
+ }
213
+ }
src/MailCatcher.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP;
4
+
5
+ // Load PHPMailer class, so we can subclass it.
6
+ if ( ! class_exists( 'PHPMailer', false ) ) {
7
+ require_once ABSPATH . WPINC . '/class-phpmailer.php';
8
+ }
9
+
10
+ /**
11
+ * Class MailCatcher replaces the \PHPMailer and modifies the email sending logic.
12
+ * Thus, we can use other mailers API to do what we need, or stop emails completely.
13
+ *
14
+ * @since 1.0.0
15
+ */
16
+ class MailCatcher extends \PHPMailer {
17
+
18
+ /**
19
+ * Modify the default send() behaviour.
20
+ * For those mailers, that relies on PHPMailer class - call it directly.
21
+ * For others - init the correct provider and process it.
22
+ *
23
+ * @since 1.0.0
24
+ *
25
+ * @throws \phpmailerException Throws when sending via PhpMailer fails for some reason.
26
+ *
27
+ * @return bool
28
+ */
29
+ public function send() {
30
+
31
+ $options = new Options();
32
+ $mailer = $options->get( 'mail', 'mailer' );
33
+
34
+ // Use the default PHPMailer, as we inject our settings there for certain providers.
35
+ if (
36
+ $mailer === 'mail' ||
37
+ $mailer === 'smtp' ||
38
+ $mailer === 'pepipost'
39
+ ) {
40
+ return parent::send();
41
+ }
42
+
43
+ // Prepare everything (including the message) for sending.
44
+ if ( ! $this->preSend() ) {
45
+ return false;
46
+ }
47
+
48
+ $mailer = wp_mail_smtp()->get_providers()->get_mailer( $mailer, $this );
49
+
50
+ if ( ! $mailer ) {
51
+ return false;
52
+ }
53
+
54
+ if ( ! $mailer->is_php_compatible() ) {
55
+ return false;
56
+ }
57
+
58
+ /*
59
+ * Send the actual email.
60
+ * We reuse everything, that was preprocessed for usage in \PHPMailer.
61
+ */
62
+ $mailer->send();
63
+
64
+ return $mailer->is_email_sent();
65
+ }
66
+ }
src/Migration.php ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP;
4
+
5
+ /**
6
+ * Class Migration helps migrate all plugin options saved into DB to a new storage location.
7
+ *
8
+ * @since 1.0.0
9
+ */
10
+ class Migration {
11
+
12
+ /**
13
+ * All old values for pre 1.0 version of a plugin.
14
+ *
15
+ * @var array
16
+ */
17
+ protected $old_keys = array(
18
+ 'pepipost_ssl',
19
+ 'pepipost_port',
20
+ 'pepipost_pass',
21
+ 'pepipost_user',
22
+ 'smtp_pass',
23
+ 'smtp_user',
24
+ 'smtp_auth',
25
+ 'smtp_ssl',
26
+ 'smtp_port',
27
+ 'smtp_host',
28
+ 'mail_set_return_path',
29
+ 'mailer',
30
+ 'mail_from_name',
31
+ 'mail_from',
32
+ 'wp_mail_smtp_am_notifications_hidden',
33
+ );
34
+
35
+ /**
36
+ * Old values, taken from $old_keys options.
37
+ *
38
+ * @var array
39
+ */
40
+ protected $old_values = array();
41
+
42
+ /**
43
+ * Converted array of data from previous option values.
44
+ *
45
+ * @var array
46
+ */
47
+ protected $new_values = array();
48
+
49
+ /**
50
+ * Migration constructor.
51
+ *
52
+ * @since 1.0.0
53
+ */
54
+ public function __construct() {
55
+
56
+ if ( $this->is_migrated() ) {
57
+ return;
58
+ }
59
+
60
+ $this->old_values = $this->get_old_values();
61
+ $this->new_values = $this->get_converted_options();
62
+
63
+ Options::init()->set( $this->new_values );
64
+
65
+ // Removing all options will be enabled some time in the future.
66
+ // $this->clean_deprecated_data();
67
+ }
68
+
69
+ /**
70
+ * Whether we already migrated or not.
71
+ *
72
+ * @since 1.0.0
73
+ *
74
+ * @return bool
75
+ */
76
+ protected function is_migrated() {
77
+
78
+ $is_migrated = false;
79
+ $new_values = get_option( Options::META_KEY, array() );
80
+
81
+ if ( ! empty( $new_values ) ) {
82
+ $is_migrated = true;
83
+ }
84
+
85
+ return $is_migrated;
86
+ }
87
+
88
+ /**
89
+ * Get all old values from DB.
90
+ *
91
+ * @since 1.0.0
92
+ *
93
+ * @return array
94
+ */
95
+ protected function get_old_values() {
96
+
97
+ $old_values = array();
98
+
99
+ foreach ( $this->old_keys as $old_key ) {
100
+ $old_values[ $old_key ] = get_option( $old_key, '' );
101
+ }
102
+
103
+ return $old_values;
104
+ }
105
+
106
+ /**
107
+ * Convert old values from key=>value to a multidimensional array of data.
108
+ *
109
+ * @since 1.0.0
110
+ */
111
+ protected function get_converted_options() {
112
+
113
+ $converted = array();
114
+
115
+ foreach ( $this->old_keys as $old_key ) {
116
+
117
+ switch ( $old_key ) {
118
+ case 'pepipost_user':
119
+ case 'pepipost_pass':
120
+ case 'pepipost_port':
121
+ case 'pepipost_ssl':
122
+ // Do not migrate pepipost options if it's not activated at the moment.
123
+ if ( 'pepipost' === $this->old_values['mailer'] ) {
124
+ $shortcut = explode( '_', $old_key );
125
+
126
+ if ( $old_key === 'pepipost_ssl' ) {
127
+ $converted[ $shortcut[0] ]['encryption'] = $this->old_values[ $old_key ];
128
+ } else {
129
+ $converted[ $shortcut[0] ][ $shortcut[1] ] = $this->old_values[ $old_key ];
130
+ }
131
+ }
132
+ break;
133
+
134
+ case 'smtp_host':
135
+ case 'smtp_port':
136
+ case 'smtp_ssl':
137
+ case 'smtp_auth':
138
+ case 'smtp_user':
139
+ case 'smtp_pass':
140
+ $shortcut = explode( '_', $old_key );
141
+
142
+ if ( $old_key === 'smtp_ssl' ) {
143
+ $converted[ $shortcut[0] ]['encryption'] = $this->old_values[ $old_key ];
144
+ } elseif ( $old_key === 'smtp_auth' ) {
145
+ $converted[ $shortcut[0] ][ $shortcut[1] ] = ( $this->old_values[ $old_key ] === 'true' ? 'yes' : 'no' );
146
+ } else {
147
+ $converted[ $shortcut[0] ][ $shortcut[1] ] = $this->old_values[ $old_key ];
148
+ }
149
+
150
+ break;
151
+
152
+ case 'mail_from':
153
+ $converted['mail']['from_email'] = $this->old_values[ $old_key ];
154
+ break;
155
+ case 'mail_from_name':
156
+ $converted['mail']['from_name'] = $this->old_values[ $old_key ];
157
+ break;
158
+ case 'mail_set_return_path':
159
+ $converted['mail']['return_path'] = ( $this->old_values[ $old_key ] === 'true' );
160
+ break;
161
+ case 'mailer':
162
+ $converted['mail']['mailer'] = $this->old_values[ $old_key ];
163
+ break;
164
+ case 'wp_mail_smtp_am_notifications_hidden':
165
+ $converted['general']['am_notifications_hidden'] = ( $this->old_values[ $old_key ] === 'true' );
166
+ break;
167
+ }
168
+ }
169
+
170
+ $converted = $this->get_converted_constants_options( $converted );
171
+
172
+ return $converted;
173
+ }
174
+
175
+ /**
176
+ * Some users use constants in wp-config.php to define values.
177
+ * We need to prioritize them and reapply data to options.
178
+ * Use only those that are actually defined.
179
+ *
180
+ * @since 1.0.0
181
+ *
182
+ * @param array $converted
183
+ *
184
+ * @return array
185
+ */
186
+ protected function get_converted_constants_options( $converted ) {
187
+
188
+ // Are we configured via constants?
189
+ if ( ! defined( 'WPMS_ON' ) || ! WPMS_ON ) {
190
+ return $converted;
191
+ }
192
+
193
+ /*
194
+ * Mail settings.
195
+ */
196
+ if ( defined( 'WPMS_MAIL_FROM' ) ) {
197
+ $converted['mail']['from_email'] = WPMS_MAIL_FROM;
198
+ }
199
+ if ( defined( 'WPMS_MAIL_FROM_NAME' ) ) {
200
+ $converted['mail']['from_name'] = WPMS_MAIL_FROM_NAME;
201
+ }
202
+ if ( defined( 'WPMS_MAILER' ) ) {
203
+ $converted['mail']['return_path'] = WPMS_MAILER;
204
+ }
205
+ if ( defined( 'WPMS_SET_RETURN_PATH' ) ) {
206
+ $converted['mail']['mailer'] = WPMS_SET_RETURN_PATH;
207
+ }
208
+
209
+ /*
210
+ * SMTP settings.
211
+ */
212
+ if ( defined( 'WPMS_SMTP_HOST' ) ) {
213
+ $converted['smtp']['host'] = WPMS_SMTP_HOST;
214
+ }
215
+ if ( defined( 'WPMS_SMTP_PORT' ) ) {
216
+ $converted['smtp']['port'] = WPMS_SMTP_PORT;
217
+ }
218
+ if ( defined( 'WPMS_SSL' ) ) {
219
+ $converted['smtp']['ssl'] = WPMS_SSL;
220
+ }
221
+ if ( defined( 'WPMS_SMTP_AUTH' ) ) {
222
+ $converted['smtp']['auth'] = WPMS_SMTP_AUTH;
223
+ }
224
+ if ( defined( 'WPMS_SMTP_USER' ) ) {
225
+ $converted['smtp']['user'] = WPMS_SMTP_USER;
226
+ }
227
+ if ( defined( 'WPMS_SMTP_PASS' ) ) {
228
+ $converted['smtp']['pass'] = WPMS_SMTP_PASS;
229
+ }
230
+
231
+ return $converted;
232
+ }
233
+
234
+ /**
235
+ * Delete all old values that are stored separately each.
236
+ *
237
+ * @since 1.0.0
238
+ */
239
+ protected function clean_deprecated_data() {
240
+
241
+ foreach ( $this->old_keys as $old_key ) {
242
+ delete_option( $old_key );
243
+ }
244
+ }
245
+ }
src/Options.php ADDED
@@ -0,0 +1,469 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP;
4
+
5
+ /**
6
+ * Class Options to handle all options management.
7
+ * WordPress does all the heavy work for caching get_option() data,
8
+ * so we don't have to do that. But we want to minimize cyclomatic complexity
9
+ * of calling a bunch of WP functions, thus we will cache them in a class as well.
10
+ *
11
+ * @since 1.0.0
12
+ */
13
+ class Options {
14
+
15
+ /**
16
+ * That's where plugin options are saved in wp_options table.
17
+ *
18
+ * @var string
19
+ */
20
+ const META_KEY = 'wp_mail_smtp';
21
+
22
+ /**
23
+ * All the plugin options.
24
+ *
25
+ * @var array
26
+ */
27
+ private $_options = array();
28
+
29
+ /**
30
+ * Init the Options class.
31
+ *
32
+ * @since 1.0.0
33
+ */
34
+ public function __construct() {
35
+ $this->populate_options();
36
+ }
37
+
38
+ /**
39
+ * Initialize all the options, used for chaining.
40
+ *
41
+ * One-liner:
42
+ * Options::init()->get('smtp', 'host');
43
+ * Options::init()->is_pepipost_active();
44
+ *
45
+ * Or multiple-usage:
46
+ * $options = new Options();
47
+ * $options->get('smtp', 'host');
48
+ *
49
+ * @since 1.0.0
50
+ *
51
+ * @return Options
52
+ */
53
+ public static function init() {
54
+
55
+ static $instance;
56
+
57
+ if ( ! $instance ) {
58
+ $instance = new self();
59
+ }
60
+
61
+ return $instance;
62
+ }
63
+
64
+ /**
65
+ * Retrieve all options of the plugin.
66
+ *
67
+ * @since 1.0.0
68
+ */
69
+ protected function populate_options() {
70
+ $this->_options = get_option( self::META_KEY, array() );
71
+ }
72
+
73
+ /**
74
+ * Get all the options.
75
+ *
76
+ * Options::init()->get_all();
77
+ *
78
+ * @since 1.0.0
79
+ *
80
+ * @return array
81
+ */
82
+ public function get_all() {
83
+ return apply_filters( 'wp_mail_smtp_options_get_all', $this->_options );
84
+ }
85
+
86
+
87
+ /**
88
+ * Get all the options for a group.
89
+ *
90
+ * Options::init()->get_group('smtp') - will return only array of options (or empty array if no key doesn't exist).
91
+ *
92
+ * @since 1.0.0
93
+ *
94
+ * @param string $group
95
+ *
96
+ * @return mixed
97
+ */
98
+ public function get_group( $group ) {
99
+
100
+ // Just to feel safe.
101
+ $group = sanitize_key( $group );
102
+
103
+ if ( isset( $this->_options[ $group ] ) ) {
104
+ return apply_filters( 'wp_mail_smtp_options_get_group', $this->_options[ $group ], $group );
105
+ }
106
+
107
+ return array();
108
+ }
109
+
110
+ /**
111
+ * Get options by a group and a key.
112
+ *
113
+ * Options::init()->get('smtp', 'host') - will return only SMTP 'host' option.
114
+ *
115
+ * @since 1.0.0
116
+ *
117
+ * @param string $group
118
+ * @param string $key
119
+ *
120
+ * @return mixed
121
+ */
122
+ public function get( $group, $key ) {
123
+
124
+ // Just to feel safe.
125
+ $group = sanitize_key( $group );
126
+ $key = sanitize_key( $key );
127
+
128
+ // Get the options group.
129
+ if ( isset( $this->_options[ $group ] ) ) {
130
+
131
+ // Get the options key of a group.
132
+ if ( isset( $this->_options[ $group ][ $key ] ) ) {
133
+ $value = $this->get_const_value( $group, $key, $this->_options[ $group ][ $key ] );
134
+ } else {
135
+ $value = $this->postprocess_key_defaults( $group, $key, '' );
136
+ }
137
+ } else {
138
+ $value = $this->postprocess_key_defaults( $group, $key, '' );
139
+ }
140
+
141
+ return apply_filters( 'wp_mail_smtp_options_get', $value, $group, $key );
142
+ }
143
+
144
+ /**
145
+ * Some options may be non-empty by default,
146
+ * so we need to postprocess them to convert.
147
+ *
148
+ * @since 1.0.0
149
+ *
150
+ * @param string $group
151
+ * @param string $key
152
+ * @param mixed $value Default value, it's '' (empty string).
153
+ *
154
+ * @return mixed
155
+ */
156
+ protected function postprocess_key_defaults( $group, $key, $value ) {
157
+
158
+ switch ( $key ) {
159
+ case 'return_path':
160
+ $value = $group === 'mail' && empty( $value ) ? false : true;
161
+ break;
162
+
163
+ case 'encryption':
164
+ $value = $group === 'smtp' && empty( $value ) ? 'none' : $value;
165
+ break;
166
+
167
+ case 'auth':
168
+ $value = $group === 'smtp' && empty( $value ) ? false : true;
169
+ break;
170
+ }
171
+
172
+ return $value;
173
+ }
174
+
175
+ /**
176
+ * Process the options values through the constants check.
177
+ * If we have defined associated constant - use it instead of a DB value.
178
+ * Backward compatibility is hard.
179
+ * General section of options won't have constants, so we are omitting those checks and just return default value.
180
+ *
181
+ * @since 1.0.0
182
+ *
183
+ * @param string $group
184
+ * @param string $key
185
+ * @param mixed $value
186
+ *
187
+ * @return mixed
188
+ */
189
+ protected function get_const_value( $group, $key, $value ) {
190
+
191
+ if ( ! $this->is_const_enabled() ) {
192
+ return $value;
193
+ }
194
+
195
+ switch ( $group ) {
196
+ case 'mail':
197
+ switch ( $key ) {
198
+ case 'from_name':
199
+ /** @noinspection PhpUndefinedConstantInspection */
200
+ return $this->is_const_defined( $group, $key ) ? WPMS_MAIL_FROM_NAME : $value;
201
+ case 'from_email':
202
+ /** @noinspection PhpUndefinedConstantInspection */
203
+ return $this->is_const_defined( $group, $key ) ? WPMS_MAIL_FROM : $value;
204
+ case 'mailer':
205
+ /** @noinspection PhpUndefinedConstantInspection */
206
+ return $this->is_const_defined( $group, $key ) ? WPMS_MAILER : $value;
207
+ case 'return_path':
208
+ return $this->is_const_defined( $group, $key ) ? true : $value;
209
+ }
210
+
211
+ break;
212
+
213
+ case 'smtp':
214
+ switch ( $key ) {
215
+ case 'host':
216
+ /** @noinspection PhpUndefinedConstantInspection */
217
+ return $this->is_const_defined( $group, $key ) ? WPMS_SMTP_HOST : $value;
218
+ case 'port':
219
+ /** @noinspection PhpUndefinedConstantInspection */
220
+ return $this->is_const_defined( $group, $key ) ? WPMS_SMTP_PORT : $value;
221
+ case 'encryption':
222
+ /** @noinspection PhpUndefinedConstantInspection */
223
+ return $this->is_const_defined( $group, $key )
224
+ ? ( WPMS_SSL === '' ? 'none' : WPMS_SSL )
225
+ : $value;
226
+ case 'auth':
227
+ /** @noinspection PhpUndefinedConstantInspection */
228
+ return $this->is_const_defined( $group, $key ) ? WPMS_SMTP_AUTH : $value;
229
+ case 'user':
230
+ /** @noinspection PhpUndefinedConstantInspection */
231
+ return $this->is_const_defined( $group, $key ) ? WPMS_SMTP_USER : $value;
232
+ case 'pass':
233
+ /** @noinspection PhpUndefinedConstantInspection */
234
+ return $this->is_const_defined( $group, $key ) ? WPMS_SMTP_PASS : $value;
235
+ }
236
+
237
+ break;
238
+
239
+ case 'gmail':
240
+ switch ( $key ) {
241
+ case 'client_id':
242
+ /** @noinspection PhpUndefinedConstantInspection */
243
+ return $this->is_const_defined( $group, $key ) ? WPMS_GMAIL_CLIENT_ID : $value;
244
+ case 'client_secret':
245
+ /** @noinspection PhpUndefinedConstantInspection */
246
+ return $this->is_const_defined( $group, $key ) ? WPMS_GMAIL_CLIENT_SECRET : $value;
247
+ }
248
+
249
+ break;
250
+
251
+ case 'mailgun':
252
+ switch ( $key ) {
253
+ case 'api_key':
254
+ /** @noinspection PhpUndefinedConstantInspection */
255
+ return $this->is_const_defined( $group, $key ) ? WPMS_MAILGUN_API_KEY : $value;
256
+ case 'domain':
257
+ /** @noinspection PhpUndefinedConstantInspection */
258
+ return $this->is_const_defined( $group, $key ) ? WPMS_MAILGUN_DOMAIN : $value;
259
+ }
260
+
261
+ break;
262
+
263
+ case 'sendgrid':
264
+ switch ( $key ) {
265
+ case 'api_key':
266
+ /** @noinspection PhpUndefinedConstantInspection */
267
+ return $this->is_const_defined( $group, $key ) ? WPMS_SENDGRID_API_KEY : $value;
268
+ }
269
+
270
+ break;
271
+ }
272
+
273
+ // Always return the default value if nothing from above matches the request.
274
+ return $value;
275
+ }
276
+
277
+ /**
278
+ * Whether constants redefinition is enabled or not.
279
+ *
280
+ * @since 1.0.0
281
+ *
282
+ * @return bool
283
+ */
284
+ public function is_const_enabled() {
285
+ return defined( 'WPMS_ON' ) && WPMS_ON === true;
286
+ }
287
+
288
+ /**
289
+ * We need this check to reuse later in admin area,
290
+ * to distinguish settings fields that were redefined,
291
+ * and display them differently.
292
+ *
293
+ * @since 1.0.0
294
+ *
295
+ * @param string $group
296
+ * @param string $key
297
+ *
298
+ * @return bool
299
+ */
300
+ public function is_const_defined( $group, $key ) {
301
+
302
+ if ( ! $this->is_const_enabled() ) {
303
+ return false;
304
+ }
305
+
306
+ // Just to feel safe.
307
+ $group = sanitize_key( $group );
308
+ $key = sanitize_key( $key );
309
+
310
+ switch ( $group ) {
311
+ case 'mail':
312
+ switch ( $key ) {
313
+ case 'from_name':
314
+ return defined( 'WPMS_MAIL_FROM_NAME' ) && WPMS_MAIL_FROM_NAME;
315
+ case 'from_email':
316
+ return defined( 'WPMS_MAIL_FROM' ) && WPMS_MAIL_FROM;
317
+ case 'mailer':
318
+ return defined( 'WPMS_MAILER' ) && WPMS_MAILER;
319
+ case 'return_path':
320
+ return defined( 'WPMS_SET_RETURN_PATH' ) && ( WPMS_SET_RETURN_PATH === 'true' || WPMS_SET_RETURN_PATH === true );
321
+ }
322
+
323
+ break;
324
+
325
+ case 'smtp':
326
+ switch ( $key ) {
327
+ case 'host':
328
+ return defined( 'WPMS_SMTP_HOST' ) && WPMS_SMTP_HOST;
329
+ case 'port':
330
+ return defined( 'WPMS_SMTP_PORT' ) && WPMS_SMTP_PORT;
331
+ case 'encryption':
332
+ return defined( 'WPMS_SSL' );
333
+ case 'auth':
334
+ return defined( 'WPMS_SMTP_AUTH' ) && WPMS_SMTP_AUTH;
335
+ case 'user':
336
+ return defined( 'WPMS_SMTP_USER' ) && WPMS_SMTP_USER;
337
+ case 'pass':
338
+ return defined( 'WPMS_SMTP_PASS' ) && WPMS_SMTP_PASS;
339
+ }
340
+
341
+ break;
342
+
343
+ case 'gmail':
344
+ switch ( $key ) {
345
+ case 'client_id':
346
+ return defined( 'WPMS_GMAIL_CLIENT_ID' ) && WPMS_GMAIL_CLIENT_ID;
347
+ case 'client_secret':
348
+ return defined( 'WPMS_GMAIL_CLIENT_SECRET' ) && WPMS_GMAIL_CLIENT_SECRET;
349
+ }
350
+
351
+ break;
352
+
353
+ case 'mailgun':
354
+ switch ( $key ) {
355
+ case 'api_key':
356
+ return defined( 'WPMS_MAILGUN_API_KEY' ) && WPMS_MAILGUN_API_KEY;
357
+ case 'domain':
358
+ return defined( 'WPMS_MAILGUN_DOMAIN' ) && WPMS_MAILGUN_DOMAIN;
359
+ }
360
+
361
+ break;
362
+
363
+ case 'sendgrid':
364
+ switch ( $key ) {
365
+ case 'api_key':
366
+ return defined( 'WPMS_SENDGRID_API_KEY' ) && WPMS_SENDGRID_API_KEY;
367
+ }
368
+
369
+ break;
370
+ }
371
+
372
+ return false;
373
+ }
374
+
375
+ /**
376
+ * Set plugin options, all at once.
377
+ *
378
+ * @since 1.0.0
379
+ *
380
+ * @param array $options Data to save.
381
+ */
382
+ public function set( $options ) {
383
+
384
+ foreach ( (array) $options as $group => $keys ) {
385
+ foreach ( $keys as $key_name => $key_value ) {
386
+ switch ( $group ) {
387
+ case 'mail':
388
+ switch ( $key_name ) {
389
+ case 'from_name':
390
+ case 'mailer':
391
+ $options[ $group ][ $key_name ] = $this->get_const_value( $group, $key_name, sanitize_text_field( $options[ $group ][ $key_name ] ) );
392
+ break;
393
+ case 'from_email':
394
+ if ( filter_var( $options[ $group ][ $key_name ], FILTER_VALIDATE_EMAIL ) ) {
395
+ $options[ $group ][ $key_name ] = $this->get_const_value( $group, $key_name, sanitize_email( $options[ $group ][ $key_name ] ) );
396
+ }
397
+ break;
398
+ case 'return_path':
399
+ $options[ $group ][ $key_name ] = $this->get_const_value( $group, $key_name, (bool) $options[ $group ][ $key_name ] );
400
+ break;
401
+ }
402
+ break;
403
+
404
+ case 'general':
405
+ switch ( $key_name ) {
406
+ case 'am_notifications_hidden':
407
+ $options[ $group ][ $key_name ] = (bool) $options[ $group ][ $key_name ];
408
+ break;
409
+ }
410
+ }
411
+ }
412
+ }
413
+
414
+ if (
415
+ isset( $options[ $options['mail']['mailer'] ] ) &&
416
+ in_array( $options['mail']['mailer'], array( 'pepipost', 'smtp', 'sendgrid', 'mailgun', 'gmail' ), true )
417
+ ) {
418
+
419
+ $mailer = $options['mail']['mailer'];
420
+
421
+ foreach ( $options[ $mailer ] as $key_name => $key_value ) {
422
+ switch ( $key_name ) {
423
+ case 'host':
424
+ case 'user':
425
+ case 'pass':
426
+ case 'api_key':
427
+ case 'domain':
428
+ case 'client_id':
429
+ case 'client_secret':
430
+ $options[ $mailer ][ $key_name ] = $this->get_const_value( $mailer, $key_name, sanitize_text_field( $options[ $mailer ][ $key_name ] ) );
431
+ break;
432
+ case 'port':
433
+ $options[ $mailer ][ $key_name ] = $this->get_const_value( $mailer, $key_name, intval( $options[ $mailer ][ $key_name ] ) );
434
+ break;
435
+ case 'encryption':
436
+ $options[ $mailer ][ $key_name ] = $this->get_const_value( $mailer, $key_name, sanitize_text_field( $options[ $mailer ][ $key_name ] ) );
437
+ break;
438
+ case 'auth':
439
+ $value = $options[ $mailer ][ $key_name ] === 'yes' || $options[ $mailer ][ $key_name ] === true ? true : false;
440
+
441
+ $options[ $mailer ][ $key_name ] = $this->get_const_value( $mailer, $key_name, $value );
442
+ break;
443
+
444
+ case 'auth_code':
445
+ case 'access_token':
446
+ // Do nothing for them.
447
+ }
448
+ }
449
+ }
450
+
451
+ $options = apply_filters( 'wp_mail_smtp_options_set', $options );
452
+
453
+ update_option( self::META_KEY, $options );
454
+
455
+ // Now we need to re-cache values.
456
+ $this->populate_options();
457
+ }
458
+
459
+ /**
460
+ * Check whether the site is using Pepipost or not.
461
+ *
462
+ * @since 1.0.0
463
+ *
464
+ * @return bool
465
+ */
466
+ public function is_pepipost_active() {
467
+ return apply_filters( 'wp_mail_smtp_options_is_pepipost_active', 'pepipost' === $this->get( 'mail', 'mailer' ) );
468
+ }
469
+ }
src/Processor.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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' ) );
31
+ add_filter( 'wp_mail_from_name', array( $this, 'filter_mail_from_name' ), 11 );
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 = Options::init()->get_all();
44
+ $mailer = $options['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['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['pepipost']['user'] && ! $options['pepipost']['pass'] )
58
+ ) {
59
+ return;
60
+ }
61
+
62
+ // Set the mailer type as per config above, this overrides the already called isMail method.
63
+ $phpmailer->Mailer = $mailer;
64
+
65
+ // Set the Sender (return-path) if required.
66
+ if ( isset( $options['mail']['return_path'] ) && $options['mail']['return_path'] ) {
67
+ $phpmailer->Sender = $phpmailer->From;
68
+ }
69
+
70
+ // Set the SMTPSecure value, if set to none, leave this blank.
71
+ $phpmailer->SMTPSecure = 'smtp';
72
+ if ( isset( $options[ $mailer ]['encryption'] ) && 'none' === $options[ $mailer ]['encryption'] ) {
73
+ $phpmailer->SMTPSecure = '';
74
+ $phpmailer->SMTPAutoTLS = false;
75
+ }
76
+
77
+ // If we're sending via SMTP, set the host.
78
+ if ( 'smtp' === $mailer ) {
79
+ // Set the other options.
80
+ $phpmailer->Host = $options[ $mailer ]['host'];
81
+ $phpmailer->Port = $options[ $mailer ]['port'];
82
+
83
+ // If we're using smtp auth, set the username & password.
84
+ if ( $options[ $mailer ]['auth'] ) {
85
+ $phpmailer->SMTPAuth = true;
86
+ $phpmailer->Username = $options[ $mailer ]['user'];
87
+ $phpmailer->Password = $options[ $mailer ]['pass'];
88
+ }
89
+ } elseif ( 'pepipost' === $mailer ) {
90
+ // Set the Pepipost settings for BC.
91
+ $phpmailer->Mailer = 'smtp';
92
+ $phpmailer->Host = 'smtp.pepipost.com';
93
+ $phpmailer->Port = $options[ $mailer ]['port'];
94
+ $phpmailer->SMTPSecure = $options[ $mailer ]['encryption'] === 'none' ? '' : $options[ $mailer ]['encryption'];
95
+ $phpmailer->SMTPAuth = true;
96
+ $phpmailer->Username = $options[ $mailer ]['user'];
97
+ $phpmailer->Password = $options[ $mailer ]['pass'];
98
+ }
99
+
100
+ // You can add your own options here.
101
+ // See the phpmailer documentation for more info: https://github.com/PHPMailer/PHPMailer/tree/5.2-stable.
102
+ /** @noinspection PhpUnusedLocalVariableInspection It's passed by reference. */
103
+ $phpmailer = apply_filters( 'wp_mail_smtp_custom_options', $phpmailer );
104
+ }
105
+
106
+ /**
107
+ * Modify the email address that is used for sending emails.
108
+ *
109
+ * @since 1.0.0
110
+ *
111
+ * @param string $email
112
+ *
113
+ * @return string
114
+ */
115
+ public function filter_mail_from_email( $email ) {
116
+
117
+ // If the from email is not the default, return it unchanged.
118
+ if ( $email !== $this->get_default_email() ) {
119
+ return $email;
120
+ }
121
+
122
+ $from_email = Options::init()->get( 'mail', 'from_email' );
123
+
124
+ if ( ! empty( $from_email ) ) {
125
+ return $from_email;
126
+ }
127
+
128
+ return $email;
129
+ }
130
+
131
+ /**
132
+ * Modify the sender name that is used for sending emails.
133
+ *
134
+ * @since 1.0.0
135
+ *
136
+ * @param string $name
137
+ *
138
+ * @return string
139
+ */
140
+ public function filter_mail_from_name( $name ) {
141
+
142
+ if ( 'WordPress' === $name ) {
143
+ $name = Options::init()->get( 'mail', 'from_name' );
144
+ }
145
+
146
+ return $name;
147
+ }
148
+
149
+ /**
150
+ * Get the default email address based on domain name.
151
+ *
152
+ * @since 1.0.0
153
+ *
154
+ * @return string
155
+ */
156
+ public function get_default_email() {
157
+
158
+ // In case of CLI we don't have SERVER_NAME, so use host name instead, may be not a domain name.
159
+ $server_name = ! empty( $_SERVER['SERVER_NAME'] ) ? $_SERVER['SERVER_NAME'] : wp_parse_url( get_home_url( get_current_blog_id() ), PHP_URL_HOST );
160
+
161
+ // Get the site domain and get rid of www.
162
+ $sitename = strtolower( $server_name );
163
+ if ( substr( $sitename, 0, 4 ) === 'www.' ) {
164
+ $sitename = substr( $sitename, 4 );
165
+ }
166
+
167
+ return 'wordpress@' . $sitename;
168
+ }
169
+ }
src/Providers/AuthAbstract.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers;
4
+
5
+ /**
6
+ * Class AuthAbstract.
7
+ *
8
+ * @since 1.0.0
9
+ */
10
+ abstract class AuthAbstract implements AuthInterface {
11
+
12
+ /**
13
+ * Get the url, that users will be redirected back to finish the OAuth process.
14
+ *
15
+ * @since 1.0.0
16
+ *
17
+ * @return string
18
+ */
19
+ public static function get_plugin_auth_url() {
20
+ return add_query_arg( 'tab', 'auth', wp_mail_smtp()->get_admin()->get_admin_page_url() );
21
+ }
22
+ }
src/Providers/AuthInterface.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers;
4
+
5
+ /**
6
+ * Interface AuthInterface.
7
+ *
8
+ * @since 1.0.0
9
+ */
10
+ interface AuthInterface {
11
+
12
+ /**
13
+ * Do something for this Auth implementation.
14
+ *
15
+ * @since 1.0.0
16
+ */
17
+ public function process();
18
+
19
+ }
src/Providers/Gmail/Auth.php ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers\Gmail;
4
+
5
+ use WPMailSMTP\Options as PluginOptions;
6
+ use WPMailSMTP\Providers\AuthAbstract;
7
+
8
+ /**
9
+ * Class Auth to request access and refresh tokens.
10
+ *
11
+ * @since 1.0.0
12
+ */
13
+ class Auth extends AuthAbstract {
14
+
15
+ /**
16
+ * Gmail options.
17
+ *
18
+ * @var array
19
+ */
20
+ private $gmail;
21
+
22
+ /**
23
+ * @var \Google_Client
24
+ */
25
+ private $client;
26
+
27
+ /**
28
+ * @var string
29
+ */
30
+ private $mailer;
31
+
32
+ /**
33
+ * Auth constructor.
34
+ *
35
+ * @since 1.0.0
36
+ */
37
+ public function __construct() {
38
+
39
+ $options = new PluginOptions();
40
+ $this->mailer = $options->get( 'mail', 'mailer' );
41
+ $this->gmail = $options->get_group( $this->mailer );
42
+
43
+ if ( $this->is_clients_saved() ) {
44
+
45
+ $this->include_google_lib();
46
+
47
+ $this->client = $this->get_client();
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Use the composer autoloader to include the Google Library and all its dependencies.
53
+ *
54
+ * @since 1.0.0
55
+ */
56
+ protected function include_google_lib() {
57
+ require wp_mail_smtp()->plugin_path . '/vendor/autoload.php';
58
+ }
59
+
60
+ /**
61
+ * Init and get the Google Client object.
62
+ *
63
+ * @since 1.0.0
64
+ */
65
+ public function get_client() {
66
+
67
+ // Doesn't load client twice + gives ability to overwrite.
68
+ if ( ! empty( $this->client ) ) {
69
+ return $this->client;
70
+ }
71
+
72
+ $client = new \Google_Client(
73
+ array(
74
+ 'client_id' => $this->gmail['client_id'],
75
+ 'client_secret' => $this->gmail['client_secret'],
76
+ 'redirect_uris' => array(
77
+ Auth::get_plugin_auth_url(),
78
+ ),
79
+ )
80
+ );
81
+ $client->setAccessType( 'offline' );
82
+ $client->setApprovalPrompt( 'force' );
83
+ $client->setIncludeGrantedScopes( true );
84
+ // We request only the sending capability, as it's what we only need to do.
85
+ $client->setScopes( array( \Google_Service_Gmail::GMAIL_SEND ) );
86
+ $client->setRedirectUri( self::get_plugin_auth_url() );
87
+
88
+ if (
89
+ empty( $this->gmail['access_token'] ) &&
90
+ ! empty( $this->gmail['auth_code'] )
91
+ ) {
92
+ $client->fetchAccessTokenWithAuthCode( $this->gmail['auth_code'] );
93
+
94
+ // Bail if we have an error.
95
+ if ( ! empty( $creds['error'] ) ) {
96
+ // TODO: save this error to display to a user later.
97
+ return $client;
98
+ }
99
+
100
+ $this->update_access_token( $client->getAccessToken() );
101
+ $this->update_refresh_token( $client->getRefreshToken() );
102
+ }
103
+
104
+ if ( ! empty( $this->gmail['access_token'] ) ) {
105
+ $client->setAccessToken( $this->gmail['access_token'] );
106
+ }
107
+
108
+ // Refresh the token if it's expired.
109
+ if ( $client->isAccessTokenExpired() ) {
110
+ $refresh = $client->getRefreshToken();
111
+ if ( empty( $refresh ) && isset( $this->gmail['refresh_token'] ) ) {
112
+ $refresh = $this->gmail['refresh_token'];
113
+ }
114
+
115
+ if ( ! empty( $refresh ) ) {
116
+ $client->fetchAccessTokenWithRefreshToken( $refresh );
117
+ $this->update_access_token( $client->getAccessToken() );
118
+ $this->update_refresh_token( $client->getRefreshToken() );
119
+ }
120
+ }
121
+
122
+ return $client;
123
+ }
124
+
125
+ /**
126
+ * Get the auth code from the $_GET and save it.
127
+ * Redirect user back to settings with an error message, if failed.
128
+ *
129
+ * @since 1.0.0
130
+ */
131
+ public function process() {
132
+
133
+ // We can't process without saved client_id/secret.
134
+ if ( ! $this->is_clients_saved() ) {
135
+ wp_redirect(
136
+ add_query_arg(
137
+ 'error',
138
+ 'google_no_clients',
139
+ wp_mail_smtp()->get_admin()->get_admin_page_url()
140
+ )
141
+ );
142
+ exit;
143
+ }
144
+
145
+ $code = '';
146
+ $scope = '';
147
+ $error = '';
148
+
149
+ if ( isset( $_GET['error'] ) ) {
150
+ $error = sanitize_key( $_GET['error'] );
151
+ }
152
+
153
+ // In case of any error: display a message to a user.
154
+ if ( ! empty( $error ) ) {
155
+ wp_redirect(
156
+ add_query_arg(
157
+ 'error',
158
+ 'google_' . $error,
159
+ wp_mail_smtp()->get_admin()->get_admin_page_url()
160
+ )
161
+ );
162
+ exit;
163
+ }
164
+
165
+ if ( isset( $_GET['code'] ) ) {
166
+ $code = $_GET['code'];
167
+ }
168
+ if ( isset( $_GET['scope'] ) ) {
169
+ $scope = urldecode( $_GET['scope'] );
170
+ }
171
+
172
+ // Let's try to get the access token.
173
+ if (
174
+ ! empty( $code ) &&
175
+ (
176
+ $scope === ( \Google_Service_Gmail::GMAIL_SEND . ' ' . \Google_Service_Gmail::MAIL_GOOGLE_COM ) ||
177
+ $scope === \Google_Service_Gmail::GMAIL_SEND
178
+ )
179
+ ) {
180
+ // Save the auth code. So \Google_Client can reuse it to retrieve the access token.
181
+ $this->update_auth_code( $code );
182
+ } else {
183
+ wp_redirect(
184
+ add_query_arg(
185
+ 'error',
186
+ 'google_no_code_scope',
187
+ wp_mail_smtp()->get_admin()->get_admin_page_url()
188
+ )
189
+ );
190
+ exit;
191
+ }
192
+
193
+ wp_redirect(
194
+ add_query_arg(
195
+ 'success',
196
+ 'google_site_linked',
197
+ wp_mail_smtp()->get_admin()->get_admin_page_url()
198
+ )
199
+ );
200
+ exit;
201
+ }
202
+
203
+ /**
204
+ * Update access token in our DB.
205
+ *
206
+ * @since 1.0.0
207
+ *
208
+ * @param array $token
209
+ */
210
+ protected function update_access_token( $token ) {
211
+
212
+ $options = new PluginOptions();
213
+ $all = $options->get_all();
214
+
215
+ $all[ $this->mailer ]['access_token'] = $token;
216
+ $this->gmail['access_token'] = $token;
217
+
218
+ $options->set( $all );
219
+ }
220
+
221
+ /**
222
+ * Update refresh token in our DB.
223
+ *
224
+ * @since 1.0.0
225
+ *
226
+ * @param array $token
227
+ */
228
+ protected function update_refresh_token( $token ) {
229
+
230
+ $options = new PluginOptions();
231
+ $all = $options->get_all();
232
+
233
+ $all[ $this->mailer ]['refresh_token'] = $token;
234
+ $this->gmail['refresh_token'] = $token;
235
+
236
+ $options->set( $all );
237
+ }
238
+
239
+ /**
240
+ * Update auth code in our DB.
241
+ *
242
+ * @since 1.0.0
243
+ *
244
+ * @param string $code
245
+ */
246
+ protected function update_auth_code( $code ) {
247
+
248
+ $options = new PluginOptions();
249
+ $all = $options->get_all();
250
+
251
+ $all[ $this->mailer ]['auth_code'] = $code;
252
+ $this->gmail['auth_code'] = $code;
253
+
254
+
255
+ $options->set( $all );
256
+ }
257
+
258
+ /**
259
+ * Get the auth URL used to proceed to Google to request access to send emails.
260
+ *
261
+ * @since 1.0.0
262
+ *
263
+ * @return string
264
+ */
265
+ public function get_google_auth_url() {
266
+ if (
267
+ ! empty( $this->client ) &&
268
+ class_exists( 'Google_Client', false ) &&
269
+ $this->client instanceof \Google_Client
270
+ ) {
271
+ return filter_var( $this->client->createAuthUrl(), FILTER_SANITIZE_URL );
272
+ }
273
+
274
+ return '';
275
+ }
276
+
277
+ /**
278
+ * Whether user saved Client ID and Client Secret or not.
279
+ * Both options are required.
280
+ *
281
+ * @since 1.0.0
282
+ *
283
+ * @return bool
284
+ */
285
+ public function is_clients_saved() {
286
+ return ! empty( $this->gmail['client_id'] ) && ! empty( $this->gmail['client_secret'] );
287
+ }
288
+
289
+ /**
290
+ * Whether we have an access and refresh tokens or not.
291
+ *
292
+ * @since 1.0.0
293
+ *
294
+ * @return bool
295
+ */
296
+ public function is_auth_required() {
297
+ return empty( $this->gmail['access_token'] ) || empty( $this->gmail['refresh_token'] );
298
+ }
299
+ }
src/Providers/Gmail/Mailer.php ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers\Gmail;
4
+
5
+ use WPMailSMTP\Providers\MailerAbstract;
6
+
7
+ /**
8
+ * Class Mailer.
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ class Mailer extends MailerAbstract {
13
+
14
+ /**
15
+ * URL to make an API request to.
16
+ * Not used for Gmail, as we are using its API.
17
+ *
18
+ * @var string
19
+ */
20
+ protected $url = 'https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send';
21
+
22
+ /**
23
+ * Gmail custom Auth library.
24
+ *
25
+ * @var Auth
26
+ */
27
+ protected $auth;
28
+
29
+ /**
30
+ * Gmail message.
31
+ *
32
+ * @var \Google_Service_Gmail_Message
33
+ */
34
+ protected $message;
35
+
36
+ /**
37
+ * Mailer constructor.
38
+ *
39
+ * @since 1.0.0
40
+ *
41
+ * @param \WPMailSMTP\MailCatcher $phpmailer
42
+ */
43
+ public function __construct( $phpmailer ) {
44
+ parent::__construct( $phpmailer );
45
+
46
+ if ( ! $this->is_php_compatible() ) {
47
+ return;
48
+ }
49
+
50
+ // Include the Google library.
51
+ require wp_mail_smtp()->plugin_path . '/vendor/autoload.php';
52
+
53
+ $this->auth = new Auth();
54
+ $this->message = new \Google_Service_Gmail_Message();
55
+ }
56
+
57
+ /**
58
+ * Set email FROM.
59
+ *
60
+ * @since 1.0.0
61
+ *
62
+ * @param string $email
63
+ * @param string $name
64
+ */
65
+ public function set_from( $email, $name ) {
66
+ }
67
+
68
+ /**
69
+ * Set a bunch of email recipients: to, cc, bcc.
70
+ *
71
+ * @since 1.0.0
72
+ *
73
+ * @param array $recipients
74
+ */
75
+ public function set_recipients( $recipients ) {
76
+ }
77
+
78
+ /**
79
+ * Set the email content.
80
+ *
81
+ * @since 1.0.0
82
+ *
83
+ * @param string|array $content
84
+ */
85
+ public function set_content( $content ) {
86
+ }
87
+
88
+ /**
89
+ * Set the email attachments.
90
+ *
91
+ * @since 1.0.0
92
+ *
93
+ * @param array $attachments
94
+ */
95
+ public function set_attachments( $attachments ) {
96
+ }
97
+
98
+ /**
99
+ * Set the email reply_to option.
100
+ *
101
+ * @since 1.0.0
102
+ *
103
+ * @param array $reply_to
104
+ */
105
+ public function set_reply_to( $reply_to ) {
106
+ }
107
+
108
+ /**
109
+ * Set the email return_path (when supported).
110
+ *
111
+ * @since 1.0.0
112
+ *
113
+ * @param string $email
114
+ */
115
+ public function set_return_path( $email ) {
116
+ }
117
+
118
+ /**
119
+ * Use Google API Services to send emails.
120
+ *
121
+ * @since 1.0.0
122
+ */
123
+ public function send() {
124
+
125
+ // Get the raw MIME email using \PHPMailer data.
126
+ $mime = $this->phpmailer->getSentMIMEMessage();
127
+ $data = base64_encode( $mime );
128
+ $data = str_replace( array( '+', '/', '=' ), array( '-', '_', '' ), $data ); // url safe.
129
+ $this->message->setRaw( $data );
130
+
131
+ $service = new \Google_Service_Gmail( $this->auth->get_client() );
132
+
133
+ try {
134
+ $response = $service->users_messages->send( 'me', $this->message );
135
+
136
+ $this->process_response( $response );
137
+ } catch ( \Exception $e ) {
138
+ // TODO: save here the error message to display to a user later.
139
+ return;
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Save response from the API to use it later.
145
+ *
146
+ * @since 1.0.0
147
+ *
148
+ * @param \Google_Service_Gmail_Message $response
149
+ */
150
+ protected function process_response( $response ) {
151
+ $this->response = $response;
152
+ }
153
+
154
+ /**
155
+ * Check whether the email was sent.
156
+ *
157
+ * @since 1.0.0
158
+ *
159
+ * @return bool
160
+ */
161
+ public function is_email_sent() {
162
+ $is_sent = false;
163
+
164
+ if ( method_exists( $this->response, 'getId' ) ) {
165
+ $message_id = $this->response->getId();
166
+ if ( ! empty( $message_id ) ) {
167
+ return true;
168
+ }
169
+ }
170
+
171
+ return $is_sent;
172
+ }
173
+ }
src/Providers/Gmail/Options.php ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers\Gmail;
4
+
5
+ use WPMailSMTP\Providers\OptionAbstract;
6
+
7
+ /**
8
+ * Class Option.
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ class Options extends OptionAbstract {
13
+
14
+ /**
15
+ * Mailgun constructor.
16
+ *
17
+ * @since 1.0.0
18
+ */
19
+ public function __construct() {
20
+
21
+ parent::__construct(
22
+ array(
23
+ 'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/gmail.png',
24
+ 'slug' => 'gmail',
25
+ 'title' => esc_html__( 'Gmail', 'wp-mail-smtp' ),
26
+ 'description' => sprintf(
27
+ wp_kses(
28
+ /* translators: %1$s - opening link tag; %2$s - closing link tag. */
29
+ __( 'Send emails using your Gmail or G Suite (formerly Google Apps) account, all while keeping your login credentials safe. Other Google SMTP methods require enabling less secure apps in your account and entering your password. However, this integration uses the Google API to improve email delivery issues while keeping your site secure.<br><br>Read our %1$sGmail documentation%2$s to learn how to configure Gmail or G Suite.', 'wp-mail-smtp' ),
30
+ array(
31
+ 'br' => array(),
32
+ 'a' => array(
33
+ 'href' => array(),
34
+ 'rel' => array(),
35
+ 'target' => array(),
36
+ ),
37
+ )
38
+ ),
39
+ '<a href="https://wpforms.com/how-to-securely-send-wordpress-emails-using-gmail-smtp/" target="_blank" rel="noopener noreferrer">',
40
+ '</a>'
41
+ ),
42
+ 'php' => '5.5',
43
+ )
44
+ );
45
+ }
46
+
47
+ /**
48
+ * @inheritdoc
49
+ */
50
+ public function display_options() {
51
+
52
+ // Do not display options if PHP version is not correct.
53
+ if ( ! $this->is_php_correct() ) {
54
+ $this->display_php_warning();
55
+
56
+ return;
57
+ }
58
+ ?>
59
+
60
+ <!-- Client ID -->
61
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_id" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
62
+ <div class="wp-mail-smtp-setting-label">
63
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_id"><?php esc_html_e( 'Client ID', 'wp-mail-smtp' ); ?></label>
64
+ </div>
65
+ <div class="wp-mail-smtp-setting-field">
66
+ <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][client_id]" type="text"
67
+ value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'client_id' ) ); ?>"
68
+ <?php echo $this->options->is_const_defined( $this->get_slug(), 'client_id' ) ? 'disabled' : ''; ?>
69
+ id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_id" spellcheck="false"
70
+ />
71
+ </div>
72
+ </div>
73
+
74
+ <!-- Client Secret -->
75
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
76
+ <div class="wp-mail-smtp-setting-label">
77
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret"><?php esc_html_e( 'Client Secret', 'wp-mail-smtp' ); ?></label>
78
+ </div>
79
+ <div class="wp-mail-smtp-setting-field">
80
+ <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][client_secret]" type="text"
81
+ value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'client_secret' ) ); ?>"
82
+ <?php echo $this->options->is_const_defined( $this->get_slug(), 'client_secret' ) ? 'disabled' : ''; ?>
83
+ id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret" spellcheck="false"
84
+ />
85
+ </div>
86
+ </div>
87
+
88
+ <!-- Authorized redirect URI -->
89
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
90
+ <div class="wp-mail-smtp-setting-label">
91
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect"><?php esc_html_e( 'Authorized redirect URI', 'wp-mail-smtp' ); ?></label>
92
+ </div>
93
+ <div class="wp-mail-smtp-setting-field">
94
+ <input type="text" readonly="readonly"
95
+ value="<?php echo esc_attr( Auth::get_plugin_auth_url() ); ?>"
96
+ id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect"
97
+ />
98
+ <button type="button" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-light-grey wp-mail-smtp-setting-copy"
99
+ title="<?php esc_attr_e( 'Copy URL to clipboard', 'wp-mail-smtp' ); ?>"
100
+ data-source_id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect">
101
+ <span class="dashicons dashicons-admin-page"></span>
102
+ </button>
103
+ <p class="desc">
104
+ <?php esc_html_e( 'This is the path on your site that you will be redirected to after you have authenticated with Google.', 'wp-mail-smtp' ); ?>
105
+ <br>
106
+ <?php esc_html_e( 'You need to copy this URL into "Authorized redirect URIs" field for you web application on Google APIs site for your project there.', 'wp-mail-smtp' ); ?>
107
+ </p>
108
+ </div>
109
+ </div>
110
+
111
+ <!-- Auth users button -->
112
+ <?php $auth = new Auth(); ?>
113
+ <?php if ( $auth->is_clients_saved() && $auth->is_auth_required() ) : ?>
114
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-authorize" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
115
+ <div class="wp-mail-smtp-setting-label">
116
+ <label><?php esc_html_e( 'Authorize', 'wp-mail-smtp' ); ?></label>
117
+ </div>
118
+ <div class="wp-mail-smtp-setting-field">
119
+ <a href="<?php echo esc_url( $auth->get_google_auth_url() ); ?>" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange">
120
+ <?php esc_html_e( 'Allow plugin to send emails using your Google account', 'wp-mail-smtp' ); ?>
121
+ </a>
122
+ <p class="desc">
123
+ <?php esc_html_e( 'Click the button above to confirm authorization.', 'wp-mail-smtp' ); ?>
124
+ </p>
125
+ </div>
126
+ </div>
127
+ <?php endif; ?>
128
+
129
+ <?php
130
+ }
131
+ }
src/Providers/Loader.php ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers;
4
+
5
+ use WPMailSMTP\MailCatcher;
6
+
7
+ /**
8
+ * Class Loader.
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ class Loader {
13
+
14
+ /**
15
+ * Key is the mailer option, value is the path to its classes.
16
+ *
17
+ * @var array
18
+ */
19
+ protected $providers = array(
20
+ 'mail' => '\WPMailSMTP\Providers\Mail\\',
21
+ 'gmail' => '\WPMailSMTP\Providers\Gmail\\',
22
+ 'mailgun' => '\WPMailSMTP\Providers\Mailgun\\',
23
+ 'sendgrid' => '\WPMailSMTP\Providers\Sendgrid\\',
24
+ 'pepipost' => '\WPMailSMTP\Providers\Pepipost\\',
25
+ 'smtp' => '\WPMailSMTP\Providers\SMTP\\',
26
+ );
27
+
28
+ /**
29
+ * @var \WPMailSMTP\MailCatcher
30
+ */
31
+ private $phpmailer;
32
+
33
+ /**
34
+ * Get all the supported providers.
35
+ *
36
+ * @since 1.0.0
37
+ *
38
+ * @return array
39
+ */
40
+ public function get_providers() {
41
+ return apply_filters( 'wp_mail_smtp_providers_loader_get_providers', $this->providers );
42
+ }
43
+
44
+ /**
45
+ * Get a single provider FQN-path based on its name.
46
+ *
47
+ * @since 1.0.0
48
+ *
49
+ * @param string $provider
50
+ *
51
+ * @return array
52
+ */
53
+ public function get_provider_path( $provider ) {
54
+ $provider = sanitize_key( $provider );
55
+
56
+ return apply_filters(
57
+ 'wp_mail_smtp_providers_loader_get_provider_path',
58
+ isset( $this->providers[ $provider ] ) ? $this->providers[ $provider ] : null,
59
+ $provider
60
+ );
61
+ }
62
+
63
+ /**
64
+ * Get the provider options, if exists.
65
+ *
66
+ * @since 1.0.0
67
+ *
68
+ * @param string $provider
69
+ *
70
+ * @return \WPMailSMTP\Providers\OptionAbstract|null
71
+ */
72
+ public function get_options( $provider ) {
73
+ return $this->get_entity( $provider, 'Options' );
74
+ }
75
+
76
+ /**
77
+ * Get all options of all providers.
78
+ *
79
+ * @since 1.0.0
80
+ *
81
+ * @return \WPMailSMTP\Providers\OptionAbstract[]
82
+ */
83
+ public function get_options_all() {
84
+ $options = array();
85
+
86
+ foreach ( $this->get_providers() as $provider => $path ) {
87
+
88
+ $option = $this->get_options( $provider );
89
+
90
+ if ( ! $option instanceof OptionAbstract ) {
91
+ continue;
92
+ }
93
+
94
+ $slug = $option->get_slug();
95
+ $title = $option->get_title();
96
+
97
+ if ( empty( $title ) || empty( $slug ) ) {
98
+ continue;
99
+ }
100
+
101
+ $options[] = $option;
102
+ }
103
+
104
+ return apply_filters( 'wp_mail_smtp_providers_loader_get_providers_all', $options );
105
+ }
106
+
107
+ /**
108
+ * Get the provider mailer, if exists.
109
+ *
110
+ * @since 1.0.0
111
+ *
112
+ * @param string $provider
113
+ * @param MailCatcher $phpmailer
114
+ *
115
+ * @return \WPMailSMTP\Providers\MailerAbstract|null
116
+ */
117
+ public function get_mailer( $provider, $phpmailer ) {
118
+
119
+ if ( $phpmailer instanceof MailCatcher ) {
120
+ $this->phpmailer = $phpmailer;
121
+ }
122
+
123
+ return $this->get_entity( $provider, 'Mailer' );
124
+ }
125
+
126
+ /**
127
+ * Get the provider auth, if exists.
128
+ *
129
+ * @param string $provider
130
+ *
131
+ * @return \WPMailSMTP\Providers\AuthAbstract|null
132
+ */
133
+ public function get_auth( $provider ) {
134
+ return $this->get_entity( $provider, 'Auth' );
135
+ }
136
+
137
+ /**
138
+ * Get a generic entity based on the request.
139
+ *
140
+ * @uses ReflectionClass
141
+ *
142
+ * @since 1.0.0
143
+ *
144
+ * @param string $provider
145
+ * @param string $request
146
+ *
147
+ * @return null
148
+ */
149
+ protected function get_entity( $provider, $request ) {
150
+
151
+ $provider = sanitize_key( $provider );
152
+ $request = sanitize_text_field( $request );
153
+ $path = $this->get_provider_path( $provider );
154
+ $entity = null;
155
+
156
+ if ( empty( $path ) ) {
157
+ return $entity;
158
+ }
159
+
160
+ try {
161
+ $reflection = new \ReflectionClass( $path . $request );
162
+
163
+ if ( file_exists( $reflection->getFileName() ) ) {
164
+ $class = $path . $request;
165
+ if ( $this->phpmailer ) {
166
+ $entity = new $class( $this->phpmailer );
167
+ } else {
168
+ $entity = new $class();
169
+ }
170
+ }
171
+ } catch ( \Exception $e ) {
172
+ // TODO: save error message later to display a user.
173
+ $entity = null;
174
+ }
175
+
176
+ return apply_filters( 'wp_mail_smtp_providers_loader_get_entity', $entity, $provider, $request );
177
+ }
178
+ }
src/Providers/Mail/Options.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers\Mail;
4
+
5
+ use WPMailSMTP\Providers\OptionAbstract;
6
+
7
+ /**
8
+ * Class Option.
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ class Options extends OptionAbstract {
13
+
14
+ /**
15
+ * Mail constructor.
16
+ *
17
+ * @since 1.0.0
18
+ */
19
+ public function __construct() {
20
+
21
+ parent::__construct(
22
+ array(
23
+ 'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/php.png',
24
+ 'slug' => 'mail',
25
+ 'title' => esc_html__( 'Default (none)', 'wp-mail-smtp' ),
26
+ )
27
+ );
28
+ }
29
+
30
+ /**
31
+ * @inheritdoc
32
+ */
33
+ public function display_options() {
34
+ ?>
35
+
36
+ <blockquote>
37
+ <?php esc_html_e( 'You currently have the native WordPress option selected. Please select any other Mailer option above to continue the setup.', 'wp-mail-smtp' ); ?>
38
+ </blockquote>
39
+
40
+ <?php
41
+ }
42
+ }
src/Providers/MailerAbstract.php ADDED
@@ -0,0 +1,346 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers;
4
+
5
+ use WPMailSMTP\MailCatcher;
6
+ use WPMailSMTP\Options;
7
+
8
+ /**
9
+ * Class MailerAbstract.
10
+ *
11
+ * @since 1.0.0
12
+ */
13
+ abstract class MailerAbstract implements MailerInterface {
14
+
15
+ /**
16
+ * Which response code from HTTP provider is considered to be successful?
17
+ *
18
+ * @var int
19
+ */
20
+ protected $email_sent_code = 200;
21
+ /**
22
+ * @var Options
23
+ */
24
+ protected $options;
25
+ /**
26
+ * @var MailCatcher
27
+ */
28
+ protected $phpmailer;
29
+ /**
30
+ * @var string
31
+ */
32
+ protected $mailer = '';
33
+
34
+ /**
35
+ * URL to make an API request to.
36
+ *
37
+ * @var string
38
+ */
39
+ protected $url = '';
40
+ /**
41
+ * @var array
42
+ */
43
+ protected $headers = array();
44
+ /**
45
+ * @var array
46
+ */
47
+ protected $body = array();
48
+ /**
49
+ * @var mixed
50
+ */
51
+ protected $response = array();
52
+
53
+ /**
54
+ * Mailer constructor.
55
+ *
56
+ * @since 1.0.0
57
+ *
58
+ * @param MailCatcher $phpmailer
59
+ */
60
+ public function __construct( MailCatcher $phpmailer ) {
61
+
62
+ if ( empty( $this->url ) ) {
63
+ return;
64
+ }
65
+
66
+ $this->options = new Options();
67
+ $this->mailer = $this->options->get( 'mail', 'mailer' );
68
+
69
+ $this->process_phpmailer( $phpmailer );
70
+ }
71
+
72
+ /**
73
+ * Re-use the MailCatcher class methods and properties.
74
+ *
75
+ * @since 1.0.0
76
+ *
77
+ * @param MailCatcher $phpmailer
78
+ */
79
+ protected function process_phpmailer( $phpmailer ) {
80
+
81
+ // Make sure that we have access to PHPMailer class methods.
82
+ if ( ! $phpmailer instanceof MailCatcher ) {
83
+ return;
84
+ }
85
+
86
+ $this->phpmailer = $phpmailer;
87
+
88
+ $this->set_headers( $this->phpmailer->getCustomHeaders() );
89
+ $this->set_from( $this->phpmailer->From, $this->phpmailer->FromName );
90
+ $this->set_recipients(
91
+ array(
92
+ 'to' => $this->phpmailer->getToAddresses(),
93
+ 'cc' => $this->phpmailer->getCcAddresses(),
94
+ 'bcc' => $this->phpmailer->getBccAddresses(),
95
+ )
96
+ );
97
+ $this->set_subject( $this->phpmailer->Subject );
98
+ $this->set_content(
99
+ array(
100
+ 'html' => $this->phpmailer->Body,
101
+ 'text' => $this->phpmailer->AltBody,
102
+ )
103
+ );
104
+ $this->set_return_path( $this->phpmailer->From );
105
+ $this->set_reply_to( $this->phpmailer->getReplyToAddresses() );
106
+
107
+ /*
108
+ * In some cases we will need to modify the internal structure
109
+ * of the body content, if attachments are present.
110
+ * So lets make this call the last one.
111
+ */
112
+ $this->set_attachments( $this->phpmailer->getAttachments() );
113
+ }
114
+
115
+ /**
116
+ * @inheritdoc
117
+ */
118
+ public function set_subject( $subject ) {
119
+
120
+ $this->set_body_param(
121
+ array(
122
+ 'subject' => $subject,
123
+ )
124
+ );
125
+ }
126
+
127
+ /**
128
+ * Set the request params, that goes to the body of the HTTP request.
129
+ *
130
+ * @since 1.0.0
131
+ *
132
+ * @param array $param Key=>value of what should be sent to a 3rd party API.
133
+ *
134
+ * @internal param array $params
135
+ */
136
+ protected function set_body_param( $param ) {
137
+ $this->body = $this->array_merge_recursive( $this->body, $param );
138
+ }
139
+
140
+ /**
141
+ * @inheritdoc
142
+ */
143
+ public function set_headers( $headers ) {
144
+
145
+ foreach ( $headers as $header ) {
146
+ $name = isset( $header[0] ) ? $header[0] : false;
147
+ $value = isset( $header[1] ) ? $header[1] : false;
148
+
149
+ if ( empty( $name ) || empty( $value ) ) {
150
+ continue;
151
+ }
152
+
153
+ $this->set_header( $name, $value );
154
+ }
155
+ }
156
+
157
+ /**
158
+ * @inheritdoc
159
+ */
160
+ public function set_header( $name, $value ) {
161
+
162
+ $process_value = function ( $value ) {
163
+ // Remove HTML tags.
164
+ $filtered = wp_strip_all_tags( $value, false );
165
+ // Remove multi-lines/tabs.
166
+ $filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered );
167
+ // Remove whitespaces.
168
+ $filtered = trim( $filtered );
169
+
170
+ // Remove octets.
171
+ $found = false;
172
+ while ( preg_match( '/%[a-f0-9]{2}/i', $filtered, $match ) ) {
173
+ $filtered = str_replace( $match[0], '', $filtered );
174
+ $found = true;
175
+ }
176
+
177
+ if ( $found ) {
178
+ // Strip out the whitespace that may now exist after removing the octets.
179
+ $filtered = trim( preg_replace( '/ +/', ' ', $filtered ) );
180
+ }
181
+
182
+ return $filtered;
183
+ };
184
+
185
+ $name = sanitize_text_field( $name );
186
+ if ( empty( $name ) ) {
187
+ return;
188
+ }
189
+
190
+ $value = $process_value( $value );
191
+
192
+ $this->headers[ $name ] = $value;
193
+ }
194
+
195
+ /**
196
+ * @inheritdoc
197
+ */
198
+ public function get_body() {
199
+ return apply_filters( 'wp_mail_smtp_providers_mailer_get_body', $this->body );
200
+ }
201
+
202
+ /**
203
+ * @inheritdoc
204
+ */
205
+ public function get_headers() {
206
+ return apply_filters( 'wp_mail_smtp_providers_mailer_get_headers', $this->headers );
207
+ }
208
+
209
+ /**
210
+ * @inheritdoc
211
+ */
212
+ public function send() {
213
+
214
+ $params = $this->array_merge_recursive( $this->get_default_params(), array(
215
+ 'headers' => $this->get_headers(),
216
+ 'body' => $this->get_body(),
217
+ ) );
218
+
219
+ $response = wp_safe_remote_post( $this->url, $params );
220
+
221
+ $this->process_response( $response );
222
+ }
223
+
224
+ /**
225
+ * We might need to do something after the email was sent to the API.
226
+ * In this method we preprocess the response from the API.
227
+ *
228
+ * @since 1.0.0
229
+ *
230
+ * @param array|\WP_Error $response
231
+ */
232
+ protected function process_response( $response ) {
233
+
234
+ if ( is_wp_error( $response ) ) {
235
+ return;
236
+ }
237
+
238
+ if ( isset( $response['body'] ) && $this->is_json( $response['body'] ) ) {
239
+ $response['body'] = json_decode( $response['body'] );
240
+ }
241
+
242
+ $this->response = $response;
243
+ }
244
+
245
+ /**
246
+ * Get the default params, required for wp_safe_remote_post().
247
+ *
248
+ * @since 1.0.0
249
+ *
250
+ * @return array
251
+ */
252
+ protected function get_default_params() {
253
+
254
+ return apply_filters( 'wp_mail_smtp_providers_mailer_get_default_params', array(
255
+ 'timeout' => 15,
256
+ 'httpversion' => '1.1',
257
+ 'blocking' => true,
258
+ ) );
259
+ }
260
+
261
+ /**
262
+ * @inheritdoc
263
+ */
264
+ public function is_email_sent() {
265
+
266
+ $is_sent = false;
267
+
268
+ if ( wp_remote_retrieve_response_code( $this->response ) === $this->email_sent_code ) {
269
+ $is_sent = true;
270
+ }
271
+
272
+ return apply_filters( 'wp_mail_smtp_providers_mailer_is_email_sent', $is_sent );
273
+ }
274
+
275
+ /**
276
+ * @inheritdoc
277
+ */
278
+ public function is_php_compatible() {
279
+
280
+ $options = wp_mail_smtp()->get_providers()->get_options( $this->mailer );
281
+
282
+ return version_compare( phpversion(), $options->get_php_version(), '>=' );
283
+ }
284
+
285
+ /**
286
+ * Check whether the string is a JSON or not.
287
+ *
288
+ * @since 1.0.0
289
+ *
290
+ * @param string $string
291
+ *
292
+ * @return bool
293
+ */
294
+ protected function is_json( $string ) {
295
+ return is_string( $string ) && is_array( json_decode( $string, true ) ) && ( json_last_error() === JSON_ERROR_NONE ) ? true : false;
296
+ }
297
+
298
+ /**
299
+ * Merge recursively, including a proper substitution of values in sub-arrays when keys are the same.
300
+ * It's more like array_merge() and array_merge_recursive() combined.
301
+ *
302
+ * @since 1.0.0
303
+ *
304
+ * @return array
305
+ */
306
+ protected function array_merge_recursive() {
307
+
308
+ $arrays = func_get_args();
309
+
310
+ if ( count( $arrays ) < 2 ) {
311
+ return isset( $arrays[0] ) ? $arrays[0] : array();
312
+ }
313
+
314
+ $merged = array();
315
+
316
+ while ( $arrays ) {
317
+ $array = array_shift( $arrays );
318
+
319
+ if ( ! is_array( $array ) ) {
320
+ return array();
321
+ }
322
+
323
+ if ( empty( $array ) ) {
324
+ continue;
325
+ }
326
+
327
+ foreach ( $array as $key => $value ) {
328
+ if ( is_string( $key ) ) {
329
+ if (
330
+ is_array( $value ) &&
331
+ array_key_exists( $key, $merged ) &&
332
+ is_array( $merged[ $key ] )
333
+ ) {
334
+ $merged[ $key ] = call_user_func( __FUNCTION__, $merged[ $key ], $value );
335
+ } else {
336
+ $merged[ $key ] = $value;
337
+ }
338
+ } else {
339
+ $merged[] = $value;
340
+ }
341
+ }
342
+ }
343
+
344
+ return $merged;
345
+ }
346
+ }
src/Providers/MailerInterface.php ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers;
4
+
5
+ /**
6
+ * Interface MailerInterface.
7
+ *
8
+ * @since 1.0.0
9
+ */
10
+ interface MailerInterface {
11
+
12
+ /**
13
+ * Send the email.
14
+ *
15
+ * @since 1.0.0
16
+ */
17
+ public function send();
18
+
19
+ /**
20
+ * Whether the email is sent or not.
21
+ * We basically check the response code from a request to provider.
22
+ * Might not be 100% correct, not guarantees that email is delivered.
23
+ *
24
+ * @since 1.0.0
25
+ *
26
+ * @return bool
27
+ */
28
+ public function is_email_sent();
29
+
30
+ /**
31
+ * Whether the mailer supports the current PHP version or not.
32
+ *
33
+ * @since 1.0.0
34
+ *
35
+ * @return bool
36
+ */
37
+ public function is_php_compatible();
38
+
39
+ /**
40
+ * Set the email headers in bulk.
41
+ *
42
+ * @since 1.0.0
43
+ *
44
+ * @param array $headers
45
+ */
46
+ public function set_headers( $headers );
47
+
48
+ /**
49
+ * Set the email single header.
50
+ *
51
+ * @since 1.0.0
52
+ *
53
+ * @param string $name
54
+ * @param string $value
55
+ */
56
+ public function set_header( $name, $value );
57
+
58
+ /**
59
+ * Set email FROM.
60
+ *
61
+ * @since 1.0.0
62
+ *
63
+ * @param string $email
64
+ * @param string $name
65
+ */
66
+ public function set_from( $email, $name );
67
+
68
+ /**
69
+ * Set a bunch of email recipients: to, cc, bcc.
70
+ *
71
+ * @since 1.0.0
72
+ *
73
+ * @param array $recipients
74
+ */
75
+ public function set_recipients( $recipients );
76
+
77
+ /**
78
+ * Set the email subject.
79
+ *
80
+ * @since 1.0.0
81
+ *
82
+ * @param string $subject
83
+ */
84
+ public function set_subject( $subject );
85
+
86
+ /**
87
+ * Set the email content.
88
+ *
89
+ * @since 1.0.0
90
+ *
91
+ * @param string|array $content
92
+ */
93
+ public function set_content( $content );
94
+
95
+ /**
96
+ * Set the email attachments.
97
+ *
98
+ * @since 1.0.0
99
+ *
100
+ * @param array $attachments
101
+ */
102
+ public function set_attachments( $attachments );
103
+
104
+ /**
105
+ * Set the email reply_to option.
106
+ *
107
+ * @since 1.0.0
108
+ *
109
+ * @param array $reply_to
110
+ */
111
+ public function set_reply_to( $reply_to );
112
+
113
+ /**
114
+ * Set the email return_path (when supported).
115
+ *
116
+ * @since 1.0.0
117
+ *
118
+ * @param string $email
119
+ */
120
+ public function set_return_path( $email );
121
+
122
+ /**
123
+ * Get the email body.
124
+ *
125
+ * @since 1.0.0
126
+ *
127
+ * @return string|array
128
+ */
129
+ public function get_body();
130
+
131
+ /**
132
+ * Get the email headers.
133
+ *
134
+ * @since 1.0.0
135
+ *
136
+ * @return array
137
+ */
138
+ public function get_headers();
139
+ }
src/Providers/Mailgun/Mailer.php ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers\Mailgun;
4
+
5
+ use WPMailSMTP\Providers\MailerAbstract;
6
+
7
+ /**
8
+ * Class Mailer.
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ class Mailer extends MailerAbstract {
13
+
14
+ /**
15
+ * Which response code from HTTP provider is considered to be successful?
16
+ *
17
+ * @var int
18
+ */
19
+ protected $email_sent_code = 200;
20
+
21
+ /**
22
+ * URL to make an API request to.
23
+ *
24
+ * @var string
25
+ */
26
+ protected $url = 'https://api.mailgun.net/v3/';
27
+
28
+ /**
29
+ * @inheritdoc
30
+ */
31
+ public function __construct( $phpmailer ) {
32
+
33
+ // We want to prefill everything from \PHPMailer class.
34
+ parent::__construct( $phpmailer );
35
+
36
+ /*
37
+ * Append the url with a domain,
38
+ * to avoid passing the domain name as a query parameter with all requests.
39
+ */
40
+ $this->url .= sanitize_text_field( $this->options->get( $this->mailer, 'domain' ) . '/messages' );
41
+
42
+ $this->set_header( 'Authorization', 'Basic ' . base64_encode( 'api:' . $this->options->get( $this->mailer, 'api_key' ) ) );
43
+ }
44
+
45
+ /**
46
+ * @inheritdoc
47
+ */
48
+ public function set_from( $email, $name = '' ) {
49
+
50
+ if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
51
+ return;
52
+ }
53
+
54
+ if ( ! empty( $name ) ) {
55
+ $this->set_body_param(
56
+ array(
57
+ 'from' => $name . ' <' . $email . '>',
58
+ )
59
+ );
60
+ } else {
61
+ $this->set_body_param(
62
+ array(
63
+ 'from' => $email,
64
+ )
65
+ );
66
+ }
67
+ }
68
+
69
+ /**
70
+ * @inheritdoc
71
+ */
72
+ public function set_recipients( $recipients ) {
73
+
74
+ if ( empty( $recipients ) ) {
75
+ return;
76
+ }
77
+
78
+ $default = array( 'to', 'cc', 'bcc' );
79
+
80
+ foreach ( $recipients as $kind => $emails ) {
81
+ if (
82
+ ! in_array( $kind, $default, true ) ||
83
+ empty( $emails ) ||
84
+ ! is_array( $emails )
85
+ ) {
86
+ continue;
87
+ }
88
+
89
+ $data = array();
90
+
91
+ foreach ( $emails as $email ) {
92
+ $addr = isset( $email[0] ) ? $email[0] : false;
93
+ $name = isset( $email[1] ) ? $email[1] : false;
94
+
95
+ if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
96
+ continue;
97
+ }
98
+
99
+ if ( ! empty( $name ) ) {
100
+ $data[] = $name . ' <' . $addr . '>';
101
+ } else {
102
+ $data[] = $addr;
103
+ }
104
+ }
105
+
106
+ if ( ! empty( $data ) ) {
107
+ $this->set_body_param(
108
+ array(
109
+ $kind => implode( ', ', $data ),
110
+ )
111
+ );
112
+ }
113
+ }
114
+ }
115
+
116
+ /**
117
+ * @inheritdoc
118
+ */
119
+ public function set_content( $content ) {
120
+
121
+ if ( is_array( $content ) ) {
122
+
123
+ $default = array( 'text', 'html' );
124
+
125
+ foreach ( $content as $type => $mail ) {
126
+ if (
127
+ ! in_array( $type, $default, true ) ||
128
+ empty( $mail )
129
+ ) {
130
+ continue;
131
+ }
132
+
133
+ $this->set_body_param(
134
+ array(
135
+ $type => $mail,
136
+ )
137
+ );
138
+ }
139
+ } else {
140
+ $type = 'text';
141
+
142
+ if ( $this->phpmailer->ContentType === 'text/html' ) {
143
+ $type = 'html';
144
+ }
145
+
146
+ if ( ! empty( $content ) ) {
147
+ $this->set_body_param(
148
+ array(
149
+ $type => $content,
150
+ )
151
+ );
152
+ }
153
+ }
154
+ }
155
+
156
+ /**
157
+ * It's the last one, so we can modify the whole body.
158
+ *
159
+ * @since 1.0.0
160
+ *
161
+ * @param array $attachments
162
+ */
163
+ public function set_attachments( $attachments ) {
164
+
165
+ if ( empty( $attachments ) ) {
166
+ return;
167
+ }
168
+
169
+ $payload = '';
170
+ $data = array();
171
+
172
+ foreach ( $attachments as $attachment ) {
173
+ $file = false;
174
+
175
+ /*
176
+ * We are not using WP_Filesystem API as we can't reliably work with it.
177
+ * It is not always available, same as credentials for FTP.
178
+ */
179
+ try {
180
+ if ( is_file( $attachment[0] ) && is_readable( $attachment[0] ) ) {
181
+ $file = file_get_contents( $attachment[0] );
182
+ }
183
+ } catch ( \Exception $e ) {
184
+ $file = false;
185
+ }
186
+
187
+ if ( $file === false ) {
188
+ continue;
189
+ }
190
+
191
+ $data[] = array(
192
+ 'content' => $file,
193
+ 'name' => $attachment[1],
194
+ );
195
+ }
196
+
197
+ if ( ! empty( $data ) ) {
198
+
199
+ // First, generate a boundary for the multipart message.
200
+ $boundary = base_convert( uniqid( 'boundary', true ), 10, 36 );
201
+
202
+ // Iterate through pre-built params and build a payload.
203
+ foreach ( $this->body as $key => $value ) {
204
+ if ( is_array( $value ) ) {
205
+ foreach ( $value as $child_key => $child_value ) {
206
+ $payload .= '--' . $boundary;
207
+ $payload .= "\r\n";
208
+ $payload .= 'Content-Disposition: form-data; name="' . $key . "\"\r\n\r\n";
209
+ $payload .= $child_value;
210
+ $payload .= "\r\n";
211
+ }
212
+ } else {
213
+ $payload .= '--' . $boundary;
214
+ $payload .= "\r\n";
215
+ $payload .= 'Content-Disposition: form-data; name="' . $key . '"' . "\r\n\r\n";
216
+ $payload .= $value;
217
+ $payload .= "\r\n";
218
+ }
219
+ }
220
+
221
+ // Now iterate through our attachments, and add them too.
222
+ foreach ( $data as $key => $attachment ) {
223
+ $payload .= '--' . $boundary;
224
+ $payload .= "\r\n";
225
+ $payload .= 'Content-Disposition: form-data; name="attachment[' . $key . ']"; filename="' . $attachment['name'] . '"' . "\r\n\r\n";
226
+ $payload .= $attachment['content'];
227
+ $payload .= "\r\n";
228
+ }
229
+
230
+ $payload .= '--' . $boundary . '--';
231
+
232
+ // Redefine the body the "dirty way".
233
+ $this->body = $payload;
234
+
235
+ $this->set_header( 'Content-Type', 'multipart/form-data; boundary=' . $boundary );
236
+ }
237
+ }
238
+
239
+ /**
240
+ * @inheritdoc
241
+ */
242
+ public function set_reply_to( $reply_to ) {
243
+
244
+ if ( empty( $reply_to ) ) {
245
+ return;
246
+ }
247
+
248
+ $data = array();
249
+
250
+ foreach ( $reply_to as $key => $emails ) {
251
+ if (
252
+ empty( $emails ) ||
253
+ ! is_array( $emails )
254
+ ) {
255
+ continue;
256
+ }
257
+
258
+ $addr = isset( $emails[0] ) ? $emails[0] : false;
259
+ $name = isset( $emails[1] ) ? $emails[1] : false;
260
+
261
+ if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
262
+ continue;
263
+ }
264
+
265
+ if ( ! empty( $name ) ) {
266
+ $data[] = $name . ' <' . $addr . '>';
267
+ } else {
268
+ $data[] = $addr;
269
+ }
270
+ }
271
+
272
+ if ( ! empty( $data ) ) {
273
+ $this->set_body_param(
274
+ array(
275
+ 'h:Reply-To' => implode( ',', $data ),
276
+ )
277
+ );
278
+ }
279
+ }
280
+
281
+ /**
282
+ * @inheritdoc
283
+ */
284
+ public function set_return_path( $email ) {
285
+
286
+ if (
287
+ $this->options->get( 'mail', 'return_path' ) !== true ||
288
+ ! filter_var( $email, FILTER_VALIDATE_EMAIL )
289
+ ) {
290
+ return;
291
+ }
292
+
293
+ $this->set_body_param(
294
+ array(
295
+ 'sender' => $email,
296
+ )
297
+ );
298
+ }
299
+ }
src/Providers/Mailgun/Options.php ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers\Mailgun;
4
+
5
+ use WPMailSMTP\Providers\OptionAbstract;
6
+
7
+ /**
8
+ * Class Option.
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ class Options extends OptionAbstract {
13
+
14
+ /**
15
+ * Mailgun constructor.
16
+ *
17
+ * @since 1.0.0
18
+ */
19
+ public function __construct() {
20
+
21
+ parent::__construct(
22
+ array(
23
+ 'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/mailgun.png',
24
+ 'slug' => 'mailgun',
25
+ 'title' => esc_html__( 'Mailgun', 'wp-mail-smtp' ),
26
+ 'description' => sprintf(
27
+ wp_kses(
28
+ /* translators: %1$s - opening link tag; %2$s - closing link tag; %3$s - opening link tag; %4$s - closing link tag. */
29
+ __( '%1$sMailgun%2$s is one of the leading transactional email services trusted by over 10,000 website and application developers. They provide users 10,000 free emails per month.<br><br>Read our %3$sMailgun documentation%4$s to learn how to configure Mailgun and improve your email deliverability.', 'wp-mail-smtp' ),
30
+ array(
31
+ 'br' => array(),
32
+ 'a' => array(
33
+ 'href' => array(),
34
+ 'rel' => array(),
35
+ 'target' => array(),
36
+ ),
37
+ )
38
+ ),
39
+ '<a href="https://www.mailgun.com" target="_blank" rel="noopener noreferrer">',
40
+ '</a>',
41
+ '<a href="https://wpforms.com/how-to-send-wordpress-emails-with-mailgun/" target="_blank" rel="noopener noreferrer">',
42
+ '</a>'
43
+ ),
44
+ )
45
+ );
46
+ }
47
+
48
+ /**
49
+ * @inheritdoc
50
+ */
51
+ public function display_options() {
52
+ ?>
53
+
54
+ <!-- API Key -->
55
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
56
+ <div class="wp-mail-smtp-setting-label">
57
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'Private API Key', 'wp-mail-smtp' ); ?></label>
58
+ </div>
59
+ <div class="wp-mail-smtp-setting-field">
60
+ <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]" type="text"
61
+ value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'api_key' ) ); ?>"
62
+ <?php echo $this->options->is_const_defined( $this->get_slug(), 'api_key' ) ? 'disabled' : ''; ?>
63
+ id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" spellcheck="false"
64
+ />
65
+ <p class="desc">
66
+ <?php
67
+ printf(
68
+ /* translators: %s - API key link. */
69
+ esc_html__( 'Follow this link to get an API Key from Mailgun: %s.', 'wp-mail-smtp' ),
70
+ '<a href="https://app.mailgun.com/app/account/security" target="_blank" rel="noopener noreferrer">' .
71
+ esc_html__( 'Get a Private API Key', 'wp-mail-smtp' ) .
72
+ '</a>'
73
+ );
74
+ ?>
75
+ </p>
76
+ </div>
77
+ </div>
78
+
79
+ <!-- Domain -->
80
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-domain" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
81
+ <div class="wp-mail-smtp-setting-label">
82
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-domain"><?php esc_html_e( 'Domain Name', 'wp-mail-smtp' ); ?></label>
83
+ </div>
84
+ <div class="wp-mail-smtp-setting-field">
85
+ <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][domain]" type="text"
86
+ value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'domain' ) ); ?>"
87
+ <?php echo $this->options->is_const_defined( $this->get_slug(), 'domain' ) ? 'disabled' : ''; ?>
88
+ id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-domain" spellcheck="false"
89
+ />
90
+ <p class="desc">
91
+ <?php
92
+ printf(
93
+ /* translators: %s - Domain Name link. */
94
+ esc_html__( 'Follow this link to get a Domain Name from Mailgun: %s.', 'wp-mail-smtp' ),
95
+ '<a href="https://app.mailgun.com/app/domains" target="_blank" rel="noopener noreferrer">' .
96
+ esc_html__( 'Get a Domain Name', 'wp-mail-smtp' ) .
97
+ '</a>'
98
+ );
99
+ ?>
100
+ </p>
101
+ </div>
102
+ </div>
103
+
104
+ <?php
105
+ }
106
+ }
src/Providers/OptionAbstract.php ADDED
@@ -0,0 +1,291 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers;
4
+
5
+ use WPMailSMTP\Options;
6
+
7
+ /**
8
+ * Abstract Class ProviderAbstract to contain common providers functionality.
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ abstract class OptionAbstract implements OptionInterface {
13
+
14
+ /**
15
+ * @var string
16
+ */
17
+ private $logo_url = '';
18
+ /**
19
+ * @var string
20
+ */
21
+ private $slug = '';
22
+ /**
23
+ * @var string
24
+ */
25
+ private $title = '';
26
+ /**
27
+ * @var string
28
+ */
29
+ private $description = '';
30
+ /**
31
+ * @var string
32
+ */
33
+ private $php = WPMS_PHP_VER;
34
+ /**
35
+ * @var Options
36
+ */
37
+ protected $options;
38
+
39
+ /**
40
+ * ProviderAbstract constructor.
41
+ *
42
+ * @since 1.0.0
43
+ *
44
+ * @param array $params
45
+ */
46
+ public function __construct( $params ) {
47
+
48
+ if (
49
+ empty( $params['slug'] ) ||
50
+ empty( $params['title'] )
51
+ ) {
52
+ return;
53
+ }
54
+
55
+ $this->slug = sanitize_key( $params['slug'] );
56
+ $this->title = sanitize_text_field( $params['title'] );
57
+
58
+ if ( ! empty( $params['description'] ) ) {
59
+ $this->description = wp_kses( $params['description'],
60
+ array(
61
+ 'br' => array(),
62
+ 'a' => array(
63
+ 'href' => array(),
64
+ 'rel' => array(),
65
+ 'target' => array(),
66
+ ),
67
+ )
68
+ );
69
+ }
70
+
71
+ if ( ! empty( $params['php'] ) ) {
72
+ $this->php = sanitize_text_field( $params['php'] );
73
+ }
74
+
75
+ if ( ! empty( $params['logo_url'] ) ) {
76
+ $this->logo_url = esc_url_raw( $params['logo_url'] );
77
+ }
78
+
79
+ $this->options = new Options();
80
+ }
81
+
82
+ /**
83
+ * @inheritdoc
84
+ */
85
+ public function get_logo_url() {
86
+ return apply_filters( 'wp_mail_smtp_providers_provider_get_logo_url', $this->logo_url, $this );
87
+ }
88
+
89
+ /**
90
+ * @inheritdoc
91
+ */
92
+ public function get_slug() {
93
+ return apply_filters( 'wp_mail_smtp_providers_provider_get_slug', $this->slug, $this );
94
+ }
95
+
96
+ /**
97
+ * @inheritdoc
98
+ */
99
+ public function get_title() {
100
+ return apply_filters( 'wp_mail_smtp_providers_provider_get_title', $this->title, $this );
101
+ }
102
+
103
+ /**
104
+ * @inheritdoc
105
+ */
106
+ public function get_description() {
107
+ return apply_filters( 'wp_mail_smtp_providers_provider_get_description', $this->description, $this );
108
+ }
109
+
110
+ /**
111
+ * @inheritdoc
112
+ */
113
+ public function get_php_version() {
114
+ return apply_filters( 'wp_mail_smtp_providers_provider_get_php_version', $this->php, $this );
115
+ }
116
+
117
+ /**
118
+ * @inheritdoc
119
+ */
120
+ public function display_options() {
121
+ ?>
122
+
123
+ <!-- SMTP Host -->
124
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-host" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
125
+ <div class="wp-mail-smtp-setting-label">
126
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-host"><?php esc_html_e( 'SMTP Host', 'wp-mail-smtp' ); ?></label>
127
+ </div>
128
+ <div class="wp-mail-smtp-setting-field">
129
+ <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][host]" type="text"
130
+ value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'host' ) ); ?>"
131
+ <?php echo $this->options->is_const_defined( $this->get_slug(), 'host' ) ? 'disabled' : ''; ?>
132
+ id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-host" spellcheck="false"
133
+ />
134
+ </div>
135
+ </div>
136
+
137
+ <!-- SMTP Port -->
138
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-port" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-number wp-mail-smtp-clear">
139
+ <div class="wp-mail-smtp-setting-label">
140
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-port"><?php esc_html_e( 'SMTP Port', 'wp-mail-smtp' ); ?></label>
141
+ </div>
142
+ <div class="wp-mail-smtp-setting-field">
143
+ <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][port]" type="number"
144
+ value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'port' ) ); ?>"
145
+ <?php echo $this->options->is_const_defined( $this->get_slug(), 'port' ) ? 'disabled' : ''; ?>
146
+ id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-port" class="small-text" spellcheck="false"
147
+ />
148
+ </div>
149
+ </div>
150
+
151
+ <!-- SMTP Encryption -->
152
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-encryption" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-radio wp-mail-smtp-clear">
153
+ <div class="wp-mail-smtp-setting-label">
154
+ <label><?php esc_html_e( 'Encryption', 'wp-mail-smtp' ); ?></label>
155
+ </div>
156
+ <div class="wp-mail-smtp-setting-field">
157
+
158
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-none">
159
+ <input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-none"
160
+ name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][encryption]" value="none"
161
+ <?php echo $this->options->is_const_defined( $this->get_slug(), 'encryption' ) ? 'disabled' : ''; ?>
162
+ <?php checked( 'none', $this->options->get( $this->get_slug(), 'encryption' ) ); ?>
163
+ />
164
+ <?php esc_html_e( 'None', 'wp-mail-smtp' ); ?>
165
+ </label>
166
+
167
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-ssl">
168
+ <input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-ssl"
169
+ name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][encryption]" value="ssl"
170
+ <?php echo $this->options->is_const_defined( $this->get_slug(), 'encryption' ) ? 'disabled' : ''; ?>
171
+ <?php checked( 'ssl', $this->options->get( $this->get_slug(), 'encryption' ) ); ?>
172
+ />
173
+ <?php esc_html_e( 'SSL', 'wp-mail-smtp' ); ?>
174
+ </label>
175
+
176
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-tls">
177
+ <input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-tls"
178
+ name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][encryption]" value="tls"
179
+ <?php echo $this->options->is_const_defined( $this->get_slug(), 'encryption' ) ? 'disabled' : ''; ?>
180
+ <?php checked( 'tls', $this->options->get( $this->get_slug(), 'encryption' ) ); ?>
181
+ />
182
+ <?php esc_html_e( 'TLS', 'wp-mail-smtp' ); ?>
183
+ </label>
184
+
185
+ <p class="desc">
186
+ <?php esc_html_e( 'TLS is not the same as STARTTLS. For most servers SSL is the recommended option.', 'wp-mail-smtp' ); ?>
187
+ </p>
188
+ </div>
189
+ </div>
190
+
191
+
192
+ <!-- SMTP Authentication -->
193
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-auth" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox-toggle wp-mail-smtp-clear">
194
+ <div class="wp-mail-smtp-setting-label">
195
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-auth"><?php esc_html_e( 'Authentication', 'wp-mail-smtp' ); ?></label>
196
+ </div>
197
+ <div class="wp-mail-smtp-setting-field">
198
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-auth">
199
+ <input type="checkbox" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-auth"
200
+ name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][auth]" value="yes"
201
+ <?php echo $this->options->is_const_defined( $this->get_slug(), 'auth' ) ? 'disabled' : ''; ?>
202
+ <?php checked( true, $this->options->get( $this->get_slug(), 'auth' ) ); ?>
203
+ />
204
+ <span class="wp-mail-smtp-setting-toggle-switch"></span>
205
+ <span class="wp-mail-smtp-setting-toggle-checked-label"><?php esc_html_e( 'On', 'wp-mail-smtp' ); ?></span>
206
+ <span class="wp-mail-smtp-setting-toggle-unchecked-label"><?php esc_html_e( 'Off', 'wp-mail-smtp' ); ?></span>
207
+ </label>
208
+ </div>
209
+ </div>
210
+
211
+ <!-- SMTP Username -->
212
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-user" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear <?php echo ! $this->options->is_const_defined( $this->get_slug(), 'auth' ) && ! $this->options->get( $this->get_slug(), 'auth' ) ? 'inactive' : ''; ?>">
213
+ <div class="wp-mail-smtp-setting-label">
214
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-user"><?php esc_html_e( 'SMTP Username', 'wp-mail-smtp' ); ?></label>
215
+ </div>
216
+ <div class="wp-mail-smtp-setting-field">
217
+ <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][user]" type="text"
218
+ value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'user' ) ); ?>"
219
+ <?php echo $this->options->is_const_defined( $this->get_slug(), 'user' ) ? 'disabled' : ''; ?>
220
+ id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-user" spellcheck="false" autocomplete="off"
221
+ />
222
+ </div>
223
+ </div>
224
+
225
+ <!-- SMTP Password -->
226
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-pass" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-password wp-mail-smtp-clear <?php echo ! $this->options->is_const_defined( $this->get_slug(), 'auth' ) && ! $this->options->get( $this->get_slug(), 'auth' ) ? 'inactive' : ''; ?>">
227
+ <div class="wp-mail-smtp-setting-label">
228
+ <label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-pass"><?php esc_html_e( 'SMTP Password', 'wp-mail-smtp' ); ?></label>
229
+ </div>
230
+ <div class="wp-mail-smtp-setting-field">
231
+ <?php if ( $this->options->is_const_defined( $this->get_slug(), 'pass' ) ) : ?>
232
+ <input type="text" value="*************" disabled id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-pass"/>
233
+ <?php else : ?>
234
+ <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][pass]" type="password"
235
+ value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'pass' ) ); ?>"
236
+ id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-pass" spellcheck="false" autocomplete="off"
237
+ />
238
+ <p class="desc">
239
+ <?php
240
+ printf(
241
+ /* translators: %s - wp-config.php. */
242
+ esc_html__( 'The password is stored in plain text. We highly recommend you setup your password in your WordPress configuration file for improved security; to do this add the lines below to your %s file.', 'wp-mail-smtp' ),
243
+ '<code>wp-config.php</code>'
244
+ );
245
+ ?>
246
+ </p>
247
+ <pre>
248
+ define( 'WPMS_ON', true );
249
+ define( 'WPMS_SMTP_PASS', 'your_password' );
250
+ </pre>
251
+ <?php endif; ?>
252
+ </div>
253
+ </div>
254
+
255
+ <?php
256
+ }
257
+
258
+ /**
259
+ * Check whether we can use this provider based on the PHP version.
260
+ * Valid for those, that use SDK.
261
+ *
262
+ * @return bool
263
+ */
264
+ protected function is_php_correct() {
265
+ return version_compare( phpversion(), $this->php, '>=' );
266
+ }
267
+
268
+ /**
269
+ * Display a helpful message to those users, that are using an outdated version of PHP,
270
+ * which is not supported by the currently selected Provider.
271
+ */
272
+ protected function display_php_warning() {
273
+ ?>
274
+
275
+ <blockquote>
276
+ <?php
277
+ printf(
278
+ /* translators: %1$s - Provider name; %2$s - PHP version required by Provider; %3$s - current PHP version. */
279
+ esc_html__( '%1$s requires PHP %2$s to work and does not support your current PHP version %3$s. Please contact your host and request a PHP upgrade to the latest one.', 'wp-mail-smtp' ),
280
+ $this->title,
281
+ $this->php,
282
+ phpversion()
283
+ )
284
+ ?>
285
+ <br>
286
+ <?php esc_html_e( 'Meanwhile you can switch to the "Other SMTP" Mailer option.', 'wp-mail-smtp' ); ?>
287
+ </blockquote>
288
+
289
+ <?php
290
+ }
291
+ }
src/Providers/OptionInterface.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers;
4
+
5
+ /**
6
+ * Interface ProviderInterface, shared between all current and future providers.
7
+ * Defines required methods across all providers.
8
+ *
9
+ * @since 1.0.0
10
+ */
11
+ interface OptionInterface {
12
+
13
+ /**
14
+ * Get the mailer provider slug.
15
+ *
16
+ * @since 1.0.0
17
+ *
18
+ * @return string
19
+ */
20
+ public function get_slug();
21
+
22
+ /**
23
+ * Get the mailer provider title (or name).
24
+ *
25
+ * @since 1.0.0
26
+ *
27
+ * @return string
28
+ */
29
+ public function get_title();
30
+
31
+ /**
32
+ * Get the mailer provider description.
33
+ *
34
+ * @since 1.0.0
35
+ *
36
+ * @return string
37
+ */
38
+ public function get_description();
39
+
40
+ /**
41
+ * Get the mailer provider minimum PHP version.
42
+ *
43
+ * @since 1.0.0
44
+ *
45
+ * @return string
46
+ */
47
+ public function get_php_version();
48
+
49
+ /**
50
+ * Get the mailer provider logo URL.
51
+ *
52
+ * @since 1.0.0
53
+ *
54
+ * @return string
55
+ */
56
+ public function get_logo_url();
57
+
58
+ /**
59
+ * Output the mailer provider options.
60
+ *
61
+ * @since 1.0.0
62
+ */
63
+ public function display_options();
64
+ }
src/Providers/Pepipost/Options.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers\Pepipost;
4
+
5
+ use WPMailSMTP\Providers\OptionAbstract;
6
+
7
+ /**
8
+ * Class Option.
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ class Option extends OptionAbstract {
13
+
14
+ /**
15
+ * Pepipost constructor.
16
+ *
17
+ * @since 1.0.0
18
+ */
19
+ public function __construct() {
20
+
21
+ parent::__construct(
22
+ array(
23
+ 'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/pepipost.png',
24
+ 'slug' => 'pepipost',
25
+ 'title' => esc_html__( 'Pepipost', 'wp-mail-smtp' ),
26
+ )
27
+ );
28
+ }
29
+ }
src/Providers/SMTP/Options.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers\SMTP;
4
+
5
+ use WPMailSMTP\Providers\OptionAbstract;
6
+
7
+ /**
8
+ * Class SMTP.
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ class Options extends OptionAbstract {
13
+
14
+ /**
15
+ * SMTP constructor.
16
+ *
17
+ * @since 1.0.0
18
+ */
19
+ public function __construct() {
20
+
21
+ parent::__construct(
22
+ array(
23
+ 'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/smtp.png',
24
+ 'slug' => 'smtp',
25
+ 'title' => esc_html__( 'Other SMTP', 'wp-mail-smtp' ),
26
+ /* translators: %1$s - opening link tag; %2$s - closing link tag. */
27
+ 'description' => sprintf(
28
+ wp_kses(
29
+ __( 'Use the SMTP details provided by your hosting provider or email service.<br><br>To see recommended settings for the popular services as well as troubleshooting tips, check out our %1$sSMTP documentation%2$s.', 'wp-mail-smtp' ),
30
+ array(
31
+ 'br' => array(),
32
+ 'a' => array(
33
+ 'href' => array(),
34
+ 'rel' => array(),
35
+ 'target' => array(),
36
+ ),
37
+ )
38
+ ),
39
+ '<a href="https://wpforms.com/docs/how-to-set-up-smtp-using-the-wp-mail-smtp-plugin/" target="_blank" rel="noopener noreferrer">',
40
+ '</a>'
41
+ ),
42
+ )
43
+ );
44
+ }
45
+ }
src/Providers/Sendgrid/Mailer.php ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers\Sendgrid;
4
+
5
+ use WPMailSMTP\Providers\MailerAbstract;
6
+
7
+ /**
8
+ * Class Mailer.
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ class Mailer extends MailerAbstract {
13
+
14
+ /**
15
+ * Which response code from HTTP provider is considered to be successful?
16
+ *
17
+ * @var int
18
+ */
19
+ protected $email_sent_code = 202;
20
+
21
+ /**
22
+ * URL to make an API request to.
23
+ *
24
+ * @var string
25
+ */
26
+ protected $url = 'https://api.sendgrid.com/v3/mail/send';
27
+
28
+ /**
29
+ * Mailer constructor.
30
+ *
31
+ * @since 1.0.0
32
+ *
33
+ * @param \PHPMailer $phpmailer
34
+ */
35
+ public function __construct( $phpmailer ) {
36
+
37
+ // We want to prefill everything from \PHPMailer class.
38
+ parent::__construct( $phpmailer );
39
+
40
+ $this->set_header( 'Authorization', 'Bearer ' . $this->options->get( $this->mailer, 'api_key' ) );
41
+ $this->set_header( 'content-type', 'application/json' );
42
+ }
43
+
44
+ /**
45
+ * Redefine the way email body is returned.
46
+ * By default we are sending an array of data.
47
+ * SendGrid requires a JSON, so we encode the body.
48
+ *
49
+ * @since 1.0.0
50
+ */
51
+ public function get_body() {
52
+
53
+ $body = parent::get_body();
54
+
55
+ return wp_json_encode( $body );
56
+ }
57
+
58
+ /**
59
+ * @inheritdoc
60
+ */
61
+ public function set_from( $email, $name = '' ) {
62
+
63
+ if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
64
+ return;
65
+ }
66
+
67
+ $from['email'] = $email;
68
+
69
+ if ( ! empty( $name ) ) {
70
+ $from['name'] = $name;
71
+ }
72
+
73
+ $this->set_body_param(
74
+ array(
75
+ 'from' => $from,
76
+ )
77
+ );
78
+ }
79
+
80
+ /**
81
+ * @inheritdoc
82
+ */
83
+ public function set_recipients( $recipients ) {
84
+
85
+ if ( empty( $recipients ) ) {
86
+ return;
87
+ }
88
+
89
+ // Allow for now only these recipient types.
90
+ $default = array( 'to', 'cc', 'bcc' );
91
+ $data = array();
92
+
93
+ foreach ( $recipients as $type => $emails ) {
94
+ if (
95
+ ! in_array( $type, $default, true ) ||
96
+ empty( $emails ) ||
97
+ ! is_array( $emails )
98
+ ) {
99
+ continue;
100
+ }
101
+
102
+ $data[ $type ] = array();
103
+
104
+ // Iterate over all emails for each type.
105
+ // There might be multiple cc/to/bcc emails.
106
+ foreach ( $emails as $email ) {
107
+ $holder = array();
108
+ $addr = isset( $email[0] ) ? $email[0] : false;
109
+ $name = isset( $email[1] ) ? $email[1] : false;
110
+
111
+ if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
112
+ continue;
113
+ }
114
+
115
+ $holder['email'] = $addr;
116
+ if ( ! empty( $name ) ) {
117
+ $holder['name'] = $name;
118
+ }
119
+
120
+ array_push( $data[ $type ], $holder );
121
+ }
122
+ }
123
+
124
+ if ( ! empty( $data ) ) {
125
+ $this->set_body_param(
126
+ array(
127
+ 'personalizations' => array( $data ),
128
+ )
129
+ );
130
+ }
131
+ }
132
+
133
+ /**
134
+ * @inheritdoc
135
+ */
136
+ public function set_content( $content ) {
137
+
138
+ if ( empty( $content ) ) {
139
+ return;
140
+ }
141
+
142
+ if ( is_array( $content ) ) {
143
+
144
+ $default = array( 'text', 'html' );
145
+ $data = array();
146
+
147
+ foreach ( $content as $type => $body ) {
148
+ if (
149
+ ! in_array( $type, $default, true ) ||
150
+ empty( $body )
151
+ ) {
152
+ continue;
153
+ }
154
+
155
+ $content_type = 'text/plain';
156
+ $content_value = $body;
157
+
158
+ if ( $type === 'html' ) {
159
+ $content_type = 'text/html';
160
+ }
161
+
162
+ $data[] = array(
163
+ 'type' => $content_type,
164
+ 'value' => $content_value,
165
+ );
166
+ }
167
+
168
+ $this->set_body_param(
169
+ array(
170
+ 'content' => $data,
171
+ )
172
+ );
173
+ } else {
174
+ $data['type'] = 'text/plain';
175
+ $data['value'] = $content;
176
+
177
+ if ( $this->phpmailer->ContentType === 'text/html' ) {
178
+ $data['type'] = 'text/html';
179
+ }
180
+
181
+ $this->set_body_param(
182
+ array(
183
+ 'content' => array( $data ),
184
+ )
185
+ );
186
+ }
187
+ }
188
+
189
+ /**
190
+ * SendGrid accepts an array of files content in body, so we will include all files and send.
191
+ * Doesn't handle exceeding the limits etc, as this is done and reported be SendGrid API.
192
+ *
193
+ * @since 1.0.0
194
+ *
195
+ * @param array $attachments
196
+ */
197
+ public function set_attachments( $attachments ) {
198
+
199
+ if ( empty( $attachments ) ) {
200
+ return;
201
+ }
202
+
203
+ $data = array();
204
+
205
+ foreach ( $attachments as $attachment ) {
206
+ $file = false;
207
+
208
+ /*
209
+ * We are not using WP_Filesystem API as we can't reliably work with it.
210
+ * It is not always available, same as credentials for FTP.
211
+ */
212
+ try {
213
+ if ( is_file( $attachment[0] ) && is_readable( $attachment[0] ) ) {
214
+ $file = file_get_contents( $attachment[0] );
215
+ }
216
+ } catch ( \Exception $e ) {
217
+ $file = false;
218
+ }
219
+
220
+ if ( $file === false ) {
221
+ continue;
222
+ }
223
+
224
+ $data[] = array(
225
+ 'content' => base64_encode( $file ),
226
+ 'type' => $attachment[4],
227
+ 'filename' => $attachment[1],
228
+ 'disposition' => $attachment[6],
229
+ );
230
+ }
231
+
232
+ if ( ! empty( $data ) ) {
233
+ $this->set_body_param(
234
+ array(
235
+ 'attachments' => $data,
236
+ )
237
+ );
238
+ }
239
+ }
240
+
241
+ /**
242
+ * @inheritdoc
243
+ */
244
+ public function set_reply_to( $reply_to ) {
245
+
246
+ if ( empty( $reply_to ) ) {
247
+ return;
248
+ }
249
+
250
+ $data = array();
251
+
252
+ foreach ( $reply_to as $key => $emails ) {
253
+ if (
254
+ empty( $emails ) ||
255
+ ! is_array( $emails )
256
+ ) {
257
+ continue;
258
+ }
259
+
260
+ $addr = isset( $emails[0] ) ? $emails[0] : false;
261
+ $name = isset( $emails[1] ) ? $emails[1] : false;
262
+
263
+ if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
264
+ continue;
265
+ }
266
+
267
+ $data['email'] = $addr;
268
+ if ( ! empty( $name ) ) {
269
+ $data['name'] = $name;
270
+ }
271
+
272
+ break;
273
+ }
274
+
275
+ if ( ! empty( $data ) ) {
276
+ $this->set_body_param(
277
+ array(
278
+ 'reply_to' => $data,
279
+ )
280
+ );
281
+ }
282
+ }
283
+
284
+ /**
285
+ * SendGrid doesn't support sender or return_path params.
286
+ * So we do nothing.
287
+ *
288
+ * @since 1.0.0
289
+ *
290
+ * @param string $email
291
+ */
292
+ public function set_return_path( $email ) {
293
+ }
294
+ }
src/Providers/Sendgrid/Options.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP\Providers\Sendgrid;
4
+
5
+ use WPMailSMTP\Providers\OptionAbstract;
6
+
7
+ /**
8
+ * Class Option.
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ class Options extends OptionAbstract {
13
+
14
+ /**
15
+ * Options constructor.
16
+ *
17
+ * @since 1.0.0
18
+ */
19
+ public function __construct() {
20
+
21
+ parent::__construct(
22
+ array(
23
+ 'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/sendgrid.png',
24
+ 'slug' => 'sendgrid',
25
+ 'title' => esc_html__( 'SendGrid', 'wp-mail-smtp' ),
26
+ 'description' => sprintf(
27
+ wp_kses(
28
+ /* translators: %1$s - opening link tag; %2$s - closing link tag; %3$s - opening link tag; %4$s - closing link tag. */
29
+ __( '%1$sSendGrid%2$s is one of the leading transactional email services, sending over 35 billion emails every month. They provide users 100 free emails per month.<br><br>Read our %3$sSendGrid documentation%4$s to learn how to set up SendGrid and improve your email deliverability.', 'wp-mail-smtp' ),
30
+ array(
31
+ 'br' => array(),
32
+ 'a' => array(
33
+ 'href' => array(),
34
+ 'rel' => array(),
35
+ 'target' => array(),
36
+ ),
37
+ )
38
+ ),
39
+ '<a href="https://sendgrid.com" target="_blank" rel="noopener noreferrer">',
40
+ '</a>',
41
+ '<a href="https://wpforms.com/fix-wordpress-email-notifications-with-sendgrid/" target="_blank" rel="noopener noreferrer">',
42
+ '</a>'
43
+ ),
44
+ )
45
+ );
46
+ }
47
+
48
+ /**
49
+ * @inheritdoc
50
+ */
51
+ public function display_options() {
52
+ ?>
53
+
54
+ <!-- API Key -->
55
+ <div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
56
+ <div class="wp-mail-smtp-setting-label">
57
+ <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>
58
+ </div>
59
+ <div class="wp-mail-smtp-setting-field">
60
+ <input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]" type="text"
61
+ value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'api_key' ) ); ?>"
62
+ <?php echo $this->options->is_const_defined( $this->get_slug(), 'api_key' ) ? 'disabled' : ''; ?>
63
+ id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" spellcheck="false"
64
+ />
65
+ <p class="desc">
66
+ <?php
67
+ printf(
68
+ /* translators: %s - API key link. */
69
+ esc_html__( 'Follow this link to get an API Key from SendGrid: %s.', 'wp-mail-smtp' ),
70
+ '<a href="https://app.sendgrid.com/settings/api_keys" target="_blank" rel="noopener noreferrer">' .
71
+ esc_html__( 'Create API Key', 'wp-mail-smtp' ) .
72
+ '</a>'
73
+ );
74
+ ?>
75
+ <br/>
76
+ <?php
77
+ printf(
78
+ /* translators: %s - SendGrid access level. */
79
+ esc_html__( 'To send emails you will need only a %s access level for this API key.', 'wp-mail-smtp' ),
80
+ '<code>Mail Send</code>'
81
+ );
82
+ ?>
83
+ </p>
84
+ </div>
85
+ </div>
86
+
87
+ <?php
88
+ }
89
+ }
src/WP.php ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPMailSMTP;
4
+
5
+ /**
6
+ * Class WP provides WordPress shortcuts.
7
+ *
8
+ * @since 1.0.0
9
+ */
10
+ class WP {
11
+
12
+ /**
13
+ * The "queue" of notices.
14
+ *
15
+ * @var array
16
+ */
17
+ protected static $admin_notices = array();
18
+ /**
19
+ * @var string
20
+ */
21
+ const ADMIN_NOTICE_SUCCESS = 'notice-success';
22
+ /**
23
+ * @var string
24
+ */
25
+ const ADMIN_NOTICE_ERROR = 'notice-error';
26
+ /**
27
+ * @var string
28
+ */
29
+ const ADMIN_NOTICE_INFO = 'notice-info';
30
+ /**
31
+ * @var string
32
+ */
33
+ const ADMIN_NOTICE_WARNING = 'notice-warning';
34
+
35
+ /**
36
+ * True is WP is processing an AJAX call.
37
+ *
38
+ * @since 1.0.0
39
+ *
40
+ * @return bool
41
+ */
42
+ public static function is_doing_ajax() {
43
+
44
+ if ( function_exists( 'wp_doing_ajax' ) ) {
45
+ return wp_doing_ajax();
46
+ }
47
+
48
+ return ( defined( 'DOING_AJAX' ) && DOING_AJAX );
49
+ }
50
+
51
+ /**
52
+ * True if I am in the Admin Panel, not doing AJAX.
53
+ *
54
+ * @since 1.0.0
55
+ *
56
+ * @return bool
57
+ */
58
+ public static function in_wp_admin() {
59
+ return ( is_admin() && ! self::is_doing_ajax() );
60
+ }
61
+
62
+ /**
63
+ * Add a notice to the "queue of notices".
64
+ *
65
+ * @since 1.0.0
66
+ *
67
+ * @param string $message Message text (HTML is OK).
68
+ * @param string $class Display class (severity).
69
+ */
70
+ public static function add_admin_notice( $message, $class = self::ADMIN_NOTICE_INFO ) {
71
+
72
+ self::$admin_notices[] = array(
73
+ 'message' => $message,
74
+ 'class' => $class,
75
+ );
76
+ }
77
+
78
+ /**
79
+ * Display all notices.
80
+ *
81
+ * @since 1.0.0
82
+ */
83
+ public static function display_admin_notices() {
84
+
85
+ foreach ( (array) self::$admin_notices as $notice ) : ?>
86
+
87
+ <div id="message" class="<?php echo esc_attr( $notice['class'] ); ?> notice is-dismissible">
88
+ <p>
89
+ <?php echo $notice['message']; ?>
90
+ </p>
91
+ </div>
92
+
93
+ <?php
94
+ endforeach;
95
+ }
96
+
97
+ /**
98
+ * Check whether WP_DEBUG is active.
99
+ *
100
+ * @since 1.0.0
101
+ *
102
+ * @return bool
103
+ */
104
+ public static function is_debug() {
105
+ return defined( 'WP_DEBUG' ) && WP_DEBUG;
106
+ }
107
+
108
+ /**
109
+ * Shortcut to global $wpdb.
110
+ *
111
+ * @since 1.0.0
112
+ *
113
+ * @return \wpdb
114
+ */
115
+ public static function wpdb() {
116
+
117
+ global $wpdb;
118
+
119
+ return $wpdb;
120
+ }
121
+
122
+ /**
123
+ * Get the postfix for assets files - ".min" or empty.
124
+ * ".min" if in production mode.
125
+ *
126
+ * @since 1.0.0
127
+ *
128
+ * @return string
129
+ */
130
+ public static function asset_min() {
131
+
132
+ $min = '.min';
133
+
134
+ if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
135
+ $min = '';
136
+ }
137
+
138
+ return $min;
139
+ }
140
+ }
vendor/autoload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload.php @generated by Composer
4
+
5
+ require_once __DIR__ . '/composer' . '/autoload_real.php';
6
+
7
+ return ComposerAutoloaderInit07e98588aa3894ff9e3dc547d403ad69::getLoader();
vendor/composer/ClassLoader.php ADDED
@@ -0,0 +1,413 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Composer.
5
+ *
6
+ * (c) Nils Adermann <naderman@naderman.de>
7
+ * Jordi Boggiano <j.boggiano@seld.be>
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ namespace Composer\Autoload;
14
+
15
+ /**
16
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17
+ *
18
+ * $loader = new \Composer\Autoload\ClassLoader();
19
+ *
20
+ * // register classes with namespaces
21
+ * $loader->add('Symfony\Component', __DIR__.'/component');
22
+ * $loader->add('Symfony', __DIR__.'/framework');
23
+ *
24
+ * // activate the autoloader
25
+ * $loader->register();
26
+ *
27
+ * // to enable searching the include path (eg. for PEAR packages)
28
+ * $loader->setUseIncludePath(true);
29
+ *
30
+ * In this example, if you try to use a class in the Symfony\Component
31
+ * namespace or one of its children (Symfony\Component\Console for instance),
32
+ * the autoloader will first look for the class under the component/
33
+ * directory, and it will then fallback to the framework/ directory if not
34
+ * found before giving up.
35
+ *
36
+ * This class is loosely based on the Symfony UniversalClassLoader.
37
+ *
38
+ * @author Fabien Potencier <fabien@symfony.com>
39
+ * @author Jordi Boggiano <j.boggiano@seld.be>
40
+ * @see http://www.php-fig.org/psr/psr-0/
41
+ * @see http://www.php-fig.org/psr/psr-4/
42
+ */
43
+ class ClassLoader
44
+ {
45
+ // PSR-4
46
+ private $prefixLengthsPsr4 = array();
47
+ private $prefixDirsPsr4 = array();
48
+ private $fallbackDirsPsr4 = array();
49
+
50
+ // PSR-0
51
+ private $prefixesPsr0 = array();
52
+ private $fallbackDirsPsr0 = array();
53
+
54
+ private $useIncludePath = false;
55
+ private $classMap = array();
56
+
57
+ private $classMapAuthoritative = false;
58
+
59
+ public function getPrefixes()
60
+ {
61
+ if (!empty($this->prefixesPsr0)) {
62
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
63
+ }
64
+
65
+ return array();
66
+ }
67
+
68
+ public function getPrefixesPsr4()
69
+ {
70
+ return $this->prefixDirsPsr4;
71
+ }
72
+
73
+ public function getFallbackDirs()
74
+ {
75
+ return $this->fallbackDirsPsr0;
76
+ }
77
+
78
+ public function getFallbackDirsPsr4()
79
+ {
80
+ return $this->fallbackDirsPsr4;
81
+ }
82
+
83
+ public function getClassMap()
84
+ {
85
+ return $this->classMap;
86
+ }
87
+
88
+ /**
89
+ * @param array $classMap Class to filename map
90
+ */
91
+ public function addClassMap(array $classMap)
92
+ {
93
+ if ($this->classMap) {
94
+ $this->classMap = array_merge($this->classMap, $classMap);
95
+ } else {
96
+ $this->classMap = $classMap;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Registers a set of PSR-0 directories for a given prefix, either
102
+ * appending or prepending to the ones previously set for this prefix.
103
+ *
104
+ * @param string $prefix The prefix
105
+ * @param array|string $paths The PSR-0 root directories
106
+ * @param bool $prepend Whether to prepend the directories
107
+ */
108
+ public function add($prefix, $paths, $prepend = false)
109
+ {
110
+ if (!$prefix) {
111
+ if ($prepend) {
112
+ $this->fallbackDirsPsr0 = array_merge(
113
+ (array) $paths,
114
+ $this->fallbackDirsPsr0
115
+ );
116
+ } else {
117
+ $this->fallbackDirsPsr0 = array_merge(
118
+ $this->fallbackDirsPsr0,
119
+ (array) $paths
120
+ );
121
+ }
122
+
123
+ return;
124
+ }
125
+
126
+ $first = $prefix[0];
127
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
128
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
129
+
130
+ return;
131
+ }
132
+ if ($prepend) {
133
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
134
+ (array) $paths,
135
+ $this->prefixesPsr0[$first][$prefix]
136
+ );
137
+ } else {
138
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
139
+ $this->prefixesPsr0[$first][$prefix],
140
+ (array) $paths
141
+ );
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Registers a set of PSR-4 directories for a given namespace, either
147
+ * appending or prepending to the ones previously set for this namespace.
148
+ *
149
+ * @param string $prefix The prefix/namespace, with trailing '\\'
150
+ * @param array|string $paths The PSR-4 base directories
151
+ * @param bool $prepend Whether to prepend the directories
152
+ *
153
+ * @throws \InvalidArgumentException
154
+ */
155
+ public function addPsr4($prefix, $paths, $prepend = false)
156
+ {
157
+ if (!$prefix) {
158
+ // Register directories for the root namespace.
159
+ if ($prepend) {
160
+ $this->fallbackDirsPsr4 = array_merge(
161
+ (array) $paths,
162
+ $this->fallbackDirsPsr4
163
+ );
164
+ } else {
165
+ $this->fallbackDirsPsr4 = array_merge(
166
+ $this->fallbackDirsPsr4,
167
+ (array) $paths
168
+ );
169
+ }
170
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
171
+ // Register directories for a new namespace.
172
+ $length = strlen($prefix);
173
+ if ('\\' !== $prefix[$length - 1]) {
174
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
175
+ }
176
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
177
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
178
+ } elseif ($prepend) {
179
+ // Prepend directories for an already registered namespace.
180
+ $this->prefixDirsPsr4[$prefix] = array_merge(
181
+ (array) $paths,
182
+ $this->prefixDirsPsr4[$prefix]
183
+ );
184
+ } else {
185
+ // Append directories for an already registered namespace.
186
+ $this->prefixDirsPsr4[$prefix] = array_merge(
187
+ $this->prefixDirsPsr4[$prefix],
188
+ (array) $paths
189
+ );
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Registers a set of PSR-0 directories for a given prefix,
195
+ * replacing any others previously set for this prefix.
196
+ *
197
+ * @param string $prefix The prefix
198
+ * @param array|string $paths The PSR-0 base directories
199
+ */
200
+ public function set($prefix, $paths)
201
+ {
202
+ if (!$prefix) {
203
+ $this->fallbackDirsPsr0 = (array) $paths;
204
+ } else {
205
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Registers a set of PSR-4 directories for a given namespace,
211
+ * replacing any others previously set for this namespace.
212
+ *
213
+ * @param string $prefix The prefix/namespace, with trailing '\\'
214
+ * @param array|string $paths The PSR-4 base directories
215
+ *
216
+ * @throws \InvalidArgumentException
217
+ */
218
+ public function setPsr4($prefix, $paths)
219
+ {
220
+ if (!$prefix) {
221
+ $this->fallbackDirsPsr4 = (array) $paths;
222
+ } else {
223
+ $length = strlen($prefix);
224
+ if ('\\' !== $prefix[$length - 1]) {
225
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
226
+ }
227
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
228
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Turns on searching the include path for class files.
234
+ *
235
+ * @param bool $useIncludePath
236
+ */
237
+ public function setUseIncludePath($useIncludePath)
238
+ {
239
+ $this->useIncludePath = $useIncludePath;
240
+ }
241
+
242
+ /**
243
+ * Can be used to check if the autoloader uses the include path to check
244
+ * for classes.
245
+ *
246
+ * @return bool
247
+ */
248
+ public function getUseIncludePath()
249
+ {
250
+ return $this->useIncludePath;
251
+ }
252
+
253
+ /**
254
+ * Turns off searching the prefix and fallback directories for classes
255
+ * that have not been registered with the class map.
256
+ *
257
+ * @param bool $classMapAuthoritative
258
+ */
259
+ public function setClassMapAuthoritative($classMapAuthoritative)
260
+ {
261
+ $this->classMapAuthoritative = $classMapAuthoritative;
262
+ }
263
+
264
+ /**
265
+ * Should class lookup fail if not found in the current class map?
266
+ *
267
+ * @return bool
268
+ */
269
+ public function isClassMapAuthoritative()
270
+ {
271
+ return $this->classMapAuthoritative;
272
+ }
273
+
274
+ /**
275
+ * Registers this instance as an autoloader.
276
+ *
277
+ * @param bool $prepend Whether to prepend the autoloader or not
278
+ */
279
+ public function register($prepend = false)
280
+ {
281
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
282
+ }
283
+
284
+ /**
285
+ * Unregisters this instance as an autoloader.
286
+ */
287
+ public function unregister()
288
+ {
289
+ spl_autoload_unregister(array($this, 'loadClass'));
290
+ }
291
+
292
+ /**
293
+ * Loads the given class or interface.
294
+ *
295
+ * @param string $class The name of the class
296
+ * @return bool|null True if loaded, null otherwise
297
+ */
298
+ public function loadClass($class)
299
+ {
300
+ if ($file = $this->findFile($class)) {
301
+ includeFile($file);
302
+
303
+ return true;
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Finds the path to the file where the class is defined.
309
+ *
310
+ * @param string $class The name of the class
311
+ *
312
+ * @return string|false The path if found, false otherwise
313
+ */
314
+ public function findFile($class)
315
+ {
316
+ // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
317
+ if ('\\' == $class[0]) {
318
+ $class = substr($class, 1);
319
+ }
320
+
321
+ // class map lookup
322
+ if (isset($this->classMap[$class])) {
323
+ return $this->classMap[$class];
324
+ }
325
+ if ($this->classMapAuthoritative) {
326
+ return false;
327
+ }
328
+
329
+ $file = $this->findFileWithExtension($class, '.php');
330
+
331
+ // Search for Hack files if we are running on HHVM
332
+ if ($file === null && defined('HHVM_VERSION')) {
333
+ $file = $this->findFileWithExtension($class, '.hh');
334
+ }
335
+
336
+ if ($file === null) {
337
+ // Remember that this class does not exist.
338
+ return $this->classMap[$class] = false;
339
+ }
340
+
341
+ return $file;
342
+ }
343
+
344
+ private function findFileWithExtension($class, $ext)
345
+ {
346
+ // PSR-4 lookup
347
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
348
+
349
+ $first = $class[0];
350
+ if (isset($this->prefixLengthsPsr4[$first])) {
351
+ foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
352
+ if (0 === strpos($class, $prefix)) {
353
+ foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
354
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
355
+ return $file;
356
+ }
357
+ }
358
+ }
359
+ }
360
+ }
361
+
362
+ // PSR-4 fallback dirs
363
+ foreach ($this->fallbackDirsPsr4 as $dir) {
364
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
365
+ return $file;
366
+ }
367
+ }
368
+
369
+ // PSR-0 lookup
370
+ if (false !== $pos = strrpos($class, '\\')) {
371
+ // namespaced class name
372
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
373
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
374
+ } else {
375
+ // PEAR-like class name
376
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
377
+ }
378
+
379
+ if (isset($this->prefixesPsr0[$first])) {
380
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
381
+ if (0 === strpos($class, $prefix)) {
382
+ foreach ($dirs as $dir) {
383
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
384
+ return $file;
385
+ }
386
+ }
387
+ }
388
+ }
389
+ }
390
+
391
+ // PSR-0 fallback dirs
392
+ foreach ($this->fallbackDirsPsr0 as $dir) {
393
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
394
+ return $file;
395
+ }
396
+ }
397
+
398
+ // PSR-0 include paths.
399
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
400
+ return $file;
401
+ }
402
+ }
403
+ }
404
+
405
+ /**
406
+ * Scope isolated include.
407
+ *
408
+ * Prevents access to $this/self from included files.
409
+ */
410
+ function includeFile($file)
411
+ {
412
+ include $file;
413
+ }
vendor/composer/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Copyright (c) 2016 Nils Adermann, Jordi Boggiano
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished
9
+ to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
vendor/composer/autoload_classmap.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_classmap.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'Google_Service_Exception' => $vendorDir . '/google/apiclient/src/Google/Service/Exception.php',
10
+ 'Google_Service_Resource' => $vendorDir . '/google/apiclient/src/Google/Service/Resource.php',
11
+ );
vendor/composer/autoload_files.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_files.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
10
+ 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
11
+ '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
12
+ 'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
13
+ '36d9695c51c127dacf01b83c468dbbdb' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail.php',
14
+ 'd95a5932fb3c05855cde09b51efec1ac' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Message.php',
15
+ '1a8cb0c91ca8ad9f9147193a084f80bd' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/Users.php',
16
+ '5d5f545fa7a58b1185f901d0c1006a41' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersDrafts.php',
17
+ '79c900432abc031cbad7036b9fce5523' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersHistory.php',
18
+ '1a56422ddba9140c62183b59448a7227' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersLabels.php',
19
+ 'f7d0eb6d1da014e7ff1b6038c3314921' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersMessages.php',
20
+ 'ed22ed3db05c96f75d2885e41650be07' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersMessagesAttachments.php',
21
+ '535c184b9a328f2295fc70c028f13aa7' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettings.php',
22
+ 'fc9b994b4190b187884a1bb5b334c54d' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsFilters.php',
23
+ '3a081d084d3ba366d67d7139e5d9fbcf' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsForwardingAddresses.php',
24
+ '60d509e933e5ca336a897bb7b549f15b' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsSendAs.php',
25
+ '39c11aa4169566f44661343f8929bbd0' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsSendAsSmimeInfo.php',
26
+ 'cf7f0634ca5d41f748c82f89bd3e960b' => $vendorDir . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersThreads.php',
27
+ );
vendor/composer/autoload_namespaces.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_namespaces.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'Google_Service_' => array($vendorDir . '/google/apiclient-services/src'),
10
+ 'Google_' => array($vendorDir . '/google/apiclient/src'),
11
+ );
vendor/composer/autoload_psr4.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_psr4.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'phpseclib\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
10
+ 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
11
+ 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
12
+ 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
13
+ 'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
14
+ 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
15
+ 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
16
+ 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
17
+ 'Google\\Auth\\' => array($vendorDir . '/google/auth/src'),
18
+ 'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'),
19
+ 'Composer\\Installers\\' => array($vendorDir . '/composer/installers/src/Composer/Installers'),
20
+ );
vendor/composer/autoload_real.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInit07e98588aa3894ff9e3dc547d403ad69
6
+ {
7
+ private static $loader;
8
+
9
+ public static function loadClassLoader($class)
10
+ {
11
+ if ('Composer\Autoload\ClassLoader' === $class) {
12
+ require __DIR__ . '/ClassLoader.php';
13
+ }
14
+ }
15
+
16
+ public static function getLoader()
17
+ {
18
+ if (null !== self::$loader) {
19
+ return self::$loader;
20
+ }
21
+
22
+ spl_autoload_register(array('ComposerAutoloaderInit07e98588aa3894ff9e3dc547d403ad69', 'loadClassLoader'), true, false);
23
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit07e98588aa3894ff9e3dc547d403ad69', 'loadClassLoader'));
25
+
26
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
27
+ if ($useStaticLoader) {
28
+ require_once __DIR__ . '/autoload_static.php';
29
+
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit07e98588aa3894ff9e3dc547d403ad69::getInitializer($loader));
31
+ } else {
32
+ $map = require __DIR__ . '/autoload_namespaces.php';
33
+ foreach ($map as $namespace => $path) {
34
+ $loader->set($namespace, $path);
35
+ }
36
+
37
+ $map = require __DIR__ . '/autoload_psr4.php';
38
+ foreach ($map as $namespace => $path) {
39
+ $loader->setPsr4($namespace, $path);
40
+ }
41
+
42
+ $classMap = require __DIR__ . '/autoload_classmap.php';
43
+ if ($classMap) {
44
+ $loader->addClassMap($classMap);
45
+ }
46
+ }
47
+
48
+ $loader->register(false);
49
+
50
+ if ($useStaticLoader) {
51
+ $includeFiles = Composer\Autoload\ComposerStaticInit07e98588aa3894ff9e3dc547d403ad69::$files;
52
+ } else {
53
+ $includeFiles = require __DIR__ . '/autoload_files.php';
54
+ }
55
+ foreach ($includeFiles as $fileIdentifier => $file) {
56
+ composerRequire07e98588aa3894ff9e3dc547d403ad69($fileIdentifier, $file);
57
+ }
58
+
59
+ return $loader;
60
+ }
61
+ }
62
+
63
+ function composerRequire07e98588aa3894ff9e3dc547d403ad69($fileIdentifier, $file)
64
+ {
65
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
+ require $file;
67
+
68
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
69
+ }
70
+ }
vendor/composer/autoload_static.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_static.php @generated by Composer
4
+
5
+ namespace Composer\Autoload;
6
+
7
+ class ComposerStaticInit07e98588aa3894ff9e3dc547d403ad69
8
+ {
9
+ public static $files = array (
10
+ 'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
11
+ 'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
12
+ '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
13
+ 'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
14
+ '36d9695c51c127dacf01b83c468dbbdb' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail.php',
15
+ 'd95a5932fb3c05855cde09b51efec1ac' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Message.php',
16
+ '1a8cb0c91ca8ad9f9147193a084f80bd' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/Users.php',
17
+ '5d5f545fa7a58b1185f901d0c1006a41' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersDrafts.php',
18
+ '79c900432abc031cbad7036b9fce5523' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersHistory.php',
19
+ '1a56422ddba9140c62183b59448a7227' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersLabels.php',
20
+ 'f7d0eb6d1da014e7ff1b6038c3314921' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersMessages.php',
21
+ 'ed22ed3db05c96f75d2885e41650be07' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersMessagesAttachments.php',
22
+ '535c184b9a328f2295fc70c028f13aa7' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettings.php',
23
+ 'fc9b994b4190b187884a1bb5b334c54d' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsFilters.php',
24
+ '3a081d084d3ba366d67d7139e5d9fbcf' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsForwardingAddresses.php',
25
+ '60d509e933e5ca336a897bb7b549f15b' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsSendAs.php',
26
+ '39c11aa4169566f44661343f8929bbd0' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsSendAsSmimeInfo.php',
27
+ 'cf7f0634ca5d41f748c82f89bd3e960b' => __DIR__ . '/..' . '/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersThreads.php',
28
+ );
29
+
30
+ public static $prefixLengthsPsr4 = array (
31
+ 'p' =>
32
+ array (
33
+ 'phpseclib\\' => 10,
34
+ ),
35
+ 'P' =>
36
+ array (
37
+ 'Psr\\Log\\' => 8,
38
+ 'Psr\\Http\\Message\\' => 17,
39
+ 'Psr\\Cache\\' => 10,
40
+ ),
41
+ 'M' =>
42
+ array (
43
+ 'Monolog\\' => 8,
44
+ ),
45
+ 'G' =>
46
+ array (
47
+ 'GuzzleHttp\\Psr7\\' => 16,
48
+ 'GuzzleHttp\\Promise\\' => 19,
49
+ 'GuzzleHttp\\' => 11,
50
+ 'Google\\Auth\\' => 12,
51
+ ),
52
+ 'F' =>
53
+ array (
54
+ 'Firebase\\JWT\\' => 13,
55
+ ),
56
+ 'C' =>
57
+ array (
58
+ 'Composer\\Installers\\' => 20,
59
+ ),
60
+ );
61
+
62
+ public static $prefixDirsPsr4 = array (
63
+ 'phpseclib\\' =>
64
+ array (
65
+ 0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
66
+ ),
67
+ 'Psr\\Log\\' =>
68
+ array (
69
+ 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
70
+ ),
71
+ 'Psr\\Http\\Message\\' =>
72
+ array (
73
+ 0 => __DIR__ . '/..' . '/psr/http-message/src',
74
+ ),
75
+ 'Psr\\Cache\\' =>
76
+ array (
77
+ 0 => __DIR__ . '/..' . '/psr/cache/src',
78
+ ),
79
+ 'Monolog\\' =>
80
+ array (
81
+ 0 => __DIR__ . '/..' . '/monolog/monolog/src/Monolog',
82
+ ),
83
+ 'GuzzleHttp\\Psr7\\' =>
84
+ array (
85
+ 0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
86
+ ),
87
+ 'GuzzleHttp\\Promise\\' =>
88
+ array (
89
+ 0 => __DIR__ . '/..' . '/guzzlehttp/promises/src',
90
+ ),
91
+ 'GuzzleHttp\\' =>
92
+ array (
93
+ 0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
94
+ ),
95
+ 'Google\\Auth\\' =>
96
+ array (
97
+ 0 => __DIR__ . '/..' . '/google/auth/src',
98
+ ),
99
+ 'Firebase\\JWT\\' =>
100
+ array (
101
+ 0 => __DIR__ . '/..' . '/firebase/php-jwt/src',
102
+ ),
103
+ 'Composer\\Installers\\' =>
104
+ array (
105
+ 0 => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers',
106
+ ),
107
+ );
108
+
109
+ public static $prefixesPsr0 = array (
110
+ 'G' =>
111
+ array (
112
+ 'Google_Service_' =>
113
+ array (
114
+ 0 => __DIR__ . '/..' . '/google/apiclient-services/src',
115
+ ),
116
+ 'Google_' =>
117
+ array (
118
+ 0 => __DIR__ . '/..' . '/google/apiclient/src',
119
+ ),
120
+ ),
121
+ );
122
+
123
+ public static $classMap = array (
124
+ 'Google_Service_Exception' => __DIR__ . '/..' . '/google/apiclient/src/Google/Service/Exception.php',
125
+ 'Google_Service_Resource' => __DIR__ . '/..' . '/google/apiclient/src/Google/Service/Resource.php',
126
+ );
127
+
128
+ public static function getInitializer(ClassLoader $loader)
129
+ {
130
+ return \Closure::bind(function () use ($loader) {
131
+ $loader->prefixLengthsPsr4 = ComposerStaticInit07e98588aa3894ff9e3dc547d403ad69::$prefixLengthsPsr4;
132
+ $loader->prefixDirsPsr4 = ComposerStaticInit07e98588aa3894ff9e3dc547d403ad69::$prefixDirsPsr4;
133
+ $loader->prefixesPsr0 = ComposerStaticInit07e98588aa3894ff9e3dc547d403ad69::$prefixesPsr0;
134
+ $loader->classMap = ComposerStaticInit07e98588aa3894ff9e3dc547d403ad69::$classMap;
135
+
136
+ }, null, ClassLoader::class);
137
+ }
138
+ }
vendor/google/apiclient-services/LICENSE ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
202
+
203
+
vendor/google/apiclient-services/src/Google/Service/Gmail.php ADDED
@@ -0,0 +1,1136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ /**
19
+ * Service definition for Gmail (v1).
20
+ *
21
+ * <p>
22
+ * Access Gmail mailboxes including sending user email.</p>
23
+ *
24
+ * <p>
25
+ * For more information about this service, see the API
26
+ * <a href="https://developers.google.com/gmail/api/" target="_blank">Documentation</a>
27
+ * </p>
28
+ *
29
+ * @author Google, Inc.
30
+ */
31
+ class Google_Service_Gmail extends Google_Service
32
+ {
33
+ /** Read, send, delete, and manage your email. */
34
+ const MAIL_GOOGLE_COM =
35
+ "https://mail.google.com/";
36
+ /** Manage drafts and send emails. */
37
+ const GMAIL_COMPOSE =
38
+ "https://www.googleapis.com/auth/gmail.compose";
39
+ /** Insert mail into your mailbox. */
40
+ const GMAIL_INSERT =
41
+ "https://www.googleapis.com/auth/gmail.insert";
42
+ /** Manage mailbox labels. */
43
+ const GMAIL_LABELS =
44
+ "https://www.googleapis.com/auth/gmail.labels";
45
+ /** View your email message metadata such as labels and headers, but not the email body. */
46
+ const GMAIL_METADATA =
47
+ "https://www.googleapis.com/auth/gmail.metadata";
48
+ /** View and modify but not delete your email. */
49
+ const GMAIL_MODIFY =
50
+ "https://www.googleapis.com/auth/gmail.modify";
51
+ /** View your email messages and settings. */
52
+ const GMAIL_READONLY =
53
+ "https://www.googleapis.com/auth/gmail.readonly";
54
+ /** Send email on your behalf. */
55
+ const GMAIL_SEND =
56
+ "https://www.googleapis.com/auth/gmail.send";
57
+ /** Manage your basic mail settings. */
58
+ const GMAIL_SETTINGS_BASIC =
59
+ "https://www.googleapis.com/auth/gmail.settings.basic";
60
+ /** Manage your sensitive mail settings, including who can manage your mail. */
61
+ const GMAIL_SETTINGS_SHARING =
62
+ "https://www.googleapis.com/auth/gmail.settings.sharing";
63
+
64
+ public $users;
65
+ public $users_drafts;
66
+ public $users_history;
67
+ public $users_labels;
68
+ public $users_messages;
69
+ public $users_messages_attachments;
70
+ public $users_settings;
71
+ public $users_settings_filters;
72
+ public $users_settings_forwardingAddresses;
73
+ public $users_settings_sendAs;
74
+ public $users_settings_sendAs_smimeInfo;
75
+ public $users_threads;
76
+
77
+ /**
78
+ * Constructs the internal representation of the Gmail service.
79
+ *
80
+ * @param Google_Client $client
81
+ */
82
+ public function __construct(Google_Client $client)
83
+ {
84
+ parent::__construct($client);
85
+ $this->rootUrl = 'https://www.googleapis.com/';
86
+ $this->servicePath = 'gmail/v1/users/';
87
+ $this->version = 'v1';
88
+ $this->serviceName = 'gmail';
89
+
90
+ $this->users = new Google_Service_Gmail_Resource_Users(
91
+ $this,
92
+ $this->serviceName,
93
+ 'users',
94
+ array(
95
+ 'methods' => array(
96
+ 'getProfile' => array(
97
+ 'path' => '{userId}/profile',
98
+ 'httpMethod' => 'GET',
99
+ 'parameters' => array(
100
+ 'userId' => array(
101
+ 'location' => 'path',
102
+ 'type' => 'string',
103
+ 'required' => true,
104
+ ),
105
+ ),
106
+ ),'stop' => array(
107
+ 'path' => '{userId}/stop',
108
+ 'httpMethod' => 'POST',
109
+ 'parameters' => array(
110
+ 'userId' => array(
111
+ 'location' => 'path',
112
+ 'type' => 'string',
113
+ 'required' => true,
114
+ ),
115
+ ),
116
+ ),'watch' => array(
117
+ 'path' => '{userId}/watch',
118
+ 'httpMethod' => 'POST',
119
+ 'parameters' => array(
120
+ 'userId' => array(
121
+ 'location' => 'path',
122
+ 'type' => 'string',
123
+ 'required' => true,
124
+ ),
125
+ ),
126
+ ),
127
+ )
128
+ )
129
+ );
130
+ $this->users_drafts = new Google_Service_Gmail_Resource_UsersDrafts(
131
+ $this,
132
+ $this->serviceName,
133
+ 'drafts',
134
+ array(
135
+ 'methods' => array(
136
+ 'create' => array(
137
+ 'path' => '{userId}/drafts',
138
+ 'httpMethod' => 'POST',
139
+ 'parameters' => array(
140
+ 'userId' => array(
141
+ 'location' => 'path',
142
+ 'type' => 'string',
143
+ 'required' => true,
144
+ ),
145
+ ),
146
+ ),'delete' => array(
147
+ 'path' => '{userId}/drafts/{id}',
148
+ 'httpMethod' => 'DELETE',
149
+ 'parameters' => array(
150
+ 'userId' => array(
151
+ 'location' => 'path',
152
+ 'type' => 'string',
153
+ 'required' => true,
154
+ ),
155
+ 'id' => array(
156
+ 'location' => 'path',
157
+ 'type' => 'string',
158
+ 'required' => true,
159
+ ),
160
+ ),
161
+ ),'get' => array(
162
+ 'path' => '{userId}/drafts/{id}',
163
+ 'httpMethod' => 'GET',
164
+ 'parameters' => array(
165
+ 'userId' => array(
166
+ 'location' => 'path',
167
+ 'type' => 'string',
168
+ 'required' => true,
169
+ ),
170
+ 'id' => array(
171
+ 'location' => 'path',
172
+ 'type' => 'string',
173
+ 'required' => true,
174
+ ),
175
+ 'format' => array(
176
+ 'location' => 'query',
177
+ 'type' => 'string',
178
+ ),
179
+ ),
180
+ ),'list' => array(
181
+ 'path' => '{userId}/drafts',
182
+ 'httpMethod' => 'GET',
183
+ 'parameters' => array(
184
+ 'userId' => array(
185
+ 'location' => 'path',
186
+ 'type' => 'string',
187
+ 'required' => true,
188
+ ),
189
+ 'includeSpamTrash' => array(
190
+ 'location' => 'query',
191
+ 'type' => 'boolean',
192
+ ),
193
+ 'maxResults' => array(
194
+ 'location' => 'query',
195
+ 'type' => 'integer',
196
+ ),
197
+ 'pageToken' => array(
198
+ 'location' => 'query',
199
+ 'type' => 'string',
200
+ ),
201
+ 'q' => array(
202
+ 'location' => 'query',
203
+ 'type' => 'string',
204
+ ),
205
+ ),
206
+ ),'send' => array(
207
+ 'path' => '{userId}/drafts/send',
208
+ 'httpMethod' => 'POST',
209
+ 'parameters' => array(
210
+ 'userId' => array(
211
+ 'location' => 'path',
212
+ 'type' => 'string',
213
+ 'required' => true,
214
+ ),
215
+ ),
216
+ ),'update' => array(
217
+ 'path' => '{userId}/drafts/{id}',
218
+ 'httpMethod' => 'PUT',
219
+ 'parameters' => array(
220
+ 'userId' => array(
221
+ 'location' => 'path',
222
+ 'type' => 'string',
223
+ 'required' => true,
224
+ ),
225
+ 'id' => array(
226
+ 'location' => 'path',
227
+ 'type' => 'string',
228
+ 'required' => true,
229
+ ),
230
+ ),
231
+ ),
232
+ )
233
+ )
234
+ );
235
+ $this->users_history = new Google_Service_Gmail_Resource_UsersHistory(
236
+ $this,
237
+ $this->serviceName,
238
+ 'history',
239
+ array(
240
+ 'methods' => array(
241
+ 'list' => array(
242
+ 'path' => '{userId}/history',
243
+ 'httpMethod' => 'GET',
244
+ 'parameters' => array(
245
+ 'userId' => array(
246
+ 'location' => 'path',
247
+ 'type' => 'string',
248
+ 'required' => true,
249
+ ),
250
+ 'historyTypes' => array(
251
+ 'location' => 'query',
252
+ 'type' => 'string',
253
+ 'repeated' => true,
254
+ ),
255
+ 'labelId' => array(
256
+ 'location' => 'query',
257
+ 'type' => 'string',
258
+ ),
259
+ 'maxResults' => array(
260
+ 'location' => 'query',
261
+ 'type' => 'integer',
262
+ ),
263
+ 'pageToken' => array(
264
+ 'location' => 'query',
265
+ 'type' => 'string',
266
+ ),
267
+ 'startHistoryId' => array(
268
+ 'location' => 'query',
269
+ 'type' => 'string',
270
+ ),
271
+ ),
272
+ ),
273
+ )
274
+ )
275
+ );
276
+ $this->users_labels = new Google_Service_Gmail_Resource_UsersLabels(
277
+ $this,
278
+ $this->serviceName,
279
+ 'labels',
280
+ array(
281
+ 'methods' => array(
282
+ 'create' => array(
283
+ 'path' => '{userId}/labels',
284
+ 'httpMethod' => 'POST',
285
+ 'parameters' => array(
286
+ 'userId' => array(
287
+ 'location' => 'path',
288
+ 'type' => 'string',
289
+ 'required' => true,
290
+ ),
291
+ ),
292
+ ),'delete' => array(
293
+ 'path' => '{userId}/labels/{id}',
294
+ 'httpMethod' => 'DELETE',
295
+ 'parameters' => array(
296
+ 'userId' => array(
297
+ 'location' => 'path',
298
+ 'type' => 'string',
299
+ 'required' => true,
300
+ ),
301
+ 'id' => array(
302
+ 'location' => 'path',
303
+ 'type' => 'string',
304
+ 'required' => true,
305
+ ),
306
+ ),
307
+ ),'get' => array(
308
+ 'path' => '{userId}/labels/{id}',
309
+ 'httpMethod' => 'GET',
310
+ 'parameters' => array(
311
+ 'userId' => array(
312
+ 'location' => 'path',
313
+ 'type' => 'string',
314
+ 'required' => true,
315
+ ),
316
+ 'id' => array(
317
+ 'location' => 'path',
318
+ 'type' => 'string',
319
+ 'required' => true,
320
+ ),
321
+ ),
322
+ ),'list' => array(
323
+ 'path' => '{userId}/labels',
324
+ 'httpMethod' => 'GET',
325
+ 'parameters' => array(
326
+ 'userId' => array(
327
+ 'location' => 'path',
328
+ 'type' => 'string',
329
+ 'required' => true,
330
+ ),
331
+ ),
332
+ ),'patch' => array(
333
+ 'path' => '{userId}/labels/{id}',
334
+ 'httpMethod' => 'PATCH',
335
+ 'parameters' => array(
336
+ 'userId' => array(
337
+ 'location' => 'path',
338
+ 'type' => 'string',
339
+ 'required' => true,
340
+ ),
341
+ 'id' => array(
342
+ 'location' => 'path',
343
+ 'type' => 'string',
344
+ 'required' => true,
345
+ ),
346
+ ),
347
+ ),'update' => array(
348
+ 'path' => '{userId}/labels/{id}',
349
+ 'httpMethod' => 'PUT',
350
+ 'parameters' => array(
351
+ 'userId' => array(
352
+ 'location' => 'path',
353
+ 'type' => 'string',
354
+ 'required' => true,
355
+ ),
356
+ 'id' => array(
357
+ 'location' => 'path',
358
+ 'type' => 'string',
359
+ 'required' => true,
360
+ ),
361
+ ),
362
+ ),
363
+ )
364
+ )
365
+ );
366
+ $this->users_messages = new Google_Service_Gmail_Resource_UsersMessages(
367
+ $this,
368
+ $this->serviceName,
369
+ 'messages',
370
+ array(
371
+ 'methods' => array(
372
+ 'batchDelete' => array(
373
+ 'path' => '{userId}/messages/batchDelete',
374
+ 'httpMethod' => 'POST',
375
+ 'parameters' => array(
376
+ 'userId' => array(
377
+ 'location' => 'path',
378
+ 'type' => 'string',
379
+ 'required' => true,
380
+ ),
381
+ ),
382
+ ),'batchModify' => array(
383
+ 'path' => '{userId}/messages/batchModify',
384
+ 'httpMethod' => 'POST',
385
+ 'parameters' => array(
386
+ 'userId' => array(
387
+ 'location' => 'path',
388
+ 'type' => 'string',
389
+ 'required' => true,
390
+ ),
391
+ ),
392
+ ),'delete' => array(
393
+ 'path' => '{userId}/messages/{id}',
394
+ 'httpMethod' => 'DELETE',
395
+ 'parameters' => array(
396
+ 'userId' => array(
397
+ 'location' => 'path',
398
+ 'type' => 'string',
399
+ 'required' => true,
400
+ ),
401
+ 'id' => array(
402
+ 'location' => 'path',
403
+ 'type' => 'string',
404
+ 'required' => true,
405
+ ),
406
+ ),
407
+ ),'get' => array(
408
+ 'path' => '{userId}/messages/{id}',
409
+ 'httpMethod' => 'GET',
410
+ 'parameters' => array(
411
+ 'userId' => array(
412
+ 'location' => 'path',
413
+ 'type' => 'string',
414
+ 'required' => true,
415
+ ),
416
+ 'id' => array(
417
+ 'location' => 'path',
418
+ 'type' => 'string',
419
+ 'required' => true,
420
+ ),
421
+ 'format' => array(
422
+ 'location' => 'query',
423
+ 'type' => 'string',
424
+ ),
425
+ 'metadataHeaders' => array(
426
+ 'location' => 'query',
427
+ 'type' => 'string',
428
+ 'repeated' => true,
429
+ ),
430
+ ),
431
+ ),'import' => array(
432
+ 'path' => '{userId}/messages/import',
433
+ 'httpMethod' => 'POST',
434
+ 'parameters' => array(
435
+ 'userId' => array(
436
+ 'location' => 'path',
437
+ 'type' => 'string',
438
+ 'required' => true,
439
+ ),
440
+ 'deleted' => array(
441
+ 'location' => 'query',
442
+ 'type' => 'boolean',
443
+ ),
444
+ 'internalDateSource' => array(
445
+ 'location' => 'query',
446
+ 'type' => 'string',
447
+ ),
448
+ 'neverMarkSpam' => array(
449
+ 'location' => 'query',
450
+ 'type' => 'boolean',
451
+ ),
452
+ 'processForCalendar' => array(
453
+ 'location' => 'query',
454
+ 'type' => 'boolean',
455
+ ),
456
+ ),
457
+ ),'insert' => array(
458
+ 'path' => '{userId}/messages',
459
+ 'httpMethod' => 'POST',
460
+ 'parameters' => array(
461
+ 'userId' => array(
462
+ 'location' => 'path',
463
+ 'type' => 'string',
464
+ 'required' => true,
465
+ ),
466
+ 'deleted' => array(
467
+ 'location' => 'query',
468
+ 'type' => 'boolean',
469
+ ),
470
+ 'internalDateSource' => array(
471
+ 'location' => 'query',
472
+ 'type' => 'string',
473
+ ),
474
+ ),
475
+ ),'list' => array(
476
+ 'path' => '{userId}/messages',
477
+ 'httpMethod' => 'GET',
478
+ 'parameters' => array(
479
+ 'userId' => array(
480
+ 'location' => 'path',
481
+ 'type' => 'string',
482
+ 'required' => true,
483
+ ),
484
+ 'includeSpamTrash' => array(
485
+ 'location' => 'query',
486
+ 'type' => 'boolean',
487
+ ),
488
+ 'labelIds' => array(
489
+ 'location' => 'query',
490
+ 'type' => 'string',
491
+ 'repeated' => true,
492
+ ),
493
+ 'maxResults' => array(
494
+ 'location' => 'query',
495
+ 'type' => 'integer',
496
+ ),
497
+ 'pageToken' => array(
498
+ 'location' => 'query',
499
+ 'type' => 'string',
500
+ ),
501
+ 'q' => array(
502
+ 'location' => 'query',
503
+ 'type' => 'string',
504
+ ),
505
+ ),
506
+ ),'modify' => array(
507
+ 'path' => '{userId}/messages/{id}/modify',
508
+ 'httpMethod' => 'POST',
509
+ 'parameters' => array(
510
+ 'userId' => array(
511
+ 'location' => 'path',
512
+ 'type' => 'string',
513
+ 'required' => true,
514
+ ),
515
+ 'id' => array(
516
+ 'location' => 'path',
517
+ 'type' => 'string',
518
+ 'required' => true,
519
+ ),
520
+ ),
521
+ ),'send' => array(
522
+ 'path' => '{userId}/messages/send',
523
+ 'httpMethod' => 'POST',
524
+ 'parameters' => array(
525
+ 'userId' => array(
526
+ 'location' => 'path',
527
+ 'type' => 'string',
528
+ 'required' => true,
529
+ ),
530
+ ),
531
+ ),'trash' => array(
532
+ 'path' => '{userId}/messages/{id}/trash',
533
+ 'httpMethod' => 'POST',
534
+ 'parameters' => array(
535
+ 'userId' => array(
536
+ 'location' => 'path',
537
+ 'type' => 'string',
538
+ 'required' => true,
539
+ ),
540
+ 'id' => array(
541
+ 'location' => 'path',
542
+ 'type' => 'string',
543
+ 'required' => true,
544
+ ),
545
+ ),
546
+ ),'untrash' => array(
547
+ 'path' => '{userId}/messages/{id}/untrash',
548
+ 'httpMethod' => 'POST',
549
+ 'parameters' => array(
550
+ 'userId' => array(
551
+ 'location' => 'path',
552
+ 'type' => 'string',
553
+ 'required' => true,
554
+ ),
555
+ 'id' => array(
556
+ 'location' => 'path',
557
+ 'type' => 'string',
558
+ 'required' => true,
559
+ ),
560
+ ),
561
+ ),
562
+ )
563
+ )
564
+ );
565
+ $this->users_messages_attachments = new Google_Service_Gmail_Resource_UsersMessagesAttachments(
566
+ $this,
567
+ $this->serviceName,
568
+ 'attachments',
569
+ array(
570
+ 'methods' => array(
571
+ 'get' => array(
572
+ 'path' => '{userId}/messages/{messageId}/attachments/{id}',
573
+ 'httpMethod' => 'GET',
574
+ 'parameters' => array(
575
+ 'userId' => array(
576
+ 'location' => 'path',
577
+ 'type' => 'string',
578
+ 'required' => true,
579
+ ),
580
+ 'messageId' => array(
581
+ 'location' => 'path',
582
+ 'type' => 'string',
583
+ 'required' => true,
584
+ ),
585
+ 'id' => array(
586
+ 'location' => 'path',
587
+ 'type' => 'string',
588
+ 'required' => true,
589
+ ),
590
+ ),
591
+ ),
592
+ )
593
+ )
594
+ );
595
+ $this->users_settings = new Google_Service_Gmail_Resource_UsersSettings(
596
+ $this,
597
+ $this->serviceName,
598
+ 'settings',
599
+ array(
600
+ 'methods' => array(
601
+ 'getAutoForwarding' => array(
602
+ 'path' => '{userId}/settings/autoForwarding',
603
+ 'httpMethod' => 'GET',
604
+ 'parameters' => array(
605
+ 'userId' => array(
606
+ 'location' => 'path',
607
+ 'type' => 'string',
608
+ 'required' => true,
609
+ ),
610
+ ),
611
+ ),'getImap' => array(
612
+ 'path' => '{userId}/settings/imap',
613
+ 'httpMethod' => 'GET',
614
+ 'parameters' => array(
615
+ 'userId' => array(
616
+ 'location' => 'path',
617
+ 'type' => 'string',
618
+ 'required' => true,
619
+ ),
620
+ ),
621
+ ),'getPop' => array(
622
+ 'path' => '{userId}/settings/pop',
623
+ 'httpMethod' => 'GET',
624
+ 'parameters' => array(
625
+ 'userId' => array(
626
+ 'location' => 'path',
627
+ 'type' => 'string',
628
+ 'required' => true,
629
+ ),
630
+ ),
631
+ ),'getVacation' => array(
632
+ 'path' => '{userId}/settings/vacation',
633
+ 'httpMethod' => 'GET',
634
+ 'parameters' => array(
635
+ 'userId' => array(
636
+ 'location' => 'path',
637
+ 'type' => 'string',
638
+ 'required' => true,
639
+ ),
640
+ ),
641
+ ),'updateAutoForwarding' => array(
642
+ 'path' => '{userId}/settings/autoForwarding',
643
+ 'httpMethod' => 'PUT',
644
+ 'parameters' => array(
645
+ 'userId' => array(
646
+ 'location' => 'path',
647
+ 'type' => 'string',
648
+ 'required' => true,
649
+ ),
650
+ ),
651
+ ),'updateImap' => array(
652
+ 'path' => '{userId}/settings/imap',
653
+ 'httpMethod' => 'PUT',
654
+ 'parameters' => array(
655
+ 'userId' => array(
656
+ 'location' => 'path',
657
+ 'type' => 'string',
658
+ 'required' => true,
659
+ ),
660
+ ),
661
+ ),'updatePop' => array(
662
+ 'path' => '{userId}/settings/pop',
663
+ 'httpMethod' => 'PUT',
664
+ 'parameters' => array(
665
+ 'userId' => array(
666
+ 'location' => 'path',
667
+ 'type' => 'string',
668
+ 'required' => true,
669
+ ),
670
+ ),
671
+ ),'updateVacation' => array(
672
+ 'path' => '{userId}/settings/vacation',
673
+ 'httpMethod' => 'PUT',
674
+ 'parameters' => array(
675
+ 'userId' => array(
676
+ 'location' => 'path',
677
+ 'type' => 'string',
678
+ 'required' => true,
679
+ ),
680
+ ),
681
+ ),
682
+ )
683
+ )
684
+ );
685
+ $this->users_settings_filters = new Google_Service_Gmail_Resource_UsersSettingsFilters(
686
+ $this,
687
+ $this->serviceName,
688
+ 'filters',
689
+ array(
690
+ 'methods' => array(
691
+ 'create' => array(
692
+ 'path' => '{userId}/settings/filters',
693
+ 'httpMethod' => 'POST',
694
+ 'parameters' => array(
695
+ 'userId' => array(
696
+ 'location' => 'path',
697
+ 'type' => 'string',
698
+ 'required' => true,
699
+ ),
700
+ ),
701
+ ),'delete' => array(
702
+ 'path' => '{userId}/settings/filters/{id}',
703
+ 'httpMethod' => 'DELETE',
704
+ 'parameters' => array(
705
+ 'userId' => array(
706
+ 'location' => 'path',
707
+ 'type' => 'string',
708
+ 'required' => true,
709
+ ),
710
+ 'id' => array(
711
+ 'location' => 'path',
712
+ 'type' => 'string',
713
+ 'required' => true,
714
+ ),
715
+ ),
716
+ ),'get' => array(
717
+ 'path' => '{userId}/settings/filters/{id}',
718
+ 'httpMethod' => 'GET',
719
+ 'parameters' => array(
720
+ 'userId' => array(
721
+ 'location' => 'path',
722
+ 'type' => 'string',
723
+ 'required' => true,
724
+ ),
725
+ 'id' => array(
726
+ 'location' => 'path',
727
+ 'type' => 'string',
728
+ 'required' => true,
729
+ ),
730
+ ),
731
+ ),'list' => array(
732
+ 'path' => '{userId}/settings/filters',
733
+ 'httpMethod' => 'GET',
734
+ 'parameters' => array(
735
+ 'userId' => array(
736
+ 'location' => 'path',
737
+ 'type' => 'string',
738
+ 'required' => true,
739
+ ),
740
+ ),
741
+ ),
742
+ )
743
+ )
744
+ );
745
+ $this->users_settings_forwardingAddresses = new Google_Service_Gmail_Resource_UsersSettingsForwardingAddresses(
746
+ $this,
747
+ $this->serviceName,
748
+ 'forwardingAddresses',
749
+ array(
750
+ 'methods' => array(
751
+ 'create' => array(
752
+ 'path' => '{userId}/settings/forwardingAddresses',
753
+ 'httpMethod' => 'POST',
754
+ 'parameters' => array(
755
+ 'userId' => array(
756
+ 'location' => 'path',
757
+ 'type' => 'string',
758
+ 'required' => true,
759
+ ),
760
+ ),
761
+ ),'delete' => array(
762
+ 'path' => '{userId}/settings/forwardingAddresses/{forwardingEmail}',
763
+ 'httpMethod' => 'DELETE',
764
+ 'parameters' => array(
765
+ 'userId' => array(
766
+ 'location' => 'path',
767
+ 'type' => 'string',
768
+ 'required' => true,
769
+ ),
770
+ 'forwardingEmail' => array(
771
+ 'location' => 'path',
772
+ 'type' => 'string',
773
+ 'required' => true,
774
+ ),
775
+ ),
776
+ ),'get' => array(
777
+ 'path' => '{userId}/settings/forwardingAddresses/{forwardingEmail}',
778
+ 'httpMethod' => 'GET',
779
+ 'parameters' => array(
780
+ 'userId' => array(
781
+ 'location' => 'path',
782
+ 'type' => 'string',
783
+ 'required' => true,
784
+ ),
785
+ 'forwardingEmail' => array(
786
+ 'location' => 'path',
787
+ 'type' => 'string',
788
+ 'required' => true,
789
+ ),
790
+ ),
791
+ ),'list' => array(
792
+ 'path' => '{userId}/settings/forwardingAddresses',
793
+ 'httpMethod' => 'GET',
794
+ 'parameters' => array(
795
+ 'userId' => array(
796
+ 'location' => 'path',
797
+ 'type' => 'string',
798
+ 'required' => true,
799
+ ),
800
+ ),
801
+ ),
802
+ )
803
+ )
804
+ );
805
+ $this->users_settings_sendAs = new Google_Service_Gmail_Resource_UsersSettingsSendAs(
806
+ $this,
807
+ $this->serviceName,
808
+ 'sendAs',
809
+ array(
810
+ 'methods' => array(
811
+ 'create' => array(
812
+ 'path' => '{userId}/settings/sendAs',
813
+ 'httpMethod' => 'POST',
814
+ 'parameters' => array(
815
+ 'userId' => array(
816
+ 'location' => 'path',
817
+ 'type' => 'string',
818
+ 'required' => true,
819
+ ),
820
+ ),
821
+ ),'delete' => array(
822
+ 'path' => '{userId}/settings/sendAs/{sendAsEmail}',
823
+ 'httpMethod' => 'DELETE',
824
+ 'parameters' => array(
825
+ 'userId' => array(
826
+ 'location' => 'path',
827
+ 'type' => 'string',
828
+ 'required' => true,
829
+ ),
830
+ 'sendAsEmail' => array(
831
+ 'location' => 'path',
832
+ 'type' => 'string',
833
+ 'required' => true,
834
+ ),
835
+ ),
836
+ ),'get' => array(
837
+ 'path' => '{userId}/settings/sendAs/{sendAsEmail}',
838
+ 'httpMethod' => 'GET',
839
+ 'parameters' => array(
840
+ 'userId' => array(
841
+ 'location' => 'path',
842
+ 'type' => 'string',
843
+ 'required' => true,
844
+ ),
845
+ 'sendAsEmail' => array(
846
+ 'location' => 'path',
847
+ 'type' => 'string',
848
+ 'required' => true,
849
+ ),
850
+ ),
851
+ ),'list' => array(
852
+ 'path' => '{userId}/settings/sendAs',
853
+ 'httpMethod' => 'GET',
854
+ 'parameters' => array(
855
+ 'userId' => array(
856
+ 'location' => 'path',
857
+ 'type' => 'string',
858
+ 'required' => true,
859
+ ),
860
+ ),
861
+ ),'patch' => array(
862
+ 'path' => '{userId}/settings/sendAs/{sendAsEmail}',
863
+ 'httpMethod' => 'PATCH',
864
+ 'parameters' => array(
865
+ 'userId' => array(
866
+ 'location' => 'path',
867
+ 'type' => 'string',
868
+ 'required' => true,
869
+ ),
870
+ 'sendAsEmail' => array(
871
+ 'location' => 'path',
872
+ 'type' => 'string',
873
+ 'required' => true,
874
+ ),
875
+ ),
876
+ ),'update' => array(
877
+ 'path' => '{userId}/settings/sendAs/{sendAsEmail}',
878
+ 'httpMethod' => 'PUT',
879
+ 'parameters' => array(
880
+ 'userId' => array(
881
+ 'location' => 'path',
882
+ 'type' => 'string',
883
+ 'required' => true,
884
+ ),
885
+ 'sendAsEmail' => array(
886
+ 'location' => 'path',
887
+ 'type' => 'string',
888
+ 'required' => true,
889
+ ),
890
+ ),
891
+ ),'verify' => array(
892
+ 'path' => '{userId}/settings/sendAs/{sendAsEmail}/verify',
893
+ 'httpMethod' => 'POST',
894
+ 'parameters' => array(
895
+ 'userId' => array(
896
+ 'location' => 'path',
897
+ 'type' => 'string',
898
+ 'required' => true,
899
+ ),
900
+ 'sendAsEmail' => array(
901
+ 'location' => 'path',
902
+ 'type' => 'string',
903
+ 'required' => true,
904
+ ),
905
+ ),
906
+ ),
907
+ )
908
+ )
909
+ );
910
+ $this->users_settings_sendAs_smimeInfo = new Google_Service_Gmail_Resource_UsersSettingsSendAsSmimeInfo(
911
+ $this,
912
+ $this->serviceName,
913
+ 'smimeInfo',
914
+ array(
915
+ 'methods' => array(
916
+ 'delete' => array(
917
+ 'path' => '{userId}/settings/sendAs/{sendAsEmail}/smimeInfo/{id}',
918
+ 'httpMethod' => 'DELETE',
919
+ 'parameters' => array(
920
+ 'userId' => array(
921
+ 'location' => 'path',
922
+ 'type' => 'string',
923
+ 'required' => true,
924
+ ),
925
+ 'sendAsEmail' => array(
926
+ 'location' => 'path',
927
+ 'type' => 'string',
928
+ 'required' => true,
929
+ ),
930
+ 'id' => array(
931
+ 'location' => 'path',
932
+ 'type' => 'string',
933
+ 'required' => true,
934
+ ),
935
+ ),
936
+ ),'get' => array(
937
+ 'path' => '{userId}/settings/sendAs/{sendAsEmail}/smimeInfo/{id}',
938
+ 'httpMethod' => 'GET',
939
+ 'parameters' => array(
940
+ 'userId' => array(
941
+ 'location' => 'path',
942
+ 'type' => 'string',
943
+ 'required' => true,
944
+ ),
945
+ 'sendAsEmail' => array(
946
+ 'location' => 'path',
947
+ 'type' => 'string',
948
+ 'required' => true,
949
+ ),
950
+ 'id' => array(
951
+ 'location' => 'path',
952
+ 'type' => 'string',
953
+ 'required' => true,
954
+ ),
955
+ ),
956
+ ),'insert' => array(
957
+ 'path' => '{userId}/settings/sendAs/{sendAsEmail}/smimeInfo',
958
+ 'httpMethod' => 'POST',
959
+ 'parameters' => array(
960
+ 'userId' => array(
961
+ 'location' => 'path',
962
+ 'type' => 'string',
963
+ 'required' => true,
964
+ ),
965
+ 'sendAsEmail' => array(
966
+ 'location' => 'path',
967
+ 'type' => 'string',
968
+ 'required' => true,
969
+ ),
970
+ ),
971
+ ),'list' => array(
972
+ 'path' => '{userId}/settings/sendAs/{sendAsEmail}/smimeInfo',
973
+ 'httpMethod' => 'GET',
974
+ 'parameters' => array(
975
+ 'userId' => array(
976
+ 'location' => 'path',
977
+ 'type' => 'string',
978
+ 'required' => true,
979
+ ),
980
+ 'sendAsEmail' => array(
981
+ 'location' => 'path',
982
+ 'type' => 'string',
983
+ 'required' => true,
984
+ ),
985
+ ),
986
+ ),'setDefault' => array(
987
+ 'path' => '{userId}/settings/sendAs/{sendAsEmail}/smimeInfo/{id}/setDefault',
988
+ 'httpMethod' => 'POST',
989
+ 'parameters' => array(
990
+ 'userId' => array(
991
+ 'location' => 'path',
992
+ 'type' => 'string',
993
+ 'required' => true,
994
+ ),
995
+ 'sendAsEmail' => array(
996
+ 'location' => 'path',
997
+ 'type' => 'string',
998
+ 'required' => true,
999
+ ),
1000
+ 'id' => array(
1001
+ 'location' => 'path',
1002
+ 'type' => 'string',
1003
+ 'required' => true,
1004
+ ),
1005
+ ),
1006
+ ),
1007
+ )
1008
+ )
1009
+ );
1010
+ $this->users_threads = new Google_Service_Gmail_Resource_UsersThreads(
1011
+ $this,
1012
+ $this->serviceName,
1013
+ 'threads',
1014
+ array(
1015
+ 'methods' => array(
1016
+ 'delete' => array(
1017
+ 'path' => '{userId}/threads/{id}',
1018
+ 'httpMethod' => 'DELETE',
1019
+ 'parameters' => array(
1020
+ 'userId' => array(
1021
+ 'location' => 'path',
1022
+ 'type' => 'string',
1023
+ 'required' => true,
1024
+ ),
1025
+ 'id' => array(
1026
+ 'location' => 'path',
1027
+ 'type' => 'string',
1028
+ 'required' => true,
1029
+ ),
1030
+ ),
1031
+ ),'get' => array(
1032
+ 'path' => '{userId}/threads/{id}',
1033
+ 'httpMethod' => 'GET',
1034
+ 'parameters' => array(
1035
+ 'userId' => array(
1036
+ 'location' => 'path',
1037
+ 'type' => 'string',
1038
+ 'required' => true,
1039
+ ),
1040
+ 'id' => array(
1041
+ 'location' => 'path',
1042
+ 'type' => 'string',
1043
+ 'required' => true,
1044
+ ),
1045
+ 'format' => array(
1046
+ 'location' => 'query',
1047
+ 'type' => 'string',
1048
+ ),
1049
+ 'metadataHeaders' => array(
1050
+ 'location' => 'query',
1051
+ 'type' => 'string',
1052
+ 'repeated' => true,
1053
+ ),
1054
+ ),
1055
+ ),'list' => array(
1056
+ 'path' => '{userId}/threads',
1057
+ 'httpMethod' => 'GET',
1058
+ 'parameters' => array(
1059
+ 'userId' => array(
1060
+ 'location' => 'path',
1061
+ 'type' => 'string',
1062
+ 'required' => true,
1063
+ ),
1064
+ 'includeSpamTrash' => array(
1065
+ 'location' => 'query',
1066
+ 'type' => 'boolean',
1067
+ ),
1068
+ 'labelIds' => array(
1069
+ 'location' => 'query',
1070
+ 'type' => 'string',
1071
+ 'repeated' => true,
1072
+ ),
1073
+ 'maxResults' => array(
1074
+ 'location' => 'query',
1075
+ 'type' => 'integer',
1076
+ ),
1077
+ 'pageToken' => array(
1078
+ 'location' => 'query',
1079
+ 'type' => 'string',
1080
+ ),
1081
+ 'q' => array(
1082
+ 'location' => 'query',
1083
+ 'type' => 'string',
1084
+ ),
1085
+ ),
1086
+ ),'modify' => array(
1087
+ 'path' => '{userId}/threads/{id}/modify',
1088
+ 'httpMethod' => 'POST',
1089
+ 'parameters' => array(
1090
+ 'userId' => array(
1091
+ 'location' => 'path',
1092
+ 'type' => 'string',
1093
+ 'required' => true,
1094
+ ),
1095
+ 'id' => array(
1096
+ 'location' => 'path',
1097
+ 'type' => 'string',
1098
+ 'required' => true,
1099
+ ),
1100
+ ),
1101
+ ),'trash' => array(
1102
+ 'path' => '{userId}/threads/{id}/trash',
1103
+ 'httpMethod' => 'POST',
1104
+ 'parameters' => array(
1105
+ 'userId' => array(
1106
+ 'location' => 'path',
1107
+ 'type' => 'string',
1108
+ 'required' => true,
1109
+ ),
1110
+ 'id' => array(
1111
+ 'location' => 'path',
1112
+ 'type' => 'string',
1113
+ 'required' => true,
1114
+ ),
1115
+ ),
1116
+ ),'untrash' => array(
1117
+ 'path' => '{userId}/threads/{id}/untrash',
1118
+ 'httpMethod' => 'POST',
1119
+ 'parameters' => array(
1120
+ 'userId' => array(
1121
+ 'location' => 'path',
1122
+ 'type' => 'string',
1123
+ 'required' => true,
1124
+ ),
1125
+ 'id' => array(
1126
+ 'location' => 'path',
1127
+ 'type' => 'string',
1128
+ 'required' => true,
1129
+ ),
1130
+ ),
1131
+ ),
1132
+ )
1133
+ )
1134
+ );
1135
+ }
1136
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/AutoForwarding.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_AutoForwarding extends Google_Model
19
+ {
20
+ public $disposition;
21
+ public $emailAddress;
22
+ public $enabled;
23
+
24
+ public function setDisposition($disposition)
25
+ {
26
+ $this->disposition = $disposition;
27
+ }
28
+ public function getDisposition()
29
+ {
30
+ return $this->disposition;
31
+ }
32
+ public function setEmailAddress($emailAddress)
33
+ {
34
+ $this->emailAddress = $emailAddress;
35
+ }
36
+ public function getEmailAddress()
37
+ {
38
+ return $this->emailAddress;
39
+ }
40
+ public function setEnabled($enabled)
41
+ {
42
+ $this->enabled = $enabled;
43
+ }
44
+ public function getEnabled()
45
+ {
46
+ return $this->enabled;
47
+ }
48
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/BatchDeleteMessagesRequest.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_BatchDeleteMessagesRequest extends Google_Collection
19
+ {
20
+ protected $collection_key = 'ids';
21
+ public $ids;
22
+
23
+ public function setIds($ids)
24
+ {
25
+ $this->ids = $ids;
26
+ }
27
+ public function getIds()
28
+ {
29
+ return $this->ids;
30
+ }
31
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/BatchModifyMessagesRequest.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_BatchModifyMessagesRequest extends Google_Collection
19
+ {
20
+ protected $collection_key = 'removeLabelIds';
21
+ public $addLabelIds;
22
+ public $ids;
23
+ public $removeLabelIds;
24
+
25
+ public function setAddLabelIds($addLabelIds)
26
+ {
27
+ $this->addLabelIds = $addLabelIds;
28
+ }
29
+ public function getAddLabelIds()
30
+ {
31
+ return $this->addLabelIds;
32
+ }
33
+ public function setIds($ids)
34
+ {
35
+ $this->ids = $ids;
36
+ }
37
+ public function getIds()
38
+ {
39
+ return $this->ids;
40
+ }
41
+ public function setRemoveLabelIds($removeLabelIds)
42
+ {
43
+ $this->removeLabelIds = $removeLabelIds;
44
+ }
45
+ public function getRemoveLabelIds()
46
+ {
47
+ return $this->removeLabelIds;
48
+ }
49
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Draft.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_Draft extends Google_Model
19
+ {
20
+ public $id;
21
+ protected $messageType = 'Google_Service_Gmail_Message';
22
+ protected $messageDataType = '';
23
+
24
+ public function setId($id)
25
+ {
26
+ $this->id = $id;
27
+ }
28
+ public function getId()
29
+ {
30
+ return $this->id;
31
+ }
32
+ /**
33
+ * @param Google_Service_Gmail_Message
34
+ */
35
+ public function setMessage(Google_Service_Gmail_Message $message)
36
+ {
37
+ $this->message = $message;
38
+ }
39
+ /**
40
+ * @return Google_Service_Gmail_Message
41
+ */
42
+ public function getMessage()
43
+ {
44
+ return $this->message;
45
+ }
46
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Filter.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_Filter extends Google_Model
19
+ {
20
+ protected $actionType = 'Google_Service_Gmail_FilterAction';
21
+ protected $actionDataType = '';
22
+ protected $criteriaType = 'Google_Service_Gmail_FilterCriteria';
23
+ protected $criteriaDataType = '';
24
+ public $id;
25
+
26
+ /**
27
+ * @param Google_Service_Gmail_FilterAction
28
+ */
29
+ public function setAction(Google_Service_Gmail_FilterAction $action)
30
+ {
31
+ $this->action = $action;
32
+ }
33
+ /**
34
+ * @return Google_Service_Gmail_FilterAction
35
+ */
36
+ public function getAction()
37
+ {
38
+ return $this->action;
39
+ }
40
+ /**
41
+ * @param Google_Service_Gmail_FilterCriteria
42
+ */
43
+ public function setCriteria(Google_Service_Gmail_FilterCriteria $criteria)
44
+ {
45
+ $this->criteria = $criteria;
46
+ }
47
+ /**
48
+ * @return Google_Service_Gmail_FilterCriteria
49
+ */
50
+ public function getCriteria()
51
+ {
52
+ return $this->criteria;
53
+ }
54
+ public function setId($id)
55
+ {
56
+ $this->id = $id;
57
+ }
58
+ public function getId()
59
+ {
60
+ return $this->id;
61
+ }
62
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/FilterAction.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_FilterAction extends Google_Collection
19
+ {
20
+ protected $collection_key = 'removeLabelIds';
21
+ public $addLabelIds;
22
+ public $forward;
23
+ public $removeLabelIds;
24
+
25
+ public function setAddLabelIds($addLabelIds)
26
+ {
27
+ $this->addLabelIds = $addLabelIds;
28
+ }
29
+ public function getAddLabelIds()
30
+ {
31
+ return $this->addLabelIds;
32
+ }
33
+ public function setForward($forward)
34
+ {
35
+ $this->forward = $forward;
36
+ }
37
+ public function getForward()
38
+ {
39
+ return $this->forward;
40
+ }
41
+ public function setRemoveLabelIds($removeLabelIds)
42
+ {
43
+ $this->removeLabelIds = $removeLabelIds;
44
+ }
45
+ public function getRemoveLabelIds()
46
+ {
47
+ return $this->removeLabelIds;
48
+ }
49
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/FilterCriteria.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_FilterCriteria extends Google_Model
19
+ {
20
+ public $excludeChats;
21
+ public $from;
22
+ public $hasAttachment;
23
+ public $negatedQuery;
24
+ public $query;
25
+ public $size;
26
+ public $sizeComparison;
27
+ public $subject;
28
+ public $to;
29
+
30
+ public function setExcludeChats($excludeChats)
31
+ {
32
+ $this->excludeChats = $excludeChats;
33
+ }
34
+ public function getExcludeChats()
35
+ {
36
+ return $this->excludeChats;
37
+ }
38
+ public function setFrom($from)
39
+ {
40
+ $this->from = $from;
41
+ }
42
+ public function getFrom()
43
+ {
44
+ return $this->from;
45
+ }
46
+ public function setHasAttachment($hasAttachment)
47
+ {
48
+ $this->hasAttachment = $hasAttachment;
49
+ }
50
+ public function getHasAttachment()
51
+ {
52
+ return $this->hasAttachment;
53
+ }
54
+ public function setNegatedQuery($negatedQuery)
55
+ {
56
+ $this->negatedQuery = $negatedQuery;
57
+ }
58
+ public function getNegatedQuery()
59
+ {
60
+ return $this->negatedQuery;
61
+ }
62
+ public function setQuery($query)
63
+ {
64
+ $this->query = $query;
65
+ }
66
+ public function getQuery()
67
+ {
68
+ return $this->query;
69
+ }
70
+ public function setSize($size)
71
+ {
72
+ $this->size = $size;
73
+ }
74
+ public function getSize()
75
+ {
76
+ return $this->size;
77
+ }
78
+ public function setSizeComparison($sizeComparison)
79
+ {
80
+ $this->sizeComparison = $sizeComparison;
81
+ }
82
+ public function getSizeComparison()
83
+ {
84
+ return $this->sizeComparison;
85
+ }
86
+ public function setSubject($subject)
87
+ {
88
+ $this->subject = $subject;
89
+ }
90
+ public function getSubject()
91
+ {
92
+ return $this->subject;
93
+ }
94
+ public function setTo($to)
95
+ {
96
+ $this->to = $to;
97
+ }
98
+ public function getTo()
99
+ {
100
+ return $this->to;
101
+ }
102
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/ForwardingAddress.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_ForwardingAddress extends Google_Model
19
+ {
20
+ public $forwardingEmail;
21
+ public $verificationStatus;
22
+
23
+ public function setForwardingEmail($forwardingEmail)
24
+ {
25
+ $this->forwardingEmail = $forwardingEmail;
26
+ }
27
+ public function getForwardingEmail()
28
+ {
29
+ return $this->forwardingEmail;
30
+ }
31
+ public function setVerificationStatus($verificationStatus)
32
+ {
33
+ $this->verificationStatus = $verificationStatus;
34
+ }
35
+ public function getVerificationStatus()
36
+ {
37
+ return $this->verificationStatus;
38
+ }
39
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/History.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_History extends Google_Collection
19
+ {
20
+ protected $collection_key = 'messagesDeleted';
21
+ public $id;
22
+ protected $labelsAddedType = 'Google_Service_Gmail_HistoryLabelAdded';
23
+ protected $labelsAddedDataType = 'array';
24
+ protected $labelsRemovedType = 'Google_Service_Gmail_HistoryLabelRemoved';
25
+ protected $labelsRemovedDataType = 'array';
26
+ protected $messagesType = 'Google_Service_Gmail_Message';
27
+ protected $messagesDataType = 'array';
28
+ protected $messagesAddedType = 'Google_Service_Gmail_HistoryMessageAdded';
29
+ protected $messagesAddedDataType = 'array';
30
+ protected $messagesDeletedType = 'Google_Service_Gmail_HistoryMessageDeleted';
31
+ protected $messagesDeletedDataType = 'array';
32
+
33
+ public function setId($id)
34
+ {
35
+ $this->id = $id;
36
+ }
37
+ public function getId()
38
+ {
39
+ return $this->id;
40
+ }
41
+ /**
42
+ * @param Google_Service_Gmail_HistoryLabelAdded
43
+ */
44
+ public function setLabelsAdded($labelsAdded)
45
+ {
46
+ $this->labelsAdded = $labelsAdded;
47
+ }
48
+ /**
49
+ * @return Google_Service_Gmail_HistoryLabelAdded
50
+ */
51
+ public function getLabelsAdded()
52
+ {
53
+ return $this->labelsAdded;
54
+ }
55
+ /**
56
+ * @param Google_Service_Gmail_HistoryLabelRemoved
57
+ */
58
+ public function setLabelsRemoved($labelsRemoved)
59
+ {
60
+ $this->labelsRemoved = $labelsRemoved;
61
+ }
62
+ /**
63
+ * @return Google_Service_Gmail_HistoryLabelRemoved
64
+ */
65
+ public function getLabelsRemoved()
66
+ {
67
+ return $this->labelsRemoved;
68
+ }
69
+ /**
70
+ * @param Google_Service_Gmail_Message
71
+ */
72
+ public function setMessages($messages)
73
+ {
74
+ $this->messages = $messages;
75
+ }
76
+ /**
77
+ * @return Google_Service_Gmail_Message
78
+ */
79
+ public function getMessages()
80
+ {
81
+ return $this->messages;
82
+ }
83
+ /**
84
+ * @param Google_Service_Gmail_HistoryMessageAdded
85
+ */
86
+ public function setMessagesAdded($messagesAdded)
87
+ {
88
+ $this->messagesAdded = $messagesAdded;
89
+ }
90
+ /**
91
+ * @return Google_Service_Gmail_HistoryMessageAdded
92
+ */
93
+ public function getMessagesAdded()
94
+ {
95
+ return $this->messagesAdded;
96
+ }
97
+ /**
98
+ * @param Google_Service_Gmail_HistoryMessageDeleted
99
+ */
100
+ public function setMessagesDeleted($messagesDeleted)
101
+ {
102
+ $this->messagesDeleted = $messagesDeleted;
103
+ }
104
+ /**
105
+ * @return Google_Service_Gmail_HistoryMessageDeleted
106
+ */
107
+ public function getMessagesDeleted()
108
+ {
109
+ return $this->messagesDeleted;
110
+ }
111
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/HistoryLabelAdded.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_HistoryLabelAdded extends Google_Collection
19
+ {
20
+ protected $collection_key = 'labelIds';
21
+ public $labelIds;
22
+ protected $messageType = 'Google_Service_Gmail_Message';
23
+ protected $messageDataType = '';
24
+
25
+ public function setLabelIds($labelIds)
26
+ {
27
+ $this->labelIds = $labelIds;
28
+ }
29
+ public function getLabelIds()
30
+ {
31
+ return $this->labelIds;
32
+ }
33
+ /**
34
+ * @param Google_Service_Gmail_Message
35
+ */
36
+ public function setMessage(Google_Service_Gmail_Message $message)
37
+ {
38
+ $this->message = $message;
39
+ }
40
+ /**
41
+ * @return Google_Service_Gmail_Message
42
+ */
43
+ public function getMessage()
44
+ {
45
+ return $this->message;
46
+ }
47
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/HistoryLabelRemoved.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_HistoryLabelRemoved extends Google_Collection
19
+ {
20
+ protected $collection_key = 'labelIds';
21
+ public $labelIds;
22
+ protected $messageType = 'Google_Service_Gmail_Message';
23
+ protected $messageDataType = '';
24
+
25
+ public function setLabelIds($labelIds)
26
+ {
27
+ $this->labelIds = $labelIds;
28
+ }
29
+ public function getLabelIds()
30
+ {
31
+ return $this->labelIds;
32
+ }
33
+ /**
34
+ * @param Google_Service_Gmail_Message
35
+ */
36
+ public function setMessage(Google_Service_Gmail_Message $message)
37
+ {
38
+ $this->message = $message;
39
+ }
40
+ /**
41
+ * @return Google_Service_Gmail_Message
42
+ */
43
+ public function getMessage()
44
+ {
45
+ return $this->message;
46
+ }
47
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/HistoryMessageAdded.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_HistoryMessageAdded extends Google_Model
19
+ {
20
+ protected $messageType = 'Google_Service_Gmail_Message';
21
+ protected $messageDataType = '';
22
+
23
+ /**
24
+ * @param Google_Service_Gmail_Message
25
+ */
26
+ public function setMessage(Google_Service_Gmail_Message $message)
27
+ {
28
+ $this->message = $message;
29
+ }
30
+ /**
31
+ * @return Google_Service_Gmail_Message
32
+ */
33
+ public function getMessage()
34
+ {
35
+ return $this->message;
36
+ }
37
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/HistoryMessageDeleted.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_HistoryMessageDeleted extends Google_Model
19
+ {
20
+ protected $messageType = 'Google_Service_Gmail_Message';
21
+ protected $messageDataType = '';
22
+
23
+ /**
24
+ * @param Google_Service_Gmail_Message
25
+ */
26
+ public function setMessage(Google_Service_Gmail_Message $message)
27
+ {
28
+ $this->message = $message;
29
+ }
30
+ /**
31
+ * @return Google_Service_Gmail_Message
32
+ */
33
+ public function getMessage()
34
+ {
35
+ return $this->message;
36
+ }
37
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/ImapSettings.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_ImapSettings extends Google_Model
19
+ {
20
+ public $autoExpunge;
21
+ public $enabled;
22
+ public $expungeBehavior;
23
+ public $maxFolderSize;
24
+
25
+ public function setAutoExpunge($autoExpunge)
26
+ {
27
+ $this->autoExpunge = $autoExpunge;
28
+ }
29
+ public function getAutoExpunge()
30
+ {
31
+ return $this->autoExpunge;
32
+ }
33
+ public function setEnabled($enabled)
34
+ {
35
+ $this->enabled = $enabled;
36
+ }
37
+ public function getEnabled()
38
+ {
39
+ return $this->enabled;
40
+ }
41
+ public function setExpungeBehavior($expungeBehavior)
42
+ {
43
+ $this->expungeBehavior = $expungeBehavior;
44
+ }
45
+ public function getExpungeBehavior()
46
+ {
47
+ return $this->expungeBehavior;
48
+ }
49
+ public function setMaxFolderSize($maxFolderSize)
50
+ {
51
+ $this->maxFolderSize = $maxFolderSize;
52
+ }
53
+ public function getMaxFolderSize()
54
+ {
55
+ return $this->maxFolderSize;
56
+ }
57
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Label.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_Label extends Google_Model
19
+ {
20
+ public $id;
21
+ public $labelListVisibility;
22
+ public $messageListVisibility;
23
+ public $messagesTotal;
24
+ public $messagesUnread;
25
+ public $name;
26
+ public $threadsTotal;
27
+ public $threadsUnread;
28
+ public $type;
29
+
30
+ public function setId($id)
31
+ {
32
+ $this->id = $id;
33
+ }
34
+ public function getId()
35
+ {
36
+ return $this->id;
37
+ }
38
+ public function setLabelListVisibility($labelListVisibility)
39
+ {
40
+ $this->labelListVisibility = $labelListVisibility;
41
+ }
42
+ public function getLabelListVisibility()
43
+ {
44
+ return $this->labelListVisibility;
45
+ }
46
+ public function setMessageListVisibility($messageListVisibility)
47
+ {
48
+ $this->messageListVisibility = $messageListVisibility;
49
+ }
50
+ public function getMessageListVisibility()
51
+ {
52
+ return $this->messageListVisibility;
53
+ }
54
+ public function setMessagesTotal($messagesTotal)
55
+ {
56
+ $this->messagesTotal = $messagesTotal;
57
+ }
58
+ public function getMessagesTotal()
59
+ {
60
+ return $this->messagesTotal;
61
+ }
62
+ public function setMessagesUnread($messagesUnread)
63
+ {
64
+ $this->messagesUnread = $messagesUnread;
65
+ }
66
+ public function getMessagesUnread()
67
+ {
68
+ return $this->messagesUnread;
69
+ }
70
+ public function setName($name)
71
+ {
72
+ $this->name = $name;
73
+ }
74
+ public function getName()
75
+ {
76
+ return $this->name;
77
+ }
78
+ public function setThreadsTotal($threadsTotal)
79
+ {
80
+ $this->threadsTotal = $threadsTotal;
81
+ }
82
+ public function getThreadsTotal()
83
+ {
84
+ return $this->threadsTotal;
85
+ }
86
+ public function setThreadsUnread($threadsUnread)
87
+ {
88
+ $this->threadsUnread = $threadsUnread;
89
+ }
90
+ public function getThreadsUnread()
91
+ {
92
+ return $this->threadsUnread;
93
+ }
94
+ public function setType($type)
95
+ {
96
+ $this->type = $type;
97
+ }
98
+ public function getType()
99
+ {
100
+ return $this->type;
101
+ }
102
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/ListDraftsResponse.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_ListDraftsResponse extends Google_Collection
19
+ {
20
+ protected $collection_key = 'drafts';
21
+ protected $draftsType = 'Google_Service_Gmail_Draft';
22
+ protected $draftsDataType = 'array';
23
+ public $nextPageToken;
24
+ public $resultSizeEstimate;
25
+
26
+ /**
27
+ * @param Google_Service_Gmail_Draft
28
+ */
29
+ public function setDrafts($drafts)
30
+ {
31
+ $this->drafts = $drafts;
32
+ }
33
+ /**
34
+ * @return Google_Service_Gmail_Draft
35
+ */
36
+ public function getDrafts()
37
+ {
38
+ return $this->drafts;
39
+ }
40
+ public function setNextPageToken($nextPageToken)
41
+ {
42
+ $this->nextPageToken = $nextPageToken;
43
+ }
44
+ public function getNextPageToken()
45
+ {
46
+ return $this->nextPageToken;
47
+ }
48
+ public function setResultSizeEstimate($resultSizeEstimate)
49
+ {
50
+ $this->resultSizeEstimate = $resultSizeEstimate;
51
+ }
52
+ public function getResultSizeEstimate()
53
+ {
54
+ return $this->resultSizeEstimate;
55
+ }
56
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/ListFiltersResponse.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_ListFiltersResponse extends Google_Collection
19
+ {
20
+ protected $collection_key = 'filter';
21
+ protected $filterType = 'Google_Service_Gmail_Filter';
22
+ protected $filterDataType = 'array';
23
+
24
+ /**
25
+ * @param Google_Service_Gmail_Filter
26
+ */
27
+ public function setFilter($filter)
28
+ {
29
+ $this->filter = $filter;
30
+ }
31
+ /**
32
+ * @return Google_Service_Gmail_Filter
33
+ */
34
+ public function getFilter()
35
+ {
36
+ return $this->filter;
37
+ }
38
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/ListForwardingAddressesResponse.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_ListForwardingAddressesResponse extends Google_Collection
19
+ {
20
+ protected $collection_key = 'forwardingAddresses';
21
+ protected $forwardingAddressesType = 'Google_Service_Gmail_ForwardingAddress';
22
+ protected $forwardingAddressesDataType = 'array';
23
+
24
+ /**
25
+ * @param Google_Service_Gmail_ForwardingAddress
26
+ */
27
+ public function setForwardingAddresses($forwardingAddresses)
28
+ {
29
+ $this->forwardingAddresses = $forwardingAddresses;
30
+ }
31
+ /**
32
+ * @return Google_Service_Gmail_ForwardingAddress
33
+ */
34
+ public function getForwardingAddresses()
35
+ {
36
+ return $this->forwardingAddresses;
37
+ }
38
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/ListHistoryResponse.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_ListHistoryResponse extends Google_Collection
19
+ {
20
+ protected $collection_key = 'history';
21
+ protected $historyType = 'Google_Service_Gmail_History';
22
+ protected $historyDataType = 'array';
23
+ public $historyId;
24
+ public $nextPageToken;
25
+
26
+ /**
27
+ * @param Google_Service_Gmail_History
28
+ */
29
+ public function setHistory($history)
30
+ {
31
+ $this->history = $history;
32
+ }
33
+ /**
34
+ * @return Google_Service_Gmail_History
35
+ */
36
+ public function getHistory()
37
+ {
38
+ return $this->history;
39
+ }
40
+ public function setHistoryId($historyId)
41
+ {
42
+ $this->historyId = $historyId;
43
+ }
44
+ public function getHistoryId()
45
+ {
46
+ return $this->historyId;
47
+ }
48
+ public function setNextPageToken($nextPageToken)
49
+ {
50
+ $this->nextPageToken = $nextPageToken;
51
+ }
52
+ public function getNextPageToken()
53
+ {
54
+ return $this->nextPageToken;
55
+ }
56
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/ListLabelsResponse.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_ListLabelsResponse extends Google_Collection
19
+ {
20
+ protected $collection_key = 'labels';
21
+ protected $labelsType = 'Google_Service_Gmail_Label';
22
+ protected $labelsDataType = 'array';
23
+
24
+ /**
25
+ * @param Google_Service_Gmail_Label
26
+ */
27
+ public function setLabels($labels)
28
+ {
29
+ $this->labels = $labels;
30
+ }
31
+ /**
32
+ * @return Google_Service_Gmail_Label
33
+ */
34
+ public function getLabels()
35
+ {
36
+ return $this->labels;
37
+ }
38
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/ListMessagesResponse.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_ListMessagesResponse extends Google_Collection
19
+ {
20
+ protected $collection_key = 'messages';
21
+ protected $messagesType = 'Google_Service_Gmail_Message';
22
+ protected $messagesDataType = 'array';
23
+ public $nextPageToken;
24
+ public $resultSizeEstimate;
25
+
26
+ /**
27
+ * @param Google_Service_Gmail_Message
28
+ */
29
+ public function setMessages($messages)
30
+ {
31
+ $this->messages = $messages;
32
+ }
33
+ /**
34
+ * @return Google_Service_Gmail_Message
35
+ */
36
+ public function getMessages()
37
+ {
38
+ return $this->messages;
39
+ }
40
+ public function setNextPageToken($nextPageToken)
41
+ {
42
+ $this->nextPageToken = $nextPageToken;
43
+ }
44
+ public function getNextPageToken()
45
+ {
46
+ return $this->nextPageToken;
47
+ }
48
+ public function setResultSizeEstimate($resultSizeEstimate)
49
+ {
50
+ $this->resultSizeEstimate = $resultSizeEstimate;
51
+ }
52
+ public function getResultSizeEstimate()
53
+ {
54
+ return $this->resultSizeEstimate;
55
+ }
56
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/ListSendAsResponse.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_ListSendAsResponse extends Google_Collection
19
+ {
20
+ protected $collection_key = 'sendAs';
21
+ protected $sendAsType = 'Google_Service_Gmail_SendAs';
22
+ protected $sendAsDataType = 'array';
23
+
24
+ /**
25
+ * @param Google_Service_Gmail_SendAs
26
+ */
27
+ public function setSendAs($sendAs)
28
+ {
29
+ $this->sendAs = $sendAs;
30
+ }
31
+ /**
32
+ * @return Google_Service_Gmail_SendAs
33
+ */
34
+ public function getSendAs()
35
+ {
36
+ return $this->sendAs;
37
+ }
38
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/ListSmimeInfoResponse.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_ListSmimeInfoResponse extends Google_Collection
19
+ {
20
+ protected $collection_key = 'smimeInfo';
21
+ protected $smimeInfoType = 'Google_Service_Gmail_SmimeInfo';
22
+ protected $smimeInfoDataType = 'array';
23
+
24
+ /**
25
+ * @param Google_Service_Gmail_SmimeInfo
26
+ */
27
+ public function setSmimeInfo($smimeInfo)
28
+ {
29
+ $this->smimeInfo = $smimeInfo;
30
+ }
31
+ /**
32
+ * @return Google_Service_Gmail_SmimeInfo
33
+ */
34
+ public function getSmimeInfo()
35
+ {
36
+ return $this->smimeInfo;
37
+ }
38
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/ListThreadsResponse.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_ListThreadsResponse extends Google_Collection
19
+ {
20
+ protected $collection_key = 'threads';
21
+ public $nextPageToken;
22
+ public $resultSizeEstimate;
23
+ protected $threadsType = 'Google_Service_Gmail_Thread';
24
+ protected $threadsDataType = 'array';
25
+
26
+ public function setNextPageToken($nextPageToken)
27
+ {
28
+ $this->nextPageToken = $nextPageToken;
29
+ }
30
+ public function getNextPageToken()
31
+ {
32
+ return $this->nextPageToken;
33
+ }
34
+ public function setResultSizeEstimate($resultSizeEstimate)
35
+ {
36
+ $this->resultSizeEstimate = $resultSizeEstimate;
37
+ }
38
+ public function getResultSizeEstimate()
39
+ {
40
+ return $this->resultSizeEstimate;
41
+ }
42
+ /**
43
+ * @param Google_Service_Gmail_Thread
44
+ */
45
+ public function setThreads($threads)
46
+ {
47
+ $this->threads = $threads;
48
+ }
49
+ /**
50
+ * @return Google_Service_Gmail_Thread
51
+ */
52
+ public function getThreads()
53
+ {
54
+ return $this->threads;
55
+ }
56
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Message.php ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_Message extends Google_Collection
19
+ {
20
+ protected $collection_key = 'labelIds';
21
+ public $historyId;
22
+ public $id;
23
+ public $internalDate;
24
+ public $labelIds;
25
+ protected $payloadType = 'Google_Service_Gmail_MessagePart';
26
+ protected $payloadDataType = '';
27
+ public $raw;
28
+ public $sizeEstimate;
29
+ public $snippet;
30
+ public $threadId;
31
+
32
+ public function setHistoryId($historyId)
33
+ {
34
+ $this->historyId = $historyId;
35
+ }
36
+ public function getHistoryId()
37
+ {
38
+ return $this->historyId;
39
+ }
40
+ public function setId($id)
41
+ {
42
+ $this->id = $id;
43
+ }
44
+ public function getId()
45
+ {
46
+ return $this->id;
47
+ }
48
+ public function setInternalDate($internalDate)
49
+ {
50
+ $this->internalDate = $internalDate;
51
+ }
52
+ public function getInternalDate()
53
+ {
54
+ return $this->internalDate;
55
+ }
56
+ public function setLabelIds($labelIds)
57
+ {
58
+ $this->labelIds = $labelIds;
59
+ }
60
+ public function getLabelIds()
61
+ {
62
+ return $this->labelIds;
63
+ }
64
+ /**
65
+ * @param Google_Service_Gmail_MessagePart
66
+ */
67
+ public function setPayload(Google_Service_Gmail_MessagePart $payload)
68
+ {
69
+ $this->payload = $payload;
70
+ }
71
+ /**
72
+ * @return Google_Service_Gmail_MessagePart
73
+ */
74
+ public function getPayload()
75
+ {
76
+ return $this->payload;
77
+ }
78
+ public function setRaw($raw)
79
+ {
80
+ $this->raw = $raw;
81
+ }
82
+ public function getRaw()
83
+ {
84
+ return $this->raw;
85
+ }
86
+ public function setSizeEstimate($sizeEstimate)
87
+ {
88
+ $this->sizeEstimate = $sizeEstimate;
89
+ }
90
+ public function getSizeEstimate()
91
+ {
92
+ return $this->sizeEstimate;
93
+ }
94
+ public function setSnippet($snippet)
95
+ {
96
+ $this->snippet = $snippet;
97
+ }
98
+ public function getSnippet()
99
+ {
100
+ return $this->snippet;
101
+ }
102
+ public function setThreadId($threadId)
103
+ {
104
+ $this->threadId = $threadId;
105
+ }
106
+ public function getThreadId()
107
+ {
108
+ return $this->threadId;
109
+ }
110
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/MessagePart.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_MessagePart extends Google_Collection
19
+ {
20
+ protected $collection_key = 'parts';
21
+ protected $bodyType = 'Google_Service_Gmail_MessagePartBody';
22
+ protected $bodyDataType = '';
23
+ public $filename;
24
+ protected $headersType = 'Google_Service_Gmail_MessagePartHeader';
25
+ protected $headersDataType = 'array';
26
+ public $mimeType;
27
+ public $partId;
28
+ protected $partsType = 'Google_Service_Gmail_MessagePart';
29
+ protected $partsDataType = 'array';
30
+
31
+ /**
32
+ * @param Google_Service_Gmail_MessagePartBody
33
+ */
34
+ public function setBody(Google_Service_Gmail_MessagePartBody $body)
35
+ {
36
+ $this->body = $body;
37
+ }
38
+ /**
39
+ * @return Google_Service_Gmail_MessagePartBody
40
+ */
41
+ public function getBody()
42
+ {
43
+ return $this->body;
44
+ }
45
+ public function setFilename($filename)
46
+ {
47
+ $this->filename = $filename;
48
+ }
49
+ public function getFilename()
50
+ {
51
+ return $this->filename;
52
+ }
53
+ /**
54
+ * @param Google_Service_Gmail_MessagePartHeader
55
+ */
56
+ public function setHeaders($headers)
57
+ {
58
+ $this->headers = $headers;
59
+ }
60
+ /**
61
+ * @return Google_Service_Gmail_MessagePartHeader
62
+ */
63
+ public function getHeaders()
64
+ {
65
+ return $this->headers;
66
+ }
67
+ public function setMimeType($mimeType)
68
+ {
69
+ $this->mimeType = $mimeType;
70
+ }
71
+ public function getMimeType()
72
+ {
73
+ return $this->mimeType;
74
+ }
75
+ public function setPartId($partId)
76
+ {
77
+ $this->partId = $partId;
78
+ }
79
+ public function getPartId()
80
+ {
81
+ return $this->partId;
82
+ }
83
+ /**
84
+ * @param Google_Service_Gmail_MessagePart
85
+ */
86
+ public function setParts($parts)
87
+ {
88
+ $this->parts = $parts;
89
+ }
90
+ /**
91
+ * @return Google_Service_Gmail_MessagePart
92
+ */
93
+ public function getParts()
94
+ {
95
+ return $this->parts;
96
+ }
97
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/MessagePartBody.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_MessagePartBody extends Google_Model
19
+ {
20
+ public $attachmentId;
21
+ public $data;
22
+ public $size;
23
+
24
+ public function setAttachmentId($attachmentId)
25
+ {
26
+ $this->attachmentId = $attachmentId;
27
+ }
28
+ public function getAttachmentId()
29
+ {
30
+ return $this->attachmentId;
31
+ }
32
+ public function setData($data)
33
+ {
34
+ $this->data = $data;
35
+ }
36
+ public function getData()
37
+ {
38
+ return $this->data;
39
+ }
40
+ public function setSize($size)
41
+ {
42
+ $this->size = $size;
43
+ }
44
+ public function getSize()
45
+ {
46
+ return $this->size;
47
+ }
48
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/MessagePartHeader.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_MessagePartHeader extends Google_Model
19
+ {
20
+ public $name;
21
+ public $value;
22
+
23
+ public function setName($name)
24
+ {
25
+ $this->name = $name;
26
+ }
27
+ public function getName()
28
+ {
29
+ return $this->name;
30
+ }
31
+ public function setValue($value)
32
+ {
33
+ $this->value = $value;
34
+ }
35
+ public function getValue()
36
+ {
37
+ return $this->value;
38
+ }
39
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/ModifyMessageRequest.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_ModifyMessageRequest extends Google_Collection
19
+ {
20
+ protected $collection_key = 'removeLabelIds';
21
+ public $addLabelIds;
22
+ public $removeLabelIds;
23
+
24
+ public function setAddLabelIds($addLabelIds)
25
+ {
26
+ $this->addLabelIds = $addLabelIds;
27
+ }
28
+ public function getAddLabelIds()
29
+ {
30
+ return $this->addLabelIds;
31
+ }
32
+ public function setRemoveLabelIds($removeLabelIds)
33
+ {
34
+ $this->removeLabelIds = $removeLabelIds;
35
+ }
36
+ public function getRemoveLabelIds()
37
+ {
38
+ return $this->removeLabelIds;
39
+ }
40
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/ModifyThreadRequest.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_ModifyThreadRequest extends Google_Collection
19
+ {
20
+ protected $collection_key = 'removeLabelIds';
21
+ public $addLabelIds;
22
+ public $removeLabelIds;
23
+
24
+ public function setAddLabelIds($addLabelIds)
25
+ {
26
+ $this->addLabelIds = $addLabelIds;
27
+ }
28
+ public function getAddLabelIds()
29
+ {
30
+ return $this->addLabelIds;
31
+ }
32
+ public function setRemoveLabelIds($removeLabelIds)
33
+ {
34
+ $this->removeLabelIds = $removeLabelIds;
35
+ }
36
+ public function getRemoveLabelIds()
37
+ {
38
+ return $this->removeLabelIds;
39
+ }
40
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/PopSettings.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_PopSettings extends Google_Model
19
+ {
20
+ public $accessWindow;
21
+ public $disposition;
22
+
23
+ public function setAccessWindow($accessWindow)
24
+ {
25
+ $this->accessWindow = $accessWindow;
26
+ }
27
+ public function getAccessWindow()
28
+ {
29
+ return $this->accessWindow;
30
+ }
31
+ public function setDisposition($disposition)
32
+ {
33
+ $this->disposition = $disposition;
34
+ }
35
+ public function getDisposition()
36
+ {
37
+ return $this->disposition;
38
+ }
39
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Profile.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_Profile extends Google_Model
19
+ {
20
+ public $emailAddress;
21
+ public $historyId;
22
+ public $messagesTotal;
23
+ public $threadsTotal;
24
+
25
+ public function setEmailAddress($emailAddress)
26
+ {
27
+ $this->emailAddress = $emailAddress;
28
+ }
29
+ public function getEmailAddress()
30
+ {
31
+ return $this->emailAddress;
32
+ }
33
+ public function setHistoryId($historyId)
34
+ {
35
+ $this->historyId = $historyId;
36
+ }
37
+ public function getHistoryId()
38
+ {
39
+ return $this->historyId;
40
+ }
41
+ public function setMessagesTotal($messagesTotal)
42
+ {
43
+ $this->messagesTotal = $messagesTotal;
44
+ }
45
+ public function getMessagesTotal()
46
+ {
47
+ return $this->messagesTotal;
48
+ }
49
+ public function setThreadsTotal($threadsTotal)
50
+ {
51
+ $this->threadsTotal = $threadsTotal;
52
+ }
53
+ public function getThreadsTotal()
54
+ {
55
+ return $this->threadsTotal;
56
+ }
57
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/Users.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ /**
19
+ * The "users" collection of methods.
20
+ * Typical usage is:
21
+ * <code>
22
+ * $gmailService = new Google_Service_Gmail(...);
23
+ * $users = $gmailService->users;
24
+ * </code>
25
+ */
26
+ class Google_Service_Gmail_Resource_Users extends Google_Service_Resource
27
+ {
28
+ /**
29
+ * Gets the current user's Gmail profile. (users.getProfile)
30
+ *
31
+ * @param string $userId The user's email address. The special value me can be
32
+ * used to indicate the authenticated user.
33
+ * @param array $optParams Optional parameters.
34
+ * @return Google_Service_Gmail_Profile
35
+ */
36
+ public function getProfile($userId, $optParams = array())
37
+ {
38
+ $params = array('userId' => $userId);
39
+ $params = array_merge($params, $optParams);
40
+ return $this->call('getProfile', array($params), "Google_Service_Gmail_Profile");
41
+ }
42
+ /**
43
+ * Stop receiving push notifications for the given user mailbox. (users.stop)
44
+ *
45
+ * @param string $userId The user's email address. The special value me can be
46
+ * used to indicate the authenticated user.
47
+ * @param array $optParams Optional parameters.
48
+ */
49
+ public function stop($userId, $optParams = array())
50
+ {
51
+ $params = array('userId' => $userId);
52
+ $params = array_merge($params, $optParams);
53
+ return $this->call('stop', array($params));
54
+ }
55
+ /**
56
+ * Set up or update a push notification watch on the given user mailbox.
57
+ * (users.watch)
58
+ *
59
+ * @param string $userId The user's email address. The special value me can be
60
+ * used to indicate the authenticated user.
61
+ * @param Google_Service_Gmail_WatchRequest $postBody
62
+ * @param array $optParams Optional parameters.
63
+ * @return Google_Service_Gmail_WatchResponse
64
+ */
65
+ public function watch($userId, Google_Service_Gmail_WatchRequest $postBody, $optParams = array())
66
+ {
67
+ $params = array('userId' => $userId, 'postBody' => $postBody);
68
+ $params = array_merge($params, $optParams);
69
+ return $this->call('watch', array($params), "Google_Service_Gmail_WatchResponse");
70
+ }
71
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersDrafts.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ /**
19
+ * The "drafts" collection of methods.
20
+ * Typical usage is:
21
+ * <code>
22
+ * $gmailService = new Google_Service_Gmail(...);
23
+ * $drafts = $gmailService->drafts;
24
+ * </code>
25
+ */
26
+ class Google_Service_Gmail_Resource_UsersDrafts extends Google_Service_Resource
27
+ {
28
+ /**
29
+ * Creates a new draft with the DRAFT label. (drafts.create)
30
+ *
31
+ * @param string $userId The user's email address. The special value me can be
32
+ * used to indicate the authenticated user.
33
+ * @param Google_Service_Gmail_Draft $postBody
34
+ * @param array $optParams Optional parameters.
35
+ * @return Google_Service_Gmail_Draft
36
+ */
37
+ public function create($userId, Google_Service_Gmail_Draft $postBody, $optParams = array())
38
+ {
39
+ $params = array('userId' => $userId, 'postBody' => $postBody);
40
+ $params = array_merge($params, $optParams);
41
+ return $this->call('create', array($params), "Google_Service_Gmail_Draft");
42
+ }
43
+ /**
44
+ * Immediately and permanently deletes the specified draft. Does not simply
45
+ * trash it. (drafts.delete)
46
+ *
47
+ * @param string $userId The user's email address. The special value me can be
48
+ * used to indicate the authenticated user.
49
+ * @param string $id The ID of the draft to delete.
50
+ * @param array $optParams Optional parameters.
51
+ */
52
+ public function delete($userId, $id, $optParams = array())
53
+ {
54
+ $params = array('userId' => $userId, 'id' => $id);
55
+ $params = array_merge($params, $optParams);
56
+ return $this->call('delete', array($params));
57
+ }
58
+ /**
59
+ * Gets the specified draft. (drafts.get)
60
+ *
61
+ * @param string $userId The user's email address. The special value me can be
62
+ * used to indicate the authenticated user.
63
+ * @param string $id The ID of the draft to retrieve.
64
+ * @param array $optParams Optional parameters.
65
+ *
66
+ * @opt_param string format The format to return the draft in.
67
+ * @return Google_Service_Gmail_Draft
68
+ */
69
+ public function get($userId, $id, $optParams = array())
70
+ {
71
+ $params = array('userId' => $userId, 'id' => $id);
72
+ $params = array_merge($params, $optParams);
73
+ return $this->call('get', array($params), "Google_Service_Gmail_Draft");
74
+ }
75
+ /**
76
+ * Lists the drafts in the user's mailbox. (drafts.listUsersDrafts)
77
+ *
78
+ * @param string $userId The user's email address. The special value me can be
79
+ * used to indicate the authenticated user.
80
+ * @param array $optParams Optional parameters.
81
+ *
82
+ * @opt_param bool includeSpamTrash Include drafts from SPAM and TRASH in the
83
+ * results.
84
+ * @opt_param string maxResults Maximum number of drafts to return.
85
+ * @opt_param string pageToken Page token to retrieve a specific page of results
86
+ * in the list.
87
+ * @opt_param string q Only return draft messages matching the specified query.
88
+ * Supports the same query format as the Gmail search box. For example,
89
+ * "from:someuser@example.com rfc822msgid: is:unread".
90
+ * @return Google_Service_Gmail_ListDraftsResponse
91
+ */
92
+ public function listUsersDrafts($userId, $optParams = array())
93
+ {
94
+ $params = array('userId' => $userId);
95
+ $params = array_merge($params, $optParams);
96
+ return $this->call('list', array($params), "Google_Service_Gmail_ListDraftsResponse");
97
+ }
98
+ /**
99
+ * Sends the specified, existing draft to the recipients in the To, Cc, and Bcc
100
+ * headers. (drafts.send)
101
+ *
102
+ * @param string $userId The user's email address. The special value me can be
103
+ * used to indicate the authenticated user.
104
+ * @param Google_Service_Gmail_Draft $postBody
105
+ * @param array $optParams Optional parameters.
106
+ * @return Google_Service_Gmail_Message
107
+ */
108
+ public function send($userId, Google_Service_Gmail_Draft $postBody, $optParams = array())
109
+ {
110
+ $params = array('userId' => $userId, 'postBody' => $postBody);
111
+ $params = array_merge($params, $optParams);
112
+ return $this->call('send', array($params), "Google_Service_Gmail_Message");
113
+ }
114
+ /**
115
+ * Replaces a draft's content. (drafts.update)
116
+ *
117
+ * @param string $userId The user's email address. The special value me can be
118
+ * used to indicate the authenticated user.
119
+ * @param string $id The ID of the draft to update.
120
+ * @param Google_Service_Gmail_Draft $postBody
121
+ * @param array $optParams Optional parameters.
122
+ * @return Google_Service_Gmail_Draft
123
+ */
124
+ public function update($userId, $id, Google_Service_Gmail_Draft $postBody, $optParams = array())
125
+ {
126
+ $params = array('userId' => $userId, 'id' => $id, 'postBody' => $postBody);
127
+ $params = array_merge($params, $optParams);
128
+ return $this->call('update', array($params), "Google_Service_Gmail_Draft");
129
+ }
130
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersHistory.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ /**
19
+ * The "history" collection of methods.
20
+ * Typical usage is:
21
+ * <code>
22
+ * $gmailService = new Google_Service_Gmail(...);
23
+ * $history = $gmailService->history;
24
+ * </code>
25
+ */
26
+ class Google_Service_Gmail_Resource_UsersHistory extends Google_Service_Resource
27
+ {
28
+ /**
29
+ * Lists the history of all changes to the given mailbox. History results are
30
+ * returned in chronological order (increasing historyId).
31
+ * (history.listUsersHistory)
32
+ *
33
+ * @param string $userId The user's email address. The special value me can be
34
+ * used to indicate the authenticated user.
35
+ * @param array $optParams Optional parameters.
36
+ *
37
+ * @opt_param string historyTypes History types to be returned by the function
38
+ * @opt_param string labelId Only return messages with a label matching the ID.
39
+ * @opt_param string maxResults The maximum number of history records to return.
40
+ * @opt_param string pageToken Page token to retrieve a specific page of results
41
+ * in the list.
42
+ * @opt_param string startHistoryId Required. Returns history records after the
43
+ * specified startHistoryId. The supplied startHistoryId should be obtained from
44
+ * the historyId of a message, thread, or previous list response. History IDs
45
+ * increase chronologically but are not contiguous with random gaps in between
46
+ * valid IDs. Supplying an invalid or out of date startHistoryId typically
47
+ * returns an HTTP 404 error code. A historyId is typically valid for at least a
48
+ * week, but in some rare circumstances may be valid for only a few hours. If
49
+ * you receive an HTTP 404 error response, your application should perform a
50
+ * full sync. If you receive no nextPageToken in the response, there are no
51
+ * updates to retrieve and you can store the returned historyId for a future
52
+ * request.
53
+ * @return Google_Service_Gmail_ListHistoryResponse
54
+ */
55
+ public function listUsersHistory($userId, $optParams = array())
56
+ {
57
+ $params = array('userId' => $userId);
58
+ $params = array_merge($params, $optParams);
59
+ return $this->call('list', array($params), "Google_Service_Gmail_ListHistoryResponse");
60
+ }
61
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersLabels.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ /**
19
+ * The "labels" collection of methods.
20
+ * Typical usage is:
21
+ * <code>
22
+ * $gmailService = new Google_Service_Gmail(...);
23
+ * $labels = $gmailService->labels;
24
+ * </code>
25
+ */
26
+ class Google_Service_Gmail_Resource_UsersLabels extends Google_Service_Resource
27
+ {
28
+ /**
29
+ * Creates a new label. (labels.create)
30
+ *
31
+ * @param string $userId The user's email address. The special value me can be
32
+ * used to indicate the authenticated user.
33
+ * @param Google_Service_Gmail_Label $postBody
34
+ * @param array $optParams Optional parameters.
35
+ * @return Google_Service_Gmail_Label
36
+ */
37
+ public function create($userId, Google_Service_Gmail_Label $postBody, $optParams = array())
38
+ {
39
+ $params = array('userId' => $userId, 'postBody' => $postBody);
40
+ $params = array_merge($params, $optParams);
41
+ return $this->call('create', array($params), "Google_Service_Gmail_Label");
42
+ }
43
+ /**
44
+ * Immediately and permanently deletes the specified label and removes it from
45
+ * any messages and threads that it is applied to. (labels.delete)
46
+ *
47
+ * @param string $userId The user's email address. The special value me can be
48
+ * used to indicate the authenticated user.
49
+ * @param string $id The ID of the label to delete.
50
+ * @param array $optParams Optional parameters.
51
+ */
52
+ public function delete($userId, $id, $optParams = array())
53
+ {
54
+ $params = array('userId' => $userId, 'id' => $id);
55
+ $params = array_merge($params, $optParams);
56
+ return $this->call('delete', array($params));
57
+ }
58
+ /**
59
+ * Gets the specified label. (labels.get)
60
+ *
61
+ * @param string $userId The user's email address. The special value me can be
62
+ * used to indicate the authenticated user.
63
+ * @param string $id The ID of the label to retrieve.
64
+ * @param array $optParams Optional parameters.
65
+ * @return Google_Service_Gmail_Label
66
+ */
67
+ public function get($userId, $id, $optParams = array())
68
+ {
69
+ $params = array('userId' => $userId, 'id' => $id);
70
+ $params = array_merge($params, $optParams);
71
+ return $this->call('get', array($params), "Google_Service_Gmail_Label");
72
+ }
73
+ /**
74
+ * Lists all labels in the user's mailbox. (labels.listUsersLabels)
75
+ *
76
+ * @param string $userId The user's email address. The special value me can be
77
+ * used to indicate the authenticated user.
78
+ * @param array $optParams Optional parameters.
79
+ * @return Google_Service_Gmail_ListLabelsResponse
80
+ */
81
+ public function listUsersLabels($userId, $optParams = array())
82
+ {
83
+ $params = array('userId' => $userId);
84
+ $params = array_merge($params, $optParams);
85
+ return $this->call('list', array($params), "Google_Service_Gmail_ListLabelsResponse");
86
+ }
87
+ /**
88
+ * Updates the specified label. This method supports patch semantics.
89
+ * (labels.patch)
90
+ *
91
+ * @param string $userId The user's email address. The special value me can be
92
+ * used to indicate the authenticated user.
93
+ * @param string $id The ID of the label to update.
94
+ * @param Google_Service_Gmail_Label $postBody
95
+ * @param array $optParams Optional parameters.
96
+ * @return Google_Service_Gmail_Label
97
+ */
98
+ public function patch($userId, $id, Google_Service_Gmail_Label $postBody, $optParams = array())
99
+ {
100
+ $params = array('userId' => $userId, 'id' => $id, 'postBody' => $postBody);
101
+ $params = array_merge($params, $optParams);
102
+ return $this->call('patch', array($params), "Google_Service_Gmail_Label");
103
+ }
104
+ /**
105
+ * Updates the specified label. (labels.update)
106
+ *
107
+ * @param string $userId The user's email address. The special value me can be
108
+ * used to indicate the authenticated user.
109
+ * @param string $id The ID of the label to update.
110
+ * @param Google_Service_Gmail_Label $postBody
111
+ * @param array $optParams Optional parameters.
112
+ * @return Google_Service_Gmail_Label
113
+ */
114
+ public function update($userId, $id, Google_Service_Gmail_Label $postBody, $optParams = array())
115
+ {
116
+ $params = array('userId' => $userId, 'id' => $id, 'postBody' => $postBody);
117
+ $params = array_merge($params, $optParams);
118
+ return $this->call('update', array($params), "Google_Service_Gmail_Label");
119
+ }
120
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersMessages.php ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ /**
19
+ * The "messages" collection of methods.
20
+ * Typical usage is:
21
+ * <code>
22
+ * $gmailService = new Google_Service_Gmail(...);
23
+ * $messages = $gmailService->messages;
24
+ * </code>
25
+ */
26
+ class Google_Service_Gmail_Resource_UsersMessages extends Google_Service_Resource
27
+ {
28
+ /**
29
+ * Deletes many messages by message ID. Provides no guarantees that messages
30
+ * were not already deleted or even existed at all. (messages.batchDelete)
31
+ *
32
+ * @param string $userId The user's email address. The special value me can be
33
+ * used to indicate the authenticated user.
34
+ * @param Google_Service_Gmail_BatchDeleteMessagesRequest $postBody
35
+ * @param array $optParams Optional parameters.
36
+ */
37
+ public function batchDelete($userId, Google_Service_Gmail_BatchDeleteMessagesRequest $postBody, $optParams = array())
38
+ {
39
+ $params = array('userId' => $userId, 'postBody' => $postBody);
40
+ $params = array_merge($params, $optParams);
41
+ return $this->call('batchDelete', array($params));
42
+ }
43
+ /**
44
+ * Modifies the labels on the specified messages. (messages.batchModify)
45
+ *
46
+ * @param string $userId The user's email address. The special value me can be
47
+ * used to indicate the authenticated user.
48
+ * @param Google_Service_Gmail_BatchModifyMessagesRequest $postBody
49
+ * @param array $optParams Optional parameters.
50
+ */
51
+ public function batchModify($userId, Google_Service_Gmail_BatchModifyMessagesRequest $postBody, $optParams = array())
52
+ {
53
+ $params = array('userId' => $userId, 'postBody' => $postBody);
54
+ $params = array_merge($params, $optParams);
55
+ return $this->call('batchModify', array($params));
56
+ }
57
+ /**
58
+ * Immediately and permanently deletes the specified message. This operation
59
+ * cannot be undone. Prefer messages.trash instead. (messages.delete)
60
+ *
61
+ * @param string $userId The user's email address. The special value me can be
62
+ * used to indicate the authenticated user.
63
+ * @param string $id The ID of the message to delete.
64
+ * @param array $optParams Optional parameters.
65
+ */
66
+ public function delete($userId, $id, $optParams = array())
67
+ {
68
+ $params = array('userId' => $userId, 'id' => $id);
69
+ $params = array_merge($params, $optParams);
70
+ return $this->call('delete', array($params));
71
+ }
72
+ /**
73
+ * Gets the specified message. (messages.get)
74
+ *
75
+ * @param string $userId The user's email address. The special value me can be
76
+ * used to indicate the authenticated user.
77
+ * @param string $id The ID of the message to retrieve.
78
+ * @param array $optParams Optional parameters.
79
+ *
80
+ * @opt_param string format The format to return the message in.
81
+ * @opt_param string metadataHeaders When given and format is METADATA, only
82
+ * include headers specified.
83
+ * @return Google_Service_Gmail_Message
84
+ */
85
+ public function get($userId, $id, $optParams = array())
86
+ {
87
+ $params = array('userId' => $userId, 'id' => $id);
88
+ $params = array_merge($params, $optParams);
89
+ return $this->call('get', array($params), "Google_Service_Gmail_Message");
90
+ }
91
+ /**
92
+ * Imports a message into only this user's mailbox, with standard email delivery
93
+ * scanning and classification similar to receiving via SMTP. Does not send a
94
+ * message. (messages.import)
95
+ *
96
+ * @param string $userId The user's email address. The special value me can be
97
+ * used to indicate the authenticated user.
98
+ * @param Google_Service_Gmail_Message $postBody
99
+ * @param array $optParams Optional parameters.
100
+ *
101
+ * @opt_param bool deleted Mark the email as permanently deleted (not TRASH) and
102
+ * only visible in Google Vault to a Vault administrator. Only used for G Suite
103
+ * accounts.
104
+ * @opt_param string internalDateSource Source for Gmail's internal date of the
105
+ * message.
106
+ * @opt_param bool neverMarkSpam Ignore the Gmail spam classifier decision and
107
+ * never mark this email as SPAM in the mailbox.
108
+ * @opt_param bool processForCalendar Process calendar invites in the email and
109
+ * add any extracted meetings to the Google Calendar for this user.
110
+ * @return Google_Service_Gmail_Message
111
+ */
112
+ public function import($userId, Google_Service_Gmail_Message $postBody, $optParams = array())
113
+ {
114
+ $params = array('userId' => $userId, 'postBody' => $postBody);
115
+ $params = array_merge($params, $optParams);
116
+ return $this->call('import', array($params), "Google_Service_Gmail_Message");
117
+ }
118
+ /**
119
+ * Directly inserts a message into only this user's mailbox similar to IMAP
120
+ * APPEND, bypassing most scanning and classification. Does not send a message.
121
+ * (messages.insert)
122
+ *
123
+ * @param string $userId The user's email address. The special value me can be
124
+ * used to indicate the authenticated user.
125
+ * @param Google_Service_Gmail_Message $postBody
126
+ * @param array $optParams Optional parameters.
127
+ *
128
+ * @opt_param bool deleted Mark the email as permanently deleted (not TRASH) and
129
+ * only visible in Google Vault to a Vault administrator. Only used for G Suite
130
+ * accounts.
131
+ * @opt_param string internalDateSource Source for Gmail's internal date of the
132
+ * message.
133
+ * @return Google_Service_Gmail_Message
134
+ */
135
+ public function insert($userId, Google_Service_Gmail_Message $postBody, $optParams = array())
136
+ {
137
+ $params = array('userId' => $userId, 'postBody' => $postBody);
138
+ $params = array_merge($params, $optParams);
139
+ return $this->call('insert', array($params), "Google_Service_Gmail_Message");
140
+ }
141
+ /**
142
+ * Lists the messages in the user's mailbox. (messages.listUsersMessages)
143
+ *
144
+ * @param string $userId The user's email address. The special value me can be
145
+ * used to indicate the authenticated user.
146
+ * @param array $optParams Optional parameters.
147
+ *
148
+ * @opt_param bool includeSpamTrash Include messages from SPAM and TRASH in the
149
+ * results.
150
+ * @opt_param string labelIds Only return messages with labels that match all of
151
+ * the specified label IDs.
152
+ * @opt_param string maxResults Maximum number of messages to return.
153
+ * @opt_param string pageToken Page token to retrieve a specific page of results
154
+ * in the list.
155
+ * @opt_param string q Only return messages matching the specified query.
156
+ * Supports the same query format as the Gmail search box. For example,
157
+ * "from:someuser@example.com rfc822msgid: is:unread". Parameter cannot be used
158
+ * when accessing the api using the gmail.metadata scope.
159
+ * @return Google_Service_Gmail_ListMessagesResponse
160
+ */
161
+ public function listUsersMessages($userId, $optParams = array())
162
+ {
163
+ $params = array('userId' => $userId);
164
+ $params = array_merge($params, $optParams);
165
+ return $this->call('list', array($params), "Google_Service_Gmail_ListMessagesResponse");
166
+ }
167
+ /**
168
+ * Modifies the labels on the specified message. (messages.modify)
169
+ *
170
+ * @param string $userId The user's email address. The special value me can be
171
+ * used to indicate the authenticated user.
172
+ * @param string $id The ID of the message to modify.
173
+ * @param Google_Service_Gmail_ModifyMessageRequest $postBody
174
+ * @param array $optParams Optional parameters.
175
+ * @return Google_Service_Gmail_Message
176
+ */
177
+ public function modify($userId, $id, Google_Service_Gmail_ModifyMessageRequest $postBody, $optParams = array())
178
+ {
179
+ $params = array('userId' => $userId, 'id' => $id, 'postBody' => $postBody);
180
+ $params = array_merge($params, $optParams);
181
+ return $this->call('modify', array($params), "Google_Service_Gmail_Message");
182
+ }
183
+ /**
184
+ * Sends the specified message to the recipients in the To, Cc, and Bcc headers.
185
+ * (messages.send)
186
+ *
187
+ * @param string $userId The user's email address. The special value me can be
188
+ * used to indicate the authenticated user.
189
+ * @param Google_Service_Gmail_Message $postBody
190
+ * @param array $optParams Optional parameters.
191
+ * @return Google_Service_Gmail_Message
192
+ */
193
+ public function send($userId, Google_Service_Gmail_Message $postBody, $optParams = array())
194
+ {
195
+ $params = array('userId' => $userId, 'postBody' => $postBody);
196
+ $params = array_merge($params, $optParams);
197
+ return $this->call('send', array($params), "Google_Service_Gmail_Message");
198
+ }
199
+ /**
200
+ * Moves the specified message to the trash. (messages.trash)
201
+ *
202
+ * @param string $userId The user's email address. The special value me can be
203
+ * used to indicate the authenticated user.
204
+ * @param string $id The ID of the message to Trash.
205
+ * @param array $optParams Optional parameters.
206
+ * @return Google_Service_Gmail_Message
207
+ */
208
+ public function trash($userId, $id, $optParams = array())
209
+ {
210
+ $params = array('userId' => $userId, 'id' => $id);
211
+ $params = array_merge($params, $optParams);
212
+ return $this->call('trash', array($params), "Google_Service_Gmail_Message");
213
+ }
214
+ /**
215
+ * Removes the specified message from the trash. (messages.untrash)
216
+ *
217
+ * @param string $userId The user's email address. The special value me can be
218
+ * used to indicate the authenticated user.
219
+ * @param string $id The ID of the message to remove from Trash.
220
+ * @param array $optParams Optional parameters.
221
+ * @return Google_Service_Gmail_Message
222
+ */
223
+ public function untrash($userId, $id, $optParams = array())
224
+ {
225
+ $params = array('userId' => $userId, 'id' => $id);
226
+ $params = array_merge($params, $optParams);
227
+ return $this->call('untrash', array($params), "Google_Service_Gmail_Message");
228
+ }
229
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersMessagesAttachments.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ /**
19
+ * The "attachments" collection of methods.
20
+ * Typical usage is:
21
+ * <code>
22
+ * $gmailService = new Google_Service_Gmail(...);
23
+ * $attachments = $gmailService->attachments;
24
+ * </code>
25
+ */
26
+ class Google_Service_Gmail_Resource_UsersMessagesAttachments extends Google_Service_Resource
27
+ {
28
+ /**
29
+ * Gets the specified message attachment. (attachments.get)
30
+ *
31
+ * @param string $userId The user's email address. The special value me can be
32
+ * used to indicate the authenticated user.
33
+ * @param string $messageId The ID of the message containing the attachment.
34
+ * @param string $id The ID of the attachment.
35
+ * @param array $optParams Optional parameters.
36
+ * @return Google_Service_Gmail_MessagePartBody
37
+ */
38
+ public function get($userId, $messageId, $id, $optParams = array())
39
+ {
40
+ $params = array('userId' => $userId, 'messageId' => $messageId, 'id' => $id);
41
+ $params = array_merge($params, $optParams);
42
+ return $this->call('get', array($params), "Google_Service_Gmail_MessagePartBody");
43
+ }
44
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettings.php ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ /**
19
+ * The "settings" collection of methods.
20
+ * Typical usage is:
21
+ * <code>
22
+ * $gmailService = new Google_Service_Gmail(...);
23
+ * $settings = $gmailService->settings;
24
+ * </code>
25
+ */
26
+ class Google_Service_Gmail_Resource_UsersSettings extends Google_Service_Resource
27
+ {
28
+ /**
29
+ * Gets the auto-forwarding setting for the specified account.
30
+ * (settings.getAutoForwarding)
31
+ *
32
+ * @param string $userId User's email address. The special value "me" can be
33
+ * used to indicate the authenticated user.
34
+ * @param array $optParams Optional parameters.
35
+ * @return Google_Service_Gmail_AutoForwarding
36
+ */
37
+ public function getAutoForwarding($userId, $optParams = array())
38
+ {
39
+ $params = array('userId' => $userId);
40
+ $params = array_merge($params, $optParams);
41
+ return $this->call('getAutoForwarding', array($params), "Google_Service_Gmail_AutoForwarding");
42
+ }
43
+ /**
44
+ * Gets IMAP settings. (settings.getImap)
45
+ *
46
+ * @param string $userId User's email address. The special value "me" can be
47
+ * used to indicate the authenticated user.
48
+ * @param array $optParams Optional parameters.
49
+ * @return Google_Service_Gmail_ImapSettings
50
+ */
51
+ public function getImap($userId, $optParams = array())
52
+ {
53
+ $params = array('userId' => $userId);
54
+ $params = array_merge($params, $optParams);
55
+ return $this->call('getImap', array($params), "Google_Service_Gmail_ImapSettings");
56
+ }
57
+ /**
58
+ * Gets POP settings. (settings.getPop)
59
+ *
60
+ * @param string $userId User's email address. The special value "me" can be
61
+ * used to indicate the authenticated user.
62
+ * @param array $optParams Optional parameters.
63
+ * @return Google_Service_Gmail_PopSettings
64
+ */
65
+ public function getPop($userId, $optParams = array())
66
+ {
67
+ $params = array('userId' => $userId);
68
+ $params = array_merge($params, $optParams);
69
+ return $this->call('getPop', array($params), "Google_Service_Gmail_PopSettings");
70
+ }
71
+ /**
72
+ * Gets vacation responder settings. (settings.getVacation)
73
+ *
74
+ * @param string $userId User's email address. The special value "me" can be
75
+ * used to indicate the authenticated user.
76
+ * @param array $optParams Optional parameters.
77
+ * @return Google_Service_Gmail_VacationSettings
78
+ */
79
+ public function getVacation($userId, $optParams = array())
80
+ {
81
+ $params = array('userId' => $userId);
82
+ $params = array_merge($params, $optParams);
83
+ return $this->call('getVacation', array($params), "Google_Service_Gmail_VacationSettings");
84
+ }
85
+ /**
86
+ * Updates the auto-forwarding setting for the specified account. A verified
87
+ * forwarding address must be specified when auto-forwarding is enabled.
88
+ *
89
+ * This method is only available to service account clients that have been
90
+ * delegated domain-wide authority. (settings.updateAutoForwarding)
91
+ *
92
+ * @param string $userId User's email address. The special value "me" can be
93
+ * used to indicate the authenticated user.
94
+ * @param Google_Service_Gmail_AutoForwarding $postBody
95
+ * @param array $optParams Optional parameters.
96
+ * @return Google_Service_Gmail_AutoForwarding
97
+ */
98
+ public function updateAutoForwarding($userId, Google_Service_Gmail_AutoForwarding $postBody, $optParams = array())
99
+ {
100
+ $params = array('userId' => $userId, 'postBody' => $postBody);
101
+ $params = array_merge($params, $optParams);
102
+ return $this->call('updateAutoForwarding', array($params), "Google_Service_Gmail_AutoForwarding");
103
+ }
104
+ /**
105
+ * Updates IMAP settings. (settings.updateImap)
106
+ *
107
+ * @param string $userId User's email address. The special value "me" can be
108
+ * used to indicate the authenticated user.
109
+ * @param Google_Service_Gmail_ImapSettings $postBody
110
+ * @param array $optParams Optional parameters.
111
+ * @return Google_Service_Gmail_ImapSettings
112
+ */
113
+ public function updateImap($userId, Google_Service_Gmail_ImapSettings $postBody, $optParams = array())
114
+ {
115
+ $params = array('userId' => $userId, 'postBody' => $postBody);
116
+ $params = array_merge($params, $optParams);
117
+ return $this->call('updateImap', array($params), "Google_Service_Gmail_ImapSettings");
118
+ }
119
+ /**
120
+ * Updates POP settings. (settings.updatePop)
121
+ *
122
+ * @param string $userId User's email address. The special value "me" can be
123
+ * used to indicate the authenticated user.
124
+ * @param Google_Service_Gmail_PopSettings $postBody
125
+ * @param array $optParams Optional parameters.
126
+ * @return Google_Service_Gmail_PopSettings
127
+ */
128
+ public function updatePop($userId, Google_Service_Gmail_PopSettings $postBody, $optParams = array())
129
+ {
130
+ $params = array('userId' => $userId, 'postBody' => $postBody);
131
+ $params = array_merge($params, $optParams);
132
+ return $this->call('updatePop', array($params), "Google_Service_Gmail_PopSettings");
133
+ }
134
+ /**
135
+ * Updates vacation responder settings. (settings.updateVacation)
136
+ *
137
+ * @param string $userId User's email address. The special value "me" can be
138
+ * used to indicate the authenticated user.
139
+ * @param Google_Service_Gmail_VacationSettings $postBody
140
+ * @param array $optParams Optional parameters.
141
+ * @return Google_Service_Gmail_VacationSettings
142
+ */
143
+ public function updateVacation($userId, Google_Service_Gmail_VacationSettings $postBody, $optParams = array())
144
+ {
145
+ $params = array('userId' => $userId, 'postBody' => $postBody);
146
+ $params = array_merge($params, $optParams);
147
+ return $this->call('updateVacation', array($params), "Google_Service_Gmail_VacationSettings");
148
+ }
149
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsFilters.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ /**
19
+ * The "filters" collection of methods.
20
+ * Typical usage is:
21
+ * <code>
22
+ * $gmailService = new Google_Service_Gmail(...);
23
+ * $filters = $gmailService->filters;
24
+ * </code>
25
+ */
26
+ class Google_Service_Gmail_Resource_UsersSettingsFilters extends Google_Service_Resource
27
+ {
28
+ /**
29
+ * Creates a filter. (filters.create)
30
+ *
31
+ * @param string $userId User's email address. The special value "me" can be
32
+ * used to indicate the authenticated user.
33
+ * @param Google_Service_Gmail_Filter $postBody
34
+ * @param array $optParams Optional parameters.
35
+ * @return Google_Service_Gmail_Filter
36
+ */
37
+ public function create($userId, Google_Service_Gmail_Filter $postBody, $optParams = array())
38
+ {
39
+ $params = array('userId' => $userId, 'postBody' => $postBody);
40
+ $params = array_merge($params, $optParams);
41
+ return $this->call('create', array($params), "Google_Service_Gmail_Filter");
42
+ }
43
+ /**
44
+ * Deletes a filter. (filters.delete)
45
+ *
46
+ * @param string $userId User's email address. The special value "me" can be
47
+ * used to indicate the authenticated user.
48
+ * @param string $id The ID of the filter to be deleted.
49
+ * @param array $optParams Optional parameters.
50
+ */
51
+ public function delete($userId, $id, $optParams = array())
52
+ {
53
+ $params = array('userId' => $userId, 'id' => $id);
54
+ $params = array_merge($params, $optParams);
55
+ return $this->call('delete', array($params));
56
+ }
57
+ /**
58
+ * Gets a filter. (filters.get)
59
+ *
60
+ * @param string $userId User's email address. The special value "me" can be
61
+ * used to indicate the authenticated user.
62
+ * @param string $id The ID of the filter to be fetched.
63
+ * @param array $optParams Optional parameters.
64
+ * @return Google_Service_Gmail_Filter
65
+ */
66
+ public function get($userId, $id, $optParams = array())
67
+ {
68
+ $params = array('userId' => $userId, 'id' => $id);
69
+ $params = array_merge($params, $optParams);
70
+ return $this->call('get', array($params), "Google_Service_Gmail_Filter");
71
+ }
72
+ /**
73
+ * Lists the message filters of a Gmail user. (filters.listUsersSettingsFilters)
74
+ *
75
+ * @param string $userId User's email address. The special value "me" can be
76
+ * used to indicate the authenticated user.
77
+ * @param array $optParams Optional parameters.
78
+ * @return Google_Service_Gmail_ListFiltersResponse
79
+ */
80
+ public function listUsersSettingsFilters($userId, $optParams = array())
81
+ {
82
+ $params = array('userId' => $userId);
83
+ $params = array_merge($params, $optParams);
84
+ return $this->call('list', array($params), "Google_Service_Gmail_ListFiltersResponse");
85
+ }
86
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsForwardingAddresses.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ /**
19
+ * The "forwardingAddresses" collection of methods.
20
+ * Typical usage is:
21
+ * <code>
22
+ * $gmailService = new Google_Service_Gmail(...);
23
+ * $forwardingAddresses = $gmailService->forwardingAddresses;
24
+ * </code>
25
+ */
26
+ class Google_Service_Gmail_Resource_UsersSettingsForwardingAddresses extends Google_Service_Resource
27
+ {
28
+ /**
29
+ * Creates a forwarding address. If ownership verification is required, a
30
+ * message will be sent to the recipient and the resource's verification status
31
+ * will be set to pending; otherwise, the resource will be created with
32
+ * verification status set to accepted.
33
+ *
34
+ * This method is only available to service account clients that have been
35
+ * delegated domain-wide authority. (forwardingAddresses.create)
36
+ *
37
+ * @param string $userId User's email address. The special value "me" can be
38
+ * used to indicate the authenticated user.
39
+ * @param Google_Service_Gmail_ForwardingAddress $postBody
40
+ * @param array $optParams Optional parameters.
41
+ * @return Google_Service_Gmail_ForwardingAddress
42
+ */
43
+ public function create($userId, Google_Service_Gmail_ForwardingAddress $postBody, $optParams = array())
44
+ {
45
+ $params = array('userId' => $userId, 'postBody' => $postBody);
46
+ $params = array_merge($params, $optParams);
47
+ return $this->call('create', array($params), "Google_Service_Gmail_ForwardingAddress");
48
+ }
49
+ /**
50
+ * Deletes the specified forwarding address and revokes any verification that
51
+ * may have been required.
52
+ *
53
+ * This method is only available to service account clients that have been
54
+ * delegated domain-wide authority. (forwardingAddresses.delete)
55
+ *
56
+ * @param string $userId User's email address. The special value "me" can be
57
+ * used to indicate the authenticated user.
58
+ * @param string $forwardingEmail The forwarding address to be deleted.
59
+ * @param array $optParams Optional parameters.
60
+ */
61
+ public function delete($userId, $forwardingEmail, $optParams = array())
62
+ {
63
+ $params = array('userId' => $userId, 'forwardingEmail' => $forwardingEmail);
64
+ $params = array_merge($params, $optParams);
65
+ return $this->call('delete', array($params));
66
+ }
67
+ /**
68
+ * Gets the specified forwarding address. (forwardingAddresses.get)
69
+ *
70
+ * @param string $userId User's email address. The special value "me" can be
71
+ * used to indicate the authenticated user.
72
+ * @param string $forwardingEmail The forwarding address to be retrieved.
73
+ * @param array $optParams Optional parameters.
74
+ * @return Google_Service_Gmail_ForwardingAddress
75
+ */
76
+ public function get($userId, $forwardingEmail, $optParams = array())
77
+ {
78
+ $params = array('userId' => $userId, 'forwardingEmail' => $forwardingEmail);
79
+ $params = array_merge($params, $optParams);
80
+ return $this->call('get', array($params), "Google_Service_Gmail_ForwardingAddress");
81
+ }
82
+ /**
83
+ * Lists the forwarding addresses for the specified account.
84
+ * (forwardingAddresses.listUsersSettingsForwardingAddresses)
85
+ *
86
+ * @param string $userId User's email address. The special value "me" can be
87
+ * used to indicate the authenticated user.
88
+ * @param array $optParams Optional parameters.
89
+ * @return Google_Service_Gmail_ListForwardingAddressesResponse
90
+ */
91
+ public function listUsersSettingsForwardingAddresses($userId, $optParams = array())
92
+ {
93
+ $params = array('userId' => $userId);
94
+ $params = array_merge($params, $optParams);
95
+ return $this->call('list', array($params), "Google_Service_Gmail_ListForwardingAddressesResponse");
96
+ }
97
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsSendAs.php ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ /**
19
+ * The "sendAs" collection of methods.
20
+ * Typical usage is:
21
+ * <code>
22
+ * $gmailService = new Google_Service_Gmail(...);
23
+ * $sendAs = $gmailService->sendAs;
24
+ * </code>
25
+ */
26
+ class Google_Service_Gmail_Resource_UsersSettingsSendAs extends Google_Service_Resource
27
+ {
28
+ /**
29
+ * Creates a custom "from" send-as alias. If an SMTP MSA is specified, Gmail
30
+ * will attempt to connect to the SMTP service to validate the configuration
31
+ * before creating the alias. If ownership verification is required for the
32
+ * alias, a message will be sent to the email address and the resource's
33
+ * verification status will be set to pending; otherwise, the resource will be
34
+ * created with verification status set to accepted. If a signature is provided,
35
+ * Gmail will sanitize the HTML before saving it with the alias.
36
+ *
37
+ * This method is only available to service account clients that have been
38
+ * delegated domain-wide authority. (sendAs.create)
39
+ *
40
+ * @param string $userId User's email address. The special value "me" can be
41
+ * used to indicate the authenticated user.
42
+ * @param Google_Service_Gmail_SendAs $postBody
43
+ * @param array $optParams Optional parameters.
44
+ * @return Google_Service_Gmail_SendAs
45
+ */
46
+ public function create($userId, Google_Service_Gmail_SendAs $postBody, $optParams = array())
47
+ {
48
+ $params = array('userId' => $userId, 'postBody' => $postBody);
49
+ $params = array_merge($params, $optParams);
50
+ return $this->call('create', array($params), "Google_Service_Gmail_SendAs");
51
+ }
52
+ /**
53
+ * Deletes the specified send-as alias. Revokes any verification that may have
54
+ * been required for using it.
55
+ *
56
+ * This method is only available to service account clients that have been
57
+ * delegated domain-wide authority. (sendAs.delete)
58
+ *
59
+ * @param string $userId User's email address. The special value "me" can be
60
+ * used to indicate the authenticated user.
61
+ * @param string $sendAsEmail The send-as alias to be deleted.
62
+ * @param array $optParams Optional parameters.
63
+ */
64
+ public function delete($userId, $sendAsEmail, $optParams = array())
65
+ {
66
+ $params = array('userId' => $userId, 'sendAsEmail' => $sendAsEmail);
67
+ $params = array_merge($params, $optParams);
68
+ return $this->call('delete', array($params));
69
+ }
70
+ /**
71
+ * Gets the specified send-as alias. Fails with an HTTP 404 error if the
72
+ * specified address is not a member of the collection. (sendAs.get)
73
+ *
74
+ * @param string $userId User's email address. The special value "me" can be
75
+ * used to indicate the authenticated user.
76
+ * @param string $sendAsEmail The send-as alias to be retrieved.
77
+ * @param array $optParams Optional parameters.
78
+ * @return Google_Service_Gmail_SendAs
79
+ */
80
+ public function get($userId, $sendAsEmail, $optParams = array())
81
+ {
82
+ $params = array('userId' => $userId, 'sendAsEmail' => $sendAsEmail);
83
+ $params = array_merge($params, $optParams);
84
+ return $this->call('get', array($params), "Google_Service_Gmail_SendAs");
85
+ }
86
+ /**
87
+ * Lists the send-as aliases for the specified account. The result includes the
88
+ * primary send-as address associated with the account as well as any custom
89
+ * "from" aliases. (sendAs.listUsersSettingsSendAs)
90
+ *
91
+ * @param string $userId User's email address. The special value "me" can be
92
+ * used to indicate the authenticated user.
93
+ * @param array $optParams Optional parameters.
94
+ * @return Google_Service_Gmail_ListSendAsResponse
95
+ */
96
+ public function listUsersSettingsSendAs($userId, $optParams = array())
97
+ {
98
+ $params = array('userId' => $userId);
99
+ $params = array_merge($params, $optParams);
100
+ return $this->call('list', array($params), "Google_Service_Gmail_ListSendAsResponse");
101
+ }
102
+ /**
103
+ * Updates a send-as alias. If a signature is provided, Gmail will sanitize the
104
+ * HTML before saving it with the alias.
105
+ *
106
+ * Addresses other than the primary address for the account can only be updated
107
+ * by service account clients that have been delegated domain-wide authority.
108
+ * This method supports patch semantics. (sendAs.patch)
109
+ *
110
+ * @param string $userId User's email address. The special value "me" can be
111
+ * used to indicate the authenticated user.
112
+ * @param string $sendAsEmail The send-as alias to be updated.
113
+ * @param Google_Service_Gmail_SendAs $postBody
114
+ * @param array $optParams Optional parameters.
115
+ * @return Google_Service_Gmail_SendAs
116
+ */
117
+ public function patch($userId, $sendAsEmail, Google_Service_Gmail_SendAs $postBody, $optParams = array())
118
+ {
119
+ $params = array('userId' => $userId, 'sendAsEmail' => $sendAsEmail, 'postBody' => $postBody);
120
+ $params = array_merge($params, $optParams);
121
+ return $this->call('patch', array($params), "Google_Service_Gmail_SendAs");
122
+ }
123
+ /**
124
+ * Updates a send-as alias. If a signature is provided, Gmail will sanitize the
125
+ * HTML before saving it with the alias.
126
+ *
127
+ * Addresses other than the primary address for the account can only be updated
128
+ * by service account clients that have been delegated domain-wide authority.
129
+ * (sendAs.update)
130
+ *
131
+ * @param string $userId User's email address. The special value "me" can be
132
+ * used to indicate the authenticated user.
133
+ * @param string $sendAsEmail The send-as alias to be updated.
134
+ * @param Google_Service_Gmail_SendAs $postBody
135
+ * @param array $optParams Optional parameters.
136
+ * @return Google_Service_Gmail_SendAs
137
+ */
138
+ public function update($userId, $sendAsEmail, Google_Service_Gmail_SendAs $postBody, $optParams = array())
139
+ {
140
+ $params = array('userId' => $userId, 'sendAsEmail' => $sendAsEmail, 'postBody' => $postBody);
141
+ $params = array_merge($params, $optParams);
142
+ return $this->call('update', array($params), "Google_Service_Gmail_SendAs");
143
+ }
144
+ /**
145
+ * Sends a verification email to the specified send-as alias address. The
146
+ * verification status must be pending.
147
+ *
148
+ * This method is only available to service account clients that have been
149
+ * delegated domain-wide authority. (sendAs.verify)
150
+ *
151
+ * @param string $userId User's email address. The special value "me" can be
152
+ * used to indicate the authenticated user.
153
+ * @param string $sendAsEmail The send-as alias to be verified.
154
+ * @param array $optParams Optional parameters.
155
+ */
156
+ public function verify($userId, $sendAsEmail, $optParams = array())
157
+ {
158
+ $params = array('userId' => $userId, 'sendAsEmail' => $sendAsEmail);
159
+ $params = array_merge($params, $optParams);
160
+ return $this->call('verify', array($params));
161
+ }
162
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersSettingsSendAsSmimeInfo.php ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ /**
19
+ * The "smimeInfo" collection of methods.
20
+ * Typical usage is:
21
+ * <code>
22
+ * $gmailService = new Google_Service_Gmail(...);
23
+ * $smimeInfo = $gmailService->smimeInfo;
24
+ * </code>
25
+ */
26
+ class Google_Service_Gmail_Resource_UsersSettingsSendAsSmimeInfo extends Google_Service_Resource
27
+ {
28
+ /**
29
+ * Deletes the specified S/MIME config for the specified send-as alias.
30
+ * (smimeInfo.delete)
31
+ *
32
+ * @param string $userId The user's email address. The special value me can be
33
+ * used to indicate the authenticated user.
34
+ * @param string $sendAsEmail The email address that appears in the "From:"
35
+ * header for mail sent using this alias.
36
+ * @param string $id The immutable ID for the SmimeInfo.
37
+ * @param array $optParams Optional parameters.
38
+ */
39
+ public function delete($userId, $sendAsEmail, $id, $optParams = array())
40
+ {
41
+ $params = array('userId' => $userId, 'sendAsEmail' => $sendAsEmail, 'id' => $id);
42
+ $params = array_merge($params, $optParams);
43
+ return $this->call('delete', array($params));
44
+ }
45
+ /**
46
+ * Gets the specified S/MIME config for the specified send-as alias.
47
+ * (smimeInfo.get)
48
+ *
49
+ * @param string $userId The user's email address. The special value me can be
50
+ * used to indicate the authenticated user.
51
+ * @param string $sendAsEmail The email address that appears in the "From:"
52
+ * header for mail sent using this alias.
53
+ * @param string $id The immutable ID for the SmimeInfo.
54
+ * @param array $optParams Optional parameters.
55
+ * @return Google_Service_Gmail_SmimeInfo
56
+ */
57
+ public function get($userId, $sendAsEmail, $id, $optParams = array())
58
+ {
59
+ $params = array('userId' => $userId, 'sendAsEmail' => $sendAsEmail, 'id' => $id);
60
+ $params = array_merge($params, $optParams);
61
+ return $this->call('get', array($params), "Google_Service_Gmail_SmimeInfo");
62
+ }
63
+ /**
64
+ * Insert (upload) the given S/MIME config for the specified send-as alias. Note
65
+ * that pkcs12 format is required for the key. (smimeInfo.insert)
66
+ *
67
+ * @param string $userId The user's email address. The special value me can be
68
+ * used to indicate the authenticated user.
69
+ * @param string $sendAsEmail The email address that appears in the "From:"
70
+ * header for mail sent using this alias.
71
+ * @param Google_Service_Gmail_SmimeInfo $postBody
72
+ * @param array $optParams Optional parameters.
73
+ * @return Google_Service_Gmail_SmimeInfo
74
+ */
75
+ public function insert($userId, $sendAsEmail, Google_Service_Gmail_SmimeInfo $postBody, $optParams = array())
76
+ {
77
+ $params = array('userId' => $userId, 'sendAsEmail' => $sendAsEmail, 'postBody' => $postBody);
78
+ $params = array_merge($params, $optParams);
79
+ return $this->call('insert', array($params), "Google_Service_Gmail_SmimeInfo");
80
+ }
81
+ /**
82
+ * Lists S/MIME configs for the specified send-as alias.
83
+ * (smimeInfo.listUsersSettingsSendAsSmimeInfo)
84
+ *
85
+ * @param string $userId The user's email address. The special value me can be
86
+ * used to indicate the authenticated user.
87
+ * @param string $sendAsEmail The email address that appears in the "From:"
88
+ * header for mail sent using this alias.
89
+ * @param array $optParams Optional parameters.
90
+ * @return Google_Service_Gmail_ListSmimeInfoResponse
91
+ */
92
+ public function listUsersSettingsSendAsSmimeInfo($userId, $sendAsEmail, $optParams = array())
93
+ {
94
+ $params = array('userId' => $userId, 'sendAsEmail' => $sendAsEmail);
95
+ $params = array_merge($params, $optParams);
96
+ return $this->call('list', array($params), "Google_Service_Gmail_ListSmimeInfoResponse");
97
+ }
98
+ /**
99
+ * Sets the default S/MIME config for the specified send-as alias.
100
+ * (smimeInfo.setDefault)
101
+ *
102
+ * @param string $userId The user's email address. The special value me can be
103
+ * used to indicate the authenticated user.
104
+ * @param string $sendAsEmail The email address that appears in the "From:"
105
+ * header for mail sent using this alias.
106
+ * @param string $id The immutable ID for the SmimeInfo.
107
+ * @param array $optParams Optional parameters.
108
+ */
109
+ public function setDefault($userId, $sendAsEmail, $id, $optParams = array())
110
+ {
111
+ $params = array('userId' => $userId, 'sendAsEmail' => $sendAsEmail, 'id' => $id);
112
+ $params = array_merge($params, $optParams);
113
+ return $this->call('setDefault', array($params));
114
+ }
115
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Resource/UsersThreads.php ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ /**
19
+ * The "threads" collection of methods.
20
+ * Typical usage is:
21
+ * <code>
22
+ * $gmailService = new Google_Service_Gmail(...);
23
+ * $threads = $gmailService->threads;
24
+ * </code>
25
+ */
26
+ class Google_Service_Gmail_Resource_UsersThreads extends Google_Service_Resource
27
+ {
28
+ /**
29
+ * Immediately and permanently deletes the specified thread. This operation
30
+ * cannot be undone. Prefer threads.trash instead. (threads.delete)
31
+ *
32
+ * @param string $userId The user's email address. The special value me can be
33
+ * used to indicate the authenticated user.
34
+ * @param string $id ID of the Thread to delete.
35
+ * @param array $optParams Optional parameters.
36
+ */
37
+ public function delete($userId, $id, $optParams = array())
38
+ {
39
+ $params = array('userId' => $userId, 'id' => $id);
40
+ $params = array_merge($params, $optParams);
41
+ return $this->call('delete', array($params));
42
+ }
43
+ /**
44
+ * Gets the specified thread. (threads.get)
45
+ *
46
+ * @param string $userId The user's email address. The special value me can be
47
+ * used to indicate the authenticated user.
48
+ * @param string $id The ID of the thread to retrieve.
49
+ * @param array $optParams Optional parameters.
50
+ *
51
+ * @opt_param string format The format to return the messages in.
52
+ * @opt_param string metadataHeaders When given and format is METADATA, only
53
+ * include headers specified.
54
+ * @return Google_Service_Gmail_Thread
55
+ */
56
+ public function get($userId, $id, $optParams = array())
57
+ {
58
+ $params = array('userId' => $userId, 'id' => $id);
59
+ $params = array_merge($params, $optParams);
60
+ return $this->call('get', array($params), "Google_Service_Gmail_Thread");
61
+ }
62
+ /**
63
+ * Lists the threads in the user's mailbox. (threads.listUsersThreads)
64
+ *
65
+ * @param string $userId The user's email address. The special value me can be
66
+ * used to indicate the authenticated user.
67
+ * @param array $optParams Optional parameters.
68
+ *
69
+ * @opt_param bool includeSpamTrash Include threads from SPAM and TRASH in the
70
+ * results.
71
+ * @opt_param string labelIds Only return threads with labels that match all of
72
+ * the specified label IDs.
73
+ * @opt_param string maxResults Maximum number of threads to return.
74
+ * @opt_param string pageToken Page token to retrieve a specific page of results
75
+ * in the list.
76
+ * @opt_param string q Only return threads matching the specified query.
77
+ * Supports the same query format as the Gmail search box. For example,
78
+ * "from:someuser@example.com rfc822msgid: is:unread". Parameter cannot be used
79
+ * when accessing the api using the gmail.metadata scope.
80
+ * @return Google_Service_Gmail_ListThreadsResponse
81
+ */
82
+ public function listUsersThreads($userId, $optParams = array())
83
+ {
84
+ $params = array('userId' => $userId);
85
+ $params = array_merge($params, $optParams);
86
+ return $this->call('list', array($params), "Google_Service_Gmail_ListThreadsResponse");
87
+ }
88
+ /**
89
+ * Modifies the labels applied to the thread. This applies to all messages in
90
+ * the thread. (threads.modify)
91
+ *
92
+ * @param string $userId The user's email address. The special value me can be
93
+ * used to indicate the authenticated user.
94
+ * @param string $id The ID of the thread to modify.
95
+ * @param Google_Service_Gmail_ModifyThreadRequest $postBody
96
+ * @param array $optParams Optional parameters.
97
+ * @return Google_Service_Gmail_Thread
98
+ */
99
+ public function modify($userId, $id, Google_Service_Gmail_ModifyThreadRequest $postBody, $optParams = array())
100
+ {
101
+ $params = array('userId' => $userId, 'id' => $id, 'postBody' => $postBody);
102
+ $params = array_merge($params, $optParams);
103
+ return $this->call('modify', array($params), "Google_Service_Gmail_Thread");
104
+ }
105
+ /**
106
+ * Moves the specified thread to the trash. (threads.trash)
107
+ *
108
+ * @param string $userId The user's email address. The special value me can be
109
+ * used to indicate the authenticated user.
110
+ * @param string $id The ID of the thread to Trash.
111
+ * @param array $optParams Optional parameters.
112
+ * @return Google_Service_Gmail_Thread
113
+ */
114
+ public function trash($userId, $id, $optParams = array())
115
+ {
116
+ $params = array('userId' => $userId, 'id' => $id);
117
+ $params = array_merge($params, $optParams);
118
+ return $this->call('trash', array($params), "Google_Service_Gmail_Thread");
119
+ }
120
+ /**
121
+ * Removes the specified thread from the trash. (threads.untrash)
122
+ *
123
+ * @param string $userId The user's email address. The special value me can be
124
+ * used to indicate the authenticated user.
125
+ * @param string $id The ID of the thread to remove from Trash.
126
+ * @param array $optParams Optional parameters.
127
+ * @return Google_Service_Gmail_Thread
128
+ */
129
+ public function untrash($userId, $id, $optParams = array())
130
+ {
131
+ $params = array('userId' => $userId, 'id' => $id);
132
+ $params = array_merge($params, $optParams);
133
+ return $this->call('untrash', array($params), "Google_Service_Gmail_Thread");
134
+ }
135
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/SendAs.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_SendAs extends Google_Model
19
+ {
20
+ public $displayName;
21
+ public $isDefault;
22
+ public $isPrimary;
23
+ public $replyToAddress;
24
+ public $sendAsEmail;
25
+ public $signature;
26
+ protected $smtpMsaType = 'Google_Service_Gmail_SmtpMsa';
27
+ protected $smtpMsaDataType = '';
28
+ public $treatAsAlias;
29
+ public $verificationStatus;
30
+
31
+ public function setDisplayName($displayName)
32
+ {
33
+ $this->displayName = $displayName;
34
+ }
35
+ public function getDisplayName()
36
+ {
37
+ return $this->displayName;
38
+ }
39
+ public function setIsDefault($isDefault)
40
+ {
41
+ $this->isDefault = $isDefault;
42
+ }
43
+ public function getIsDefault()
44
+ {
45
+ return $this->isDefault;
46
+ }
47
+ public function setIsPrimary($isPrimary)
48
+ {
49
+ $this->isPrimary = $isPrimary;
50
+ }
51
+ public function getIsPrimary()
52
+ {
53
+ return $this->isPrimary;
54
+ }
55
+ public function setReplyToAddress($replyToAddress)
56
+ {
57
+ $this->replyToAddress = $replyToAddress;
58
+ }
59
+ public function getReplyToAddress()
60
+ {
61
+ return $this->replyToAddress;
62
+ }
63
+ public function setSendAsEmail($sendAsEmail)
64
+ {
65
+ $this->sendAsEmail = $sendAsEmail;
66
+ }
67
+ public function getSendAsEmail()
68
+ {
69
+ return $this->sendAsEmail;
70
+ }
71
+ public function setSignature($signature)
72
+ {
73
+ $this->signature = $signature;
74
+ }
75
+ public function getSignature()
76
+ {
77
+ return $this->signature;
78
+ }
79
+ /**
80
+ * @param Google_Service_Gmail_SmtpMsa
81
+ */
82
+ public function setSmtpMsa(Google_Service_Gmail_SmtpMsa $smtpMsa)
83
+ {
84
+ $this->smtpMsa = $smtpMsa;
85
+ }
86
+ /**
87
+ * @return Google_Service_Gmail_SmtpMsa
88
+ */
89
+ public function getSmtpMsa()
90
+ {
91
+ return $this->smtpMsa;
92
+ }
93
+ public function setTreatAsAlias($treatAsAlias)
94
+ {
95
+ $this->treatAsAlias = $treatAsAlias;
96
+ }
97
+ public function getTreatAsAlias()
98
+ {
99
+ return $this->treatAsAlias;
100
+ }
101
+ public function setVerificationStatus($verificationStatus)
102
+ {
103
+ $this->verificationStatus = $verificationStatus;
104
+ }
105
+ public function getVerificationStatus()
106
+ {
107
+ return $this->verificationStatus;
108
+ }
109
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/SmimeInfo.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_SmimeInfo extends Google_Model
19
+ {
20
+ public $encryptedKeyPassword;
21
+ public $expiration;
22
+ public $id;
23
+ public $isDefault;
24
+ public $issuerCn;
25
+ public $pem;
26
+ public $pkcs12;
27
+
28
+ public function setEncryptedKeyPassword($encryptedKeyPassword)
29
+ {
30
+ $this->encryptedKeyPassword = $encryptedKeyPassword;
31
+ }
32
+ public function getEncryptedKeyPassword()
33
+ {
34
+ return $this->encryptedKeyPassword;
35
+ }
36
+ public function setExpiration($expiration)
37
+ {
38
+ $this->expiration = $expiration;
39
+ }
40
+ public function getExpiration()
41
+ {
42
+ return $this->expiration;
43
+ }
44
+ public function setId($id)
45
+ {
46
+ $this->id = $id;
47
+ }
48
+ public function getId()
49
+ {
50
+ return $this->id;
51
+ }
52
+ public function setIsDefault($isDefault)
53
+ {
54
+ $this->isDefault = $isDefault;
55
+ }
56
+ public function getIsDefault()
57
+ {
58
+ return $this->isDefault;
59
+ }
60
+ public function setIssuerCn($issuerCn)
61
+ {
62
+ $this->issuerCn = $issuerCn;
63
+ }
64
+ public function getIssuerCn()
65
+ {
66
+ return $this->issuerCn;
67
+ }
68
+ public function setPem($pem)
69
+ {
70
+ $this->pem = $pem;
71
+ }
72
+ public function getPem()
73
+ {
74
+ return $this->pem;
75
+ }
76
+ public function setPkcs12($pkcs12)
77
+ {
78
+ $this->pkcs12 = $pkcs12;
79
+ }
80
+ public function getPkcs12()
81
+ {
82
+ return $this->pkcs12;
83
+ }
84
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/SmtpMsa.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_SmtpMsa extends Google_Model
19
+ {
20
+ public $host;
21
+ public $password;
22
+ public $port;
23
+ public $securityMode;
24
+ public $username;
25
+
26
+ public function setHost($host)
27
+ {
28
+ $this->host = $host;
29
+ }
30
+ public function getHost()
31
+ {
32
+ return $this->host;
33
+ }
34
+ public function setPassword($password)
35
+ {
36
+ $this->password = $password;
37
+ }
38
+ public function getPassword()
39
+ {
40
+ return $this->password;
41
+ }
42
+ public function setPort($port)
43
+ {
44
+ $this->port = $port;
45
+ }
46
+ public function getPort()
47
+ {
48
+ return $this->port;
49
+ }
50
+ public function setSecurityMode($securityMode)
51
+ {
52
+ $this->securityMode = $securityMode;
53
+ }
54
+ public function getSecurityMode()
55
+ {
56
+ return $this->securityMode;
57
+ }
58
+ public function setUsername($username)
59
+ {
60
+ $this->username = $username;
61
+ }
62
+ public function getUsername()
63
+ {
64
+ return $this->username;
65
+ }
66
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/Thread.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_Thread extends Google_Collection
19
+ {
20
+ protected $collection_key = 'messages';
21
+ public $historyId;
22
+ public $id;
23
+ protected $messagesType = 'Google_Service_Gmail_Message';
24
+ protected $messagesDataType = 'array';
25
+ public $snippet;
26
+
27
+ public function setHistoryId($historyId)
28
+ {
29
+ $this->historyId = $historyId;
30
+ }
31
+ public function getHistoryId()
32
+ {
33
+ return $this->historyId;
34
+ }
35
+ public function setId($id)
36
+ {
37
+ $this->id = $id;
38
+ }
39
+ public function getId()
40
+ {
41
+ return $this->id;
42
+ }
43
+ /**
44
+ * @param Google_Service_Gmail_Message
45
+ */
46
+ public function setMessages($messages)
47
+ {
48
+ $this->messages = $messages;
49
+ }
50
+ /**
51
+ * @return Google_Service_Gmail_Message
52
+ */
53
+ public function getMessages()
54
+ {
55
+ return $this->messages;
56
+ }
57
+ public function setSnippet($snippet)
58
+ {
59
+ $this->snippet = $snippet;
60
+ }
61
+ public function getSnippet()
62
+ {
63
+ return $this->snippet;
64
+ }
65
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/VacationSettings.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_VacationSettings extends Google_Model
19
+ {
20
+ public $enableAutoReply;
21
+ public $endTime;
22
+ public $responseBodyHtml;
23
+ public $responseBodyPlainText;
24
+ public $responseSubject;
25
+ public $restrictToContacts;
26
+ public $restrictToDomain;
27
+ public $startTime;
28
+
29
+ public function setEnableAutoReply($enableAutoReply)
30
+ {
31
+ $this->enableAutoReply = $enableAutoReply;
32
+ }
33
+ public function getEnableAutoReply()
34
+ {
35
+ return $this->enableAutoReply;
36
+ }
37
+ public function setEndTime($endTime)
38
+ {
39
+ $this->endTime = $endTime;
40
+ }
41
+ public function getEndTime()
42
+ {
43
+ return $this->endTime;
44
+ }
45
+ public function setResponseBodyHtml($responseBodyHtml)
46
+ {
47
+ $this->responseBodyHtml = $responseBodyHtml;
48
+ }
49
+ public function getResponseBodyHtml()
50
+ {
51
+ return $this->responseBodyHtml;
52
+ }
53
+ public function setResponseBodyPlainText($responseBodyPlainText)
54
+ {
55
+ $this->responseBodyPlainText = $responseBodyPlainText;
56
+ }
57
+ public function getResponseBodyPlainText()
58
+ {
59
+ return $this->responseBodyPlainText;
60
+ }
61
+ public function setResponseSubject($responseSubject)
62
+ {
63
+ $this->responseSubject = $responseSubject;
64
+ }
65
+ public function getResponseSubject()
66
+ {
67
+ return $this->responseSubject;
68
+ }
69
+ public function setRestrictToContacts($restrictToContacts)
70
+ {
71
+ $this->restrictToContacts = $restrictToContacts;
72
+ }
73
+ public function getRestrictToContacts()
74
+ {
75
+ return $this->restrictToContacts;
76
+ }
77
+ public function setRestrictToDomain($restrictToDomain)
78
+ {
79
+ $this->restrictToDomain = $restrictToDomain;
80
+ }
81
+ public function getRestrictToDomain()
82
+ {
83
+ return $this->restrictToDomain;
84
+ }
85
+ public function setStartTime($startTime)
86
+ {
87
+ $this->startTime = $startTime;
88
+ }
89
+ public function getStartTime()
90
+ {
91
+ return $this->startTime;
92
+ }
93
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/WatchRequest.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_WatchRequest extends Google_Collection
19
+ {
20
+ protected $collection_key = 'labelIds';
21
+ public $labelFilterAction;
22
+ public $labelIds;
23
+ public $topicName;
24
+
25
+ public function setLabelFilterAction($labelFilterAction)
26
+ {
27
+ $this->labelFilterAction = $labelFilterAction;
28
+ }
29
+ public function getLabelFilterAction()
30
+ {
31
+ return $this->labelFilterAction;
32
+ }
33
+ public function setLabelIds($labelIds)
34
+ {
35
+ $this->labelIds = $labelIds;
36
+ }
37
+ public function getLabelIds()
38
+ {
39
+ return $this->labelIds;
40
+ }
41
+ public function setTopicName($topicName)
42
+ {
43
+ $this->topicName = $topicName;
44
+ }
45
+ public function getTopicName()
46
+ {
47
+ return $this->topicName;
48
+ }
49
+ }
vendor/google/apiclient-services/src/Google/Service/Gmail/WatchResponse.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ class Google_Service_Gmail_WatchResponse extends Google_Model
19
+ {
20
+ public $expiration;
21
+ public $historyId;
22
+
23
+ public function setExpiration($expiration)
24
+ {
25
+ $this->expiration = $expiration;
26
+ }
27
+ public function getExpiration()
28
+ {
29
+ return $this->expiration;
30
+ }
31
+ public function setHistoryId($historyId)
32
+ {
33
+ $this->historyId = $historyId;
34
+ }
35
+ public function getHistoryId()
36
+ {
37
+ return $this->historyId;
38
+ }
39
+ }
vendor/google/apiclient/LICENSE ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
202
+
203
+
vendor/google/apiclient/src/Google/AccessToken/Revoke.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * Copyright 2008 Google Inc.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
20
+ use GuzzleHttp\ClientInterface;
21
+ use GuzzleHttp\Psr7;
22
+ use GuzzleHttp\Psr7\Request;
23
+
24
+ /**
25
+ * Wrapper around Google Access Tokens which provides convenience functions
26
+ *
27
+ */
28
+ class Google_AccessToken_Revoke
29
+ {
30
+ /**
31
+ * @var GuzzleHttp\ClientInterface The http client
32
+ */
33
+ private $http;
34
+
35
+ /**
36
+ * Instantiates the class, but does not initiate the login flow, leaving it
37
+ * to the discretion of the caller.
38
+ */
39
+ public function __construct(ClientInterface $http = null)
40
+ {
41
+ $this->http = $http;
42
+ }
43
+
44
+ /**
45
+ * Revoke an OAuth2 access token or refresh token. This method will revoke the current access
46
+ * token, if a token isn't provided.
47
+ *
48
+ * @param string|array $token The token (access token or a refresh token) that should be revoked.
49
+ * @return boolean Returns True if the revocation was successful, otherwise False.
50
+ */
51
+ public function revokeToken($token)
52
+ {
53
+ if (is_array($token)) {
54
+ if (isset($token['refresh_token'])) {
55
+ $token = $token['refresh_token'];
56
+ } else {
57
+ $token = $token['access_token'];
58
+ }
59
+ }
60
+
61
+ $body = Psr7\stream_for(http_build_query(array('token' => $token)));
62
+ $request = new Request(
63
+ 'POST',
64
+ Google_Client::OAUTH2_REVOKE_URI,
65
+ [
66
+ 'Cache-Control' => 'no-store',
67
+ 'Content-Type' => 'application/x-www-form-urlencoded',
68
+ ],
69
+ $body
70
+ );
71
+
72
+ $httpHandler = HttpHandlerFactory::build($this->http);
73
+
74
+ $response = $httpHandler($request);
75
+
76
+ return $response->getStatusCode() == 200;
77
+ }
78
+ }
vendor/google/apiclient/src/Google/AccessToken/Verify.php ADDED
@@ -0,0 +1,272 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * Copyright 2008 Google Inc.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ use Firebase\JWT\ExpiredException as ExpiredExceptionV3;
20
+ use Firebase\JWT\SignatureInvalidException;
21
+ use GuzzleHttp\Client;
22
+ use GuzzleHttp\ClientInterface;
23
+ use Psr\Cache\CacheItemPoolInterface;
24
+ use Google\Auth\Cache\MemoryCacheItemPool;
25
+ use Stash\Driver\FileSystem;
26
+ use Stash\Pool;
27
+
28
+ /**
29
+ * Wrapper around Google Access Tokens which provides convenience functions
30
+ *
31
+ */
32
+ class Google_AccessToken_Verify
33
+ {
34
+ const FEDERATED_SIGNON_CERT_URL = 'https://www.googleapis.com/oauth2/v3/certs';
35
+ const OAUTH2_ISSUER = 'accounts.google.com';
36
+ const OAUTH2_ISSUER_HTTPS = 'https://accounts.google.com';
37
+
38
+ /**
39
+ * @var GuzzleHttp\ClientInterface The http client
40
+ */
41
+ private $http;
42
+
43
+ /**
44
+ * @var Psr\Cache\CacheItemPoolInterface cache class
45
+ */
46
+ private $cache;
47
+
48
+ /**
49
+ * Instantiates the class, but does not initiate the login flow, leaving it
50
+ * to the discretion of the caller.
51
+ */
52
+ public function __construct(
53
+ ClientInterface $http = null,
54
+ CacheItemPoolInterface $cache = null,
55
+ $jwt = null
56
+ ) {
57
+ if (null === $http) {
58
+ $http = new Client();
59
+ }
60
+
61
+ if (null === $cache) {
62
+ $cache = new MemoryCacheItemPool;
63
+ }
64
+
65
+ $this->http = $http;
66
+ $this->cache = $cache;
67
+ $this->jwt = $jwt ?: $this->getJwtService();
68
+ }
69
+
70
+ /**
71
+ * Verifies an id token and returns the authenticated apiLoginTicket.
72
+ * Throws an exception if the id token is not valid.
73
+ * The audience parameter can be used to control which id tokens are
74
+ * accepted. By default, the id token must have been issued to this OAuth2 client.
75
+ *
76
+ * @param $audience
77
+ * @return array the token payload, if successful
78
+ */
79
+ public function verifyIdToken($idToken, $audience = null)
80
+ {
81
+ if (empty($idToken)) {
82
+ throw new LogicException('id_token cannot be null');
83
+ }
84
+
85
+ // set phpseclib constants if applicable
86
+ $this->setPhpsecConstants();
87
+
88
+ // Check signature
89
+ $certs = $this->getFederatedSignOnCerts();
90
+ foreach ($certs as $cert) {
91
+ $bigIntClass = $this->getBigIntClass();
92
+ $rsaClass = $this->getRsaClass();
93
+ $modulus = new $bigIntClass($this->jwt->urlsafeB64Decode($cert['n']), 256);
94
+ $exponent = new $bigIntClass($this->jwt->urlsafeB64Decode($cert['e']), 256);
95
+
96
+ $rsa = new $rsaClass();
97
+ $rsa->loadKey(array('n' => $modulus, 'e' => $exponent));
98
+
99
+ try {
100
+ $payload = $this->jwt->decode(
101
+ $idToken,
102
+ $rsa->getPublicKey(),
103
+ array('RS256')
104
+ );
105
+
106
+ if (property_exists($payload, 'aud')) {
107
+ if ($audience && $payload->aud != $audience) {
108
+ return false;
109
+ }
110
+ }
111
+
112
+ // support HTTP and HTTPS issuers
113
+ // @see https://developers.google.com/identity/sign-in/web/backend-auth
114
+ $issuers = array(self::OAUTH2_ISSUER, self::OAUTH2_ISSUER_HTTPS);
115
+ if (!isset($payload->iss) || !in_array($payload->iss, $issuers)) {
116
+ return false;
117
+ }
118
+
119
+ return (array) $payload;
120
+ } catch (ExpiredException $e) {
121
+ return false;
122
+ } catch (ExpiredExceptionV3 $e) {
123
+ return false;
124
+ } catch (SignatureInvalidException $e) {
125
+ // continue
126
+ } catch (DomainException $e) {
127
+ // continue
128
+ }
129
+ }
130
+
131
+ return false;
132
+ }
133
+
134
+ private function getCache()
135
+ {
136
+ return $this->cache;
137
+ }
138
+
139
+ /**
140
+ * Retrieve and cache a certificates file.
141
+ *
142
+ * @param $url string location
143
+ * @throws Google_Exception
144
+ * @return array certificates
145
+ */
146
+ private function retrieveCertsFromLocation($url)
147
+ {
148
+ // If we're retrieving a local file, just grab it.
149
+ if (0 !== strpos($url, 'http')) {
150
+ if (!$file = file_get_contents($url)) {
151
+ throw new Google_Exception(
152
+ "Failed to retrieve verification certificates: '" .
153
+ $url . "'."
154
+ );
155
+ }
156
+
157
+ return json_decode($file, true);
158
+ }
159
+
160
+ $response = $this->http->get($url);
161
+
162
+ if ($response->getStatusCode() == 200) {
163
+ return json_decode((string) $response->getBody(), true);
164
+ }
165
+ throw new Google_Exception(
166
+ sprintf(
167
+ 'Failed to retrieve verification certificates: "%s".',
168
+ $response->getBody()->getContents()
169
+ ),
170
+ $response->getStatusCode()
171
+ );
172
+ }
173
+
174
+ // Gets federated sign-on certificates to use for verifying identity tokens.
175
+ // Returns certs as array structure, where keys are key ids, and values
176
+ // are PEM encoded certificates.
177
+ private function getFederatedSignOnCerts()
178
+ {
179
+ $certs = null;
180
+ if ($cache = $this->getCache()) {
181
+ $cacheItem = $cache->getItem('federated_signon_certs_v3', 3600);
182
+ $certs = $cacheItem->get();
183
+ }
184
+
185
+
186
+ if (!$certs) {
187
+ $certs = $this->retrieveCertsFromLocation(
188
+ self::FEDERATED_SIGNON_CERT_URL
189
+ );
190
+
191
+ if ($cache) {
192
+ $cacheItem->set($certs);
193
+ $cache->save($cacheItem);
194
+ }
195
+ }
196
+
197
+ if (!isset($certs['keys'])) {
198
+ throw new InvalidArgumentException(
199
+ 'federated sign-on certs expects "keys" to be set'
200
+ );
201
+ }
202
+
203
+ return $certs['keys'];
204
+ }
205
+
206
+ private function getJwtService()
207
+ {
208
+ $jwtClass = 'JWT';
209
+ if (class_exists('\Firebase\JWT\JWT')) {
210
+ $jwtClass = 'Firebase\JWT\JWT';
211
+ }
212
+
213
+ if (property_exists($jwtClass, 'leeway')) {
214
+ // adds 1 second to JWT leeway
215
+ // @see https://github.com/google/google-api-php-client/issues/827
216
+ $jwtClass::$leeway = 1;
217
+ }
218
+
219
+ return new $jwtClass;
220
+ }
221
+
222
+ private function getRsaClass()
223
+ {
224
+ if (class_exists('phpseclib\Crypt\RSA')) {
225
+ return 'phpseclib\Crypt\RSA';
226
+ }
227
+
228
+ return 'Crypt_RSA';
229
+ }
230
+
231
+ private function getBigIntClass()
232
+ {
233
+ if (class_exists('phpseclib\Math\BigInteger')) {
234
+ return 'phpseclib\Math\BigInteger';
235
+ }
236
+
237
+ return 'Math_BigInteger';
238
+ }
239
+
240
+ private function getOpenSslConstant()
241
+ {
242
+ if (class_exists('phpseclib\Crypt\RSA')) {
243
+ return 'phpseclib\Crypt\RSA::MODE_OPENSSL';
244
+ }
245
+
246
+ if (class_exists('Crypt_RSA')) {
247
+ return 'CRYPT_RSA_MODE_OPENSSL';
248
+ }
249
+
250
+ throw new \Exception('Cannot find RSA class');
251
+ }
252
+
253
+ /**
254
+ * phpseclib calls "phpinfo" by default, which requires special
255
+ * whitelisting in the AppEngine VM environment. This function
256
+ * sets constants to bypass the need for phpseclib to check phpinfo
257
+ *
258
+ * @see phpseclib/Math/BigInteger
259
+ * @see https://github.com/GoogleCloudPlatform/getting-started-php/issues/85
260
+ */
261
+ private function setPhpsecConstants()
262
+ {
263
+ if (filter_var(getenv('GAE_VM'), FILTER_VALIDATE_BOOLEAN)) {
264
+ if (!defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
265
+ define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
266
+ }
267
+ if (!defined('CRYPT_RSA_MODE')) {
268
+ define('CRYPT_RSA_MODE', constant($this->getOpenSslConstant()));
269
+ }
270
+ }
271
+ }
272
+ }
vendor/google/apiclient/src/Google/AuthHandler/AuthHandlerFactory.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2015 Google Inc. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ use GuzzleHttp\Client;
19
+ use GuzzleHttp\ClientInterface;
20
+
21
+ class Google_AuthHandler_AuthHandlerFactory
22
+ {
23
+ /**
24
+ * Builds out a default http handler for the installed version of guzzle.
25
+ *
26
+ * @return Google_AuthHandler_Guzzle5AuthHandler|Google_AuthHandler_Guzzle6AuthHandler
27
+ * @throws Exception
28
+ */
29
+ public static function build($cache = null, array $cacheConfig = [])
30
+ {
31
+ $version = ClientInterface::VERSION;
32
+
33
+ switch ($version[0]) {
34
+ case '5':
35
+ return new Google_AuthHandler_Guzzle5AuthHandler($cache, $cacheConfig);
36
+ case '6':
37
+ return new Google_AuthHandler_Guzzle6AuthHandler($cache, $cacheConfig);
38
+ default:
39
+ throw new Exception('Version not supported');
40
+ }
41
+ }
42
+ }
vendor/google/apiclient/src/Google/AuthHandler/Guzzle5AuthHandler.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use Google\Auth\CredentialsLoader;
4
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
5
+ use Google\Auth\FetchAuthTokenCache;
6
+ use Google\Auth\Subscriber\AuthTokenSubscriber;
7
+ use Google\Auth\Subscriber\ScopedAccessTokenSubscriber;
8
+ use Google\Auth\Subscriber\SimpleSubscriber;
9
+ use GuzzleHttp\Client;
10
+ use GuzzleHttp\ClientInterface;
11
+ use Psr\Cache\CacheItemPoolInterface;
12
+
13
+ /**
14
+ *
15
+ */
16
+ class Google_AuthHandler_Guzzle5AuthHandler
17
+ {
18
+ protected $cache;
19
+ protected $cacheConfig;
20
+
21
+ public function __construct(CacheItemPoolInterface $cache = null, array $cacheConfig = [])
22
+ {
23
+ $this->cache = $cache;
24
+ $this->cacheConfig = $cacheConfig;
25
+ }
26
+
27
+ public function attachCredentials(
28
+ ClientInterface $http,
29
+ CredentialsLoader $credentials,
30
+ callable $tokenCallback = null
31
+ ) {
32
+ // use the provided cache
33
+ if ($this->cache) {
34
+ $credentials = new FetchAuthTokenCache(
35
+ $credentials,
36
+ $this->cacheConfig,
37
+ $this->cache
38
+ );
39
+ }
40
+ // if we end up needing to make an HTTP request to retrieve credentials, we
41
+ // can use our existing one, but we need to throw exceptions so the error
42
+ // bubbles up.
43
+ $authHttp = $this->createAuthHttp($http);
44
+ $authHttpHandler = HttpHandlerFactory::build($authHttp);
45
+ $subscriber = new AuthTokenSubscriber(
46
+ $credentials,
47
+ $authHttpHandler,
48
+ $tokenCallback
49
+ );
50
+
51
+ $http->setDefaultOption('auth', 'google_auth');
52
+ $http->getEmitter()->attach($subscriber);
53
+
54
+ return $http;
55
+ }
56
+
57
+ public function attachToken(ClientInterface $http, array $token, array $scopes)
58
+ {
59
+ $tokenFunc = function ($scopes) use ($token) {
60
+ return $token['access_token'];
61
+ };
62
+
63
+ $subscriber = new ScopedAccessTokenSubscriber(
64
+ $tokenFunc,
65
+ $scopes,
66
+ $this->cacheConfig,
67
+ $this->cache
68
+ );
69
+
70
+ $http->setDefaultOption('auth', 'scoped');
71
+ $http->getEmitter()->attach($subscriber);
72
+
73
+ return $http;
74
+ }
75
+
76
+ public function attachKey(ClientInterface $http, $key)
77
+ {
78
+ $subscriber = new SimpleSubscriber(['key' => $key]);
79
+
80
+ $http->setDefaultOption('auth', 'simple');
81
+ $http->getEmitter()->attach($subscriber);
82
+
83
+ return $http;
84
+ }
85
+
86
+ private function createAuthHttp(ClientInterface $http)
87
+ {
88
+ return new Client(
89
+ [
90
+ 'base_url' => $http->getBaseUrl(),
91
+ 'defaults' => [
92
+ 'exceptions' => true,
93
+ 'verify' => $http->getDefaultOption('verify'),
94
+ 'proxy' => $http->getDefaultOption('proxy'),
95
+ ]
96
+ ]
97
+ );
98
+ }
99
+ }
vendor/google/apiclient/src/Google/AuthHandler/Guzzle6AuthHandler.php ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use Google\Auth\CredentialsLoader;
4
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
5
+ use Google\Auth\FetchAuthTokenCache;
6
+ use Google\Auth\Middleware\AuthTokenMiddleware;
7
+ use Google\Auth\Middleware\ScopedAccessTokenMiddleware;
8
+ use Google\Auth\Middleware\SimpleMiddleware;
9
+ use GuzzleHttp\Client;
10
+ use GuzzleHttp\ClientInterface;
11
+ use Psr\Cache\CacheItemPoolInterface;
12
+
13
+ /**
14
+ *
15
+ */
16
+ class Google_AuthHandler_Guzzle6AuthHandler
17
+ {
18
+ protected $cache;
19
+ protected $cacheConfig;
20
+
21
+ public function __construct(CacheItemPoolInterface $cache = null, array $cacheConfig = [])
22
+ {
23
+ $this->cache = $cache;
24
+ $this->cacheConfig = $cacheConfig;
25
+ }
26
+
27
+ public function attachCredentials(
28
+ ClientInterface $http,
29
+ CredentialsLoader $credentials,
30
+ callable $tokenCallback = null
31
+ ) {
32
+ // use the provided cache
33
+ if ($this->cache) {
34
+ $credentials = new FetchAuthTokenCache(
35
+ $credentials,
36
+ $this->cacheConfig,
37
+ $this->cache
38
+ );
39
+ }
40
+ // if we end up needing to make an HTTP request to retrieve credentials, we
41
+ // can use our existing one, but we need to throw exceptions so the error
42
+ // bubbles up.
43
+ $authHttp = $this->createAuthHttp($http);
44
+ $authHttpHandler = HttpHandlerFactory::build($authHttp);
45
+ $middleware = new AuthTokenMiddleware(
46
+ $credentials,
47
+ $authHttpHandler,
48
+ $tokenCallback
49
+ );
50
+
51
+ $config = $http->getConfig();
52
+ $config['handler']->remove('google_auth');
53
+ $config['handler']->push($middleware, 'google_auth');
54
+ $config['auth'] = 'google_auth';
55
+ $http = new Client($config);
56
+
57
+ return $http;
58
+ }
59
+
60
+ public function attachToken(ClientInterface $http, array $token, array $scopes)
61
+ {
62
+ $tokenFunc = function ($scopes) use ($token) {
63
+ return $token['access_token'];
64
+ };
65
+
66
+ $middleware = new ScopedAccessTokenMiddleware(
67
+ $tokenFunc,
68
+ $scopes,
69
+ $this->cacheConfig,
70
+ $this->cache
71
+ );
72
+
73
+ $config = $http->getConfig();
74
+ $config['handler']->remove('google_auth');
75
+ $config['handler']->push($middleware, 'google_auth');
76
+ $config['auth'] = 'scoped';
77
+ $http = new Client($config);
78
+
79
+ return $http;
80
+ }
81
+
82
+ public function attachKey(ClientInterface $http, $key)
83
+ {
84
+ $middleware = new SimpleMiddleware(['key' => $key]);
85
+
86
+ $config = $http->getConfig();
87
+ $config['handler']->remove('google_auth');
88
+ $config['handler']->push($middleware, 'google_auth');
89
+ $config['auth'] = 'simple';
90
+ $http = new Client($config);
91
+
92
+ return $http;
93
+ }
94
+
95
+ private function createAuthHttp(ClientInterface $http)
96
+ {
97
+ return new Client(
98
+ [
99
+ 'base_uri' => $http->getConfig('base_uri'),
100
+ 'exceptions' => true,
101
+ 'verify' => $http->getConfig('verify'),
102
+ 'proxy' => $http->getConfig('proxy'),
103
+ ]
104
+ );
105
+ }
106
+ }
vendor/google/apiclient/src/Google/Client.php ADDED
@@ -0,0 +1,1118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2010 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ use Google\Auth\ApplicationDefaultCredentials;
19
+ use Google\Auth\Cache\MemoryCacheItemPool;
20
+ use Google\Auth\CredentialsLoader;
21
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
22
+ use Google\Auth\OAuth2;
23
+ use Google\Auth\Credentials\ServiceAccountCredentials;
24
+ use Google\Auth\Credentials\UserRefreshCredentials;
25
+ use GuzzleHttp\Client;
26
+ use GuzzleHttp\ClientInterface;
27
+ use GuzzleHttp\Ring\Client\StreamHandler;
28
+ use GuzzleHttp\Psr7;
29
+ use Psr\Cache\CacheItemPoolInterface;
30
+ use Psr\Http\Message\RequestInterface;
31
+ use Psr\Log\LoggerInterface;
32
+ use Monolog\Logger;
33
+ use Monolog\Handler\StreamHandler as MonologStreamHandler;
34
+ use Monolog\Handler\SyslogHandler as MonologSyslogHandler;
35
+
36
+ /**
37
+ * The Google API Client
38
+ * https://github.com/google/google-api-php-client
39
+ */
40
+ class Google_Client
41
+ {
42
+ const LIBVER = "2.2.1";
43
+ const USER_AGENT_SUFFIX = "google-api-php-client/";
44
+ const OAUTH2_REVOKE_URI = 'https://accounts.google.com/o/oauth2/revoke';
45
+ const OAUTH2_TOKEN_URI = 'https://www.googleapis.com/oauth2/v4/token';
46
+ const OAUTH2_AUTH_URL = 'https://accounts.google.com/o/oauth2/auth';
47
+ const API_BASE_PATH = 'https://www.googleapis.com';
48
+
49
+ /**
50
+ * @var Google\Auth\OAuth2 $auth
51
+ */
52
+ private $auth;
53
+
54
+ /**
55
+ * @var GuzzleHttp\ClientInterface $http
56
+ */
57
+ private $http;
58
+
59
+ /**
60
+ * @var Psr\Cache\CacheItemPoolInterface $cache
61
+ */
62
+ private $cache;
63
+
64
+ /**
65
+ * @var array access token
66
+ */
67
+ private $token;
68
+
69
+ /**
70
+ * @var array $config
71
+ */
72
+ private $config;
73
+
74
+ /**
75
+ * @var Psr\Log\LoggerInterface $logger
76
+ */
77
+ private $logger;
78
+
79
+ /**
80
+ * @var boolean $deferExecution
81
+ */
82
+ private $deferExecution = false;
83
+
84
+ /** @var array $scopes */
85
+ // Scopes requested by the client
86
+ protected $requestedScopes = [];
87
+
88
+ /**
89
+ * Construct the Google Client.
90
+ *
91
+ * @param array $config
92
+ */
93
+ public function __construct(array $config = array())
94
+ {
95
+ $this->config = array_merge(
96
+ [
97
+ 'application_name' => '',
98
+
99
+ // Don't change these unless you're working against a special development
100
+ // or testing environment.
101
+ 'base_path' => self::API_BASE_PATH,
102
+
103
+ // https://developers.google.com/console
104
+ 'client_id' => '',
105
+ 'client_secret' => '',
106
+ 'redirect_uri' => null,
107
+ 'state' => null,
108
+
109
+ // Simple API access key, also from the API console. Ensure you get
110
+ // a Server key, and not a Browser key.
111
+ 'developer_key' => '',
112
+
113
+ // For use with Google Cloud Platform
114
+ // fetch the ApplicationDefaultCredentials, if applicable
115
+ // @see https://developers.google.com/identity/protocols/application-default-credentials
116
+ 'use_application_default_credentials' => false,
117
+ 'signing_key' => null,
118
+ 'signing_algorithm' => null,
119
+ 'subject' => null,
120
+
121
+ // Other OAuth2 parameters.
122
+ 'hd' => '',
123
+ 'prompt' => '',
124
+ 'openid.realm' => '',
125
+ 'include_granted_scopes' => null,
126
+ 'login_hint' => '',
127
+ 'request_visible_actions' => '',
128
+ 'access_type' => 'online',
129
+ 'approval_prompt' => 'auto',
130
+
131
+ // Task Runner retry configuration
132
+ // @see Google_Task_Runner
133
+ 'retry' => array(),
134
+
135
+ // cache config for downstream auth caching
136
+ 'cache_config' => [],
137
+
138
+ // function to be called when an access token is fetched
139
+ // follows the signature function ($cacheKey, $accessToken)
140
+ 'token_callback' => null,
141
+
142
+ // Service class used in Google_Client::verifyIdToken.
143
+ // Explicitly pass this in to avoid setting JWT::$leeway
144
+ 'jwt' => null,
145
+ ],
146
+ $config
147
+ );
148
+ }
149
+
150
+ /**
151
+ * Get a string containing the version of the library.
152
+ *
153
+ * @return string
154
+ */
155
+ public function getLibraryVersion()
156
+ {
157
+ return self::LIBVER;
158
+ }
159
+
160
+ /**
161
+ * For backwards compatibility
162
+ * alias for fetchAccessTokenWithAuthCode
163
+ *
164
+ * @param $code string code from accounts.google.com
165
+ * @return array access token
166
+ * @deprecated
167
+ */
168
+ public function authenticate($code)
169
+ {
170
+ return $this->fetchAccessTokenWithAuthCode($code);
171
+ }
172
+
173
+ /**
174
+ * Attempt to exchange a code for an valid authentication token.
175
+ * Helper wrapped around the OAuth 2.0 implementation.
176
+ *
177
+ * @param $code string code from accounts.google.com
178
+ * @return array access token
179
+ */
180
+ public function fetchAccessTokenWithAuthCode($code)
181
+ {
182
+ if (strlen($code) == 0) {
183
+ throw new InvalidArgumentException("Invalid code");
184
+ }
185
+
186
+ $auth = $this->getOAuth2Service();
187
+ $auth->setCode($code);
188
+ $auth->setRedirectUri($this->getRedirectUri());
189
+
190
+ $httpHandler = HttpHandlerFactory::build($this->getHttpClient());
191
+ $creds = $auth->fetchAuthToken($httpHandler);
192
+ if ($creds && isset($creds['access_token'])) {
193
+ $creds['created'] = time();
194
+ $this->setAccessToken($creds);
195
+ }
196
+
197
+ return $creds;
198
+ }
199
+
200
+ /**
201
+ * For backwards compatibility
202
+ * alias for fetchAccessTokenWithAssertion
203
+ *
204
+ * @return array access token
205
+ * @deprecated
206
+ */
207
+ public function refreshTokenWithAssertion()
208
+ {
209
+ return $this->fetchAccessTokenWithAssertion();
210
+ }
211
+
212
+ /**
213
+ * Fetches a fresh access token with a given assertion token.
214
+ * @param $assertionCredentials optional.
215
+ * @return array access token
216
+ */
217
+ public function fetchAccessTokenWithAssertion(ClientInterface $authHttp = null)
218
+ {
219
+ if (!$this->isUsingApplicationDefaultCredentials()) {
220
+ throw new DomainException(
221
+ 'set the JSON service account credentials using'
222
+ . ' Google_Client::setAuthConfig or set the path to your JSON file'
223
+ . ' with the "GOOGLE_APPLICATION_CREDENTIALS" environment variable'
224
+ . ' and call Google_Client::useApplicationDefaultCredentials to'
225
+ . ' refresh a token with assertion.'
226
+ );
227
+ }
228
+
229
+ $this->getLogger()->log(
230
+ 'info',
231
+ 'OAuth2 access token refresh with Signed JWT assertion grants.'
232
+ );
233
+
234
+ $credentials = $this->createApplicationDefaultCredentials();
235
+
236
+ $httpHandler = HttpHandlerFactory::build($authHttp);
237
+ $creds = $credentials->fetchAuthToken($httpHandler);
238
+ if ($creds && isset($creds['access_token'])) {
239
+ $creds['created'] = time();
240
+ $this->setAccessToken($creds);
241
+ }
242
+
243
+ return $creds;
244
+ }
245
+
246
+ /**
247
+ * For backwards compatibility
248
+ * alias for fetchAccessTokenWithRefreshToken
249
+ *
250
+ * @param string $refreshToken
251
+ * @return array access token
252
+ */
253
+ public function refreshToken($refreshToken)
254
+ {
255
+ return $this->fetchAccessTokenWithRefreshToken($refreshToken);
256
+ }
257
+
258
+ /**
259
+ * Fetches a fresh OAuth 2.0 access token with the given refresh token.
260
+ * @param string $refreshToken
261
+ * @return array access token
262
+ */
263
+ public function fetchAccessTokenWithRefreshToken($refreshToken = null)
264
+ {
265
+ if (null === $refreshToken) {
266
+ if (!isset($this->token['refresh_token'])) {
267
+ throw new LogicException(
268
+ 'refresh token must be passed in or set as part of setAccessToken'
269
+ );
270
+ }
271
+ $refreshToken = $this->token['refresh_token'];
272
+ }
273
+ $this->getLogger()->info('OAuth2 access token refresh');
274
+ $auth = $this->getOAuth2Service();
275
+ $auth->setRefreshToken($refreshToken);
276
+
277
+ $httpHandler = HttpHandlerFactory::build($this->getHttpClient());
278
+ $creds = $auth->fetchAuthToken($httpHandler);
279
+ if ($creds && isset($creds['access_token'])) {
280
+ $creds['created'] = time();
281
+ if (!isset($creds['refresh_token'])) {
282
+ $creds['refresh_token'] = $refreshToken;
283
+ }
284
+ $this->setAccessToken($creds);
285
+ }
286
+
287
+ return $creds;
288
+ }
289
+
290
+ /**
291
+ * Create a URL to obtain user authorization.
292
+ * The authorization endpoint allows the user to first
293
+ * authenticate, and then grant/deny the access request.
294
+ * @param string|array $scope The scope is expressed as an array or list of space-delimited strings.
295
+ * @return string
296
+ */
297
+ public function createAuthUrl($scope = null)
298
+ {
299
+ if (empty($scope)) {
300
+ $scope = $this->prepareScopes();
301
+ }
302
+ if (is_array($scope)) {
303
+ $scope = implode(' ', $scope);
304
+ }
305
+
306
+ // only accept one of prompt or approval_prompt
307
+ $approvalPrompt = $this->config['prompt']
308
+ ? null
309
+ : $this->config['approval_prompt'];
310
+
311
+ // include_granted_scopes should be string "true", string "false", or null
312
+ $includeGrantedScopes = $this->config['include_granted_scopes'] === null
313
+ ? null
314
+ : var_export($this->config['include_granted_scopes'], true);
315
+
316
+ $params = array_filter(
317
+ [
318
+ 'access_type' => $this->config['access_type'],
319
+ 'approval_prompt' => $approvalPrompt,
320
+ 'hd' => $this->config['hd'],
321
+ 'include_granted_scopes' => $includeGrantedScopes,
322
+ 'login_hint' => $this->config['login_hint'],
323
+ 'openid.realm' => $this->config['openid.realm'],
324
+ 'prompt' => $this->config['prompt'],
325
+ 'response_type' => 'code',
326
+ 'scope' => $scope,
327
+ 'state' => $this->config['state'],
328
+ ]
329
+ );
330
+
331
+ // If the list of scopes contains plus.login, add request_visible_actions
332
+ // to auth URL.
333
+ $rva = $this->config['request_visible_actions'];
334
+ if (strlen($rva) > 0 && false !== strpos($scope, 'plus.login')) {
335
+ $params['request_visible_actions'] = $rva;
336
+ }
337
+
338
+ $auth = $this->getOAuth2Service();
339
+
340
+ return (string) $auth->buildFullAuthorizationUri($params);
341
+ }
342
+
343
+ /**
344
+ * Adds auth listeners to the HTTP client based on the credentials
345
+ * set in the Google API Client object
346
+ *
347
+ * @param GuzzleHttp\ClientInterface $http the http client object.
348
+ * @return GuzzleHttp\ClientInterface the http client object
349
+ */
350
+ public function authorize(ClientInterface $http = null)
351
+ {
352
+ $credentials = null;
353
+ $token = null;
354
+ $scopes = null;
355
+ if (null === $http) {
356
+ $http = $this->getHttpClient();
357
+ }
358
+
359
+ // These conditionals represent the decision tree for authentication
360
+ // 1. Check for Application Default Credentials
361
+ // 2. Check for API Key
362
+ // 3a. Check for an Access Token
363
+ // 3b. If access token exists but is expired, try to refresh it
364
+ if ($this->isUsingApplicationDefaultCredentials()) {
365
+ $credentials = $this->createApplicationDefaultCredentials();
366
+ } elseif ($token = $this->getAccessToken()) {
367
+ $scopes = $this->prepareScopes();
368
+ // add refresh subscriber to request a new token
369
+ if (isset($token['refresh_token']) && $this->isAccessTokenExpired()) {
370
+ $credentials = $this->createUserRefreshCredentials(
371
+ $scopes,
372
+ $token['refresh_token']
373
+ );
374
+ }
375
+ }
376
+
377
+ $authHandler = $this->getAuthHandler();
378
+
379
+ if ($credentials) {
380
+ $callback = $this->config['token_callback'];
381
+ $http = $authHandler->attachCredentials($http, $credentials, $callback);
382
+ } elseif ($token) {
383
+ $http = $authHandler->attachToken($http, $token, (array) $scopes);
384
+ } elseif ($key = $this->config['developer_key']) {
385
+ $http = $authHandler->attachKey($http, $key);
386
+ }
387
+
388
+ return $http;
389
+ }
390
+
391
+ /**
392
+ * Set the configuration to use application default credentials for
393
+ * authentication
394
+ *
395
+ * @see https://developers.google.com/identity/protocols/application-default-credentials
396
+ * @param boolean $useAppCreds
397
+ */
398
+ public function useApplicationDefaultCredentials($useAppCreds = true)
399
+ {
400
+ $this->config['use_application_default_credentials'] = $useAppCreds;
401
+ }
402
+
403
+ /**
404
+ * To prevent useApplicationDefaultCredentials from inappropriately being
405
+ * called in a conditional
406
+ *
407
+ * @see https://developers.google.com/identity/protocols/application-default-credentials
408
+ */
409
+ public function isUsingApplicationDefaultCredentials()
410
+ {
411
+ return $this->config['use_application_default_credentials'];
412
+ }
413
+
414
+ /**
415
+ * @param string|array $token
416
+ * @throws InvalidArgumentException
417
+ */
418
+ public function setAccessToken($token)
419
+ {
420
+ if (is_string($token)) {
421
+ if ($json = json_decode($token, true)) {
422
+ $token = $json;
423
+ } else {
424
+ // assume $token is just the token string
425
+ $token = array(
426
+ 'access_token' => $token,
427
+ );
428
+ }
429
+ }
430
+ if ($token == null) {
431
+ throw new InvalidArgumentException('invalid json token');
432
+ }
433
+ if (!isset($token['access_token'])) {
434
+ throw new InvalidArgumentException("Invalid token format");
435
+ }
436
+ $this->token = $token;
437
+ }
438
+
439
+ public function getAccessToken()
440
+ {
441
+ return $this->token;
442
+ }
443
+
444
+ public function getRefreshToken()
445
+ {
446
+ if (isset($this->token['refresh_token'])) {
447
+ return $this->token['refresh_token'];
448
+ }
449
+ }
450
+
451
+ /**
452
+ * Returns if the access_token is expired.
453
+ * @return bool Returns True if the access_token is expired.
454
+ */
455
+ public function isAccessTokenExpired()
456
+ {
457
+ if (!$this->token) {
458
+ return true;
459
+ }
460
+
461
+ $created = 0;
462
+ if (isset($this->token['created'])) {
463
+ $created = $this->token['created'];
464
+ } elseif (isset($this->token['id_token'])) {
465
+ // check the ID token for "iat"
466
+ // signature verification is not required here, as we are just
467
+ // using this for convenience to save a round trip request
468
+ // to the Google API server
469
+ $idToken = $this->token['id_token'];
470
+ if (substr_count($idToken, '.') == 2) {
471
+ $parts = explode('.', $idToken);
472
+ $payload = json_decode(base64_decode($parts[1]), true);
473
+ if ($payload && isset($payload['iat'])) {
474
+ $created = $payload['iat'];
475
+ }
476
+ }
477
+ }
478
+
479
+ // If the token is set to expire in the next 30 seconds.
480
+ return ($created + ($this->token['expires_in'] - 30)) < time();
481
+ }
482
+
483
+ public function getAuth()
484
+ {
485
+ throw new BadMethodCallException(
486
+ 'This function no longer exists. See UPGRADING.md for more information'
487
+ );
488
+ }
489
+
490
+ public function setAuth($auth)
491
+ {
492
+ throw new BadMethodCallException(
493
+ 'This function no longer exists. See UPGRADING.md for more information'
494
+ );
495
+ }
496
+
497
+ /**
498
+ * Set the OAuth 2.0 Client ID.
499
+ * @param string $clientId
500
+ */
501
+ public function setClientId($clientId)
502
+ {
503
+ $this->config['client_id'] = $clientId;
504
+ }
505
+
506
+ public function getClientId()
507
+ {
508
+ return $this->config['client_id'];
509
+ }
510
+
511
+ /**
512
+ * Set the OAuth 2.0 Client Secret.
513
+ * @param string $clientSecret
514
+ */
515
+ public function setClientSecret($clientSecret)
516
+ {
517
+ $this->config['client_secret'] = $clientSecret;
518
+ }
519
+
520
+ public function getClientSecret()
521
+ {
522
+ return $this->config['client_secret'];
523
+ }
524
+
525
+ /**
526
+ * Set the OAuth 2.0 Redirect URI.
527
+ * @param string $redirectUri
528
+ */
529
+ public function setRedirectUri($redirectUri)
530
+ {
531
+ $this->config['redirect_uri'] = $redirectUri;
532
+ }
533
+
534
+ public function getRedirectUri()
535
+ {
536
+ return $this->config['redirect_uri'];
537
+ }
538
+
539
+ /**
540
+ * Set OAuth 2.0 "state" parameter to achieve per-request customization.
541
+ * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-3.1.2.2
542
+ * @param string $state
543
+ */
544
+ public function setState($state)
545
+ {
546
+ $this->config['state'] = $state;
547
+ }
548
+
549
+ /**
550
+ * @param string $accessType Possible values for access_type include:
551
+ * {@code "offline"} to request offline access from the user.
552
+ * {@code "online"} to request online access from the user.
553
+ */
554
+ public function setAccessType($accessType)
555
+ {
556
+ $this->config['access_type'] = $accessType;
557
+ }
558
+
559
+ /**
560
+ * @param string $approvalPrompt Possible values for approval_prompt include:
561
+ * {@code "force"} to force the approval UI to appear.
562
+ * {@code "auto"} to request auto-approval when possible. (This is the default value)
563
+ */
564
+ public function setApprovalPrompt($approvalPrompt)
565
+ {
566
+ $this->config['approval_prompt'] = $approvalPrompt;
567
+ }
568
+
569
+ /**
570
+ * Set the login hint, email address or sub id.
571
+ * @param string $loginHint
572
+ */
573
+ public function setLoginHint($loginHint)
574
+ {
575
+ $this->config['login_hint'] = $loginHint;
576
+ }
577
+
578
+ /**
579
+ * Set the application name, this is included in the User-Agent HTTP header.
580
+ * @param string $applicationName
581
+ */
582
+ public function setApplicationName($applicationName)
583
+ {
584
+ $this->config['application_name'] = $applicationName;
585
+ }
586
+
587
+ /**
588
+ * If 'plus.login' is included in the list of requested scopes, you can use
589
+ * this method to define types of app activities that your app will write.
590
+ * You can find a list of available types here:
591
+ * @link https://developers.google.com/+/api/moment-types
592
+ *
593
+ * @param array $requestVisibleActions Array of app activity types
594
+ */
595
+ public function setRequestVisibleActions($requestVisibleActions)
596
+ {
597
+ if (is_array($requestVisibleActions)) {
598
+ $requestVisibleActions = implode(" ", $requestVisibleActions);
599
+ }
600
+ $this->config['request_visible_actions'] = $requestVisibleActions;
601
+ }
602
+
603
+ /**
604
+ * Set the developer key to use, these are obtained through the API Console.
605
+ * @see http://code.google.com/apis/console-help/#generatingdevkeys
606
+ * @param string $developerKey
607
+ */
608
+ public function setDeveloperKey($developerKey)
609
+ {
610
+ $this->config['developer_key'] = $developerKey;
611
+ }
612
+
613
+ /**
614
+ * Set the hd (hosted domain) parameter streamlines the login process for
615
+ * Google Apps hosted accounts. By including the domain of the user, you
616
+ * restrict sign-in to accounts at that domain.
617
+ * @param $hd string - the domain to use.
618
+ */
619
+ public function setHostedDomain($hd)
620
+ {
621
+ $this->config['hd'] = $hd;
622
+ }
623
+
624
+ /**
625
+ * Set the prompt hint. Valid values are none, consent and select_account.
626
+ * If no value is specified and the user has not previously authorized
627
+ * access, then the user is shown a consent screen.
628
+ * @param $prompt string
629
+ */
630
+ public function setPrompt($prompt)
631
+ {
632
+ $this->config['prompt'] = $prompt;
633
+ }
634
+
635
+ /**
636
+ * openid.realm is a parameter from the OpenID 2.0 protocol, not from OAuth
637
+ * 2.0. It is used in OpenID 2.0 requests to signify the URL-space for which
638
+ * an authentication request is valid.
639
+ * @param $realm string - the URL-space to use.
640
+ */
641
+ public function setOpenidRealm($realm)
642
+ {
643
+ $this->config['openid.realm'] = $realm;
644
+ }
645
+
646
+ /**
647
+ * If this is provided with the value true, and the authorization request is
648
+ * granted, the authorization will include any previous authorizations
649
+ * granted to this user/application combination for other scopes.
650
+ * @param $include boolean - the URL-space to use.
651
+ */
652
+ public function setIncludeGrantedScopes($include)
653
+ {
654
+ $this->config['include_granted_scopes'] = $include;
655
+ }
656
+
657
+ /**
658
+ * sets function to be called when an access token is fetched
659
+ * @param callable $tokenCallback - function ($cacheKey, $accessToken)
660
+ */
661
+ public function setTokenCallback(callable $tokenCallback)
662
+ {
663
+ $this->config['token_callback'] = $tokenCallback;
664
+ }
665
+
666
+ /**
667
+ * Revoke an OAuth2 access token or refresh token. This method will revoke the current access
668
+ * token, if a token isn't provided.
669
+ *
670
+ * @param string|null $token The token (access token or a refresh token) that should be revoked.
671
+ * @return boolean Returns True if the revocation was successful, otherwise False.
672
+ */
673
+ public function revokeToken($token = null)
674
+ {
675
+ $tokenRevoker = new Google_AccessToken_Revoke(
676
+ $this->getHttpClient()
677
+ );
678
+
679
+ return $tokenRevoker->revokeToken($token ?: $this->getAccessToken());
680
+ }
681
+
682
+ /**
683
+ * Verify an id_token. This method will verify the current id_token, if one
684
+ * isn't provided.
685
+ *
686
+ * @throws LogicException
687
+ * @param string|null $idToken The token (id_token) that should be verified.
688
+ * @return array|false Returns the token payload as an array if the verification was
689
+ * successful, false otherwise.
690
+ */
691
+ public function verifyIdToken($idToken = null)
692
+ {
693
+ $tokenVerifier = new Google_AccessToken_Verify(
694
+ $this->getHttpClient(),
695
+ $this->getCache(),
696
+ $this->config['jwt']
697
+ );
698
+
699
+ if (null === $idToken) {
700
+ $token = $this->getAccessToken();
701
+ if (!isset($token['id_token'])) {
702
+ throw new LogicException(
703
+ 'id_token must be passed in or set as part of setAccessToken'
704
+ );
705
+ }
706
+ $idToken = $token['id_token'];
707
+ }
708
+
709
+ return $tokenVerifier->verifyIdToken(
710
+ $idToken,
711
+ $this->getClientId()
712
+ );
713
+ }
714
+
715
+ /**
716
+ * Set the scopes to be requested. Must be called before createAuthUrl().
717
+ * Will remove any previously configured scopes.
718
+ * @param array $scopes, ie: array('https://www.googleapis.com/auth/plus.login',
719
+ * 'https://www.googleapis.com/auth/moderator')
720
+ */
721
+ public function setScopes($scopes)
722
+ {
723
+ $this->requestedScopes = array();
724
+ $this->addScope($scopes);
725
+ }
726
+
727
+ /**
728
+ * This functions adds a scope to be requested as part of the OAuth2.0 flow.
729
+ * Will append any scopes not previously requested to the scope parameter.
730
+ * A single string will be treated as a scope to request. An array of strings
731
+ * will each be appended.
732
+ * @param $scope_or_scopes string|array e.g. "profile"
733
+ */
734
+ public function addScope($scope_or_scopes)
735
+ {
736
+ if (is_string($scope_or_scopes) && !in_array($scope_or_scopes, $this->requestedScopes)) {
737
+ $this->requestedScopes[] = $scope_or_scopes;
738
+ } else if (is_array($scope_or_scopes)) {
739
+ foreach ($scope_or_scopes as $scope) {
740
+ $this->addScope($scope);
741
+ }
742
+ }
743
+ }
744
+
745
+ /**
746
+ * Returns the list of scopes requested by the client
747
+ * @return array the list of scopes
748
+ *
749
+ */
750
+ public function getScopes()
751
+ {
752
+ return $this->requestedScopes;
753
+ }
754
+
755
+ /**
756
+ * @return array
757
+ * @visible For Testing
758
+ */
759
+ public function prepareScopes()
760
+ {
761
+ if (empty($this->requestedScopes)) {
762
+ return null;
763
+ }
764
+
765
+ return implode(' ', $this->requestedScopes);
766
+ }
767
+
768
+ /**
769
+ * Helper method to execute deferred HTTP requests.
770
+ *
771
+ * @param $request Psr\Http\Message\RequestInterface|Google_Http_Batch
772
+ * @throws Google_Exception
773
+ * @return object of the type of the expected class or Psr\Http\Message\ResponseInterface.
774
+ */
775
+ public function execute(RequestInterface $request, $expectedClass = null)
776
+ {
777
+ $request = $request->withHeader(
778
+ 'User-Agent',
779
+ $this->config['application_name']
780
+ . " " . self::USER_AGENT_SUFFIX
781
+ . $this->getLibraryVersion()
782
+ );
783
+
784
+ // call the authorize method
785
+ // this is where most of the grunt work is done
786
+ $http = $this->authorize();
787
+
788
+ return Google_Http_REST::execute($http, $request, $expectedClass, $this->config['retry']);
789
+ }
790
+
791
+ /**
792
+ * Declare whether batch calls should be used. This may increase throughput
793
+ * by making multiple requests in one connection.
794
+ *
795
+ * @param boolean $useBatch True if the batch support should
796
+ * be enabled. Defaults to False.
797
+ */
798
+ public function setUseBatch($useBatch)
799
+ {
800
+ // This is actually an alias for setDefer.
801
+ $this->setDefer($useBatch);
802
+ }
803
+
804
+ /**
805
+ * Are we running in Google AppEngine?
806
+ * return bool
807
+ */
808
+ public function isAppEngine()
809
+ {
810
+ return (isset($_SERVER['SERVER_SOFTWARE']) &&
811
+ strpos($_SERVER['SERVER_SOFTWARE'], 'Google App Engine') !== false);
812
+ }
813
+
814
+ public function setConfig($name, $value)
815
+ {
816
+ $this->config[$name] = $value;
817
+ }
818
+
819
+ public function getConfig($name, $default = null)
820
+ {
821
+ return isset($this->config[$name]) ? $this->config[$name] : $default;
822
+ }
823
+
824
+ /**
825
+ * For backwards compatibility
826
+ * alias for setAuthConfig
827
+ *
828
+ * @param string $file the configuration file
829
+ * @throws Google_Exception
830
+ * @deprecated
831
+ */
832
+ public function setAuthConfigFile($file)
833
+ {
834
+ $this->setAuthConfig($file);
835
+ }
836
+
837
+ /**
838
+ * Set the auth config from new or deprecated JSON config.
839
+ * This structure should match the file downloaded from
840
+ * the "Download JSON" button on in the Google Developer
841
+ * Console.
842
+ * @param string|array $config the configuration json
843
+ * @throws Google_Exception
844
+ */
845
+ public function setAuthConfig($config)
846
+ {
847
+ if (is_string($config)) {
848
+ if (!file_exists($config)) {
849
+ throw new InvalidArgumentException('file does not exist');
850
+ }
851
+
852
+ $json = file_get_contents($config);
853
+
854
+ if (!$config = json_decode($json, true)) {
855
+ throw new LogicException('invalid json for auth config');
856
+ }
857
+ }
858
+
859
+ $key = isset($config['installed']) ? 'installed' : 'web';
860
+ if (isset($config['type']) && $config['type'] == 'service_account') {
861
+ // application default credentials
862
+ $this->useApplicationDefaultCredentials();
863
+
864
+ // set the information from the config
865
+ $this->setClientId($config['client_id']);
866
+ $this->config['client_email'] = $config['client_email'];
867
+ $this->config['signing_key'] = $config['private_key'];
868
+ $this->config['signing_algorithm'] = 'HS256';
869
+ } elseif (isset($config[$key])) {
870
+ // old-style
871
+ $this->setClientId($config[$key]['client_id']);
872
+ $this->setClientSecret($config[$key]['client_secret']);
873
+ if (isset($config[$key]['redirect_uris'])) {
874
+ $this->setRedirectUri($config[$key]['redirect_uris'][0]);
875
+ }
876
+ } else {
877
+ // new-style
878
+ $this->setClientId($config['client_id']);
879
+ $this->setClientSecret($config['client_secret']);
880
+ if (isset($config['redirect_uris'])) {
881
+ $this->setRedirectUri($config['redirect_uris'][0]);
882
+ }
883
+ }
884
+ }
885
+
886
+ /**
887
+ * Use when the service account has been delegated domain wide access.
888
+ *
889
+ * @param string subject an email address account to impersonate
890
+ */
891
+ public function setSubject($subject)
892
+ {
893
+ $this->config['subject'] = $subject;
894
+ }
895
+
896
+ /**
897
+ * Declare whether making API calls should make the call immediately, or
898
+ * return a request which can be called with ->execute();
899
+ *
900
+ * @param boolean $defer True if calls should not be executed right away.
901
+ */
902
+ public function setDefer($defer)
903
+ {
904
+ $this->deferExecution = $defer;
905
+ }
906
+
907
+ /**
908
+ * Whether or not to return raw requests
909
+ * @return boolean
910
+ */
911
+ public function shouldDefer()
912
+ {
913
+ return $this->deferExecution;
914
+ }
915
+
916
+ /**
917
+ * @return Google\Auth\OAuth2 implementation
918
+ */
919
+ public function getOAuth2Service()
920
+ {
921
+ if (!isset($this->auth)) {
922
+ $this->auth = $this->createOAuth2Service();
923
+ }
924
+
925
+ return $this->auth;
926
+ }
927
+
928
+ /**
929
+ * create a default google auth object
930
+ */
931
+ protected function createOAuth2Service()
932
+ {
933
+ $auth = new OAuth2(
934
+ [
935
+ 'clientId' => $this->getClientId(),
936
+ 'clientSecret' => $this->getClientSecret(),
937
+ 'authorizationUri' => self::OAUTH2_AUTH_URL,
938
+ 'tokenCredentialUri' => self::OAUTH2_TOKEN_URI,
939
+ 'redirectUri' => $this->getRedirectUri(),
940
+ 'issuer' => $this->config['client_id'],
941
+ 'signingKey' => $this->config['signing_key'],
942
+ 'signingAlgorithm' => $this->config['signing_algorithm'],
943
+ ]
944
+ );
945
+
946
+ return $auth;
947
+ }
948
+
949
+ /**
950
+ * Set the Cache object
951
+ * @param Psr\Cache\CacheItemPoolInterface $cache
952
+ */
953
+ public function setCache(CacheItemPoolInterface $cache)
954
+ {
955
+ $this->cache = $cache;
956
+ }
957
+
958
+ /**
959
+ * @return Psr\Cache\CacheItemPoolInterface Cache implementation
960
+ */
961
+ public function getCache()
962
+ {
963
+ if (!$this->cache) {
964
+ $this->cache = $this->createDefaultCache();
965
+ }
966
+
967
+ return $this->cache;
968
+ }
969
+
970
+ /**
971
+ * @return Google\Auth\CacheInterface Cache implementation
972
+ */
973
+ public function setCacheConfig(array $cacheConfig)
974
+ {
975
+ $this->config['cache_config'] = $cacheConfig;
976
+ }
977
+
978
+ /**
979
+ * Set the Logger object
980
+ * @param Psr\Log\LoggerInterface $logger
981
+ */
982
+ public function setLogger(LoggerInterface $logger)
983
+ {
984
+ $this->logger = $logger;
985
+ }
986
+
987
+ /**
988
+ * @return Psr\Log\LoggerInterface implementation
989
+ */
990
+ public function getLogger()
991
+ {
992
+ if (!isset($this->logger)) {
993
+ $this->logger = $this->createDefaultLogger();
994
+ }
995
+
996
+ return $this->logger;
997
+ }
998
+
999
+ protected function createDefaultLogger()
1000
+ {
1001
+ $logger = new Logger('google-api-php-client');
1002
+ if ($this->isAppEngine()) {
1003
+ $handler = new MonologSyslogHandler('app', LOG_USER, Logger::NOTICE);
1004
+ } else {
1005
+ $handler = new MonologStreamHandler('php://stderr', Logger::NOTICE);
1006
+ }
1007
+ $logger->pushHandler($handler);
1008
+
1009
+ return $logger;
1010
+ }
1011
+
1012
+ protected function createDefaultCache()
1013
+ {
1014
+ return new MemoryCacheItemPool;
1015
+ }
1016
+
1017
+ /**
1018
+ * Set the Http Client object
1019
+ * @param GuzzleHttp\ClientInterface $http
1020
+ */
1021
+ public function setHttpClient(ClientInterface $http)
1022
+ {
1023
+ $this->http = $http;
1024
+ }
1025
+
1026
+ /**
1027
+ * @return GuzzleHttp\ClientInterface implementation
1028
+ */
1029
+ public function getHttpClient()
1030
+ {
1031
+ if (null === $this->http) {
1032
+ $this->http = $this->createDefaultHttpClient();
1033
+ }
1034
+
1035
+ return $this->http;
1036
+ }
1037
+
1038
+ protected function createDefaultHttpClient()
1039
+ {
1040
+ $options = ['exceptions' => false];
1041
+
1042
+ $version = ClientInterface::VERSION;
1043
+ if ('5' === $version[0]) {
1044
+ $options = [
1045
+ 'base_url' => $this->config['base_path'],
1046
+ 'defaults' => $options,
1047
+ ];
1048
+ if ($this->isAppEngine()) {
1049
+ // set StreamHandler on AppEngine by default
1050
+ $options['handler'] = new StreamHandler();
1051
+ $options['defaults']['verify'] = '/etc/ca-certificates.crt';
1052
+ }
1053
+ } else {
1054
+ // guzzle 6
1055
+ $options['base_uri'] = $this->config['base_path'];
1056
+ }
1057
+
1058
+ return new Client($options);
1059
+ }
1060
+
1061
+ private function createApplicationDefaultCredentials()
1062
+ {
1063
+ $scopes = $this->prepareScopes();
1064
+ $sub = $this->config['subject'];
1065
+ $signingKey = $this->config['signing_key'];
1066
+
1067
+ // create credentials using values supplied in setAuthConfig
1068
+ if ($signingKey) {
1069
+ $serviceAccountCredentials = array(
1070
+ 'client_id' => $this->config['client_id'],
1071
+ 'client_email' => $this->config['client_email'],
1072
+ 'private_key' => $signingKey,
1073
+ 'type' => 'service_account',
1074
+ );
1075
+ $credentials = CredentialsLoader::makeCredentials($scopes, $serviceAccountCredentials);
1076
+ } else {
1077
+ $credentials = ApplicationDefaultCredentials::getCredentials($scopes);
1078
+ }
1079
+
1080
+ // for service account domain-wide authority (impersonating a user)
1081
+ // @see https://developers.google.com/identity/protocols/OAuth2ServiceAccount
1082
+ if ($sub) {
1083
+ if (!$credentials instanceof ServiceAccountCredentials) {
1084
+ throw new DomainException('domain-wide authority requires service account credentials');
1085
+ }
1086
+
1087
+ $credentials->setSub($sub);
1088
+ }
1089
+
1090
+ return $credentials;
1091
+ }
1092
+
1093
+ protected function getAuthHandler()
1094
+ {
1095
+ // Be very careful using the cache, as the underlying auth library's cache
1096
+ // implementation is naive, and the cache keys do not account for user
1097
+ // sessions.
1098
+ //
1099
+ // @see https://github.com/google/google-api-php-client/issues/821
1100
+ return Google_AuthHandler_AuthHandlerFactory::build(
1101
+ $this->getCache(),
1102
+ $this->config['cache_config']
1103
+ );
1104
+ }
1105
+
1106
+ private function createUserRefreshCredentials($scope, $refreshToken)
1107
+ {
1108
+ $creds = array_filter(
1109
+ array(
1110
+ 'client_id' => $this->getClientId(),
1111
+ 'client_secret' => $this->getClientSecret(),
1112
+ 'refresh_token' => $refreshToken,
1113
+ )
1114
+ );
1115
+
1116
+ return new UserRefreshCredentials($scope, $creds);
1117
+ }
1118
+ }
vendor/google/apiclient/src/Google/Collection.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!class_exists('Google_Client')) {
4
+ require_once __DIR__ . '/autoload.php';
5
+ }
6
+
7
+ /**
8
+ * Extension to the regular Google_Model that automatically
9
+ * exposes the items array for iteration, so you can just
10
+ * iterate over the object rather than a reference inside.
11
+ */
12
+ class Google_Collection extends Google_Model implements Iterator, Countable
13
+ {
14
+ protected $collection_key = 'items';
15
+
16
+ public function rewind()
17
+ {
18
+ if (isset($this->{$this->collection_key})
19
+ && is_array($this->{$this->collection_key})) {
20
+ reset($this->{$this->collection_key});
21
+ }
22
+ }
23
+
24
+ public function current()
25
+ {
26
+ $this->coerceType($this->key());
27
+ if (is_array($this->{$this->collection_key})) {
28
+ return current($this->{$this->collection_key});
29
+ }
30
+ }
31
+
32
+ public function key()
33
+ {
34
+ if (isset($this->{$this->collection_key})
35
+ && is_array($this->{$this->collection_key})) {
36
+ return key($this->{$this->collection_key});
37
+ }
38
+ }
39
+
40
+ public function next()
41
+ {
42
+ return next($this->{$this->collection_key});
43
+ }
44
+
45
+ public function valid()
46
+ {
47
+ $key = $this->key();
48
+ return $key !== null && $key !== false;
49
+ }
50
+
51
+ public function count()
52
+ {
53
+ if (!isset($this->{$this->collection_key})) {
54
+ return 0;
55
+ }
56
+ return count($this->{$this->collection_key});
57
+ }
58
+
59
+ public function offsetExists($offset)
60
+ {
61
+ if (!is_numeric($offset)) {
62
+ return parent::offsetExists($offset);
63
+ }
64
+ return isset($this->{$this->collection_key}[$offset]);
65
+ }
66
+
67
+ public function offsetGet($offset)
68
+ {
69
+ if (!is_numeric($offset)) {
70
+ return parent::offsetGet($offset);
71
+ }
72
+ $this->coerceType($offset);
73
+ return $this->{$this->collection_key}[$offset];
74
+ }
75
+
76
+ public function offsetSet($offset, $value)
77
+ {
78
+ if (!is_numeric($offset)) {
79
+ return parent::offsetSet($offset, $value);
80
+ }
81
+ $this->{$this->collection_key}[$offset] = $value;
82
+ }
83
+
84
+ public function offsetUnset($offset)
85
+ {
86
+ if (!is_numeric($offset)) {
87
+ return parent::offsetUnset($offset);
88
+ }
89
+ unset($this->{$this->collection_key}[$offset]);
90
+ }
91
+
92
+ private function coerceType($offset)
93
+ {
94
+ $keyType = $this->keyType($this->collection_key);
95
+ if ($keyType && !is_object($this->{$this->collection_key}[$offset])) {
96
+ $this->{$this->collection_key}[$offset] =
97
+ new $keyType($this->{$this->collection_key}[$offset]);
98
+ }
99
+ }
100
+ }
vendor/google/apiclient/src/Google/Exception.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2013 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Google_Exception extends Exception
19
+ {
20
+ }
vendor/google/apiclient/src/Google/Http/Batch.php ADDED
@@ -0,0 +1,249 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2012 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ use GuzzleHttp\Psr7;
19
+ use GuzzleHttp\Psr7\Request;
20
+ use GuzzleHttp\Psr7\Response;
21
+ use Psr\Http\Message\RequestInterface;
22
+ use Psr\Http\Message\ResponseInterface;
23
+
24
+ /**
25
+ * Class to handle batched requests to the Google API service.
26
+ */
27
+ class Google_Http_Batch
28
+ {
29
+ const BATCH_PATH = 'batch';
30
+
31
+ private static $CONNECTION_ESTABLISHED_HEADERS = array(
32
+ "HTTP/1.0 200 Connection established\r\n\r\n",
33
+ "HTTP/1.1 200 Connection established\r\n\r\n",
34
+ );
35
+
36
+ /** @var string Multipart Boundary. */
37
+ private $boundary;
38
+
39
+ /** @var array service requests to be executed. */
40
+ private $requests = array();
41
+
42
+ /** @var Google_Client */
43
+ private $client;
44
+
45
+ private $rootUrl;
46
+
47
+ private $batchPath;
48
+
49
+ public function __construct(
50
+ Google_Client $client,
51
+ $boundary = false,
52
+ $rootUrl = null,
53
+ $batchPath = null
54
+ ) {
55
+ $this->client = $client;
56
+ $this->boundary = $boundary ?: mt_rand();
57
+ $this->rootUrl = rtrim($rootUrl ?: $this->client->getConfig('base_path'), '/');
58
+ $this->batchPath = $batchPath ?: self::BATCH_PATH;
59
+ }
60
+
61
+ public function add(RequestInterface $request, $key = false)
62
+ {
63
+ if (false == $key) {
64
+ $key = mt_rand();
65
+ }
66
+
67
+ $this->requests[$key] = $request;
68
+ }
69
+
70
+ public function execute()
71
+ {
72
+ $body = '';
73
+ $classes = array();
74
+ $batchHttpTemplate = <<<EOF
75
+ --%s
76
+ Content-Type: application/http
77
+ Content-Transfer-Encoding: binary
78
+ MIME-Version: 1.0
79
+ Content-ID: %s
80
+
81
+ %s
82
+ %s%s
83
+
84
+
85
+ EOF;
86
+
87
+ /** @var Google_Http_Request $req */
88
+ foreach ($this->requests as $key => $request) {
89
+ $firstLine = sprintf(
90
+ '%s %s HTTP/%s',
91
+ $request->getMethod(),
92
+ $request->getRequestTarget(),
93
+ $request->getProtocolVersion()
94
+ );
95
+
96
+ $content = (string) $request->getBody();
97
+
98
+ $headers = '';
99
+ foreach ($request->getHeaders() as $name => $values) {
100
+ $headers .= sprintf("%s:%s\r\n", $name, implode(', ', $values));
101
+ }
102
+
103
+ $body .= sprintf(
104
+ $batchHttpTemplate,
105
+ $this->boundary,
106
+ $key,
107
+ $firstLine,
108
+ $headers,
109
+ $content ? "\n".$content : ''
110
+ );
111
+
112
+ $classes['response-' . $key] = $request->getHeaderLine('X-Php-Expected-Class');
113
+ }
114
+
115
+ $body .= "--{$this->boundary}--";
116
+ $body = trim($body);
117
+ $url = $this->rootUrl . '/' . $this->batchPath;
118
+ $headers = array(
119
+ 'Content-Type' => sprintf('multipart/mixed; boundary=%s', $this->boundary),
120
+ 'Content-Length' => strlen($body),
121
+ );
122
+
123
+ $request = new Request(
124
+ 'POST',
125
+ $url,
126
+ $headers,
127
+ $body
128
+ );
129
+
130
+ $response = $this->client->execute($request);
131
+
132
+ return $this->parseResponse($response, $classes);
133
+ }
134
+
135
+ public function parseResponse(ResponseInterface $response, $classes = array())
136
+ {
137
+ $contentType = $response->getHeaderLine('content-type');
138
+ $contentType = explode(';', $contentType);
139
+ $boundary = false;
140
+ foreach ($contentType as $part) {
141
+ $part = explode('=', $part, 2);
142
+ if (isset($part[0]) && 'boundary' == trim($part[0])) {
143
+ $boundary = $part[1];
144
+ }
145
+ }
146
+
147
+ $body = (string) $response->getBody();
148
+ if (!empty($body)) {
149
+ $body = str_replace("--$boundary--", "--$boundary", $body);
150
+ $parts = explode("--$boundary", $body);
151
+ $responses = array();
152
+ $requests = array_values($this->requests);
153
+
154
+ foreach ($parts as $i => $part) {
155
+ $part = trim($part);
156
+ if (!empty($part)) {
157
+ list($rawHeaders, $part) = explode("\r\n\r\n", $part, 2);
158
+ $headers = $this->parseRawHeaders($rawHeaders);
159
+
160
+ $status = substr($part, 0, strpos($part, "\n"));
161
+ $status = explode(" ", $status);
162
+ $status = $status[1];
163
+
164
+ list($partHeaders, $partBody) = $this->parseHttpResponse($part, false);
165
+ $response = new Response(
166
+ $status,
167
+ $partHeaders,
168
+ Psr7\stream_for($partBody)
169
+ );
170
+
171
+ // Need content id.
172
+ $key = $headers['content-id'];
173
+
174
+ try {
175
+ $response = Google_Http_REST::decodeHttpResponse($response, $requests[$i-1]);
176
+ } catch (Google_Service_Exception $e) {
177
+ // Store the exception as the response, so successful responses
178
+ // can be processed.
179
+ $response = $e;
180
+ }
181
+
182
+ $responses[$key] = $response;
183
+ }
184
+ }
185
+
186
+ return $responses;
187
+ }
188
+
189
+ return null;
190
+ }
191
+
192
+ private function parseRawHeaders($rawHeaders)
193
+ {
194
+ $headers = array();
195
+ $responseHeaderLines = explode("\r\n", $rawHeaders);
196
+ foreach ($responseHeaderLines as $headerLine) {
197
+ if ($headerLine && strpos($headerLine, ':') !== false) {
198
+ list($header, $value) = explode(': ', $headerLine, 2);
199
+ $header = strtolower($header);
200
+ if (isset($headers[$header])) {
201
+ $headers[$header] .= "\n" . $value;
202
+ } else {
203
+ $headers[$header] = $value;
204
+ }
205
+ }
206
+ }
207
+ return $headers;
208
+ }
209
+
210
+ /**
211
+ * Used by the IO lib and also the batch processing.
212
+ *
213
+ * @param $respData
214
+ * @param $headerSize
215
+ * @return array
216
+ */
217
+ private function parseHttpResponse($respData, $headerSize)
218
+ {
219
+ // check proxy header
220
+ foreach (self::$CONNECTION_ESTABLISHED_HEADERS as $established_header) {
221
+ if (stripos($respData, $established_header) !== false) {
222
+ // existed, remove it
223
+ $respData = str_ireplace($established_header, '', $respData);
224
+ // Subtract the proxy header size unless the cURL bug prior to 7.30.0
225
+ // is present which prevented the proxy header size from being taken into
226
+ // account.
227
+ // @TODO look into this
228
+ // if (!$this->needsQuirk()) {
229
+ // $headerSize -= strlen($established_header);
230
+ // }
231
+ break;
232
+ }
233
+ }
234
+
235
+ if ($headerSize) {
236
+ $responseBody = substr($respData, $headerSize);
237
+ $responseHeaders = substr($respData, 0, $headerSize);
238
+ } else {
239
+ $responseSegments = explode("\r\n\r\n", $respData, 2);
240
+ $responseHeaders = $responseSegments[0];
241
+ $responseBody = isset($responseSegments[1]) ? $responseSegments[1] :
242
+ null;
243
+ }
244
+
245
+ $responseHeaders = $this->parseRawHeaders($responseHeaders);
246
+
247
+ return array($responseHeaders, $responseBody);
248
+ }
249
+ }
vendor/google/apiclient/src/Google/Http/MediaFileUpload.php ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2012 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ use GuzzleHttp\Psr7;
19
+ use GuzzleHttp\Psr7\Request;
20
+ use GuzzleHttp\Psr7\Uri;
21
+ use Psr\Http\Message\RequestInterface;
22
+
23
+ /**
24
+ * Manage large file uploads, which may be media but can be any type
25
+ * of sizable data.
26
+ */
27
+ class Google_Http_MediaFileUpload
28
+ {
29
+ const UPLOAD_MEDIA_TYPE = 'media';
30
+ const UPLOAD_MULTIPART_TYPE = 'multipart';
31
+ const UPLOAD_RESUMABLE_TYPE = 'resumable';
32
+
33
+ /** @var string $mimeType */
34
+ private $mimeType;
35
+
36
+ /** @var string $data */
37
+ private $data;
38
+
39
+ /** @var bool $resumable */
40
+ private $resumable;
41
+
42
+ /** @var int $chunkSize */
43
+ private $chunkSize;
44
+
45
+ /** @var int $size */
46
+ private $size;
47
+
48
+ /** @var string $resumeUri */
49
+ private $resumeUri;
50
+
51
+ /** @var int $progress */
52
+ private $progress;
53
+
54
+ /** @var Google_Client */
55
+ private $client;
56
+
57
+ /** @var Psr\Http\Message\RequestInterface */
58
+ private $request;
59
+
60
+ /** @var string */
61
+ private $boundary;
62
+
63
+ /**
64
+ * Result code from last HTTP call
65
+ * @var int
66
+ */
67
+ private $httpResultCode;
68
+
69
+ /**
70
+ * @param $mimeType string
71
+ * @param $data string The bytes you want to upload.
72
+ * @param $resumable bool
73
+ * @param bool $chunkSize File will be uploaded in chunks of this many bytes.
74
+ * only used if resumable=True
75
+ */
76
+ public function __construct(
77
+ Google_Client $client,
78
+ RequestInterface $request,
79
+ $mimeType,
80
+ $data,
81
+ $resumable = false,
82
+ $chunkSize = false
83
+ ) {
84
+ $this->client = $client;
85
+ $this->request = $request;
86
+ $this->mimeType = $mimeType;
87
+ $this->data = $data;
88
+ $this->resumable = $resumable;
89
+ $this->chunkSize = $chunkSize;
90
+ $this->progress = 0;
91
+
92
+ $this->process();
93
+ }
94
+
95
+ /**
96
+ * Set the size of the file that is being uploaded.
97
+ * @param $size - int file size in bytes
98
+ */
99
+ public function setFileSize($size)
100
+ {
101
+ $this->size = $size;
102
+ }
103
+
104
+ /**
105
+ * Return the progress on the upload
106
+ * @return int progress in bytes uploaded.
107
+ */
108
+ public function getProgress()
109
+ {
110
+ return $this->progress;
111
+ }
112
+
113
+ /**
114
+ * Send the next part of the file to upload.
115
+ * @param [$chunk] the next set of bytes to send. If false will used $data passed
116
+ * at construct time.
117
+ */
118
+ public function nextChunk($chunk = false)
119
+ {
120
+ $resumeUri = $this->getResumeUri();
121
+
122
+ if (false == $chunk) {
123
+ $chunk = substr($this->data, $this->progress, $this->chunkSize);
124
+ }
125
+
126
+ $lastBytePos = $this->progress + strlen($chunk) - 1;
127
+ $headers = array(
128
+ 'content-range' => "bytes $this->progress-$lastBytePos/$this->size",
129
+ 'content-length' => strlen($chunk),
130
+ 'expect' => '',
131
+ );
132
+
133
+ $request = new Request(
134
+ 'PUT',
135
+ $resumeUri,
136
+ $headers,
137
+ Psr7\stream_for($chunk)
138
+ );
139
+
140
+ return $this->makePutRequest($request);
141
+ }
142
+
143
+ /**
144
+ * Return the HTTP result code from the last call made.
145
+ * @return int code
146
+ */
147
+ public function getHttpResultCode()
148
+ {
149
+ return $this->httpResultCode;
150
+ }
151
+
152
+ /**
153
+ * Sends a PUT-Request to google drive and parses the response,
154
+ * setting the appropiate variables from the response()
155
+ *
156
+ * @param Google_Http_Request $httpRequest the Reuqest which will be send
157
+ *
158
+ * @return false|mixed false when the upload is unfinished or the decoded http response
159
+ *
160
+ */
161
+ private function makePutRequest(RequestInterface $request)
162
+ {
163
+ $response = $this->client->execute($request);
164
+ $this->httpResultCode = $response->getStatusCode();
165
+
166
+ if (308 == $this->httpResultCode) {
167
+ // Track the amount uploaded.
168
+ $range = $response->getHeaderLine('range');
169
+ if ($range) {
170
+ $range_array = explode('-', $range);
171
+ $this->progress = $range_array[1] + 1;
172
+ }
173
+
174
+ // Allow for changing upload URLs.
175
+ $location = $response->getHeaderLine('location');
176
+ if ($location) {
177
+ $this->resumeUri = $location;
178
+ }
179
+
180
+ // No problems, but upload not complete.
181
+ return false;
182
+ }
183
+
184
+ return Google_Http_REST::decodeHttpResponse($response, $this->request);
185
+ }
186
+
187
+ /**
188
+ * Resume a previously unfinished upload
189
+ * @param $resumeUri the resume-URI of the unfinished, resumable upload.
190
+ */
191
+ public function resume($resumeUri)
192
+ {
193
+ $this->resumeUri = $resumeUri;
194
+ $headers = array(
195
+ 'content-range' => "bytes */$this->size",
196
+ 'content-length' => 0,
197
+ );
198
+ $httpRequest = new Request(
199
+ 'PUT',
200
+ $this->resumeUri,
201
+ $headers
202
+ );
203
+
204
+ return $this->makePutRequest($httpRequest);
205
+ }
206
+
207
+ /**
208
+ * @return Psr\Http\Message\RequestInterface $request
209
+ * @visible for testing
210
+ */
211
+ private function process()
212
+ {
213
+ $this->transformToUploadUrl();
214
+ $request = $this->request;
215
+
216
+ $postBody = '';
217
+ $contentType = false;
218
+
219
+ $meta = (string) $request->getBody();
220
+ $meta = is_string($meta) ? json_decode($meta, true) : $meta;
221
+
222
+ $uploadType = $this->getUploadType($meta);
223
+ $request = $request->withUri(
224
+ Uri::withQueryValue($request->getUri(), 'uploadType', $uploadType)
225
+ );
226
+
227
+ $mimeType = $this->mimeType ?: $request->getHeaderLine('content-type');
228
+
229
+ if (self::UPLOAD_RESUMABLE_TYPE == $uploadType) {
230
+ $contentType = $mimeType;
231
+ $postBody = is_string($meta) ? $meta : json_encode($meta);
232
+ } else if (self::UPLOAD_MEDIA_TYPE == $uploadType) {
233
+ $contentType = $mimeType;
234
+ $postBody = $this->data;
235
+ } else if (self::UPLOAD_MULTIPART_TYPE == $uploadType) {
236
+ // This is a multipart/related upload.
237
+ $boundary = $this->boundary ?: mt_rand();
238
+ $boundary = str_replace('"', '', $boundary);
239
+ $contentType = 'multipart/related; boundary=' . $boundary;
240
+ $related = "--$boundary\r\n";
241
+ $related .= "Content-Type: application/json; charset=UTF-8\r\n";
242
+ $related .= "\r\n" . json_encode($meta) . "\r\n";
243
+ $related .= "--$boundary\r\n";
244
+ $related .= "Content-Type: $mimeType\r\n";
245
+ $related .= "Content-Transfer-Encoding: base64\r\n";
246
+ $related .= "\r\n" . base64_encode($this->data) . "\r\n";
247
+ $related .= "--$boundary--";
248
+ $postBody = $related;
249
+ }
250
+
251
+ $request = $request->withBody(Psr7\stream_for($postBody));
252
+
253
+ if (isset($contentType) && $contentType) {
254
+ $request = $request->withHeader('content-type', $contentType);
255
+ }
256
+
257
+ return $this->request = $request;
258
+ }
259
+
260
+ /**
261
+ * Valid upload types:
262
+ * - resumable (UPLOAD_RESUMABLE_TYPE)
263
+ * - media (UPLOAD_MEDIA_TYPE)
264
+ * - multipart (UPLOAD_MULTIPART_TYPE)
265
+ * @param $meta
266
+ * @return string
267
+ * @visible for testing
268
+ */
269
+ public function getUploadType($meta)
270
+ {
271
+ if ($this->resumable) {
272
+ return self::UPLOAD_RESUMABLE_TYPE;
273
+ }
274
+
275
+ if (false == $meta && $this->data) {
276
+ return self::UPLOAD_MEDIA_TYPE;
277
+ }
278
+
279
+ return self::UPLOAD_MULTIPART_TYPE;
280
+ }
281
+
282
+ public function getResumeUri()
283
+ {
284
+ if (null === $this->resumeUri) {
285
+ $this->resumeUri = $this->fetchResumeUri();
286
+ }
287
+
288
+ return $this->resumeUri;
289
+ }
290
+
291
+ private function fetchResumeUri()
292
+ {
293
+ $body = $this->request->getBody();
294
+ if ($body) {
295
+ $headers = array(
296
+ 'content-type' => 'application/json; charset=UTF-8',
297
+ 'content-length' => $body->getSize(),
298
+ 'x-upload-content-type' => $this->mimeType,
299
+ 'x-upload-content-length' => $this->size,
300
+ 'expect' => '',
301
+ );
302
+ foreach ($headers as $key => $value) {
303
+ $this->request = $this->request->withHeader($key, $value);
304
+ }
305
+ }
306
+
307
+ $response = $this->client->execute($this->request, false);
308
+ $location = $response->getHeaderLine('location');
309
+ $code = $response->getStatusCode();
310
+
311
+ if (200 == $code && true == $location) {
312
+ return $location;
313
+ }
314
+
315
+ $message = $code;
316
+ $body = json_decode((string) $this->request->getBody(), true);
317
+ if (isset($body['error']['errors'])) {
318
+ $message .= ': ';
319
+ foreach ($body['error']['errors'] as $error) {
320
+ $message .= "{$error[domain]}, {$error[message]};";
321
+ }
322
+ $message = rtrim($message, ';');
323
+ }
324
+
325
+ $error = "Failed to start the resumable upload (HTTP {$message})";
326
+ $this->client->getLogger()->error($error);
327
+
328
+ throw new Google_Exception($error);
329
+ }
330
+
331
+ private function transformToUploadUrl()
332
+ {
333
+ $parts = parse_url((string) $this->request->getUri());
334
+ if (!isset($parts['path'])) {
335
+ $parts['path'] = '';
336
+ }
337
+ $parts['path'] = '/upload' . $parts['path'];
338
+ $uri = Uri::fromParts($parts);
339
+ $this->request = $this->request->withUri($uri);
340
+ }
341
+
342
+ public function setChunkSize($chunkSize)
343
+ {
344
+ $this->chunkSize = $chunkSize;
345
+ }
346
+
347
+ public function getRequest()
348
+ {
349
+ return $this->request;
350
+ }
351
+ }
vendor/google/apiclient/src/Google/Http/REST.php ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2010 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
19
+ use GuzzleHttp\ClientInterface;
20
+ use GuzzleHttp\Exception\RequestException;
21
+ use GuzzleHttp\Psr7\Response;
22
+ use Psr\Http\Message\RequestInterface;
23
+ use Psr\Http\Message\ResponseInterface;
24
+
25
+ /**
26
+ * This class implements the RESTful transport of apiServiceRequest()'s
27
+ */
28
+ class Google_Http_REST
29
+ {
30
+ /**
31
+ * Executes a Psr\Http\Message\RequestInterface and (if applicable) automatically retries
32
+ * when errors occur.
33
+ *
34
+ * @param Google_Client $client
35
+ * @param Psr\Http\Message\RequestInterface $req
36
+ * @return array decoded result
37
+ * @throws Google_Service_Exception on server side error (ie: not authenticated,
38
+ * invalid or malformed post body, invalid url)
39
+ */
40
+ public static function execute(
41
+ ClientInterface $client,
42
+ RequestInterface $request,
43
+ $expectedClass = null,
44
+ $config = array(),
45
+ $retryMap = null
46
+ ) {
47
+ $runner = new Google_Task_Runner(
48
+ $config,
49
+ sprintf('%s %s', $request->getMethod(), (string) $request->getUri()),
50
+ array(get_class(), 'doExecute'),
51
+ array($client, $request, $expectedClass)
52
+ );
53
+
54
+ if (null !== $retryMap) {
55
+ $runner->setRetryMap($retryMap);
56
+ }
57
+
58
+ return $runner->run();
59
+ }
60
+
61
+ /**
62
+ * Executes a Psr\Http\Message\RequestInterface
63
+ *
64
+ * @param Google_Client $client
65
+ * @param Psr\Http\Message\RequestInterface $request
66
+ * @return array decoded result
67
+ * @throws Google_Service_Exception on server side error (ie: not authenticated,
68
+ * invalid or malformed post body, invalid url)
69
+ */
70
+ public static function doExecute(ClientInterface $client, RequestInterface $request, $expectedClass = null)
71
+ {
72
+ try {
73
+ $httpHandler = HttpHandlerFactory::build($client);
74
+ $response = $httpHandler($request);
75
+ } catch (RequestException $e) {
76
+ // if Guzzle throws an exception, catch it and handle the response
77
+ if (!$e->hasResponse()) {
78
+ throw $e;
79
+ }
80
+
81
+ $response = $e->getResponse();
82
+ // specific checking for Guzzle 5: convert to PSR7 response
83
+ if ($response instanceof \GuzzleHttp\Message\ResponseInterface) {
84
+ $response = new Response(
85
+ $response->getStatusCode(),
86
+ $response->getHeaders() ?: [],
87
+ $response->getBody(),
88
+ $response->getProtocolVersion(),
89
+ $response->getReasonPhrase()
90
+ );
91
+ }
92
+ }
93
+
94
+ return self::decodeHttpResponse($response, $request, $expectedClass);
95
+ }
96
+
97
+ /**
98
+ * Decode an HTTP Response.
99
+ * @static
100
+ * @throws Google_Service_Exception
101
+ * @param Psr\Http\Message\RequestInterface $response The http response to be decoded.
102
+ * @param Psr\Http\Message\ResponseInterface $response
103
+ * @return mixed|null
104
+ */
105
+ public static function decodeHttpResponse(
106
+ ResponseInterface $response,
107
+ RequestInterface $request = null,
108
+ $expectedClass = null
109
+ ) {
110
+ $code = $response->getStatusCode();
111
+
112
+ // retry strategy
113
+ if (intVal($code) >= 400) {
114
+ // if we errored out, it should be safe to grab the response body
115
+ $body = (string) $response->getBody();
116
+
117
+ // Check if we received errors, and add those to the Exception for convenience
118
+ throw new Google_Service_Exception($body, $code, null, self::getResponseErrors($body));
119
+ }
120
+
121
+ // Ensure we only pull the entire body into memory if the request is not
122
+ // of media type
123
+ $body = self::decodeBody($response, $request);
124
+
125
+ if ($expectedClass = self::determineExpectedClass($expectedClass, $request)) {
126
+ $json = json_decode($body, true);
127
+
128
+ return new $expectedClass($json);
129
+ }
130
+
131
+ return $response;
132
+ }
133
+
134
+ private static function decodeBody(ResponseInterface $response, RequestInterface $request = null)
135
+ {
136
+ if (self::isAltMedia($request)) {
137
+ // don't decode the body, it's probably a really long string
138
+ return '';
139
+ }
140
+
141
+ return (string) $response->getBody();
142
+ }
143
+
144
+ private static function determineExpectedClass($expectedClass, RequestInterface $request = null)
145
+ {
146
+ // "false" is used to explicitly prevent an expected class from being returned
147
+ if (false === $expectedClass) {
148
+ return null;
149
+ }
150
+
151
+ // if we don't have a request, we just use what's passed in
152
+ if (null === $request) {
153
+ return $expectedClass;
154
+ }
155
+
156
+ // return what we have in the request header if one was not supplied
157
+ return $expectedClass ?: $request->getHeaderLine('X-Php-Expected-Class');
158
+ }
159
+
160
+ private static function getResponseErrors($body)
161
+ {
162
+ $json = json_decode($body, true);
163
+
164
+ if (isset($json['error']['errors'])) {
165
+ return $json['error']['errors'];
166
+ }
167
+
168
+ return null;
169
+ }
170
+
171
+ private static function isAltMedia(RequestInterface $request = null)
172
+ {
173
+ if ($request && $qs = $request->getUri()->getQuery()) {
174
+ parse_str($qs, $query);
175
+ if (isset($query['alt']) && $query['alt'] == 'media') {
176
+ return true;
177
+ }
178
+ }
179
+
180
+ return false;
181
+ }
182
+ }
vendor/google/apiclient/src/Google/Model.php ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2011 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ /**
19
+ * This class defines attributes, valid values, and usage which is generated
20
+ * from a given json schema.
21
+ * http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5
22
+ *
23
+ */
24
+ class Google_Model implements ArrayAccess
25
+ {
26
+ /**
27
+ * If you need to specify a NULL JSON value, use Google_Model::NULL_VALUE
28
+ * instead - it will be replaced when converting to JSON with a real null.
29
+ */
30
+ const NULL_VALUE = "{}gapi-php-null";
31
+ protected $internal_gapi_mappings = array();
32
+ protected $modelData = array();
33
+ protected $processed = array();
34
+
35
+ /**
36
+ * Polymorphic - accepts a variable number of arguments dependent
37
+ * on the type of the model subclass.
38
+ */
39
+ final public function __construct()
40
+ {
41
+ if (func_num_args() == 1 && is_array(func_get_arg(0))) {
42
+ // Initialize the model with the array's contents.
43
+ $array = func_get_arg(0);
44
+ $this->mapTypes($array);
45
+ }
46
+ $this->gapiInit();
47
+ }
48
+
49
+ /**
50
+ * Getter that handles passthrough access to the data array, and lazy object creation.
51
+ * @param string $key Property name.
52
+ * @return mixed The value if any, or null.
53
+ */
54
+ public function __get($key)
55
+ {
56
+ $keyType = $this->keyType($key);
57
+ $keyDataType = $this->dataType($key);
58
+ if ($keyType && !isset($this->processed[$key])) {
59
+ if (isset($this->modelData[$key])) {
60
+ $val = $this->modelData[$key];
61
+ } elseif ($keyDataType == 'array' || $keyDataType == 'map') {
62
+ $val = array();
63
+ } else {
64
+ $val = null;
65
+ }
66
+
67
+ if ($this->isAssociativeArray($val)) {
68
+ if ($keyDataType && 'map' == $keyDataType) {
69
+ foreach ($val as $arrayKey => $arrayItem) {
70
+ $this->modelData[$key][$arrayKey] =
71
+ new $keyType($arrayItem);
72
+ }
73
+ } else {
74
+ $this->modelData[$key] = new $keyType($val);
75
+ }
76
+ } else if (is_array($val)) {
77
+ $arrayObject = array();
78
+ foreach ($val as $arrayIndex => $arrayItem) {
79
+ $arrayObject[$arrayIndex] = new $keyType($arrayItem);
80
+ }
81
+ $this->modelData[$key] = $arrayObject;
82
+ }
83
+ $this->processed[$key] = true;
84
+ }
85
+
86
+ return isset($this->modelData[$key]) ? $this->modelData[$key] : null;
87
+ }
88
+
89
+ /**
90
+ * Initialize this object's properties from an array.
91
+ *
92
+ * @param array $array Used to seed this object's properties.
93
+ * @return void
94
+ */
95
+ protected function mapTypes($array)
96
+ {
97
+ // Hard initialise simple types, lazy load more complex ones.
98
+ foreach ($array as $key => $val) {
99
+ if ($keyType = $this->keyType($key)) {
100
+ $dataType = $this->dataType($key);
101
+ if ($dataType == 'array' || $dataType == 'map') {
102
+ $this->$key = array();
103
+ foreach ($val as $itemKey => $itemVal) {
104
+ if ($itemVal instanceof $keyType) {
105
+ $this->{$key}[$itemKey] = $itemVal;
106
+ } else {
107
+ $this->{$key}[$itemKey] = new $keyType($itemVal);
108
+ }
109
+ }
110
+ } elseif ($val instanceof $keyType) {
111
+ $this->$key = $val;
112
+ } else {
113
+ $this->$key = new $keyType($val);
114
+ }
115
+ unset($array[$key]);
116
+ } elseif (property_exists($this, $key)) {
117
+ $this->$key = $val;
118
+ unset($array[$key]);
119
+ } elseif (property_exists($this, $camelKey = $this->camelCase($key))) {
120
+ // This checks if property exists as camelCase, leaving it in array as snake_case
121
+ // in case of backwards compatibility issues.
122
+ $this->$camelKey = $val;
123
+ }
124
+ }
125
+ $this->modelData = $array;
126
+ }
127
+
128
+ /**
129
+ * Blank initialiser to be used in subclasses to do post-construction initialisation - this
130
+ * avoids the need for subclasses to have to implement the variadics handling in their
131
+ * constructors.
132
+ */
133
+ protected function gapiInit()
134
+ {
135
+ return;
136
+ }
137
+
138
+ /**
139
+ * Create a simplified object suitable for straightforward
140
+ * conversion to JSON. This is relatively expensive
141
+ * due to the usage of reflection, but shouldn't be called
142
+ * a whole lot, and is the most straightforward way to filter.
143
+ */
144
+ public function toSimpleObject()
145
+ {
146
+ $object = new stdClass();
147
+
148
+ // Process all other data.
149
+ foreach ($this->modelData as $key => $val) {
150
+ $result = $this->getSimpleValue($val);
151
+ if ($result !== null) {
152
+ $object->$key = $this->nullPlaceholderCheck($result);
153
+ }
154
+ }
155
+
156
+ // Process all public properties.
157
+ $reflect = new ReflectionObject($this);
158
+ $props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);
159
+ foreach ($props as $member) {
160
+ $name = $member->getName();
161
+ $result = $this->getSimpleValue($this->$name);
162
+ if ($result !== null) {
163
+ $name = $this->getMappedName($name);
164
+ $object->$name = $this->nullPlaceholderCheck($result);
165
+ }
166
+ }
167
+
168
+ return $object;
169
+ }
170
+
171
+ /**
172
+ * Handle different types of values, primarily
173
+ * other objects and map and array data types.
174
+ */
175
+ private function getSimpleValue($value)
176
+ {
177
+ if ($value instanceof Google_Model) {
178
+ return $value->toSimpleObject();
179
+ } else if (is_array($value)) {
180
+ $return = array();
181
+ foreach ($value as $key => $a_value) {
182
+ $a_value = $this->getSimpleValue($a_value);
183
+ if ($a_value !== null) {
184
+ $key = $this->getMappedName($key);
185
+ $return[$key] = $this->nullPlaceholderCheck($a_value);
186
+ }
187
+ }
188
+ return $return;
189
+ }
190
+ return $value;
191
+ }
192
+
193
+ /**
194
+ * Check whether the value is the null placeholder and return true null.
195
+ */
196
+ private function nullPlaceholderCheck($value)
197
+ {
198
+ if ($value === self::NULL_VALUE) {
199
+ return null;
200
+ }
201
+ return $value;
202
+ }
203
+
204
+ /**
205
+ * If there is an internal name mapping, use that.
206
+ */
207
+ private function getMappedName($key)
208
+ {
209
+ if (isset($this->internal_gapi_mappings, $this->internal_gapi_mappings[$key])) {
210
+ $key = $this->internal_gapi_mappings[$key];
211
+ }
212
+ return $key;
213
+ }
214
+
215
+ /**
216
+ * Returns true only if the array is associative.
217
+ * @param array $array
218
+ * @return bool True if the array is associative.
219
+ */
220
+ protected function isAssociativeArray($array)
221
+ {
222
+ if (!is_array($array)) {
223
+ return false;
224
+ }
225
+ $keys = array_keys($array);
226
+ foreach ($keys as $key) {
227
+ if (is_string($key)) {
228
+ return true;
229
+ }
230
+ }
231
+ return false;
232
+ }
233
+
234
+ /**
235
+ * Verify if $obj is an array.
236
+ * @throws Google_Exception Thrown if $obj isn't an array.
237
+ * @param array $obj Items that should be validated.
238
+ * @param string $method Method expecting an array as an argument.
239
+ */
240
+ public function assertIsArray($obj, $method)
241
+ {
242
+ if ($obj && !is_array($obj)) {
243
+ throw new Google_Exception(
244
+ "Incorrect parameter type passed to $method(). Expected an array."
245
+ );
246
+ }
247
+ }
248
+
249
+ public function offsetExists($offset)
250
+ {
251
+ return isset($this->$offset) || isset($this->modelData[$offset]);
252
+ }
253
+
254
+ public function offsetGet($offset)
255
+ {
256
+ return isset($this->$offset) ?
257
+ $this->$offset :
258
+ $this->__get($offset);
259
+ }
260
+
261
+ public function offsetSet($offset, $value)
262
+ {
263
+ if (property_exists($this, $offset)) {
264
+ $this->$offset = $value;
265
+ } else {
266
+ $this->modelData[$offset] = $value;
267
+ $this->processed[$offset] = true;
268
+ }
269
+ }
270
+
271
+ public function offsetUnset($offset)
272
+ {
273
+ unset($this->modelData[$offset]);
274
+ }
275
+
276
+ protected function keyType($key)
277
+ {
278
+ $keyType = $key . "Type";
279
+
280
+ // ensure keyType is a valid class
281
+ if (property_exists($this, $keyType) && class_exists($this->$keyType)) {
282
+ return $this->$keyType;
283
+ }
284
+ }
285
+
286
+ protected function dataType($key)
287
+ {
288
+ $dataType = $key . "DataType";
289
+
290
+ if (property_exists($this, $dataType)) {
291
+ return $this->$dataType;
292
+ }
293
+ }
294
+
295
+ public function __isset($key)
296
+ {
297
+ return isset($this->modelData[$key]);
298
+ }
299
+
300
+ public function __unset($key)
301
+ {
302
+ unset($this->modelData[$key]);
303
+ }
304
+
305
+ /**
306
+ * Convert a string to camelCase
307
+ * @param string $value
308
+ * @return string
309
+ */
310
+ private function camelCase($value)
311
+ {
312
+ $value = ucwords(str_replace(array('-', '_'), ' ', $value));
313
+ $value = str_replace(' ', '', $value);
314
+ $value[0] = strtolower($value[0]);
315
+ return $value;
316
+ }
317
+ }
vendor/google/apiclient/src/Google/Service.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2010 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Google_Service
19
+ {
20
+ public $batchPath;
21
+ public $rootUrl;
22
+ public $version;
23
+ public $servicePath;
24
+ public $availableScopes;
25
+ public $resource;
26
+ private $client;
27
+
28
+ public function __construct(Google_Client $client)
29
+ {
30
+ $this->client = $client;
31
+ }
32
+
33
+ /**
34
+ * Return the associated Google_Client class.
35
+ * @return Google_Client
36
+ */
37
+ public function getClient()
38
+ {
39
+ return $this->client;
40
+ }
41
+
42
+ /**
43
+ * Create a new HTTP Batch handler for this service
44
+ *
45
+ * @return Google_Http_Batch
46
+ */
47
+ public function createBatch()
48
+ {
49
+ return new Google_Http_Batch(
50
+ $this->client,
51
+ false,
52
+ $this->rootUrl,
53
+ $this->batchPath
54
+ );
55
+ }
56
+ }
vendor/google/apiclient/src/Google/Service/Exception.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Google_Service_Exception extends Google_Exception
19
+ {
20
+ /**
21
+ * Optional list of errors returned in a JSON body of an HTTP error response.
22
+ */
23
+ protected $errors = array();
24
+
25
+ /**
26
+ * Override default constructor to add the ability to set $errors and a retry
27
+ * map.
28
+ *
29
+ * @param string $message
30
+ * @param int $code
31
+ * @param Exception|null $previous
32
+ * @param [{string, string}] errors List of errors returned in an HTTP
33
+ * response. Defaults to [].
34
+ * @param array|null $retryMap Map of errors with retry counts.
35
+ */
36
+ public function __construct(
37
+ $message,
38
+ $code = 0,
39
+ Exception $previous = null,
40
+ $errors = array()
41
+ ) {
42
+ if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
43
+ parent::__construct($message, $code, $previous);
44
+ } else {
45
+ parent::__construct($message, $code);
46
+ }
47
+
48
+ $this->errors = $errors;
49
+ }
50
+
51
+ /**
52
+ * An example of the possible errors returned.
53
+ *
54
+ * {
55
+ * "domain": "global",
56
+ * "reason": "authError",
57
+ * "message": "Invalid Credentials",
58
+ * "locationType": "header",
59
+ * "location": "Authorization",
60
+ * }
61
+ *
62
+ * @return [{string, string}] List of errors return in an HTTP response or [].
63
+ */
64
+ public function getErrors()
65
+ {
66
+ return $this->errors;
67
+ }
68
+ }
vendor/google/apiclient/src/Google/Service/Resource.php ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2010 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ use GuzzleHttp\Psr7\Request;
19
+
20
+ /**
21
+ * Implements the actual methods/resources of the discovered Google API using magic function
22
+ * calling overloading (__call()), which on call will see if the method name (plus.activities.list)
23
+ * is available in this service, and if so construct an apiHttpRequest representing it.
24
+ *
25
+ */
26
+ class Google_Service_Resource
27
+ {
28
+ // Valid query parameters that work, but don't appear in discovery.
29
+ private $stackParameters = array(
30
+ 'alt' => array('type' => 'string', 'location' => 'query'),
31
+ 'fields' => array('type' => 'string', 'location' => 'query'),
32
+ 'trace' => array('type' => 'string', 'location' => 'query'),
33
+ 'userIp' => array('type' => 'string', 'location' => 'query'),
34
+ 'quotaUser' => array('type' => 'string', 'location' => 'query'),
35
+ 'data' => array('type' => 'string', 'location' => 'body'),
36
+ 'mimeType' => array('type' => 'string', 'location' => 'header'),
37
+ 'uploadType' => array('type' => 'string', 'location' => 'query'),
38
+ 'mediaUpload' => array('type' => 'complex', 'location' => 'query'),
39
+ 'prettyPrint' => array('type' => 'string', 'location' => 'query'),
40
+ );
41
+
42
+ /** @var string $rootUrl */
43
+ private $rootUrl;
44
+
45
+ /** @var Google_Client $client */
46
+ private $client;
47
+
48
+ /** @var string $serviceName */
49
+ private $serviceName;
50
+
51
+ /** @var string $servicePath */
52
+ private $servicePath;
53
+
54
+ /** @var string $resourceName */
55
+ private $resourceName;
56
+
57
+ /** @var array $methods */
58
+ private $methods;
59
+
60
+ public function __construct($service, $serviceName, $resourceName, $resource)
61
+ {
62
+ $this->rootUrl = $service->rootUrl;
63
+ $this->client = $service->getClient();
64
+ $this->servicePath = $service->servicePath;
65
+ $this->serviceName = $serviceName;
66
+ $this->resourceName = $resourceName;
67
+ $this->methods = is_array($resource) && isset($resource['methods']) ?
68
+ $resource['methods'] :
69
+ array($resourceName => $resource);
70
+ }
71
+
72
+ /**
73
+ * TODO: This function needs simplifying.
74
+ * @param $name
75
+ * @param $arguments
76
+ * @param $expectedClass - optional, the expected class name
77
+ * @return Google_Http_Request|expectedClass
78
+ * @throws Google_Exception
79
+ */
80
+ public function call($name, $arguments, $expectedClass = null)
81
+ {
82
+ if (! isset($this->methods[$name])) {
83
+ $this->client->getLogger()->error(
84
+ 'Service method unknown',
85
+ array(
86
+ 'service' => $this->serviceName,
87
+ 'resource' => $this->resourceName,
88
+ 'method' => $name
89
+ )
90
+ );
91
+
92
+ throw new Google_Exception(
93
+ "Unknown function: " .
94
+ "{$this->serviceName}->{$this->resourceName}->{$name}()"
95
+ );
96
+ }
97
+ $method = $this->methods[$name];
98
+ $parameters = $arguments[0];
99
+
100
+ // postBody is a special case since it's not defined in the discovery
101
+ // document as parameter, but we abuse the param entry for storing it.
102
+ $postBody = null;
103
+ if (isset($parameters['postBody'])) {
104
+ if ($parameters['postBody'] instanceof Google_Model) {
105
+ // In the cases the post body is an existing object, we want
106
+ // to use the smart method to create a simple object for
107
+ // for JSONification.
108
+ $parameters['postBody'] = $parameters['postBody']->toSimpleObject();
109
+ } else if (is_object($parameters['postBody'])) {
110
+ // If the post body is another kind of object, we will try and
111
+ // wrangle it into a sensible format.
112
+ $parameters['postBody'] =
113
+ $this->convertToArrayAndStripNulls($parameters['postBody']);
114
+ }
115
+ $postBody = (array) $parameters['postBody'];
116
+ unset($parameters['postBody']);
117
+ }
118
+
119
+ // TODO: optParams here probably should have been
120
+ // handled already - this may well be redundant code.
121
+ if (isset($parameters['optParams'])) {
122
+ $optParams = $parameters['optParams'];
123
+ unset($parameters['optParams']);
124
+ $parameters = array_merge($parameters, $optParams);
125
+ }
126
+
127
+ if (!isset($method['parameters'])) {
128
+ $method['parameters'] = array();
129
+ }
130
+
131
+ $method['parameters'] = array_merge(
132
+ $this->stackParameters,
133
+ $method['parameters']
134
+ );
135
+
136
+ foreach ($parameters as $key => $val) {
137
+ if ($key != 'postBody' && ! isset($method['parameters'][$key])) {
138
+ $this->client->getLogger()->error(
139
+ 'Service parameter unknown',
140
+ array(
141
+ 'service' => $this->serviceName,
142
+ 'resource' => $this->resourceName,
143
+ 'method' => $name,
144
+ 'parameter' => $key
145
+ )
146
+ );
147
+ throw new Google_Exception("($name) unknown parameter: '$key'");
148
+ }
149
+ }
150
+
151
+ foreach ($method['parameters'] as $paramName => $paramSpec) {
152
+ if (isset($paramSpec['required']) &&
153
+ $paramSpec['required'] &&
154
+ ! isset($parameters[$paramName])
155
+ ) {
156
+ $this->client->getLogger()->error(
157
+ 'Service parameter missing',
158
+ array(
159
+ 'service' => $this->serviceName,
160
+ 'resource' => $this->resourceName,
161
+ 'method' => $name,
162
+ 'parameter' => $paramName
163
+ )
164
+ );
165
+ throw new Google_Exception("($name) missing required param: '$paramName'");
166
+ }
167
+ if (isset($parameters[$paramName])) {
168
+ $value = $parameters[$paramName];
169
+ $parameters[$paramName] = $paramSpec;
170
+ $parameters[$paramName]['value'] = $value;
171
+ unset($parameters[$paramName]['required']);
172
+ } else {
173
+ // Ensure we don't pass nulls.
174
+ unset($parameters[$paramName]);
175
+ }
176
+ }
177
+
178
+ $this->client->getLogger()->info(
179
+ 'Service Call',
180
+ array(
181
+ 'service' => $this->serviceName,
182
+ 'resource' => $this->resourceName,
183
+ 'method' => $name,
184
+ 'arguments' => $parameters,
185
+ )
186
+ );
187
+
188
+ // build the service uri
189
+ $url = $this->createRequestUri(
190
+ $method['path'],
191
+ $parameters
192
+ );
193
+
194
+ // NOTE: because we're creating the request by hand,
195
+ // and because the service has a rootUrl property
196
+ // the "base_uri" of the Http Client is not accounted for
197
+ $request = new Request(
198
+ $method['httpMethod'],
199
+ $url,
200
+ ['content-type' => 'application/json'],
201
+ $postBody ? json_encode($postBody) : ''
202
+ );
203
+
204
+ // support uploads
205
+ if (isset($parameters['data'])) {
206
+ $mimeType = isset($parameters['mimeType'])
207
+ ? $parameters['mimeType']['value']
208
+ : 'application/octet-stream';
209
+ $data = $parameters['data']['value'];
210
+ $upload = new Google_Http_MediaFileUpload($this->client, $request, $mimeType, $data);
211
+
212
+ // pull down the modified request
213
+ $request = $upload->getRequest();
214
+ }
215
+
216
+ // if this is a media type, we will return the raw response
217
+ // rather than using an expected class
218
+ if (isset($parameters['alt']) && $parameters['alt']['value'] == 'media') {
219
+ $expectedClass = null;
220
+ }
221
+
222
+ // if the client is marked for deferring, rather than
223
+ // execute the request, return the response
224
+ if ($this->client->shouldDefer()) {
225
+ // @TODO find a better way to do this
226
+ $request = $request
227
+ ->withHeader('X-Php-Expected-Class', $expectedClass);
228
+
229
+ return $request;
230
+ }
231
+
232
+ return $this->client->execute($request, $expectedClass);
233
+ }
234
+
235
+ protected function convertToArrayAndStripNulls($o)
236
+ {
237
+ $o = (array) $o;
238
+ foreach ($o as $k => $v) {
239
+ if ($v === null) {
240
+ unset($o[$k]);
241
+ } elseif (is_object($v) || is_array($v)) {
242
+ $o[$k] = $this->convertToArrayAndStripNulls($o[$k]);
243
+ }
244
+ }
245
+ return $o;
246
+ }
247
+
248
+ /**
249
+ * Parse/expand request parameters and create a fully qualified
250
+ * request uri.
251
+ * @static
252
+ * @param string $restPath
253
+ * @param array $params
254
+ * @return string $requestUrl
255
+ */
256
+ public function createRequestUri($restPath, $params)
257
+ {
258
+ // code for leading slash
259
+ $requestUrl = $this->servicePath . $restPath;
260
+ if ($this->rootUrl) {
261
+ if ('/' !== substr($this->rootUrl, -1) && '/' !== substr($requestUrl, 0, 1)) {
262
+ $requestUrl = '/' . $requestUrl;
263
+ }
264
+ $requestUrl = $this->rootUrl . $requestUrl;
265
+ }
266
+ $uriTemplateVars = array();
267
+ $queryVars = array();
268
+ foreach ($params as $paramName => $paramSpec) {
269
+ if ($paramSpec['type'] == 'boolean') {
270
+ $paramSpec['value'] = $paramSpec['value'] ? 'true' : 'false';
271
+ }
272
+ if ($paramSpec['location'] == 'path') {
273
+ $uriTemplateVars[$paramName] = $paramSpec['value'];
274
+ } else if ($paramSpec['location'] == 'query') {
275
+ if (is_array($paramSpec['value'])) {
276
+ foreach ($paramSpec['value'] as $value) {
277
+ $queryVars[] = $paramName . '=' . rawurlencode(rawurldecode($value));
278
+ }
279
+ } else {
280
+ $queryVars[] = $paramName . '=' . rawurlencode(rawurldecode($paramSpec['value']));
281
+ }
282
+ }
283
+ }
284
+
285
+ if (count($uriTemplateVars)) {
286
+ $uriTemplateParser = new Google_Utils_UriTemplate();
287
+ $requestUrl = $uriTemplateParser->parse($requestUrl, $uriTemplateVars);
288
+ }
289
+
290
+ if (count($queryVars)) {
291
+ $requestUrl .= '?' . implode($queryVars, '&');
292
+ }
293
+
294
+ return $requestUrl;
295
+ }
296
+ }
vendor/google/apiclient/src/Google/Task/Exception.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ class Google_Task_Exception extends Google_Exception
19
+ {
20
+ }
vendor/google/apiclient/src/Google/Task/Retryable.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ /**
19
+ * Interface for checking how many times a given task can be retried following
20
+ * a failure.
21
+ */
22
+ interface Google_Task_Retryable
23
+ {
24
+ }
vendor/google/apiclient/src/Google/Task/Runner.php ADDED
@@ -0,0 +1,281 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ /**
19
+ * A task runner with exponential backoff support.
20
+ *
21
+ * @see https://developers.google.com/drive/web/handle-errors#implementing_exponential_backoff
22
+ */
23
+ class Google_Task_Runner
24
+ {
25
+ const TASK_RETRY_NEVER = 0;
26
+ const TASK_RETRY_ONCE = 1;
27
+ const TASK_RETRY_ALWAYS = -1;
28
+
29
+ /**
30
+ * @var integer $maxDelay The max time (in seconds) to wait before a retry.
31
+ */
32
+ private $maxDelay = 60;
33
+ /**
34
+ * @var integer $delay The previous delay from which the next is calculated.
35
+ */
36
+ private $delay = 1;
37
+
38
+ /**
39
+ * @var integer $factor The base number for the exponential back off.
40
+ */
41
+ private $factor = 2;
42
+ /**
43
+ * @var float $jitter A random number between -$jitter and $jitter will be
44
+ * added to $factor on each iteration to allow for a better distribution of
45
+ * retries.
46
+ */
47
+ private $jitter = 0.5;
48
+
49
+ /**
50
+ * @var integer $attempts The number of attempts that have been tried so far.
51
+ */
52
+ private $attempts = 0;
53
+ /**
54
+ * @var integer $maxAttempts The max number of attempts allowed.
55
+ */
56
+ private $maxAttempts = 1;
57
+
58
+ /**
59
+ * @var callable $action The task to run and possibly retry.
60
+ */
61
+ private $action;
62
+ /**
63
+ * @var array $arguments The task arguments.
64
+ */
65
+ private $arguments;
66
+
67
+ /**
68
+ * @var array $retryMap Map of errors with retry counts.
69
+ */
70
+ protected $retryMap = [
71
+ '500' => self::TASK_RETRY_ALWAYS,
72
+ '503' => self::TASK_RETRY_ALWAYS,
73
+ 'rateLimitExceeded' => self::TASK_RETRY_ALWAYS,
74
+ 'userRateLimitExceeded' => self::TASK_RETRY_ALWAYS,
75
+ 6 => self::TASK_RETRY_ALWAYS, // CURLE_COULDNT_RESOLVE_HOST
76
+ 7 => self::TASK_RETRY_ALWAYS, // CURLE_COULDNT_CONNECT
77
+ 28 => self::TASK_RETRY_ALWAYS, // CURLE_OPERATION_TIMEOUTED
78
+ 35 => self::TASK_RETRY_ALWAYS, // CURLE_SSL_CONNECT_ERROR
79
+ 52 => self::TASK_RETRY_ALWAYS // CURLE_GOT_NOTHING
80
+ ];
81
+
82
+ /**
83
+ * Creates a new task runner with exponential backoff support.
84
+ *
85
+ * @param array $config The task runner config
86
+ * @param string $name The name of the current task (used for logging)
87
+ * @param callable $action The task to run and possibly retry
88
+ * @param array $arguments The task arguments
89
+ * @throws Google_Task_Exception when misconfigured
90
+ */
91
+ public function __construct(
92
+ $config,
93
+ $name,
94
+ $action,
95
+ array $arguments = array()
96
+ ) {
97
+ if (isset($config['initial_delay'])) {
98
+ if ($config['initial_delay'] < 0) {
99
+ throw new Google_Task_Exception(
100
+ 'Task configuration `initial_delay` must not be negative.'
101
+ );
102
+ }
103
+
104
+ $this->delay = $config['initial_delay'];
105
+ }
106
+
107
+ if (isset($config['max_delay'])) {
108
+ if ($config['max_delay'] <= 0) {
109
+ throw new Google_Task_Exception(
110
+ 'Task configuration `max_delay` must be greater than 0.'
111
+ );
112
+ }
113
+
114
+ $this->maxDelay = $config['max_delay'];
115
+ }
116
+
117
+ if (isset($config['factor'])) {
118
+ if ($config['factor'] <= 0) {
119
+ throw new Google_Task_Exception(
120
+ 'Task configuration `factor` must be greater than 0.'
121
+ );
122
+ }
123
+
124
+ $this->factor = $config['factor'];
125
+ }
126
+
127
+ if (isset($config['jitter'])) {
128
+ if ($config['jitter'] <= 0) {
129
+ throw new Google_Task_Exception(
130
+ 'Task configuration `jitter` must be greater than 0.'
131
+ );
132
+ }
133
+
134
+ $this->jitter = $config['jitter'];
135
+ }
136
+
137
+ if (isset($config['retries'])) {
138
+ if ($config['retries'] < 0) {
139
+ throw new Google_Task_Exception(
140
+ 'Task configuration `retries` must not be negative.'
141
+ );
142
+ }
143
+ $this->maxAttempts += $config['retries'];
144
+ }
145
+
146
+ if (!is_callable($action)) {
147
+ throw new Google_Task_Exception(
148
+ 'Task argument `$action` must be a valid callable.'
149
+ );
150
+ }
151
+
152
+ $this->action = $action;
153
+ $this->arguments = $arguments;
154
+ }
155
+
156
+ /**
157
+ * Checks if a retry can be attempted.
158
+ *
159
+ * @return boolean
160
+ */
161
+ public function canAttempt()
162
+ {
163
+ return $this->attempts < $this->maxAttempts;
164
+ }
165
+
166
+ /**
167
+ * Runs the task and (if applicable) automatically retries when errors occur.
168
+ *
169
+ * @return mixed
170
+ * @throws Google_Task_Retryable on failure when no retries are available.
171
+ */
172
+ public function run()
173
+ {
174
+ while ($this->attempt()) {
175
+ try {
176
+ return call_user_func_array($this->action, $this->arguments);
177
+ } catch (Google_Service_Exception $exception) {
178
+ $allowedRetries = $this->allowedRetries(
179
+ $exception->getCode(),
180
+ $exception->getErrors()
181
+ );
182
+
183
+ if (!$this->canAttempt() || !$allowedRetries) {
184
+ throw $exception;
185
+ }
186
+
187
+ if ($allowedRetries > 0) {
188
+ $this->maxAttempts = min(
189
+ $this->maxAttempts,
190
+ $this->attempts + $allowedRetries
191
+ );
192
+ }
193
+ }
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Runs a task once, if possible. This is useful for bypassing the `run()`
199
+ * loop.
200
+ *
201
+ * NOTE: If this is not the first attempt, this function will sleep in
202
+ * accordance to the backoff configurations before running the task.
203
+ *
204
+ * @return boolean
205
+ */
206
+ public function attempt()
207
+ {
208
+ if (!$this->canAttempt()) {
209
+ return false;
210
+ }
211
+
212
+ if ($this->attempts > 0) {
213
+ $this->backOff();
214
+ }
215
+
216
+ $this->attempts++;
217
+ return true;
218
+ }
219
+
220
+ /**
221
+ * Sleeps in accordance to the backoff configurations.
222
+ */
223
+ private function backOff()
224
+ {
225
+ $delay = $this->getDelay();
226
+
227
+ usleep($delay * 1000000);
228
+ }
229
+
230
+ /**
231
+ * Gets the delay (in seconds) for the current backoff period.
232
+ *
233
+ * @return float
234
+ */
235
+ private function getDelay()
236
+ {
237
+ $jitter = $this->getJitter();
238
+ $factor = $this->attempts > 1 ? $this->factor + $jitter : 1 + abs($jitter);
239
+
240
+ return $this->delay = min($this->maxDelay, $this->delay * $factor);
241
+ }
242
+
243
+ /**
244
+ * Gets the current jitter (random number between -$this->jitter and
245
+ * $this->jitter).
246
+ *
247
+ * @return float
248
+ */
249
+ private function getJitter()
250
+ {
251
+ return $this->jitter * 2 * mt_rand() / mt_getrandmax() - $this->jitter;
252
+ }
253
+
254
+ /**
255
+ * Gets the number of times the associated task can be retried.
256
+ *
257
+ * NOTE: -1 is returned if the task can be retried indefinitely
258
+ *
259
+ * @return integer
260
+ */
261
+ public function allowedRetries($code, $errors = array())
262
+ {
263
+ if (isset($this->retryMap[$code])) {
264
+ return $this->retryMap[$code];
265
+ }
266
+
267
+ if (
268
+ !empty($errors) &&
269
+ isset($errors[0]['reason'], $this->retryMap[$errors[0]['reason']])
270
+ ) {
271
+ return $this->retryMap[$errors[0]['reason']];
272
+ }
273
+
274
+ return 0;
275
+ }
276
+
277
+ public function setRetryMap($retryMap)
278
+ {
279
+ $this->retryMap = $retryMap;
280
+ }
281
+ }
vendor/google/apiclient/src/Google/Utils/UriTemplate.php ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2013 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ /**
19
+ * Implementation of levels 1-3 of the URI Template spec.
20
+ * @see http://tools.ietf.org/html/rfc6570
21
+ */
22
+ class Google_Utils_UriTemplate
23
+ {
24
+ const TYPE_MAP = "1";
25
+ const TYPE_LIST = "2";
26
+ const TYPE_SCALAR = "4";
27
+
28
+ /**
29
+ * @var $operators array
30
+ * These are valid at the start of a template block to
31
+ * modify the way in which the variables inside are
32
+ * processed.
33
+ */
34
+ private $operators = array(
35
+ "+" => "reserved",
36
+ "/" => "segments",
37
+ "." => "dotprefix",
38
+ "#" => "fragment",
39
+ ";" => "semicolon",
40
+ "?" => "form",
41
+ "&" => "continuation"
42
+ );
43
+
44
+ /**
45
+ * @var reserved array
46
+ * These are the characters which should not be URL encoded in reserved
47
+ * strings.
48
+ */
49
+ private $reserved = array(
50
+ "=", ",", "!", "@", "|", ":", "/", "?", "#",
51
+ "[", "]",'$', "&", "'", "(", ")", "*", "+", ";"
52
+ );
53
+ private $reservedEncoded = array(
54
+ "%3D", "%2C", "%21", "%40", "%7C", "%3A", "%2F", "%3F",
55
+ "%23", "%5B", "%5D", "%24", "%26", "%27", "%28", "%29",
56
+ "%2A", "%2B", "%3B"
57
+ );
58
+
59
+ public function parse($string, array $parameters)
60
+ {
61
+ return $this->resolveNextSection($string, $parameters);
62
+ }
63
+
64
+ /**
65
+ * This function finds the first matching {...} block and
66
+ * executes the replacement. It then calls itself to find
67
+ * subsequent blocks, if any.
68
+ */
69
+ private function resolveNextSection($string, $parameters)
70
+ {
71
+ $start = strpos($string, "{");
72
+ if ($start === false) {
73
+ return $string;
74
+ }
75
+ $end = strpos($string, "}");
76
+ if ($end === false) {
77
+ return $string;
78
+ }
79
+ $string = $this->replace($string, $start, $end, $parameters);
80
+ return $this->resolveNextSection($string, $parameters);
81
+ }
82
+
83
+ private function replace($string, $start, $end, $parameters)
84
+ {
85
+ // We know a data block will have {} round it, so we can strip that.
86
+ $data = substr($string, $start + 1, $end - $start - 1);
87
+
88
+ // If the first character is one of the reserved operators, it effects
89
+ // the processing of the stream.
90
+ if (isset($this->operators[$data[0]])) {
91
+ $op = $this->operators[$data[0]];
92
+ $data = substr($data, 1);
93
+ $prefix = "";
94
+ $prefix_on_missing = false;
95
+
96
+ switch ($op) {
97
+ case "reserved":
98
+ // Reserved means certain characters should not be URL encoded
99
+ $data = $this->replaceVars($data, $parameters, ",", null, true);
100
+ break;
101
+ case "fragment":
102
+ // Comma separated with fragment prefix. Bare values only.
103
+ $prefix = "#";
104
+ $prefix_on_missing = true;
105
+ $data = $this->replaceVars($data, $parameters, ",", null, true);
106
+ break;
107
+ case "segments":
108
+ // Slash separated data. Bare values only.
109
+ $prefix = "/";
110
+ $data =$this->replaceVars($data, $parameters, "/");
111
+ break;
112
+ case "dotprefix":
113
+ // Dot separated data. Bare values only.
114
+ $prefix = ".";
115
+ $prefix_on_missing = true;
116
+ $data = $this->replaceVars($data, $parameters, ".");
117
+ break;
118
+ case "semicolon":
119
+ // Semicolon prefixed and separated. Uses the key name
120
+ $prefix = ";";
121
+ $data = $this->replaceVars($data, $parameters, ";", "=", false, true, false);
122
+ break;
123
+ case "form":
124
+ // Standard URL format. Uses the key name
125
+ $prefix = "?";
126
+ $data = $this->replaceVars($data, $parameters, "&", "=");
127
+ break;
128
+ case "continuation":
129
+ // Standard URL, but with leading ampersand. Uses key name.
130
+ $prefix = "&";
131
+ $data = $this->replaceVars($data, $parameters, "&", "=");
132
+ break;
133
+ }
134
+
135
+ // Add the initial prefix character if data is valid.
136
+ if ($data || ($data !== false && $prefix_on_missing)) {
137
+ $data = $prefix . $data;
138
+ }
139
+
140
+ } else {
141
+ // If no operator we replace with the defaults.
142
+ $data = $this->replaceVars($data, $parameters);
143
+ }
144
+ // This is chops out the {...} and replaces with the new section.
145
+ return substr($string, 0, $start) . $data . substr($string, $end + 1);
146
+ }
147
+
148
+ private function replaceVars(
149
+ $section,
150
+ $parameters,
151
+ $sep = ",",
152
+ $combine = null,
153
+ $reserved = false,
154
+ $tag_empty = false,
155
+ $combine_on_empty = true
156
+ ) {
157
+ if (strpos($section, ",") === false) {
158
+ // If we only have a single value, we can immediately process.
159
+ return $this->combine(
160
+ $section,
161
+ $parameters,
162
+ $sep,
163
+ $combine,
164
+ $reserved,
165
+ $tag_empty,
166
+ $combine_on_empty
167
+ );
168
+ } else {
169
+ // If we have multiple values, we need to split and loop over them.
170
+ // Each is treated individually, then glued together with the
171
+ // separator character.
172
+ $vars = explode(",", $section);
173
+ return $this->combineList(
174
+ $vars,
175
+ $sep,
176
+ $parameters,
177
+ $combine,
178
+ $reserved,
179
+ false, // Never emit empty strings in multi-param replacements
180
+ $combine_on_empty
181
+ );
182
+ }
183
+ }
184
+
185
+ public function combine(
186
+ $key,
187
+ $parameters,
188
+ $sep,
189
+ $combine,
190
+ $reserved,
191
+ $tag_empty,
192
+ $combine_on_empty
193
+ ) {
194
+ $length = false;
195
+ $explode = false;
196
+ $skip_final_combine = false;
197
+ $value = false;
198
+
199
+ // Check for length restriction.
200
+ if (strpos($key, ":") !== false) {
201
+ list($key, $length) = explode(":", $key);
202
+ }
203
+
204
+ // Check for explode parameter.
205
+ if ($key[strlen($key) - 1] == "*") {
206
+ $explode = true;
207
+ $key = substr($key, 0, -1);
208
+ $skip_final_combine = true;
209
+ }
210
+
211
+ // Define the list separator.
212
+ $list_sep = $explode ? $sep : ",";
213
+
214
+ if (isset($parameters[$key])) {
215
+ $data_type = $this->getDataType($parameters[$key]);
216
+ switch ($data_type) {
217
+ case self::TYPE_SCALAR:
218
+ $value = $this->getValue($parameters[$key], $length);
219
+ break;
220
+ case self::TYPE_LIST:
221
+ $values = array();
222
+ foreach ($parameters[$key] as $pkey => $pvalue) {
223
+ $pvalue = $this->getValue($pvalue, $length);
224
+ if ($combine && $explode) {
225
+ $values[$pkey] = $key . $combine . $pvalue;
226
+ } else {
227
+ $values[$pkey] = $pvalue;
228
+ }
229
+ }
230
+ $value = implode($list_sep, $values);
231
+ if ($value == '') {
232
+ return '';
233
+ }
234
+ break;
235
+ case self::TYPE_MAP:
236
+ $values = array();
237
+ foreach ($parameters[$key] as $pkey => $pvalue) {
238
+ $pvalue = $this->getValue($pvalue, $length);
239
+ if ($explode) {
240
+ $pkey = $this->getValue($pkey, $length);
241
+ $values[] = $pkey . "=" . $pvalue; // Explode triggers = combine.
242
+ } else {
243
+ $values[] = $pkey;
244
+ $values[] = $pvalue;
245
+ }
246
+ }
247
+ $value = implode($list_sep, $values);
248
+ if ($value == '') {
249
+ return false;
250
+ }
251
+ break;
252
+ }
253
+ } else if ($tag_empty) {
254
+ // If we are just indicating empty values with their key name, return that.
255
+ return $key;
256
+ } else {
257
+ // Otherwise we can skip this variable due to not being defined.
258
+ return false;
259
+ }
260
+
261
+ if ($reserved) {
262
+ $value = str_replace($this->reservedEncoded, $this->reserved, $value);
263
+ }
264
+
265
+ // If we do not need to include the key name, we just return the raw
266
+ // value.
267
+ if (!$combine || $skip_final_combine) {
268
+ return $value;
269
+ }
270
+
271
+ // Else we combine the key name: foo=bar, if value is not the empty string.
272
+ return $key . ($value != '' || $combine_on_empty ? $combine . $value : '');
273
+ }
274
+
275
+ /**
276
+ * Return the type of a passed in value
277
+ */
278
+ private function getDataType($data)
279
+ {
280
+ if (is_array($data)) {
281
+ reset($data);
282
+ if (key($data) !== 0) {
283
+ return self::TYPE_MAP;
284
+ }
285
+ return self::TYPE_LIST;
286
+ }
287
+ return self::TYPE_SCALAR;
288
+ }
289
+
290
+ /**
291
+ * Utility function that merges multiple combine calls
292
+ * for multi-key templates.
293
+ */
294
+ private function combineList(
295
+ $vars,
296
+ $sep,
297
+ $parameters,
298
+ $combine,
299
+ $reserved,
300
+ $tag_empty,
301
+ $combine_on_empty
302
+ ) {
303
+ $ret = array();
304
+ foreach ($vars as $var) {
305
+ $response = $this->combine(
306
+ $var,
307
+ $parameters,
308
+ $sep,
309
+ $combine,
310
+ $reserved,
311
+ $tag_empty,
312
+ $combine_on_empty
313
+ );
314
+ if ($response === false) {
315
+ continue;
316
+ }
317
+ $ret[] = $response;
318
+ }
319
+ return implode($sep, $ret);
320
+ }
321
+
322
+ /**
323
+ * Utility function to encode and trim values
324
+ */
325
+ private function getValue($value, $length)
326
+ {
327
+ if ($length) {
328
+ $value = substr($value, 0, $length);
329
+ }
330
+ $value = rawurlencode($value);
331
+ return $value;
332
+ }
333
+ }
vendor/google/apiclient/src/Google/autoload.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * THIS FILE IS FOR BACKWARDS COMPATIBLITY ONLY
5
+ *
6
+ * If you were not already including this file in your project, please ignore it
7
+ */
8
+
9
+ $file = __DIR__ . '/../../vendor/autoload.php';
10
+
11
+ if (!file_exists($file)) {
12
+ $exception = 'This library must be installed via composer or by downloading the full package.';
13
+ $exception .= ' See the instructions at https://github.com/google/google-api-php-client#installation.';
14
+ throw new Exception($exception);
15
+ }
16
+
17
+ $error = 'google-api-php-client\'s autoloader was moved to vendor/autoload.php in 2.0.0. This ';
18
+ $error .= 'redirect will be removed in 2.1. Please adjust your code to use the new location.';
19
+ trigger_error($error, E_USER_DEPRECATED);
20
+
21
+ require_once $file;
vendor/google/auth/COPYING ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright 2015 Google Inc.
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
vendor/google/auth/LICENSE ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
202
+
203
+
vendor/google/auth/autoload.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ function oauth2client_php_autoload($className)
19
+ {
20
+ $classPath = explode('_', $className);
21
+ if ($classPath[0] != 'Google') {
22
+ return;
23
+ }
24
+ if (count($classPath) > 3) {
25
+ // Maximum class file path depth in this project is 3.
26
+ $classPath = array_slice($classPath, 0, 3);
27
+ }
28
+ $filePath = dirname(__FILE__) . '/src/' . implode('/', $classPath) . '.php';
29
+ if (file_exists($filePath)) {
30
+ require_once $filePath;
31
+ }
32
+ }
33
+
34
+ spl_autoload_register('oauth2client_php_autoload');
vendor/google/auth/src/ApplicationDefaultCredentials.php ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ use DomainException;
21
+ use Google\Auth\Credentials\AppIdentityCredentials;
22
+ use Google\Auth\Credentials\GCECredentials;
23
+ use Google\Auth\Middleware\AuthTokenMiddleware;
24
+ use Google\Auth\Subscriber\AuthTokenSubscriber;
25
+ use Psr\Cache\CacheItemPoolInterface;
26
+
27
+ /**
28
+ * ApplicationDefaultCredentials obtains the default credentials for
29
+ * authorizing a request to a Google service.
30
+ *
31
+ * Application Default Credentials are described here:
32
+ * https://developers.google.com/accounts/docs/application-default-credentials
33
+ *
34
+ * This class implements the search for the application default credentials as
35
+ * described in the link.
36
+ *
37
+ * It provides three factory methods:
38
+ * - #get returns the computed credentials object
39
+ * - #getSubscriber returns an AuthTokenSubscriber built from the credentials object
40
+ * - #getMiddleware returns an AuthTokenMiddleware built from the credentials object
41
+ *
42
+ * This allows it to be used as follows with GuzzleHttp\Client:
43
+ *
44
+ * use Google\Auth\ApplicationDefaultCredentials;
45
+ * use GuzzleHttp\Client;
46
+ * use GuzzleHttp\HandlerStack;
47
+ *
48
+ * $middleware = ApplicationDefaultCredentials::getMiddleware(
49
+ * 'https://www.googleapis.com/auth/taskqueue'
50
+ * );
51
+ * $stack = HandlerStack::create();
52
+ * $stack->push($middleware);
53
+ *
54
+ * $client = new Client([
55
+ * 'handler' => $stack,
56
+ * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
57
+ * 'auth' => 'google_auth' // authorize all requests
58
+ * ]);
59
+ *
60
+ * $res = $client->get('myproject/taskqueues/myqueue');
61
+ */
62
+ class ApplicationDefaultCredentials
63
+ {
64
+ /**
65
+ * Obtains an AuthTokenSubscriber that uses the default FetchAuthTokenInterface
66
+ * implementation to use in this environment.
67
+ *
68
+ * If supplied, $scope is used to in creating the credentials instance if
69
+ * this does not fallback to the compute engine defaults.
70
+ *
71
+ * @param string|array scope the scope of the access request, expressed
72
+ * either as an Array or as a space-delimited String.
73
+ * @param callable $httpHandler callback which delivers psr7 request
74
+ * @param array $cacheConfig configuration for the cache when it's present
75
+ * @param CacheItemPoolInterface $cache an implementation of CacheItemPoolInterface
76
+ *
77
+ * @return AuthTokenSubscriber
78
+ *
79
+ * @throws DomainException if no implementation can be obtained.
80
+ */
81
+ public static function getSubscriber(
82
+ $scope = null,
83
+ callable $httpHandler = null,
84
+ array $cacheConfig = null,
85
+ CacheItemPoolInterface $cache = null
86
+ ) {
87
+ $creds = self::getCredentials($scope, $httpHandler, $cacheConfig, $cache);
88
+
89
+ return new AuthTokenSubscriber($creds, $cacheConfig);
90
+ }
91
+
92
+ /**
93
+ * Obtains an AuthTokenMiddleware that uses the default FetchAuthTokenInterface
94
+ * implementation to use in this environment.
95
+ *
96
+ * If supplied, $scope is used to in creating the credentials instance if
97
+ * this does not fallback to the compute engine defaults.
98
+ *
99
+ * @param string|array scope the scope of the access request, expressed
100
+ * either as an Array or as a space-delimited String.
101
+ * @param callable $httpHandler callback which delivers psr7 request
102
+ * @param array $cacheConfig configuration for the cache when it's present
103
+ * @param CacheItemPoolInterface $cache
104
+ *
105
+ * @return AuthTokenMiddleware
106
+ *
107
+ * @throws DomainException if no implementation can be obtained.
108
+ */
109
+ public static function getMiddleware(
110
+ $scope = null,
111
+ callable $httpHandler = null,
112
+ array $cacheConfig = null,
113
+ CacheItemPoolInterface $cache = null
114
+ ) {
115
+ $creds = self::getCredentials($scope, $httpHandler, $cacheConfig, $cache);
116
+
117
+ return new AuthTokenMiddleware($creds, $cacheConfig);
118
+ }
119
+
120
+ /**
121
+ * Obtains the default FetchAuthTokenInterface implementation to use
122
+ * in this environment.
123
+ *
124
+ * If supplied, $scope is used to in creating the credentials instance if
125
+ * this does not fallback to the Compute Engine defaults.
126
+ *
127
+ * @param string|array scope the scope of the access request, expressed
128
+ * either as an Array or as a space-delimited String.
129
+ * @param callable $httpHandler callback which delivers psr7 request
130
+ * @param array $cacheConfig configuration for the cache when it's present
131
+ * @param CacheItemPoolInterface $cache
132
+ *
133
+ * @return CredentialsLoader
134
+ *
135
+ * @throws DomainException if no implementation can be obtained.
136
+ */
137
+ public static function getCredentials(
138
+ $scope = null,
139
+ callable $httpHandler = null,
140
+ array $cacheConfig = null,
141
+ CacheItemPoolInterface $cache = null
142
+ ) {
143
+ $creds = null;
144
+ $jsonKey = CredentialsLoader::fromEnv()
145
+ ?: CredentialsLoader::fromWellKnownFile();
146
+
147
+ if (!is_null($jsonKey)) {
148
+ $creds = CredentialsLoader::makeCredentials($scope, $jsonKey);
149
+ } elseif (AppIdentityCredentials::onAppEngine() && !GCECredentials::onAppEngineFlexible()) {
150
+ $creds = new AppIdentityCredentials($scope);
151
+ } elseif (GCECredentials::onGce($httpHandler)) {
152
+ $creds = new GCECredentials();
153
+ }
154
+
155
+ if (is_null($creds)) {
156
+ throw new \DomainException(self::notFound());
157
+ }
158
+ if (!is_null($cache)) {
159
+ $creds = new FetchAuthTokenCache($creds, $cacheConfig, $cache);
160
+ }
161
+ return $creds;
162
+ }
163
+
164
+ private static function notFound()
165
+ {
166
+ $msg = 'Could not load the default credentials. Browse to ';
167
+ $msg .= 'https://developers.google.com';
168
+ $msg .= '/accounts/docs/application-default-credentials';
169
+ $msg .= ' for more information';
170
+
171
+ return $msg;
172
+ }
173
+ }
vendor/google/auth/src/Cache/InvalidArgumentException.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2016 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Cache;
19
+
20
+ use Psr\Cache\InvalidArgumentException as PsrInvalidArgumentException;
21
+
22
+ class InvalidArgumentException extends \InvalidArgumentException implements PsrInvalidArgumentException
23
+ {
24
+ }
vendor/google/auth/src/Cache/Item.php ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2016 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Cache;
19
+
20
+ use Psr\Cache\CacheItemInterface;
21
+
22
+ /**
23
+ * A cache item.
24
+ */
25
+ final class Item implements CacheItemInterface
26
+ {
27
+ /**
28
+ * @var string
29
+ */
30
+ private $key;
31
+
32
+ /**
33
+ * @var mixed
34
+ */
35
+ private $value;
36
+
37
+ /**
38
+ * @var \DateTime
39
+ */
40
+ private $expiration;
41
+
42
+ /**
43
+ * @var bool
44
+ */
45
+ private $isHit = false;
46
+
47
+ /**
48
+ * @param string $key
49
+ */
50
+ public function __construct($key)
51
+ {
52
+ $this->key = $key;
53
+ }
54
+
55
+ /**
56
+ * {@inheritdoc}
57
+ */
58
+ public function getKey()
59
+ {
60
+ return $this->key;
61
+ }
62
+
63
+ /**
64
+ * {@inheritdoc}
65
+ */
66
+ public function get()
67
+ {
68
+ return $this->isHit() ? $this->value : null;
69
+ }
70
+
71
+ /**
72
+ * {@inheritdoc}
73
+ */
74
+ public function isHit()
75
+ {
76
+ if (!$this->isHit) {
77
+ return false;
78
+ }
79
+
80
+ if ($this->expiration === null) {
81
+ return true;
82
+ }
83
+
84
+ return new \DateTime() < $this->expiration;
85
+ }
86
+
87
+ /**
88
+ * {@inheritdoc}
89
+ */
90
+ public function set($value)
91
+ {
92
+ $this->isHit = true;
93
+ $this->value = $value;
94
+
95
+ return $this;
96
+ }
97
+
98
+ /**
99
+ * {@inheritdoc}
100
+ */
101
+ public function expiresAt($expiration)
102
+ {
103
+ if ($this->isValidExpiration($expiration)) {
104
+ $this->expiration = $expiration;
105
+
106
+ return $this;
107
+ }
108
+
109
+ $implementationMessage = interface_exists('DateTimeInterface')
110
+ ? 'implement interface DateTimeInterface'
111
+ : 'be an instance of DateTime';
112
+
113
+ $error = sprintf(
114
+ 'Argument 1 passed to %s::expiresAt() must %s, %s given',
115
+ get_class($this),
116
+ $implementationMessage,
117
+ gettype($expiration)
118
+ );
119
+
120
+ $this->handleError($error);
121
+ }
122
+
123
+ /**
124
+ * {@inheritdoc}
125
+ */
126
+ public function expiresAfter($time)
127
+ {
128
+ if (is_int($time)) {
129
+ $this->expiration = new \DateTime("now + $time seconds");
130
+ } elseif ($time instanceof \DateInterval) {
131
+ $this->expiration = (new \DateTime())->add($time);
132
+ } elseif ($time === null) {
133
+ $this->expiration = $time;
134
+ } else {
135
+ $message = 'Argument 1 passed to %s::expiresAfter() must be an ' .
136
+ 'instance of DateInterval or of the type integer, %s given';
137
+ $error = sprintf($message, get_class($this), gettype($expiration));
138
+
139
+ $this->handleError($error);
140
+ }
141
+
142
+ return $this;
143
+ }
144
+
145
+ /**
146
+ * Handles an error.
147
+ *
148
+ * @param string $error
149
+ * @throws \TypeError
150
+ */
151
+ private function handleError($error)
152
+ {
153
+ if (class_exists('TypeError')) {
154
+ throw new \TypeError($error);
155
+ }
156
+
157
+ trigger_error($error, E_USER_ERROR);
158
+ }
159
+
160
+ /**
161
+ * Determines if an expiration is valid based on the rules defined by PSR6.
162
+ *
163
+ * @param mixed $expiration
164
+ * @return bool
165
+ */
166
+ private function isValidExpiration($expiration)
167
+ {
168
+ if ($expiration === null) {
169
+ return true;
170
+ }
171
+
172
+ // We test for two types here due to the fact the DateTimeInterface
173
+ // was not introduced until PHP 5.5. Checking for the DateTime type as
174
+ // well allows us to support 5.4.
175
+ if ($expiration instanceof \DateTimeInterface) {
176
+ return true;
177
+ }
178
+
179
+ if ($expiration instanceof \DateTime) {
180
+ return true;
181
+ }
182
+
183
+ return false;
184
+ }
185
+ }
vendor/google/auth/src/Cache/MemoryCacheItemPool.php ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2016 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Cache;
19
+
20
+ use Psr\Cache\CacheItemInterface;
21
+ use Psr\Cache\CacheItemPoolInterface;
22
+
23
+ /**
24
+ * Simple in-memory cache implementation.
25
+ */
26
+ final class MemoryCacheItemPool implements CacheItemPoolInterface
27
+ {
28
+ /**
29
+ * @var CacheItemInterface[]
30
+ */
31
+ private $items;
32
+
33
+ /**
34
+ * @var CacheItemInterface[]
35
+ */
36
+ private $deferredItems;
37
+
38
+ /**
39
+ * {@inheritdoc}
40
+ */
41
+ public function getItem($key)
42
+ {
43
+ return current($this->getItems([$key]));
44
+ }
45
+
46
+ /**
47
+ * {@inheritdoc}
48
+ */
49
+ public function getItems(array $keys = [])
50
+ {
51
+ $items = [];
52
+
53
+ foreach ($keys as $key) {
54
+ $items[$key] = $this->hasItem($key) ? clone $this->items[$key] : new Item($key);
55
+ }
56
+
57
+ return $items;
58
+ }
59
+
60
+ /**
61
+ * {@inheritdoc}
62
+ */
63
+ public function hasItem($key)
64
+ {
65
+ $this->isValidKey($key);
66
+
67
+ return isset($this->items[$key]) && $this->items[$key]->isHit();
68
+ }
69
+
70
+ /**
71
+ * {@inheritdoc}
72
+ */
73
+ public function clear()
74
+ {
75
+ $this->items = [];
76
+ $this->deferredItems = [];
77
+
78
+ return true;
79
+ }
80
+
81
+ /**
82
+ * {@inheritdoc}
83
+ */
84
+ public function deleteItem($key)
85
+ {
86
+ return $this->deleteItems([$key]);
87
+ }
88
+
89
+ /**
90
+ * {@inheritdoc}
91
+ */
92
+ public function deleteItems(array $keys)
93
+ {
94
+ array_walk($keys, [$this, 'isValidKey']);
95
+
96
+ foreach ($keys as $key) {
97
+ unset($this->items[$key]);
98
+ }
99
+
100
+ return true;
101
+ }
102
+
103
+ /**
104
+ * {@inheritdoc}
105
+ */
106
+ public function save(CacheItemInterface $item)
107
+ {
108
+ $this->items[$item->getKey()] = $item;
109
+
110
+ return true;
111
+ }
112
+
113
+ /**
114
+ * {@inheritdoc}
115
+ */
116
+ public function saveDeferred(CacheItemInterface $item)
117
+ {
118
+ $this->deferredItems[$item->getKey()] = $item;
119
+
120
+ return true;
121
+ }
122
+
123
+ /**
124
+ * {@inheritdoc}
125
+ */
126
+ public function commit()
127
+ {
128
+ foreach ($this->deferredItems as $item) {
129
+ $this->save($item);
130
+ }
131
+
132
+ $this->deferredItems = [];
133
+
134
+ return true;
135
+ }
136
+
137
+ /**
138
+ * Determines if the provided key is valid.
139
+ *
140
+ * @param string $key
141
+ * @return bool
142
+ * @throws InvalidArgumentException
143
+ */
144
+ private function isValidKey($key)
145
+ {
146
+ $invalidCharacters = '{}()/\\\\@:';
147
+
148
+ if (!is_string($key) || preg_match("#[$invalidCharacters]#", $key)) {
149
+ throw new InvalidArgumentException('The provided key is not valid: ' . var_export($key, true));
150
+ }
151
+
152
+ return true;
153
+ }
154
+ }
vendor/google/auth/src/CacheTrait.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ trait CacheTrait
21
+ {
22
+ private $maxKeyLength = 64;
23
+
24
+ /**
25
+ * Gets the cached value if it is present in the cache when that is
26
+ * available.
27
+ */
28
+ private function getCachedValue($k)
29
+ {
30
+ if (is_null($this->cache)) {
31
+ return;
32
+ }
33
+
34
+ $key = $this->getFullCacheKey($k);
35
+ if (is_null($key)) {
36
+ return;
37
+ }
38
+
39
+ $cacheItem = $this->cache->getItem($key);
40
+ if ($cacheItem->isHit()) {
41
+ return $cacheItem->get();
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Saves the value in the cache when that is available.
47
+ */
48
+ private function setCachedValue($k, $v)
49
+ {
50
+ if (is_null($this->cache)) {
51
+ return;
52
+ }
53
+
54
+ $key = $this->getFullCacheKey($k);
55
+ if (is_null($key)) {
56
+ return;
57
+ }
58
+
59
+ $cacheItem = $this->cache->getItem($key);
60
+ $cacheItem->set($v);
61
+ $cacheItem->expiresAfter($this->cacheConfig['lifetime']);
62
+ return $this->cache->save($cacheItem);
63
+ }
64
+
65
+ private function getFullCacheKey($key)
66
+ {
67
+ if (is_null($key)) {
68
+ return;
69
+ }
70
+
71
+ $key = $this->cacheConfig['prefix'] . $key;
72
+
73
+ // ensure we do not have illegal characters
74
+ $key = preg_replace('|[^a-zA-Z0-9_\.!]|', '', $key);
75
+
76
+ // Hash keys if they exceed $maxKeyLength (defaults to 64)
77
+ if ($this->maxKeyLength && strlen($key) > $this->maxKeyLength) {
78
+ $key = substr(hash('sha256', $key), 0, $this->maxKeyLength);
79
+ }
80
+
81
+ return $key;
82
+ }
83
+ }
vendor/google/auth/src/Credentials/AppIdentityCredentials.php ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Credentials;
19
+
20
+ /*
21
+ * The AppIdentityService class is automatically defined on App Engine,
22
+ * so including this dependency is not necessary, and will result in a
23
+ * PHP fatal error in the App Engine environment.
24
+ */
25
+ use google\appengine\api\app_identity\AppIdentityService;
26
+ use Google\Auth\CredentialsLoader;
27
+
28
+ /**
29
+ * AppIdentityCredentials supports authorization on Google App Engine.
30
+ *
31
+ * It can be used to authorize requests using the AuthTokenMiddleware or
32
+ * AuthTokenSubscriber, but will only succeed if being run on App Engine:
33
+ *
34
+ * use Google\Auth\Credentials\AppIdentityCredentials;
35
+ * use Google\Auth\Middleware\AuthTokenMiddleware;
36
+ * use GuzzleHttp\Client;
37
+ * use GuzzleHttp\HandlerStack;
38
+ *
39
+ * $gae = new AppIdentityCredentials('https://www.googleapis.com/auth/books');
40
+ * $middleware = new AuthTokenMiddleware($gae);
41
+ * $stack = HandlerStack::create();
42
+ * $stack->push($middleware);
43
+ *
44
+ * $client = new Client([
45
+ * 'handler' => $stack,
46
+ * 'base_uri' => 'https://www.googleapis.com/books/v1',
47
+ * 'auth' => 'google_auth'
48
+ * ]);
49
+ *
50
+ * $res = $client->get('volumes?q=Henry+David+Thoreau&country=US');
51
+ */
52
+ class AppIdentityCredentials extends CredentialsLoader
53
+ {
54
+ /**
55
+ * Result of fetchAuthToken.
56
+ *
57
+ * @array
58
+ */
59
+ protected $lastReceivedToken;
60
+
61
+ /**
62
+ * Array of OAuth2 scopes to be requested.
63
+ */
64
+ private $scope;
65
+
66
+ public function __construct($scope = array())
67
+ {
68
+ $this->scope = $scope;
69
+ }
70
+
71
+ /**
72
+ * Determines if this an App Engine instance, by accessing the
73
+ * SERVER_SOFTWARE environment variable (prod) or the APPENGINE_RUNTIME
74
+ * environment variable (dev).
75
+ *
76
+ * @return true if this an App Engine Instance, false otherwise
77
+ */
78
+ public static function onAppEngine()
79
+ {
80
+ $appEngineProduction = isset($_SERVER['SERVER_SOFTWARE']) &&
81
+ 0 === strpos($_SERVER['SERVER_SOFTWARE'], 'Google App Engine');
82
+ if ($appEngineProduction) {
83
+ return true;
84
+ }
85
+ $appEngineDevAppServer = isset($_SERVER['APPENGINE_RUNTIME']) &&
86
+ $_SERVER['APPENGINE_RUNTIME'] == 'php';
87
+ if ($appEngineDevAppServer) {
88
+ return true;
89
+ }
90
+ return false;
91
+ }
92
+
93
+ /**
94
+ * Implements FetchAuthTokenInterface#fetchAuthToken.
95
+ *
96
+ * Fetches the auth tokens using the AppIdentityService if available.
97
+ * As the AppIdentityService uses protobufs to fetch the access token,
98
+ * the GuzzleHttp\ClientInterface instance passed in will not be used.
99
+ *
100
+ * @param callable $httpHandler callback which delivers psr7 request
101
+ *
102
+ * @return array the auth metadata:
103
+ * array(2) {
104
+ * ["access_token"]=>
105
+ * string(3) "xyz"
106
+ * ["expiration_time"]=>
107
+ * string(10) "1444339905"
108
+ * }
109
+ *
110
+ * @throws \Exception
111
+ */
112
+ public function fetchAuthToken(callable $httpHandler = null)
113
+ {
114
+ if (!self::onAppEngine()) {
115
+ return array();
116
+ }
117
+
118
+ if (!class_exists('google\appengine\api\app_identity\AppIdentityService')) {
119
+ throw new \Exception(
120
+ 'This class must be run in App Engine, or you must include the AppIdentityService '
121
+ . 'mock class defined in tests/mocks/AppIdentityService.php'
122
+ );
123
+ }
124
+
125
+ // AppIdentityService expects an array when multiple scopes are supplied
126
+ $scope = is_array($this->scope) ? $this->scope : explode(' ', $this->scope);
127
+
128
+ $token = AppIdentityService::getAccessToken($scope);
129
+ $this->lastReceivedToken = $token;
130
+
131
+ return $token;
132
+ }
133
+
134
+ /**
135
+ * @return array|null
136
+ */
137
+ public function getLastReceivedToken()
138
+ {
139
+ if ($this->lastReceivedToken) {
140
+ return [
141
+ 'access_token' => $this->lastReceivedToken['access_token'],
142
+ 'expires_at' => $this->lastReceivedToken['expiration_time'],
143
+ ];
144
+ }
145
+
146
+ return null;
147
+ }
148
+
149
+ /**
150
+ * Caching is handled by the underlying AppIdentityService, return empty string
151
+ * to prevent caching.
152
+ *
153
+ * @return string
154
+ */
155
+ public function getCacheKey()
156
+ {
157
+ return '';
158
+ }
159
+ }
vendor/google/auth/src/Credentials/GCECredentials.php ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Credentials;
19
+
20
+ use Google\Auth\CredentialsLoader;
21
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
22
+ use GuzzleHttp\Exception\ClientException;
23
+ use GuzzleHttp\Exception\RequestException;
24
+ use GuzzleHttp\Exception\ServerException;
25
+ use GuzzleHttp\Psr7\Request;
26
+
27
+ /**
28
+ * GCECredentials supports authorization on Google Compute Engine.
29
+ *
30
+ * It can be used to authorize requests using the AuthTokenMiddleware, but will
31
+ * only succeed if being run on GCE:
32
+ *
33
+ * use Google\Auth\Credentials\GCECredentials;
34
+ * use Google\Auth\Middleware\AuthTokenMiddleware;
35
+ * use GuzzleHttp\Client;
36
+ * use GuzzleHttp\HandlerStack;
37
+ *
38
+ * $gce = new GCECredentials();
39
+ * $middleware = new AuthTokenMiddleware($gce);
40
+ * $stack = HandlerStack::create();
41
+ * $stack->push($middleware);
42
+ *
43
+ * $client = new Client([
44
+ * 'handler' => $stack,
45
+ * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
46
+ * 'auth' => 'google_auth'
47
+ * ]);
48
+ *
49
+ * $res = $client->get('myproject/taskqueues/myqueue');
50
+ */
51
+ class GCECredentials extends CredentialsLoader
52
+ {
53
+ const cacheKey = 'GOOGLE_AUTH_PHP_GCE';
54
+ /**
55
+ * The metadata IP address on appengine instances.
56
+ *
57
+ * The IP is used instead of the domain 'metadata' to avoid slow responses
58
+ * when not on Compute Engine.
59
+ */
60
+ const METADATA_IP = '169.254.169.254';
61
+
62
+ /**
63
+ * The metadata path of the default token.
64
+ */
65
+ const TOKEN_URI_PATH = 'v1/instance/service-accounts/default/token';
66
+
67
+ /**
68
+ * The header whose presence indicates GCE presence.
69
+ */
70
+ const FLAVOR_HEADER = 'Metadata-Flavor';
71
+
72
+ /**
73
+ * Flag used to ensure that the onGCE test is only done once;.
74
+ *
75
+ * @var bool
76
+ */
77
+ private $hasCheckedOnGce = false;
78
+
79
+ /**
80
+ * Flag that stores the value of the onGCE check.
81
+ *
82
+ * @var bool
83
+ */
84
+ private $isOnGce = false;
85
+
86
+ /**
87
+ * Result of fetchAuthToken.
88
+ */
89
+ protected $lastReceivedToken;
90
+
91
+ /**
92
+ * The full uri for accessing the default token.
93
+ *
94
+ * @return string
95
+ */
96
+ public static function getTokenUri()
97
+ {
98
+ $base = 'http://' . self::METADATA_IP . '/computeMetadata/';
99
+
100
+ return $base . self::TOKEN_URI_PATH;
101
+ }
102
+
103
+ /**
104
+ * Determines if this an App Engine Flexible instance, by accessing the
105
+ * GAE_VM environment variable.
106
+ *
107
+ * @return true if this an App Engine Flexible Instance, false otherwise
108
+ */
109
+ public static function onAppEngineFlexible()
110
+ {
111
+ return isset($_SERVER['GAE_VM']) && 'true' === $_SERVER['GAE_VM'];
112
+ }
113
+
114
+ /**
115
+ * Determines if this a GCE instance, by accessing the expected metadata
116
+ * host.
117
+ * If $httpHandler is not specified a the default HttpHandler is used.
118
+ *
119
+ * @param callable $httpHandler callback which delivers psr7 request
120
+ *
121
+ * @return true if this a GCEInstance false otherwise
122
+ */
123
+ public static function onGce(callable $httpHandler = null)
124
+ {
125
+ if (is_null($httpHandler)) {
126
+ $httpHandler = HttpHandlerFactory::build();
127
+ }
128
+ $checkUri = 'http://' . self::METADATA_IP;
129
+ try {
130
+ // Comment from: oauth2client/client.py
131
+ //
132
+ // Note: the explicit `timeout` below is a workaround. The underlying
133
+ // issue is that resolving an unknown host on some networks will take
134
+ // 20-30 seconds; making this timeout short fixes the issue, but
135
+ // could lead to false negatives in the event that we are on GCE, but
136
+ // the metadata resolution was particularly slow. The latter case is
137
+ // "unlikely".
138
+ $resp = $httpHandler(
139
+ new Request('GET', $checkUri),
140
+ ['timeout' => 0.3]
141
+ );
142
+
143
+ return $resp->getHeaderLine(self::FLAVOR_HEADER) == 'Google';
144
+ } catch (ClientException $e) {
145
+ return false;
146
+ } catch (ServerException $e) {
147
+ return false;
148
+ } catch (RequestException $e) {
149
+ return false;
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Implements FetchAuthTokenInterface#fetchAuthToken.
155
+ *
156
+ * Fetches the auth tokens from the GCE metadata host if it is available.
157
+ * If $httpHandler is not specified a the default HttpHandler is used.
158
+ *
159
+ * @param callable $httpHandler callback which delivers psr7 request
160
+ *
161
+ * @return array the response
162
+ *
163
+ * @throws \Exception
164
+ */
165
+ public function fetchAuthToken(callable $httpHandler = null)
166
+ {
167
+ if (is_null($httpHandler)) {
168
+ $httpHandler = HttpHandlerFactory::build();
169
+ }
170
+ if (!$this->hasCheckedOnGce) {
171
+ $this->isOnGce = self::onGce($httpHandler);
172
+ }
173
+ if (!$this->isOnGce) {
174
+ return array(); // return an empty array with no access token
175
+ }
176
+ $resp = $httpHandler(
177
+ new Request(
178
+ 'GET',
179
+ self::getTokenUri(),
180
+ [self::FLAVOR_HEADER => 'Google']
181
+ )
182
+ );
183
+ $body = (string)$resp->getBody();
184
+
185
+ // Assume it's JSON; if it's not throw an exception
186
+ if (null === $json = json_decode($body, true)) {
187
+ throw new \Exception('Invalid JSON response');
188
+ }
189
+
190
+ // store this so we can retrieve it later
191
+ $this->lastReceivedToken = $json;
192
+ $this->lastReceivedToken['expires_at'] = time() + $json['expires_in'];
193
+
194
+ return $json;
195
+ }
196
+
197
+ /**
198
+ * @return string
199
+ */
200
+ public function getCacheKey()
201
+ {
202
+ return self::cacheKey;
203
+ }
204
+
205
+ /**
206
+ * @return array|null
207
+ */
208
+ public function getLastReceivedToken()
209
+ {
210
+ if ($this->lastReceivedToken) {
211
+ return [
212
+ 'access_token' => $this->lastReceivedToken['access_token'],
213
+ 'expires_at' => $this->lastReceivedToken['expires_at'],
214
+ ];
215
+ }
216
+
217
+ return null;
218
+ }
219
+ }
vendor/google/auth/src/Credentials/IAMCredentials.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Credentials;
19
+
20
+ /**
21
+ * Authenticates requests using IAM credentials.
22
+ */
23
+ class IAMCredentials
24
+ {
25
+ const SELECTOR_KEY = 'x-goog-iam-authority-selector';
26
+ const TOKEN_KEY = 'x-goog-iam-authorization-token';
27
+
28
+ /**
29
+ * @var string
30
+ */
31
+ private $selector;
32
+
33
+ /**
34
+ * @var string
35
+ */
36
+ private $token;
37
+
38
+ /**
39
+ * @param $selector string the IAM selector
40
+ * @param $token string the IAM token
41
+ */
42
+ public function __construct($selector, $token)
43
+ {
44
+ if (!is_string($selector)) {
45
+ throw new \InvalidArgumentException(
46
+ 'selector must be a string');
47
+ }
48
+ if (!is_string($token)) {
49
+ throw new \InvalidArgumentException(
50
+ 'token must be a string');
51
+ }
52
+
53
+ $this->selector = $selector;
54
+ $this->token = $token;
55
+ }
56
+
57
+ /**
58
+ * export a callback function which updates runtime metadata.
59
+ *
60
+ * @return array updateMetadata function
61
+ */
62
+ public function getUpdateMetadataFunc()
63
+ {
64
+ return array($this, 'updateMetadata');
65
+ }
66
+
67
+ /**
68
+ * Updates metadata with the appropriate header metadata.
69
+ *
70
+ * @param array $metadata metadata hashmap
71
+ * @param string $unusedAuthUri optional auth uri
72
+ * @param callable $httpHandler callback which delivers psr7 request
73
+ * Note: this param is unused here, only included here for
74
+ * consistency with other credentials class
75
+ *
76
+ * @return array updated metadata hashmap
77
+ */
78
+ public function updateMetadata(
79
+ $metadata,
80
+ $unusedAuthUri = null,
81
+ callable $httpHandler = null
82
+ ) {
83
+ $metadata_copy = $metadata;
84
+ $metadata_copy[self::SELECTOR_KEY] = $this->selector;
85
+ $metadata_copy[self::TOKEN_KEY] = $this->token;
86
+
87
+ return $metadata_copy;
88
+ }
89
+ }
vendor/google/auth/src/Credentials/ServiceAccountCredentials.php ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Credentials;
19
+
20
+ use Google\Auth\CredentialsLoader;
21
+ use Google\Auth\OAuth2;
22
+
23
+ /**
24
+ * ServiceAccountCredentials supports authorization using a Google service
25
+ * account.
26
+ *
27
+ * (cf https://developers.google.com/accounts/docs/OAuth2ServiceAccount)
28
+ *
29
+ * It's initialized using the json key file that's downloadable from developer
30
+ * console, which should contain a private_key and client_email fields that it
31
+ * uses.
32
+ *
33
+ * Use it with AuthTokenMiddleware to authorize http requests:
34
+ *
35
+ * use Google\Auth\Credentials\ServiceAccountCredentials;
36
+ * use Google\Auth\Middleware\AuthTokenMiddleware;
37
+ * use GuzzleHttp\Client;
38
+ * use GuzzleHttp\HandlerStack;
39
+ *
40
+ * $sa = new ServiceAccountCredentials(
41
+ * 'https://www.googleapis.com/auth/taskqueue',
42
+ * '/path/to/your/json/key_file.json'
43
+ * );
44
+ * $middleware = new AuthTokenMiddleware($sa);
45
+ * $stack = HandlerStack::create();
46
+ * $stack->push($middleware);
47
+ *
48
+ * $client = new Client([
49
+ * 'handler' => $stack,
50
+ * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
51
+ * 'auth' => 'google_auth' // authorize all requests
52
+ * ]);
53
+ *
54
+ * $res = $client->get('myproject/taskqueues/myqueue');
55
+ */
56
+ class ServiceAccountCredentials extends CredentialsLoader
57
+ {
58
+ /**
59
+ * The OAuth2 instance used to conduct authorization.
60
+ *
61
+ * @var OAuth2
62
+ */
63
+ protected $auth;
64
+
65
+ /**
66
+ * Create a new ServiceAccountCredentials.
67
+ *
68
+ * @param string|array $scope the scope of the access request, expressed
69
+ * either as an Array or as a space-delimited String.
70
+ * @param string|array $jsonKey JSON credential file path or JSON credentials
71
+ * as an associative array
72
+ * @param string $sub an email address account to impersonate, in situations when
73
+ * the service account has been delegated domain wide access.
74
+ */
75
+ public function __construct(
76
+ $scope,
77
+ $jsonKey,
78
+ $sub = null
79
+ ) {
80
+ if (is_string($jsonKey)) {
81
+ if (!file_exists($jsonKey)) {
82
+ throw new \InvalidArgumentException('file does not exist');
83
+ }
84
+ $jsonKeyStream = file_get_contents($jsonKey);
85
+ if (!$jsonKey = json_decode($jsonKeyStream, true)) {
86
+ throw new \LogicException('invalid json for auth config');
87
+ }
88
+ }
89
+ if (!array_key_exists('client_email', $jsonKey)) {
90
+ throw new \InvalidArgumentException(
91
+ 'json key is missing the client_email field');
92
+ }
93
+ if (!array_key_exists('private_key', $jsonKey)) {
94
+ throw new \InvalidArgumentException(
95
+ 'json key is missing the private_key field');
96
+ }
97
+ $this->auth = new OAuth2([
98
+ 'audience' => self::TOKEN_CREDENTIAL_URI,
99
+ 'issuer' => $jsonKey['client_email'],
100
+ 'scope' => $scope,
101
+ 'signingAlgorithm' => 'RS256',
102
+ 'signingKey' => $jsonKey['private_key'],
103
+ 'sub' => $sub,
104
+ 'tokenCredentialUri' => self::TOKEN_CREDENTIAL_URI,
105
+ ]);
106
+ }
107
+
108
+ /**
109
+ * @param callable $httpHandler
110
+ *
111
+ * @return array
112
+ */
113
+ public function fetchAuthToken(callable $httpHandler = null)
114
+ {
115
+ return $this->auth->fetchAuthToken($httpHandler);
116
+ }
117
+
118
+ /**
119
+ * @return string
120
+ */
121
+ public function getCacheKey()
122
+ {
123
+ $key = $this->auth->getIssuer() . ':' . $this->auth->getCacheKey();
124
+ if ($sub = $this->auth->getSub()) {
125
+ $key .= ':' . $sub;
126
+ }
127
+
128
+ return $key;
129
+ }
130
+
131
+ /**
132
+ * @return array
133
+ */
134
+ public function getLastReceivedToken()
135
+ {
136
+ return $this->auth->getLastReceivedToken();
137
+ }
138
+
139
+ /**
140
+ * Updates metadata with the authorization token.
141
+ *
142
+ * @param array $metadata metadata hashmap
143
+ * @param string $authUri optional auth uri
144
+ * @param callable $httpHandler callback which delivers psr7 request
145
+ *
146
+ * @return array updated metadata hashmap
147
+ */
148
+ public function updateMetadata(
149
+ $metadata,
150
+ $authUri = null,
151
+ callable $httpHandler = null
152
+ ) {
153
+ // scope exists. use oauth implementation
154
+ $scope = $this->auth->getScope();
155
+ if (!is_null($scope)) {
156
+ return parent::updateMetadata($metadata, $authUri, $httpHandler);
157
+ }
158
+
159
+ // no scope found. create jwt with the auth uri
160
+ $credJson = array(
161
+ 'private_key' => $this->auth->getSigningKey(),
162
+ 'client_email' => $this->auth->getIssuer(),
163
+ );
164
+ $jwtCreds = new ServiceAccountJwtAccessCredentials($credJson);
165
+
166
+ return $jwtCreds->updateMetadata($metadata, $authUri, $httpHandler);
167
+ }
168
+
169
+ /**
170
+ * @param string $sub an email address account to impersonate, in situations when
171
+ * the service account has been delegated domain wide access.
172
+ */
173
+ public function setSub($sub)
174
+ {
175
+ $this->auth->setSub($sub);
176
+ }
177
+ }
vendor/google/auth/src/Credentials/ServiceAccountJwtAccessCredentials.php ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Credentials;
19
+
20
+ use Google\Auth\CredentialsLoader;
21
+ use Google\Auth\OAuth2;
22
+
23
+ /**
24
+ * Authenticates requests using Google's Service Account credentials via
25
+ * JWT Access.
26
+ *
27
+ * This class allows authorizing requests for service accounts directly
28
+ * from credentials from a json key file downloaded from the developer
29
+ * console (via 'Generate new Json Key'). It is not part of any OAuth2
30
+ * flow, rather it creates a JWT and sends that as a credential.
31
+ */
32
+ class ServiceAccountJwtAccessCredentials extends CredentialsLoader
33
+ {
34
+ /**
35
+ * The OAuth2 instance used to conduct authorization.
36
+ *
37
+ * @var OAuth2
38
+ */
39
+ protected $auth;
40
+
41
+ /**
42
+ * Create a new ServiceAccountJwtAccessCredentials.
43
+ *
44
+ * @param string|array $jsonKey JSON credential file path or JSON credentials
45
+ * as an associative array
46
+ */
47
+ public function __construct($jsonKey)
48
+ {
49
+ if (is_string($jsonKey)) {
50
+ if (!file_exists($jsonKey)) {
51
+ throw new \InvalidArgumentException('file does not exist');
52
+ }
53
+ $jsonKeyStream = file_get_contents($jsonKey);
54
+ if (!$jsonKey = json_decode($jsonKeyStream, true)) {
55
+ throw new \LogicException('invalid json for auth config');
56
+ }
57
+ }
58
+ if (!array_key_exists('client_email', $jsonKey)) {
59
+ throw new \InvalidArgumentException(
60
+ 'json key is missing the client_email field');
61
+ }
62
+ if (!array_key_exists('private_key', $jsonKey)) {
63
+ throw new \InvalidArgumentException(
64
+ 'json key is missing the private_key field');
65
+ }
66
+ $this->auth = new OAuth2([
67
+ 'issuer' => $jsonKey['client_email'],
68
+ 'sub' => $jsonKey['client_email'],
69
+ 'signingAlgorithm' => 'RS256',
70
+ 'signingKey' => $jsonKey['private_key'],
71
+ ]);
72
+ }
73
+
74
+ /**
75
+ * Updates metadata with the authorization token.
76
+ *
77
+ * @param array $metadata metadata hashmap
78
+ * @param string $authUri optional auth uri
79
+ * @param callable $httpHandler callback which delivers psr7 request
80
+ *
81
+ * @return array updated metadata hashmap
82
+ */
83
+ public function updateMetadata(
84
+ $metadata,
85
+ $authUri = null,
86
+ callable $httpHandler = null
87
+ ) {
88
+ if (empty($authUri)) {
89
+ return $metadata;
90
+ }
91
+
92
+ $this->auth->setAudience($authUri);
93
+
94
+ return parent::updateMetadata($metadata, $authUri, $httpHandler);
95
+ }
96
+
97
+ /**
98
+ * Implements FetchAuthTokenInterface#fetchAuthToken.
99
+ *
100
+ * @param callable $httpHandler
101
+ *
102
+ * @return array|void
103
+ */
104
+ public function fetchAuthToken(callable $httpHandler = null)
105
+ {
106
+ $audience = $this->auth->getAudience();
107
+ if (empty($audience)) {
108
+ return null;
109
+ }
110
+
111
+ $access_token = $this->auth->toJwt();
112
+
113
+ return array('access_token' => $access_token);
114
+ }
115
+
116
+ /**
117
+ * @return string
118
+ */
119
+ public function getCacheKey()
120
+ {
121
+ return $this->auth->getCacheKey();
122
+ }
123
+
124
+ /**
125
+ * @return array
126
+ */
127
+ public function getLastReceivedToken()
128
+ {
129
+ return $this->auth->getLastReceivedToken();
130
+ }
131
+ }
vendor/google/auth/src/Credentials/UserRefreshCredentials.php ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Credentials;
19
+
20
+ use Google\Auth\CredentialsLoader;
21
+ use Google\Auth\OAuth2;
22
+
23
+ /**
24
+ * Authenticates requests using User Refresh credentials.
25
+ *
26
+ * This class allows authorizing requests from user refresh tokens.
27
+ *
28
+ * This the end of the result of a 3LO flow. E.g, the end result of
29
+ * 'gcloud auth login' saves a file with these contents in well known
30
+ * location
31
+ *
32
+ * @see [Application Default Credentials](http://goo.gl/mkAHpZ)
33
+ */
34
+ class UserRefreshCredentials extends CredentialsLoader
35
+ {
36
+ /**
37
+ * The OAuth2 instance used to conduct authorization.
38
+ *
39
+ * @var OAuth2
40
+ */
41
+ protected $auth;
42
+
43
+ /**
44
+ * Create a new UserRefreshCredentials.
45
+ *
46
+ * @param string|array $scope the scope of the access request, expressed
47
+ * either as an Array or as a space-delimited String.
48
+ * @param string|array $jsonKey JSON credential file path or JSON credentials
49
+ * as an associative array
50
+ */
51
+ public function __construct(
52
+ $scope,
53
+ $jsonKey
54
+ ) {
55
+ if (is_string($jsonKey)) {
56
+ if (!file_exists($jsonKey)) {
57
+ throw new \InvalidArgumentException('file does not exist');
58
+ }
59
+ $jsonKeyStream = file_get_contents($jsonKey);
60
+ if (!$jsonKey = json_decode($jsonKeyStream, true)) {
61
+ throw new \LogicException('invalid json for auth config');
62
+ }
63
+ }
64
+ if (!array_key_exists('client_id', $jsonKey)) {
65
+ throw new \InvalidArgumentException(
66
+ 'json key is missing the client_id field');
67
+ }
68
+ if (!array_key_exists('client_secret', $jsonKey)) {
69
+ throw new \InvalidArgumentException(
70
+ 'json key is missing the client_secret field');
71
+ }
72
+ if (!array_key_exists('refresh_token', $jsonKey)) {
73
+ throw new \InvalidArgumentException(
74
+ 'json key is missing the refresh_token field');
75
+ }
76
+ $this->auth = new OAuth2([
77
+ 'clientId' => $jsonKey['client_id'],
78
+ 'clientSecret' => $jsonKey['client_secret'],
79
+ 'refresh_token' => $jsonKey['refresh_token'],
80
+ 'scope' => $scope,
81
+ 'tokenCredentialUri' => self::TOKEN_CREDENTIAL_URI,
82
+ ]);
83
+ }
84
+
85
+ /**
86
+ * @param callable $httpHandler
87
+ *
88
+ * @return array
89
+ */
90
+ public function fetchAuthToken(callable $httpHandler = null)
91
+ {
92
+ return $this->auth->fetchAuthToken($httpHandler);
93
+ }
94
+
95
+ /**
96
+ * @return string
97
+ */
98
+ public function getCacheKey()
99
+ {
100
+ return $this->auth->getClientId() . ':' . $this->auth->getCacheKey();
101
+ }
102
+
103
+ /**
104
+ * @return array
105
+ */
106
+ public function getLastReceivedToken()
107
+ {
108
+ return $this->auth->getLastReceivedToken();
109
+ }
110
+ }
vendor/google/auth/src/CredentialsLoader.php ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ use Google\Auth\Credentials\ServiceAccountCredentials;
21
+ use Google\Auth\Credentials\UserRefreshCredentials;
22
+
23
+ /**
24
+ * CredentialsLoader contains the behaviour used to locate and find default
25
+ * credentials files on the file system.
26
+ */
27
+ abstract class CredentialsLoader implements FetchAuthTokenInterface
28
+ {
29
+ const TOKEN_CREDENTIAL_URI = 'https://www.googleapis.com/oauth2/v4/token';
30
+ const ENV_VAR = 'GOOGLE_APPLICATION_CREDENTIALS';
31
+ const WELL_KNOWN_PATH = 'gcloud/application_default_credentials.json';
32
+ const NON_WINDOWS_WELL_KNOWN_PATH_BASE = '.config';
33
+ const AUTH_METADATA_KEY = 'authorization';
34
+
35
+ /**
36
+ * @param string $cause
37
+ * @return string
38
+ */
39
+ private static function unableToReadEnv($cause)
40
+ {
41
+ $msg = 'Unable to read the credential file specified by ';
42
+ $msg .= ' GOOGLE_APPLICATION_CREDENTIALS: ';
43
+ $msg .= $cause;
44
+
45
+ return $msg;
46
+ }
47
+
48
+ /**
49
+ * @return bool
50
+ */
51
+ private static function isOnWindows()
52
+ {
53
+ return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
54
+ }
55
+
56
+ /**
57
+ * Load a JSON key from the path specified in the environment.
58
+ *
59
+ * Load a JSON key from the path specified in the environment
60
+ * variable GOOGLE_APPLICATION_CREDENTIALS. Return null if
61
+ * GOOGLE_APPLICATION_CREDENTIALS is not specified.
62
+ *
63
+ * @return array JSON key | null
64
+ */
65
+ public static function fromEnv()
66
+ {
67
+ $path = getenv(self::ENV_VAR);
68
+ if (empty($path)) {
69
+ return;
70
+ }
71
+ if (!file_exists($path)) {
72
+ $cause = 'file ' . $path . ' does not exist';
73
+ throw new \DomainException(self::unableToReadEnv($cause));
74
+ }
75
+ $jsonKey = file_get_contents($path);
76
+ return json_decode($jsonKey, true);
77
+ }
78
+
79
+ /**
80
+ * Load a JSON key from a well known path.
81
+ *
82
+ * The well known path is OS dependent:
83
+ * - windows: %APPDATA%/gcloud/application_default_credentials.json
84
+ * - others: $HOME/.config/gcloud/application_default_credentials.json
85
+ *
86
+ * If the file does not exists, this returns null.
87
+ *
88
+ * @return array JSON key | null
89
+ */
90
+ public static function fromWellKnownFile()
91
+ {
92
+ $rootEnv = self::isOnWindows() ? 'APPDATA' : 'HOME';
93
+ $path = [getenv($rootEnv)];
94
+ if (!self::isOnWindows()) {
95
+ $path[] = self::NON_WINDOWS_WELL_KNOWN_PATH_BASE;
96
+ }
97
+ $path[] = self::WELL_KNOWN_PATH;
98
+ $path = implode(DIRECTORY_SEPARATOR, $path);
99
+ if (!file_exists($path)) {
100
+ return;
101
+ }
102
+ $jsonKey = file_get_contents($path);
103
+ return json_decode($jsonKey, true);
104
+ }
105
+
106
+ /**
107
+ * Create a new Credentials instance.
108
+ *
109
+ * @param string|array $scope the scope of the access request, expressed
110
+ * either as an Array or as a space-delimited String.
111
+ * @param array $jsonKey the JSON credentials.
112
+ *
113
+ * @return ServiceAccountCredentials|UserRefreshCredentials
114
+ */
115
+ public static function makeCredentials($scope, array $jsonKey)
116
+ {
117
+ if (!array_key_exists('type', $jsonKey)) {
118
+ throw new \InvalidArgumentException('json key is missing the type field');
119
+ }
120
+
121
+ if ($jsonKey['type'] == 'service_account') {
122
+ return new ServiceAccountCredentials($scope, $jsonKey);
123
+ } elseif ($jsonKey['type'] == 'authorized_user') {
124
+ return new UserRefreshCredentials($scope, $jsonKey);
125
+ } else {
126
+ throw new \InvalidArgumentException('invalid value in the type field');
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Create an authorized HTTP Client from an instance of FetchAuthTokenInterface.
132
+ *
133
+ * @param FetchAuthTokenInterface $fetcher is used to fetch the auth token
134
+ * @param array $httpClientOptoins (optional) Array of request options to apply.
135
+ * @param callable $httpHandler (optional) http client to fetch the token.
136
+ * @param callable $tokenCallback (optional) function to be called when a new token is fetched.
137
+ *
138
+ * @return \GuzzleHttp\Client
139
+ */
140
+ public static function makeHttpClient(
141
+ FetchAuthTokenInterface $fetcher,
142
+ array $httpClientOptions = [],
143
+ callable $httpHandler = null,
144
+ callable $tokenCallback = null
145
+ ) {
146
+ $version = \GuzzleHttp\ClientInterface::VERSION;
147
+
148
+ switch ($version[0]) {
149
+ case '5':
150
+ $client = new \GuzzleHttp\Client($httpClientOptions);
151
+ $client->setDefaultOption('auth', 'google_auth');
152
+ $subscriber = new Subscriber\AuthTokenSubscriber(
153
+ $fetcher,
154
+ $httpHandler,
155
+ $tokenCallback
156
+ );
157
+ $client->getEmitter()->attach($subscriber);
158
+ return $client;
159
+ case '6':
160
+ $middleware = new Middleware\AuthTokenMiddleware(
161
+ $fetcher,
162
+ $httpHandler,
163
+ $tokenCallback
164
+ );
165
+ $stack = \GuzzleHttp\HandlerStack::create();
166
+ $stack->push($middleware);
167
+
168
+ return new \GuzzleHttp\Client([
169
+ 'handler' => $stack,
170
+ 'auth' => 'google_auth',
171
+ ] + $httpClientOptions);
172
+ default:
173
+ throw new \Exception('Version not supported');
174
+ }
175
+ }
176
+
177
+ /**
178
+ * export a callback function which updates runtime metadata.
179
+ *
180
+ * @return array updateMetadata function
181
+ */
182
+ public function getUpdateMetadataFunc()
183
+ {
184
+ return array($this, 'updateMetadata');
185
+ }
186
+
187
+ /**
188
+ * Updates metadata with the authorization token.
189
+ *
190
+ * @param array $metadata metadata hashmap
191
+ * @param string $authUri optional auth uri
192
+ * @param callable $httpHandler callback which delivers psr7 request
193
+ *
194
+ * @return array updated metadata hashmap
195
+ */
196
+ public function updateMetadata(
197
+ $metadata,
198
+ $authUri = null,
199
+ callable $httpHandler = null
200
+ ) {
201
+ $result = $this->fetchAuthToken($httpHandler);
202
+ if (!isset($result['access_token'])) {
203
+ return $metadata;
204
+ }
205
+ $metadata_copy = $metadata;
206
+ $metadata_copy[self::AUTH_METADATA_KEY] = array('Bearer ' . $result['access_token']);
207
+
208
+ return $metadata_copy;
209
+ }
210
+ }
vendor/google/auth/src/FetchAuthTokenCache.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2010 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ use Psr\Cache\CacheItemPoolInterface;
21
+
22
+ /**
23
+ * A class to implement caching for any object implementing
24
+ * FetchAuthTokenInterface
25
+ */
26
+ class FetchAuthTokenCache implements FetchAuthTokenInterface
27
+ {
28
+ use CacheTrait;
29
+
30
+ /**
31
+ * @var FetchAuthTokenInterface
32
+ */
33
+ private $fetcher;
34
+
35
+ /**
36
+ * @var array
37
+ */
38
+ private $cacheConfig;
39
+
40
+ /**
41
+ * @var CacheItemPoolInterface
42
+ */
43
+ private $cache;
44
+
45
+ public function __construct(
46
+ FetchAuthTokenInterface $fetcher,
47
+ array $cacheConfig = null,
48
+ CacheItemPoolInterface $cache
49
+ ) {
50
+ $this->fetcher = $fetcher;
51
+ $this->cache = $cache;
52
+ $this->cacheConfig = array_merge([
53
+ 'lifetime' => 1500,
54
+ 'prefix' => '',
55
+ ], (array) $cacheConfig);
56
+ }
57
+
58
+ /**
59
+ * Implements FetchAuthTokenInterface#fetchAuthToken.
60
+ *
61
+ * Checks the cache for a valid auth token and fetches the auth tokens
62
+ * from the supplied fetcher.
63
+ *
64
+ * @param callable $httpHandler callback which delivers psr7 request
65
+ *
66
+ * @return array the response
67
+ *
68
+ * @throws \Exception
69
+ */
70
+ public function fetchAuthToken(callable $httpHandler = null)
71
+ {
72
+ // Use the cached value if its available.
73
+ //
74
+ // TODO: correct caching; update the call to setCachedValue to set the expiry
75
+ // to the value returned with the auth token.
76
+ //
77
+ // TODO: correct caching; enable the cache to be cleared.
78
+ $cacheKey = $this->fetcher->getCacheKey();
79
+ $cached = $this->getCachedValue($cacheKey);
80
+ if (!empty($cached)) {
81
+ return ['access_token' => $cached];
82
+ }
83
+
84
+ $auth_token = $this->fetcher->fetchAuthToken($httpHandler);
85
+
86
+ if (isset($auth_token['access_token'])) {
87
+ $this->setCachedValue($cacheKey, $auth_token['access_token']);
88
+ }
89
+
90
+ return $auth_token;
91
+ }
92
+
93
+ /**
94
+ * @return string
95
+ */
96
+ public function getCacheKey()
97
+ {
98
+ return $this->getFullCacheKey($this->fetcher->getCacheKey());
99
+ }
100
+
101
+ /**
102
+ * @return array|null
103
+ */
104
+ public function getLastReceivedToken()
105
+ {
106
+ return $this->fetcher->getLastReceivedToken();
107
+ }
108
+ }
vendor/google/auth/src/FetchAuthTokenInterface.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ /**
21
+ * An interface implemented by objects that can fetch auth tokens.
22
+ */
23
+ interface FetchAuthTokenInterface
24
+ {
25
+ /**
26
+ * Fetches the auth tokens based on the current state.
27
+ *
28
+ * @param callable $httpHandler callback which delivers psr7 request
29
+ *
30
+ * @return array a hash of auth tokens
31
+ */
32
+ public function fetchAuthToken(callable $httpHandler = null);
33
+
34
+ /**
35
+ * Obtains a key that can used to cache the results of #fetchAuthToken.
36
+ *
37
+ * If the value is empty, the auth token is not cached.
38
+ *
39
+ * @return string a key that may be used to cache the auth token.
40
+ */
41
+ public function getCacheKey();
42
+
43
+ /**
44
+ * Returns an associative array with the token and
45
+ * expiration time.
46
+ *
47
+ * @return null|array {
48
+ * The last received access token.
49
+ *
50
+ * @var string $access_token The access token string.
51
+ * @var int $expires_at The time the token expires as a UNIX timestamp.
52
+ * }
53
+ */
54
+ public function getLastReceivedToken();
55
+ }
vendor/google/auth/src/HttpHandler/Guzzle5HttpHandler.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2015 Google Inc. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ namespace Google\Auth\HttpHandler;
18
+
19
+ use GuzzleHttp\ClientInterface;
20
+ use GuzzleHttp\Psr7\Response;
21
+ use Psr\Http\Message\RequestInterface;
22
+ use Psr\Http\Message\ResponseInterface;
23
+
24
+ class Guzzle5HttpHandler
25
+ {
26
+ /**
27
+ * @var ClientInterface
28
+ */
29
+ private $client;
30
+
31
+ /**
32
+ * @param ClientInterface $client
33
+ */
34
+ public function __construct(ClientInterface $client)
35
+ {
36
+ $this->client = $client;
37
+ }
38
+
39
+ /**
40
+ * Accepts a PSR-7 Request and an array of options and returns a PSR-7 response.
41
+ *
42
+ * @param RequestInterface $request
43
+ * @param array $options
44
+ *
45
+ * @return ResponseInterface
46
+ */
47
+ public function __invoke(RequestInterface $request, array $options = [])
48
+ {
49
+ $request = $this->client->createRequest(
50
+ $request->getMethod(),
51
+ $request->getUri(),
52
+ array_merge([
53
+ 'headers' => $request->getHeaders(),
54
+ 'body' => $request->getBody(),
55
+ ], $options)
56
+ );
57
+
58
+ $response = $this->client->send($request);
59
+
60
+ return new Response(
61
+ $response->getStatusCode(),
62
+ $response->getHeaders() ?: [],
63
+ $response->getBody(),
64
+ $response->getProtocolVersion(),
65
+ $response->getReasonPhrase()
66
+ );
67
+ }
68
+ }
vendor/google/auth/src/HttpHandler/Guzzle6HttpHandler.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Google\Auth\HttpHandler;
4
+
5
+ use GuzzleHttp\ClientInterface;
6
+ use Psr\Http\Message\RequestInterface;
7
+ use Psr\Http\Message\ResponseInterface;
8
+
9
+ class Guzzle6HttpHandler
10
+ {
11
+ /**
12
+ * @var ClientInterface
13
+ */
14
+ private $client;
15
+
16
+ /**
17
+ * @param ClientInterface $client
18
+ */
19
+ public function __construct(ClientInterface $client)
20
+ {
21
+ $this->client = $client;
22
+ }
23
+
24
+ /**
25
+ * Accepts a PSR-7 request and an array of options and returns a PSR-7 response.
26
+ *
27
+ * @param RequestInterface $request
28
+ * @param array $options
29
+ *
30
+ * @return ResponseInterface
31
+ */
32
+ public function __invoke(RequestInterface $request, array $options = [])
33
+ {
34
+ return $this->client->send($request, $options);
35
+ }
36
+ }
vendor/google/auth/src/HttpHandler/HttpHandlerFactory.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2015 Google Inc. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ namespace Google\Auth\HttpHandler;
18
+
19
+ use GuzzleHttp\Client;
20
+ use GuzzleHttp\ClientInterface;
21
+
22
+ class HttpHandlerFactory
23
+ {
24
+ /**
25
+ * Builds out a default http handler for the installed version of guzzle.
26
+ *
27
+ * @param ClientInterface $client
28
+ *
29
+ * @return Guzzle5HttpHandler|Guzzle6HttpHandler
30
+ *
31
+ * @throws \Exception
32
+ */
33
+ public static function build(ClientInterface $client = null)
34
+ {
35
+ $version = ClientInterface::VERSION;
36
+ $client = $client ?: new Client();
37
+
38
+ switch ($version[0]) {
39
+ case '5':
40
+ return new Guzzle5HttpHandler($client);
41
+ case '6':
42
+ return new Guzzle6HttpHandler($client);
43
+ default:
44
+ throw new \Exception('Version not supported');
45
+ }
46
+ }
47
+ }
vendor/google/auth/src/Middleware/AuthTokenMiddleware.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Middleware;
19
+
20
+ use Google\Auth\FetchAuthTokenInterface;
21
+ use Psr\Http\Message\RequestInterface;
22
+
23
+ /**
24
+ * AuthTokenMiddleware is a Guzzle Middleware that adds an Authorization header
25
+ * provided by an object implementing FetchAuthTokenInterface.
26
+ *
27
+ * The FetchAuthTokenInterface#fetchAuthToken is used to obtain a hash; one of
28
+ * the values value in that hash is added as the authorization header.
29
+ *
30
+ * Requests will be accessed with the authorization header:
31
+ *
32
+ * 'authorization' 'Bearer <value of auth_token>'
33
+ */
34
+ class AuthTokenMiddleware
35
+ {
36
+ /**
37
+ * @var callback
38
+ */
39
+ private $httpHandler;
40
+
41
+ /**
42
+ * @var FetchAuthTokenInterface
43
+ */
44
+ private $fetcher;
45
+
46
+ /**
47
+ * @var callable
48
+ */
49
+ private $tokenCallback;
50
+
51
+ /**
52
+ * Creates a new AuthTokenMiddleware.
53
+ *
54
+ * @param FetchAuthTokenInterface $fetcher is used to fetch the auth token
55
+ * @param callable $httpHandler (optional) callback which delivers psr7 request
56
+ * @param callable $tokenCallback (optional) function to be called when a new token is fetched.
57
+ */
58
+ public function __construct(
59
+ FetchAuthTokenInterface $fetcher,
60
+ callable $httpHandler = null,
61
+ callable $tokenCallback = null
62
+ ) {
63
+ $this->fetcher = $fetcher;
64
+ $this->httpHandler = $httpHandler;
65
+ $this->tokenCallback = $tokenCallback;
66
+ }
67
+
68
+ /**
69
+ * Updates the request with an Authorization header when auth is 'google_auth'.
70
+ *
71
+ * use Google\Auth\Middleware\AuthTokenMiddleware;
72
+ * use Google\Auth\OAuth2;
73
+ * use GuzzleHttp\Client;
74
+ * use GuzzleHttp\HandlerStack;
75
+ *
76
+ * $config = [..<oauth config param>.];
77
+ * $oauth2 = new OAuth2($config)
78
+ * $middleware = new AuthTokenMiddleware($oauth2);
79
+ * $stack = HandlerStack::create();
80
+ * $stack->push($middleware);
81
+ *
82
+ * $client = new Client([
83
+ * 'handler' => $stack,
84
+ * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
85
+ * 'auth' => 'google_auth' // authorize all requests
86
+ * ]);
87
+ *
88
+ * $res = $client->get('myproject/taskqueues/myqueue');
89
+ *
90
+ * @param callable $handler
91
+ *
92
+ * @return \Closure
93
+ */
94
+ public function __invoke(callable $handler)
95
+ {
96
+ return function (RequestInterface $request, array $options) use ($handler) {
97
+ // Requests using "auth"="google_auth" will be authorized.
98
+ if (!isset($options['auth']) || $options['auth'] !== 'google_auth') {
99
+ return $handler($request, $options);
100
+ }
101
+
102
+ $request = $request->withHeader('authorization', 'Bearer ' . $this->fetchToken());
103
+
104
+ return $handler($request, $options);
105
+ };
106
+ }
107
+
108
+ /**
109
+ * Call fetcher to fetch the token.
110
+ *
111
+ * @return string
112
+ */
113
+ private function fetchToken()
114
+ {
115
+ $auth_tokens = $this->fetcher->fetchAuthToken($this->httpHandler);
116
+
117
+ if (array_key_exists('access_token', $auth_tokens)) {
118
+ // notify the callback if applicable
119
+ if ($this->tokenCallback) {
120
+ call_user_func($this->tokenCallback, $this->fetcher->getCacheKey(), $auth_tokens['access_token']);
121
+ }
122
+
123
+ return $auth_tokens['access_token'];
124
+ }
125
+ }
126
+ }
vendor/google/auth/src/Middleware/ScopedAccessTokenMiddleware.php ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Middleware;
19
+
20
+ use Google\Auth\CacheTrait;
21
+ use Psr\Cache\CacheItemPoolInterface;
22
+ use Psr\Http\Message\RequestInterface;
23
+
24
+ /**
25
+ * ScopedAccessTokenMiddleware is a Guzzle Middleware that adds an Authorization
26
+ * header provided by a closure.
27
+ *
28
+ * The closure returns an access token, taking the scope, either a single
29
+ * string or an array of strings, as its value. If provided, a cache will be
30
+ * used to preserve the access token for a given lifetime.
31
+ *
32
+ * Requests will be accessed with the authorization header:
33
+ *
34
+ * 'authorization' 'Bearer <value of auth_token>'
35
+ */
36
+ class ScopedAccessTokenMiddleware
37
+ {
38
+ use CacheTrait;
39
+
40
+ const DEFAULT_CACHE_LIFETIME = 1500;
41
+
42
+ /**
43
+ * @var CacheItemPoolInterface
44
+ */
45
+ private $cache;
46
+
47
+ /**
48
+ * @var array configuration
49
+ */
50
+ private $cacheConfig;
51
+
52
+ /**
53
+ * @var callable
54
+ */
55
+ private $tokenFunc;
56
+
57
+ /**
58
+ * @var array|string
59
+ */
60
+ private $scopes;
61
+
62
+ /**
63
+ * Creates a new ScopedAccessTokenMiddleware.
64
+ *
65
+ * @param callable $tokenFunc a token generator function
66
+ * @param array|string $scopes the token authentication scopes
67
+ * @param array $cacheConfig configuration for the cache when it's present
68
+ * @param CacheItemPoolInterface $cache an implementation of CacheItemPoolInterface
69
+ */
70
+ public function __construct(
71
+ callable $tokenFunc,
72
+ $scopes,
73
+ array $cacheConfig = null,
74
+ CacheItemPoolInterface $cache = null
75
+ ) {
76
+ $this->tokenFunc = $tokenFunc;
77
+ if (!(is_string($scopes) || is_array($scopes))) {
78
+ throw new \InvalidArgumentException(
79
+ 'wants scope should be string or array');
80
+ }
81
+ $this->scopes = $scopes;
82
+
83
+ if (!is_null($cache)) {
84
+ $this->cache = $cache;
85
+ $this->cacheConfig = array_merge([
86
+ 'lifetime' => self::DEFAULT_CACHE_LIFETIME,
87
+ 'prefix' => '',
88
+ ], $cacheConfig);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Updates the request with an Authorization header when auth is 'scoped'.
94
+ *
95
+ * E.g this could be used to authenticate using the AppEngine
96
+ * AppIdentityService.
97
+ *
98
+ * use google\appengine\api\app_identity\AppIdentityService;
99
+ * use Google\Auth\Middleware\ScopedAccessTokenMiddleware;
100
+ * use GuzzleHttp\Client;
101
+ * use GuzzleHttp\HandlerStack;
102
+ *
103
+ * $scope = 'https://www.googleapis.com/auth/taskqueue'
104
+ * $middleware = new ScopedAccessTokenMiddleware(
105
+ * 'AppIdentityService::getAccessToken',
106
+ * $scope,
107
+ * [ 'prefix' => 'Google\Auth\ScopedAccessToken::' ],
108
+ * $cache = new Memcache()
109
+ * );
110
+ * $stack = HandlerStack::create();
111
+ * $stack->push($middleware);
112
+ *
113
+ * $client = new Client([
114
+ * 'handler' => $stack,
115
+ * 'base_url' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
116
+ * 'auth' => 'scoped' // authorize all requests
117
+ * ]);
118
+ *
119
+ * $res = $client->get('myproject/taskqueues/myqueue');
120
+ *
121
+ * @param callable $handler
122
+ *
123
+ * @return \Closure
124
+ */
125
+ public function __invoke(callable $handler)
126
+ {
127
+ return function (RequestInterface $request, array $options) use ($handler) {
128
+ // Requests using "auth"="scoped" will be authorized.
129
+ if (!isset($options['auth']) || $options['auth'] !== 'scoped') {
130
+ return $handler($request, $options);
131
+ }
132
+
133
+ $request = $request->withHeader('authorization', 'Bearer ' . $this->fetchToken());
134
+
135
+ return $handler($request, $options);
136
+ };
137
+ }
138
+
139
+ /**
140
+ * @return string
141
+ */
142
+ private function getCacheKey()
143
+ {
144
+ $key = null;
145
+
146
+ if (is_string($this->scopes)) {
147
+ $key .= $this->scopes;
148
+ } elseif (is_array($this->scopes)) {
149
+ $key .= implode(':', $this->scopes);
150
+ }
151
+
152
+ return $key;
153
+ }
154
+
155
+ /**
156
+ * Determine if token is available in the cache, if not call tokenFunc to
157
+ * fetch it.
158
+ *
159
+ * @return string
160
+ */
161
+ private function fetchToken()
162
+ {
163
+ $cacheKey = $this->getCacheKey();
164
+ $cached = $this->getCachedValue($cacheKey);
165
+
166
+ if (!empty($cached)) {
167
+ return $cached;
168
+ }
169
+
170
+ $token = call_user_func($this->tokenFunc, $this->scopes);
171
+ $this->setCachedValue($cacheKey, $token);
172
+
173
+ return $token;
174
+ }
175
+ }
vendor/google/auth/src/Middleware/SimpleMiddleware.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Middleware;
19
+
20
+ use GuzzleHttp\Psr7;
21
+ use Psr\Http\Message\RequestInterface;
22
+
23
+ /**
24
+ * SimpleMiddleware is a Guzzle Middleware that implements Google's Simple API
25
+ * access.
26
+ *
27
+ * Requests are accessed using the Simple API access developer key.
28
+ */
29
+ class SimpleMiddleware
30
+ {
31
+ /**
32
+ * @var array
33
+ */
34
+ private $config;
35
+
36
+ /**
37
+ * Create a new Simple plugin.
38
+ *
39
+ * The configuration array expects one option
40
+ * - key: required, otherwise InvalidArgumentException is thrown
41
+ *
42
+ * @param array $config Configuration array
43
+ */
44
+ public function __construct(array $config)
45
+ {
46
+ if (!isset($config['key'])) {
47
+ throw new \InvalidArgumentException('requires a key to have been set');
48
+ }
49
+
50
+ $this->config = array_merge(['key' => null], $config);
51
+ }
52
+
53
+ /**
54
+ * Updates the request query with the developer key if auth is set to simple.
55
+ *
56
+ * use Google\Auth\Middleware\SimpleMiddleware;
57
+ * use GuzzleHttp\Client;
58
+ * use GuzzleHttp\HandlerStack;
59
+ *
60
+ * $my_key = 'is not the same as yours';
61
+ * $middleware = new SimpleMiddleware(['key' => $my_key]);
62
+ * $stack = HandlerStack::create();
63
+ * $stack->push($middleware);
64
+ *
65
+ * $client = new Client([
66
+ * 'handler' => $stack,
67
+ * 'base_uri' => 'https://www.googleapis.com/discovery/v1/',
68
+ * 'auth' => 'simple'
69
+ * ]);
70
+ *
71
+ * $res = $client->get('drive/v2/rest');
72
+ *
73
+ * @param callable $handler
74
+ *
75
+ * @return \Closure
76
+ */
77
+ public function __invoke(callable $handler)
78
+ {
79
+ return function (RequestInterface $request, array $options) use ($handler) {
80
+ // Requests using "auth"="scoped" will be authorized.
81
+ if (!isset($options['auth']) || $options['auth'] !== 'simple') {
82
+ return $handler($request, $options);
83
+ }
84
+
85
+ $query = Psr7\parse_query($request->getUri()->getQuery());
86
+ $params = array_merge($query, $this->config);
87
+ $uri = $request->getUri()->withQuery(Psr7\build_query($params));
88
+ $request = $request->withUri($uri);
89
+
90
+ return $handler($request, $options);
91
+ };
92
+ }
93
+ }
vendor/google/auth/src/OAuth2.php ADDED
@@ -0,0 +1,1335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
21
+ use GuzzleHttp\Psr7;
22
+ use GuzzleHttp\Psr7\Request;
23
+ use InvalidArgumentException;
24
+ use Psr\Http\Message\RequestInterface;
25
+ use Psr\Http\Message\ResponseInterface;
26
+ use Psr\Http\Message\UriInterface;
27
+
28
+ /**
29
+ * OAuth2 supports authentication by OAuth2 2-legged flows.
30
+ *
31
+ * It primary supports
32
+ * - service account authorization
33
+ * - authorization where a user already has an access token
34
+ */
35
+ class OAuth2 implements FetchAuthTokenInterface
36
+ {
37
+ const DEFAULT_EXPIRY_SECONDS = 3600; // 1 hour
38
+ const DEFAULT_SKEW_SECONDS = 60; // 1 minute
39
+ const JWT_URN = 'urn:ietf:params:oauth:grant-type:jwt-bearer';
40
+
41
+ /**
42
+ * TODO: determine known methods from the keys of JWT::methods.
43
+ */
44
+ public static $knownSigningAlgorithms = array(
45
+ 'HS256',
46
+ 'HS512',
47
+ 'HS384',
48
+ 'RS256',
49
+ );
50
+
51
+ /**
52
+ * The well known grant types.
53
+ *
54
+ * @var array
55
+ */
56
+ public static $knownGrantTypes = array(
57
+ 'authorization_code',
58
+ 'refresh_token',
59
+ 'password',
60
+ 'client_credentials',
61
+ );
62
+
63
+ /**
64
+ * - authorizationUri
65
+ * The authorization server's HTTP endpoint capable of
66
+ * authenticating the end-user and obtaining authorization.
67
+ *
68
+ * @var UriInterface
69
+ */
70
+ private $authorizationUri;
71
+
72
+ /**
73
+ * - tokenCredentialUri
74
+ * The authorization server's HTTP endpoint capable of issuing
75
+ * tokens and refreshing expired tokens.
76
+ *
77
+ * @var UriInterface
78
+ */
79
+ private $tokenCredentialUri;
80
+
81
+ /**
82
+ * The redirection URI used in the initial request.
83
+ *
84
+ * @var string
85
+ */
86
+ private $redirectUri;
87
+
88
+ /**
89
+ * A unique identifier issued to the client to identify itself to the
90
+ * authorization server.
91
+ *
92
+ * @var string
93
+ */
94
+ private $clientId;
95
+
96
+ /**
97
+ * A shared symmetric secret issued by the authorization server, which is
98
+ * used to authenticate the client.
99
+ *
100
+ * @var string
101
+ */
102
+ private $clientSecret;
103
+
104
+ /**
105
+ * The resource owner's username.
106
+ *
107
+ * @var string
108
+ */
109
+ private $username;
110
+
111
+ /**
112
+ * The resource owner's password.
113
+ *
114
+ * @var string
115
+ */
116
+ private $password;
117
+
118
+ /**
119
+ * The scope of the access request, expressed either as an Array or as a
120
+ * space-delimited string.
121
+ *
122
+ * @var string
123
+ */
124
+ private $scope;
125
+
126
+ /**
127
+ * An arbitrary string designed to allow the client to maintain state.
128
+ *
129
+ * @var string
130
+ */
131
+ private $state;
132
+
133
+ /**
134
+ * The authorization code issued to this client.
135
+ *
136
+ * Only used by the authorization code access grant type.
137
+ *
138
+ * @var string
139
+ */
140
+ private $code;
141
+
142
+ /**
143
+ * The issuer ID when using assertion profile.
144
+ *
145
+ * @var string
146
+ */
147
+ private $issuer;
148
+
149
+ /**
150
+ * The target audience for assertions.
151
+ *
152
+ * @var string
153
+ */
154
+ private $audience;
155
+
156
+ /**
157
+ * The target sub when issuing assertions.
158
+ *
159
+ * @var string
160
+ */
161
+ private $sub;
162
+
163
+ /**
164
+ * The number of seconds assertions are valid for.
165
+ *
166
+ * @var int
167
+ */
168
+ private $expiry;
169
+
170
+ /**
171
+ * The signing key when using assertion profile.
172
+ *
173
+ * @var string
174
+ */
175
+ private $signingKey;
176
+
177
+ /**
178
+ * The signing algorithm when using an assertion profile.
179
+ *
180
+ * @var string
181
+ */
182
+ private $signingAlgorithm;
183
+
184
+ /**
185
+ * The refresh token associated with the access token to be refreshed.
186
+ *
187
+ * @var string
188
+ */
189
+ private $refreshToken;
190
+
191
+ /**
192
+ * The current access token.
193
+ *
194
+ * @var string
195
+ */
196
+ private $accessToken;
197
+
198
+ /**
199
+ * The current ID token.
200
+ *
201
+ * @var string
202
+ */
203
+ private $idToken;
204
+
205
+ /**
206
+ * The lifetime in seconds of the current access token.
207
+ *
208
+ * @var int
209
+ */
210
+ private $expiresIn;
211
+
212
+ /**
213
+ * The expiration time of the access token as a number of seconds since the
214
+ * unix epoch.
215
+ *
216
+ * @var int
217
+ */
218
+ private $expiresAt;
219
+
220
+ /**
221
+ * The issue time of the access token as a number of seconds since the unix
222
+ * epoch.
223
+ *
224
+ * @var int
225
+ */
226
+ private $issuedAt;
227
+
228
+ /**
229
+ * The current grant type.
230
+ *
231
+ * @var string
232
+ */
233
+ private $grantType;
234
+
235
+ /**
236
+ * When using an extension grant type, this is the set of parameters used by
237
+ * that extension.
238
+ */
239
+ private $extensionParams;
240
+
241
+ /**
242
+ * When using the toJwt function, these claims will be added to the JWT
243
+ * payload.
244
+ */
245
+ private $additionalClaims;
246
+
247
+ /**
248
+ * Create a new OAuthCredentials.
249
+ *
250
+ * The configuration array accepts various options
251
+ *
252
+ * - authorizationUri
253
+ * The authorization server's HTTP endpoint capable of
254
+ * authenticating the end-user and obtaining authorization.
255
+ *
256
+ * - tokenCredentialUri
257
+ * The authorization server's HTTP endpoint capable of issuing
258
+ * tokens and refreshing expired tokens.
259
+ *
260
+ * - clientId
261
+ * A unique identifier issued to the client to identify itself to the
262
+ * authorization server.
263
+ *
264
+ * - clientSecret
265
+ * A shared symmetric secret issued by the authorization server,
266
+ * which is used to authenticate the client.
267
+ *
268
+ * - scope
269
+ * The scope of the access request, expressed either as an Array
270
+ * or as a space-delimited String.
271
+ *
272
+ * - state
273
+ * An arbitrary string designed to allow the client to maintain state.
274
+ *
275
+ * - redirectUri
276
+ * The redirection URI used in the initial request.
277
+ *
278
+ * - username
279
+ * The resource owner's username.
280
+ *
281
+ * - password
282
+ * The resource owner's password.
283
+ *
284
+ * - issuer
285
+ * Issuer ID when using assertion profile
286
+ *
287
+ * - audience
288
+ * Target audience for assertions
289
+ *
290
+ * - expiry
291
+ * Number of seconds assertions are valid for
292
+ *
293
+ * - signingKey
294
+ * Signing key when using assertion profile
295
+ *
296
+ * - refreshToken
297
+ * The refresh token associated with the access token
298
+ * to be refreshed.
299
+ *
300
+ * - accessToken
301
+ * The current access token for this client.
302
+ *
303
+ * - idToken
304
+ * The current ID token for this client.
305
+ *
306
+ * - extensionParams
307
+ * When using an extension grant type, this is the set of parameters used
308
+ * by that extension.
309
+ *
310
+ * @param array $config Configuration array
311
+ */
312
+ public function __construct(array $config)
313
+ {
314
+ $opts = array_merge([
315
+ 'expiry' => self::DEFAULT_EXPIRY_SECONDS,
316
+ 'extensionParams' => [],
317
+ 'authorizationUri' => null,
318
+ 'redirectUri' => null,
319
+ 'tokenCredentialUri' => null,
320
+ 'state' => null,
321
+ 'username' => null,
322
+ 'password' => null,
323
+ 'clientId' => null,
324
+ 'clientSecret' => null,
325
+ 'issuer' => null,
326
+ 'sub' => null,
327
+ 'audience' => null,
328
+ 'signingKey' => null,
329
+ 'signingAlgorithm' => null,
330
+ 'scope' => null,
331
+ 'additionalClaims' => [],
332
+ ], $config);
333
+
334
+ $this->setAuthorizationUri($opts['authorizationUri']);
335
+ $this->setRedirectUri($opts['redirectUri']);
336
+ $this->setTokenCredentialUri($opts['tokenCredentialUri']);
337
+ $this->setState($opts['state']);
338
+ $this->setUsername($opts['username']);
339
+ $this->setPassword($opts['password']);
340
+ $this->setClientId($opts['clientId']);
341
+ $this->setClientSecret($opts['clientSecret']);
342
+ $this->setIssuer($opts['issuer']);
343
+ $this->setSub($opts['sub']);
344
+ $this->setExpiry($opts['expiry']);
345
+ $this->setAudience($opts['audience']);
346
+ $this->setSigningKey($opts['signingKey']);
347
+ $this->setSigningAlgorithm($opts['signingAlgorithm']);
348
+ $this->setScope($opts['scope']);
349
+ $this->setExtensionParams($opts['extensionParams']);
350
+ $this->setAdditionalClaims($opts['additionalClaims']);
351
+ $this->updateToken($opts);
352
+ }
353
+
354
+ /**
355
+ * Verifies the idToken if present.
356
+ *
357
+ * - if none is present, return null
358
+ * - if present, but invalid, raises DomainException.
359
+ * - otherwise returns the payload in the idtoken as a PHP object.
360
+ *
361
+ * if $publicKey is null, the key is decoded without being verified.
362
+ *
363
+ * @param string $publicKey The public key to use to authenticate the token
364
+ * @param array $allowed_algs List of supported verification algorithms
365
+ *
366
+ * @return null|object
367
+ */
368
+ public function verifyIdToken($publicKey = null, $allowed_algs = array())
369
+ {
370
+ $idToken = $this->getIdToken();
371
+ if (is_null($idToken)) {
372
+ return null;
373
+ }
374
+
375
+ $resp = $this->jwtDecode($idToken, $publicKey, $allowed_algs);
376
+ if (!property_exists($resp, 'aud')) {
377
+ throw new \DomainException('No audience found the id token');
378
+ }
379
+ if ($resp->aud != $this->getAudience()) {
380
+ throw new \DomainException('Wrong audience present in the id token');
381
+ }
382
+
383
+ return $resp;
384
+ }
385
+
386
+ /**
387
+ * Obtains the encoded jwt from the instance data.
388
+ *
389
+ * @param array $config array optional configuration parameters
390
+ *
391
+ * @return string
392
+ */
393
+ public function toJwt(array $config = [])
394
+ {
395
+ if (is_null($this->getSigningKey())) {
396
+ throw new \DomainException('No signing key available');
397
+ }
398
+ if (is_null($this->getSigningAlgorithm())) {
399
+ throw new \DomainException('No signing algorithm specified');
400
+ }
401
+ $now = time();
402
+
403
+ $opts = array_merge([
404
+ 'skew' => self::DEFAULT_SKEW_SECONDS,
405
+ ], $config);
406
+
407
+ $assertion = [
408
+ 'iss' => $this->getIssuer(),
409
+ 'aud' => $this->getAudience(),
410
+ 'exp' => ($now + $this->getExpiry()),
411
+ 'iat' => ($now - $opts['skew']),
412
+ ];
413
+ foreach ($assertion as $k => $v) {
414
+ if (is_null($v)) {
415
+ throw new \DomainException($k . ' should not be null');
416
+ }
417
+ }
418
+ if (!(is_null($this->getScope()))) {
419
+ $assertion['scope'] = $this->getScope();
420
+ }
421
+ if (!(is_null($this->getSub()))) {
422
+ $assertion['sub'] = $this->getSub();
423
+ }
424
+ $assertion += $this->getAdditionalClaims();
425
+
426
+ return $this->jwtEncode($assertion, $this->getSigningKey(),
427
+ $this->getSigningAlgorithm());
428
+ }
429
+
430
+ /**
431
+ * Generates a request for token credentials.
432
+ *
433
+ * @return RequestInterface the authorization Url.
434
+ */
435
+ public function generateCredentialsRequest()
436
+ {
437
+ $uri = $this->getTokenCredentialUri();
438
+ if (is_null($uri)) {
439
+ throw new \DomainException('No token credential URI was set.');
440
+ }
441
+
442
+ $grantType = $this->getGrantType();
443
+ $params = array('grant_type' => $grantType);
444
+ switch ($grantType) {
445
+ case 'authorization_code':
446
+ $params['code'] = $this->getCode();
447
+ $params['redirect_uri'] = $this->getRedirectUri();
448
+ $this->addClientCredentials($params);
449
+ break;
450
+ case 'password':
451
+ $params['username'] = $this->getUsername();
452
+ $params['password'] = $this->getPassword();
453
+ $this->addClientCredentials($params);
454
+ break;
455
+ case 'refresh_token':
456
+ $params['refresh_token'] = $this->getRefreshToken();
457
+ $this->addClientCredentials($params);
458
+ break;
459
+ case self::JWT_URN:
460
+ $params['assertion'] = $this->toJwt();
461
+ break;
462
+ default:
463
+ if (!is_null($this->getRedirectUri())) {
464
+ # Grant type was supposed to be 'authorization_code', as there
465
+ # is a redirect URI.
466
+ throw new \DomainException('Missing authorization code');
467
+ }
468
+ unset($params['grant_type']);
469
+ if (!is_null($grantType)) {
470
+ $params['grant_type'] = $grantType;
471
+ }
472
+ $params = array_merge($params, $this->getExtensionParams());
473
+ }
474
+
475
+ $headers = [
476
+ 'Cache-Control' => 'no-store',
477
+ 'Content-Type' => 'application/x-www-form-urlencoded',
478
+ ];
479
+
480
+ return new Request(
481
+ 'POST',
482
+ $uri,
483
+ $headers,
484
+ Psr7\build_query($params)
485
+ );
486
+ }
487
+
488
+ /**
489
+ * Fetches the auth tokens based on the current state.
490
+ *
491
+ * @param callable $httpHandler callback which delivers psr7 request
492
+ *
493
+ * @return array the response
494
+ */
495
+ public function fetchAuthToken(callable $httpHandler = null)
496
+ {
497
+ if (is_null($httpHandler)) {
498
+ $httpHandler = HttpHandlerFactory::build();
499
+ }
500
+
501
+ $response = $httpHandler($this->generateCredentialsRequest());
502
+ $credentials = $this->parseTokenResponse($response);
503
+ $this->updateToken($credentials);
504
+
505
+ return $credentials;
506
+ }
507
+
508
+ /**
509
+ * Obtains a key that can used to cache the results of #fetchAuthToken.
510
+ *
511
+ * The key is derived from the scopes.
512
+ *
513
+ * @return string a key that may be used to cache the auth token.
514
+ */
515
+ public function getCacheKey()
516
+ {
517
+ if (is_string($this->scope)) {
518
+ return $this->scope;
519
+ } elseif (is_array($this->scope)) {
520
+ return implode(':', $this->scope);
521
+ }
522
+
523
+ // If scope has not set, return null to indicate no caching.
524
+ return null;
525
+ }
526
+
527
+ /**
528
+ * Parses the fetched tokens.
529
+ *
530
+ * @param ResponseInterface $resp the response.
531
+ *
532
+ * @return array the tokens parsed from the response body.
533
+ *
534
+ * @throws \Exception
535
+ */
536
+ public function parseTokenResponse(ResponseInterface $resp)
537
+ {
538
+ $body = (string)$resp->getBody();
539
+ if ($resp->hasHeader('Content-Type') &&
540
+ $resp->getHeaderLine('Content-Type') == 'application/x-www-form-urlencoded'
541
+ ) {
542
+ $res = array();
543
+ parse_str($body, $res);
544
+
545
+ return $res;
546
+ } else {
547
+ // Assume it's JSON; if it's not throw an exception
548
+ if (null === $res = json_decode($body, true)) {
549
+ throw new \Exception('Invalid JSON response');
550
+ }
551
+
552
+ return $res;
553
+ }
554
+ }
555
+
556
+ /**
557
+ * Updates an OAuth 2.0 client.
558
+ *
559
+ * @example
560
+ * client.updateToken([
561
+ * 'refresh_token' => 'n4E9O119d',
562
+ * 'access_token' => 'FJQbwq9',
563
+ * 'expires_in' => 3600
564
+ * ])
565
+ *
566
+ * @param array $config
567
+ * The configuration parameters related to the token.
568
+ *
569
+ * - refresh_token
570
+ * The refresh token associated with the access token
571
+ * to be refreshed.
572
+ *
573
+ * - access_token
574
+ * The current access token for this client.
575
+ *
576
+ * - id_token
577
+ * The current ID token for this client.
578
+ *
579
+ * - expires_in
580
+ * The time in seconds until access token expiration.
581
+ *
582
+ * - expires_at
583
+ * The time as an integer number of seconds since the Epoch
584
+ *
585
+ * - issued_at
586
+ * The timestamp that the token was issued at.
587
+ */
588
+ public function updateToken(array $config)
589
+ {
590
+ $opts = array_merge([
591
+ 'extensionParams' => [],
592
+ 'access_token' => null,
593
+ 'id_token' => null,
594
+ 'expires_in' => null,
595
+ 'expires_at' => null,
596
+ 'issued_at' => null,
597
+ ], $config);
598
+
599
+ $this->setExpiresAt($opts['expires_at']);
600
+ $this->setExpiresIn($opts['expires_in']);
601
+ // By default, the token is issued at `Time.now` when `expiresIn` is set,
602
+ // but this can be used to supply a more precise time.
603
+ if (!is_null($opts['issued_at'])) {
604
+ $this->setIssuedAt($opts['issued_at']);
605
+ }
606
+
607
+ $this->setAccessToken($opts['access_token']);
608
+ $this->setIdToken($opts['id_token']);
609
+ // The refresh token should only be updated if a value is explicitly
610
+ // passed in, as some access token responses do not include a refresh
611
+ // token.
612
+ if (array_key_exists('refresh_token', $opts)) {
613
+ $this->setRefreshToken($opts['refresh_token']);
614
+ }
615
+ }
616
+
617
+ /**
618
+ * Builds the authorization Uri that the user should be redirected to.
619
+ *
620
+ * @param array $config configuration options that customize the return url
621
+ *
622
+ * @return UriInterface the authorization Url.
623
+ *
624
+ * @throws InvalidArgumentException
625
+ */
626
+ public function buildFullAuthorizationUri(array $config = [])
627
+ {
628
+ if (is_null($this->getAuthorizationUri())) {
629
+ throw new InvalidArgumentException(
630
+ 'requires an authorizationUri to have been set');
631
+ }
632
+
633
+ $params = array_merge([
634
+ 'response_type' => 'code',
635
+ 'access_type' => 'offline',
636
+ 'client_id' => $this->clientId,
637
+ 'redirect_uri' => $this->redirectUri,
638
+ 'state' => $this->state,
639
+ 'scope' => $this->getScope(),
640
+ ], $config);
641
+
642
+ // Validate the auth_params
643
+ if (is_null($params['client_id'])) {
644
+ throw new InvalidArgumentException(
645
+ 'missing the required client identifier');
646
+ }
647
+ if (is_null($params['redirect_uri'])) {
648
+ throw new InvalidArgumentException('missing the required redirect URI');
649
+ }
650
+ if (!empty($params['prompt']) && !empty($params['approval_prompt'])) {
651
+ throw new InvalidArgumentException(
652
+ 'prompt and approval_prompt are mutually exclusive');
653
+ }
654
+
655
+ // Construct the uri object; return it if it is valid.
656
+ $result = clone $this->authorizationUri;
657
+ $existingParams = Psr7\parse_query($result->getQuery());
658
+
659
+ $result = $result->withQuery(
660
+ Psr7\build_query(array_merge($existingParams, $params))
661
+ );
662
+
663
+ if ($result->getScheme() != 'https') {
664
+ throw new InvalidArgumentException(
665
+ 'Authorization endpoint must be protected by TLS');
666
+ }
667
+
668
+ return $result;
669
+ }
670
+
671
+ /**
672
+ * Sets the authorization server's HTTP endpoint capable of authenticating
673
+ * the end-user and obtaining authorization.
674
+ *
675
+ * @param string $uri
676
+ */
677
+ public function setAuthorizationUri($uri)
678
+ {
679
+ $this->authorizationUri = $this->coerceUri($uri);
680
+ }
681
+
682
+ /**
683
+ * Gets the authorization server's HTTP endpoint capable of authenticating
684
+ * the end-user and obtaining authorization.
685
+ *
686
+ * @return UriInterface
687
+ */
688
+ public function getAuthorizationUri()
689
+ {
690
+ return $this->authorizationUri;
691
+ }
692
+
693
+ /**
694
+ * Gets the authorization server's HTTP endpoint capable of issuing tokens
695
+ * and refreshing expired tokens.
696
+ *
697
+ * @return string
698
+ */
699
+ public function getTokenCredentialUri()
700
+ {
701
+ return $this->tokenCredentialUri;
702
+ }
703
+
704
+ /**
705
+ * Sets the authorization server's HTTP endpoint capable of issuing tokens
706
+ * and refreshing expired tokens.
707
+ *
708
+ * @param string $uri
709
+ */
710
+ public function setTokenCredentialUri($uri)
711
+ {
712
+ $this->tokenCredentialUri = $this->coerceUri($uri);
713
+ }
714
+
715
+ /**
716
+ * Gets the redirection URI used in the initial request.
717
+ *
718
+ * @return string
719
+ */
720
+ public function getRedirectUri()
721
+ {
722
+ return $this->redirectUri;
723
+ }
724
+
725
+ /**
726
+ * Sets the redirection URI used in the initial request.
727
+ *
728
+ * @param string $uri
729
+ */
730
+ public function setRedirectUri($uri)
731
+ {
732
+ if (is_null($uri)) {
733
+ $this->redirectUri = null;
734
+
735
+ return;
736
+ }
737
+ // redirect URI must be absolute
738
+ if (!$this->isAbsoluteUri($uri)) {
739
+ // "postmessage" is a reserved URI string in Google-land
740
+ // @see https://developers.google.com/identity/sign-in/web/server-side-flow
741
+ if ('postmessage' !== (string)$uri) {
742
+ throw new InvalidArgumentException(
743
+ 'Redirect URI must be absolute');
744
+ }
745
+ }
746
+ $this->redirectUri = (string)$uri;
747
+ }
748
+
749
+ /**
750
+ * Gets the scope of the access requests as a space-delimited String.
751
+ *
752
+ * @return string
753
+ */
754
+ public function getScope()
755
+ {
756
+ if (is_null($this->scope)) {
757
+ return $this->scope;
758
+ }
759
+
760
+ return implode(' ', $this->scope);
761
+ }
762
+
763
+ /**
764
+ * Sets the scope of the access request, expressed either as an Array or as
765
+ * a space-delimited String.
766
+ *
767
+ * @param string|array $scope
768
+ *
769
+ * @throws InvalidArgumentException
770
+ */
771
+ public function setScope($scope)
772
+ {
773
+ if (is_null($scope)) {
774
+ $this->scope = null;
775
+ } elseif (is_string($scope)) {
776
+ $this->scope = explode(' ', $scope);
777
+ } elseif (is_array($scope)) {
778
+ foreach ($scope as $s) {
779
+ $pos = strpos($s, ' ');
780
+ if ($pos !== false) {
781
+ throw new InvalidArgumentException(
782
+ 'array scope values should not contain spaces');
783
+ }
784
+ }
785
+ $this->scope = $scope;
786
+ } else {
787
+ throw new InvalidArgumentException(
788
+ 'scopes should be a string or array of strings');
789
+ }
790
+ }
791
+
792
+ /**
793
+ * Gets the current grant type.
794
+ *
795
+ * @return string
796
+ */
797
+ public function getGrantType()
798
+ {
799
+ if (!is_null($this->grantType)) {
800
+ return $this->grantType;
801
+ }
802
+
803
+ // Returns the inferred grant type, based on the current object instance
804
+ // state.
805
+ if (!is_null($this->code)) {
806
+ return 'authorization_code';
807
+ } elseif (!is_null($this->refreshToken)) {
808
+ return 'refresh_token';
809
+ } elseif (!is_null($this->username) && !is_null($this->password)) {
810
+ return 'password';
811
+ } elseif (!is_null($this->issuer) && !is_null($this->signingKey)) {
812
+ return self::JWT_URN;
813
+ } else {
814
+ return null;
815
+ }
816
+ }
817
+
818
+ /**
819
+ * Sets the current grant type.
820
+ *
821
+ * @param $grantType
822
+ *
823
+ * @throws InvalidArgumentException
824
+ */
825
+ public function setGrantType($grantType)
826
+ {
827
+ if (in_array($grantType, self::$knownGrantTypes)) {
828
+ $this->grantType = $grantType;
829
+ } else {
830
+ // validate URI
831
+ if (!$this->isAbsoluteUri($grantType)) {
832
+ throw new InvalidArgumentException(
833
+ 'invalid grant type');
834
+ }
835
+ $this->grantType = (string)$grantType;
836
+ }
837
+ }
838
+
839
+ /**
840
+ * Gets an arbitrary string designed to allow the client to maintain state.
841
+ *
842
+ * @return string
843
+ */
844
+ public function getState()
845
+ {
846
+ return $this->state;
847
+ }
848
+
849
+ /**
850
+ * Sets an arbitrary string designed to allow the client to maintain state.
851
+ *
852
+ * @param string $state
853
+ */
854
+ public function setState($state)
855
+ {
856
+ $this->state = $state;
857
+ }
858
+
859
+ /**
860
+ * Gets the authorization code issued to this client.
861
+ */
862
+ public function getCode()
863
+ {
864
+ return $this->code;
865
+ }
866
+
867
+ /**
868
+ * Sets the authorization code issued to this client.
869
+ *
870
+ * @param string $code
871
+ */
872
+ public function setCode($code)
873
+ {
874
+ $this->code = $code;
875
+ }
876
+
877
+ /**
878
+ * Gets the resource owner's username.
879
+ */
880
+ public function getUsername()
881
+ {
882
+ return $this->username;
883
+ }
884
+
885
+ /**
886
+ * Sets the resource owner's username.
887
+ *
888
+ * @param string $username
889
+ */
890
+ public function setUsername($username)
891
+ {
892
+ $this->username = $username;
893
+ }
894
+
895
+ /**
896
+ * Gets the resource owner's password.
897
+ */
898
+ public function getPassword()
899
+ {
900
+ return $this->password;
901
+ }
902
+
903
+ /**
904
+ * Sets the resource owner's password.
905
+ *
906
+ * @param $password
907
+ */
908
+ public function setPassword($password)
909
+ {
910
+ $this->password = $password;
911
+ }
912
+
913
+ /**
914
+ * Sets a unique identifier issued to the client to identify itself to the
915
+ * authorization server.
916
+ */
917
+ public function getClientId()
918
+ {
919
+ return $this->clientId;
920
+ }
921
+
922
+ /**
923
+ * Sets a unique identifier issued to the client to identify itself to the
924
+ * authorization server.
925
+ *
926
+ * @param $clientId
927
+ */
928
+ public function setClientId($clientId)
929
+ {
930
+ $this->clientId = $clientId;
931
+ }
932
+
933
+ /**
934
+ * Gets a shared symmetric secret issued by the authorization server, which
935
+ * is used to authenticate the client.
936
+ */
937
+ public function getClientSecret()
938
+ {
939
+ return $this->clientSecret;
940
+ }
941
+
942
+ /**
943
+ * Sets a shared symmetric secret issued by the authorization server, which
944
+ * is used to authenticate the client.
945
+ *
946
+ * @param $clientSecret
947
+ */
948
+ public function setClientSecret($clientSecret)
949
+ {
950
+ $this->clientSecret = $clientSecret;
951
+ }
952
+
953
+ /**
954
+ * Gets the Issuer ID when using assertion profile.
955
+ */
956
+ public function getIssuer()
957
+ {
958
+ return $this->issuer;
959
+ }
960
+
961
+ /**
962
+ * Sets the Issuer ID when using assertion profile.
963
+ *
964
+ * @param string $issuer
965
+ */
966
+ public function setIssuer($issuer)
967
+ {
968
+ $this->issuer = $issuer;
969
+ }
970
+
971
+ /**
972
+ * Gets the target sub when issuing assertions.
973
+ */
974
+ public function getSub()
975
+ {
976
+ return $this->sub;
977
+ }
978
+
979
+ /**
980
+ * Sets the target sub when issuing assertions.
981
+ *
982
+ * @param string $sub
983
+ */
984
+ public function setSub($sub)
985
+ {
986
+ $this->sub = $sub;
987
+ }
988
+
989
+ /**
990
+ * Gets the target audience when issuing assertions.
991
+ */
992
+ public function getAudience()
993
+ {
994
+ return $this->audience;
995
+ }
996
+
997
+ /**
998
+ * Sets the target audience when issuing assertions.
999
+ *
1000
+ * @param string $audience
1001
+ */
1002
+ public function setAudience($audience)
1003
+ {
1004
+ $this->audience = $audience;
1005
+ }
1006
+
1007
+ /**
1008
+ * Gets the signing key when using an assertion profile.
1009
+ */
1010
+ public function getSigningKey()
1011
+ {
1012
+ return $this->signingKey;
1013
+ }
1014
+
1015
+ /**
1016
+ * Sets the signing key when using an assertion profile.
1017
+ *
1018
+ * @param string $signingKey
1019
+ */
1020
+ public function setSigningKey($signingKey)
1021
+ {
1022
+ $this->signingKey = $signingKey;
1023
+ }
1024
+
1025
+ /**
1026
+ * Gets the signing algorithm when using an assertion profile.
1027
+ *
1028
+ * @return string
1029
+ */
1030
+ public function getSigningAlgorithm()
1031
+ {
1032
+ return $this->signingAlgorithm;
1033
+ }
1034
+
1035
+ /**
1036
+ * Sets the signing algorithm when using an assertion profile.
1037
+ *
1038
+ * @param string $signingAlgorithm
1039
+ */
1040
+ public function setSigningAlgorithm($signingAlgorithm)
1041
+ {
1042
+ if (is_null($signingAlgorithm)) {
1043
+ $this->signingAlgorithm = null;
1044
+ } elseif (!in_array($signingAlgorithm, self::$knownSigningAlgorithms)) {
1045
+ throw new InvalidArgumentException('unknown signing algorithm');
1046
+ } else {
1047
+ $this->signingAlgorithm = $signingAlgorithm;
1048
+ }
1049
+ }
1050
+
1051
+ /**
1052
+ * Gets the set of parameters used by extension when using an extension
1053
+ * grant type.
1054
+ */
1055
+ public function getExtensionParams()
1056
+ {
1057
+ return $this->extensionParams;
1058
+ }
1059
+
1060
+ /**
1061
+ * Sets the set of parameters used by extension when using an extension
1062
+ * grant type.
1063
+ *
1064
+ * @param $extensionParams
1065
+ */
1066
+ public function setExtensionParams($extensionParams)
1067
+ {
1068
+ $this->extensionParams = $extensionParams;
1069
+ }
1070
+
1071
+ /**
1072
+ * Gets the number of seconds assertions are valid for.
1073
+ */
1074
+ public function getExpiry()
1075
+ {
1076
+ return $this->expiry;
1077
+ }
1078
+
1079
+ /**
1080
+ * Sets the number of seconds assertions are valid for.
1081
+ *
1082
+ * @param int $expiry
1083
+ */
1084
+ public function setExpiry($expiry)
1085
+ {
1086
+ $this->expiry = $expiry;
1087
+ }
1088
+
1089
+ /**
1090
+ * Gets the lifetime of the access token in seconds.
1091
+ */
1092
+ public function getExpiresIn()
1093
+ {
1094
+ return $this->expiresIn;
1095
+ }
1096
+
1097
+ /**
1098
+ * Sets the lifetime of the access token in seconds.
1099
+ *
1100
+ * @param int $expiresIn
1101
+ */
1102
+ public function setExpiresIn($expiresIn)
1103
+ {
1104
+ if (is_null($expiresIn)) {
1105
+ $this->expiresIn = null;
1106
+ $this->issuedAt = null;
1107
+ } else {
1108
+ $this->issuedAt = time();
1109
+ $this->expiresIn = (int)$expiresIn;
1110
+ }
1111
+ }
1112
+
1113
+ /**
1114
+ * Gets the time the current access token expires at.
1115
+ *
1116
+ * @return int
1117
+ */
1118
+ public function getExpiresAt()
1119
+ {
1120
+ if (!is_null($this->expiresAt)) {
1121
+ return $this->expiresAt;
1122
+ } elseif (!is_null($this->issuedAt) && !is_null($this->expiresIn)) {
1123
+ return $this->issuedAt + $this->expiresIn;
1124
+ }
1125
+
1126
+ return null;
1127
+ }
1128
+
1129
+ /**
1130
+ * Returns true if the acccess token has expired.
1131
+ *
1132
+ * @return bool
1133
+ */
1134
+ public function isExpired()
1135
+ {
1136
+ $expiration = $this->getExpiresAt();
1137
+ $now = time();
1138
+
1139
+ return !is_null($expiration) && $now >= $expiration;
1140
+ }
1141
+
1142
+ /**
1143
+ * Sets the time the current access token expires at.
1144
+ *
1145
+ * @param int $expiresAt
1146
+ */
1147
+ public function setExpiresAt($expiresAt)
1148
+ {
1149
+ $this->expiresAt = $expiresAt;
1150
+ }
1151
+
1152
+ /**
1153
+ * Gets the time the current access token was issued at.
1154
+ */
1155
+ public function getIssuedAt()
1156
+ {
1157
+ return $this->issuedAt;
1158
+ }
1159
+
1160
+ /**
1161
+ * Sets the time the current access token was issued at.
1162
+ *
1163
+ * @param int $issuedAt
1164
+ */
1165
+ public function setIssuedAt($issuedAt)
1166
+ {
1167
+ $this->issuedAt = $issuedAt;
1168
+ }
1169
+
1170
+ /**
1171
+ * Gets the current access token.
1172
+ */
1173
+ public function getAccessToken()
1174
+ {
1175
+ return $this->accessToken;
1176
+ }
1177
+
1178
+ /**
1179
+ * Sets the current access token.
1180
+ *
1181
+ * @param string $accessToken
1182
+ */
1183
+ public function setAccessToken($accessToken)
1184
+ {
1185
+ $this->accessToken = $accessToken;
1186
+ }
1187
+
1188
+ /**
1189
+ * Gets the current ID token.
1190
+ */
1191
+ public function getIdToken()
1192
+ {
1193
+ return $this->idToken;
1194
+ }
1195
+
1196
+ /**
1197
+ * Sets the current ID token.
1198
+ *
1199
+ * @param $idToken
1200
+ */
1201
+ public function setIdToken($idToken)
1202
+ {
1203
+ $this->idToken = $idToken;
1204
+ }
1205
+
1206
+ /**
1207
+ * Gets the refresh token associated with the current access token.
1208
+ */
1209
+ public function getRefreshToken()
1210
+ {
1211
+ return $this->refreshToken;
1212
+ }
1213
+
1214
+ /**
1215
+ * Sets the refresh token associated with the current access token.
1216
+ *
1217
+ * @param $refreshToken
1218
+ */
1219
+ public function setRefreshToken($refreshToken)
1220
+ {
1221
+ $this->refreshToken = $refreshToken;
1222
+ }
1223
+
1224
+ /**
1225
+ * Sets additional claims to be included in the JWT token
1226
+ *
1227
+ * @param array $additionalClaims
1228
+ */
1229
+ public function setAdditionalClaims(array $additionalClaims)
1230
+ {
1231
+ $this->additionalClaims = $additionalClaims;
1232
+ }
1233
+
1234
+ /**
1235
+ * Gets the additional claims to be included in the JWT token.
1236
+ *
1237
+ * @return array
1238
+ */
1239
+ public function getAdditionalClaims()
1240
+ {
1241
+ return $this->additionalClaims;
1242
+ }
1243
+
1244
+ /**
1245
+ * The expiration of the last received token.
1246
+ *
1247
+ * @return array
1248
+ */
1249
+ public function getLastReceivedToken()
1250
+ {
1251
+ if ($token = $this->getAccessToken()) {
1252
+ return [
1253
+ 'access_token' => $token,
1254
+ 'expires_at' => $this->getExpiresAt(),
1255
+ ];
1256
+ }
1257
+
1258
+ return null;
1259
+ }
1260
+
1261
+ /**
1262
+ * @todo handle uri as array
1263
+ *
1264
+ * @param string $uri
1265
+ *
1266
+ * @return null|UriInterface
1267
+ */
1268
+ private function coerceUri($uri)
1269
+ {
1270
+ if (is_null($uri)) {
1271
+ return;
1272
+ }
1273
+
1274
+ return Psr7\uri_for($uri);
1275
+ }
1276
+
1277
+ /**
1278
+ * @param string $idToken
1279
+ * @param string|array|null $publicKey
1280
+ * @param array $allowedAlgs
1281
+ *
1282
+ * @return object
1283
+ */
1284
+ private function jwtDecode($idToken, $publicKey, $allowedAlgs)
1285
+ {
1286
+ if (class_exists('Firebase\JWT\JWT')) {
1287
+ return \Firebase\JWT\JWT::decode($idToken, $publicKey, $allowedAlgs);
1288
+ }
1289
+
1290
+ return \JWT::decode($idToken, $publicKey, $allowedAlgs);
1291
+ }
1292
+
1293
+ private function jwtEncode($assertion, $signingKey, $signingAlgorithm)
1294
+ {
1295
+ if (class_exists('Firebase\JWT\JWT')) {
1296
+ return \Firebase\JWT\JWT::encode($assertion, $signingKey,
1297
+ $signingAlgorithm);
1298
+ }
1299
+
1300
+ return \JWT::encode($assertion, $signingKey, $signingAlgorithm);
1301
+ }
1302
+
1303
+ /**
1304
+ * Determines if the URI is absolute based on its scheme and host or path
1305
+ * (RFC 3986).
1306
+ *
1307
+ * @param string $uri
1308
+ *
1309
+ * @return bool
1310
+ */
1311
+ private function isAbsoluteUri($uri)
1312
+ {
1313
+ $uri = $this->coerceUri($uri);
1314
+
1315
+ return $uri->getScheme() && ($uri->getHost() || $uri->getPath());
1316
+ }
1317
+
1318
+ /**
1319
+ * @param array $params
1320
+ *
1321
+ * @return array
1322
+ */
1323
+ private function addClientCredentials(&$params)
1324
+ {
1325
+ $clientId = $this->getClientId();
1326
+ $clientSecret = $this->getClientSecret();
1327
+
1328
+ if ($clientId && $clientSecret) {
1329
+ $params['client_id'] = $clientId;
1330
+ $params['client_secret'] = $clientSecret;
1331
+ }
1332
+
1333
+ return $params;
1334
+ }
1335
+ }
vendor/google/auth/src/Subscriber/AuthTokenSubscriber.php ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Subscriber;
19
+
20
+ use Google\Auth\FetchAuthTokenInterface;
21
+ use GuzzleHttp\Event\BeforeEvent;
22
+ use GuzzleHttp\Event\RequestEvents;
23
+ use GuzzleHttp\Event\SubscriberInterface;
24
+
25
+ /**
26
+ * AuthTokenSubscriber is a Guzzle Subscriber that adds an Authorization header
27
+ * provided by an object implementing FetchAuthTokenInterface.
28
+ *
29
+ * The FetchAuthTokenInterface#fetchAuthToken is used to obtain a hash; one of
30
+ * the values value in that hash is added as the authorization header.
31
+ *
32
+ * Requests will be accessed with the authorization header:
33
+ *
34
+ * 'authorization' 'Bearer <value of auth_token>'
35
+ */
36
+ class AuthTokenSubscriber implements SubscriberInterface
37
+ {
38
+ /**
39
+ * @var callable
40
+ */
41
+ private $httpHandler;
42
+
43
+ /**
44
+ * @var FetchAuthTokenInterface
45
+ */
46
+ private $fetcher;
47
+
48
+ /**
49
+ * @var callable
50
+ */
51
+ private $tokenCallback;
52
+
53
+ /**
54
+ * Creates a new AuthTokenSubscriber.
55
+ *
56
+ * @param FetchAuthTokenInterface $fetcher is used to fetch the auth token
57
+ * @param callable $httpHandler (optional) http client to fetch the token.
58
+ * @param callable $tokenCallback (optional) function to be called when a new token is fetched.
59
+ */
60
+ public function __construct(
61
+ FetchAuthTokenInterface $fetcher,
62
+ callable $httpHandler = null,
63
+ callable $tokenCallback = null
64
+ ) {
65
+ $this->fetcher = $fetcher;
66
+ $this->httpHandler = $httpHandler;
67
+ $this->tokenCallback = $tokenCallback;
68
+ }
69
+
70
+ /**
71
+ * @return array
72
+ */
73
+ public function getEvents()
74
+ {
75
+ return ['before' => ['onBefore', RequestEvents::SIGN_REQUEST]];
76
+ }
77
+
78
+ /**
79
+ * Updates the request with an Authorization header when auth is 'fetched_auth_token'.
80
+ *
81
+ * use GuzzleHttp\Client;
82
+ * use Google\Auth\OAuth2;
83
+ * use Google\Auth\Subscriber\AuthTokenSubscriber;
84
+ *
85
+ * $config = [..<oauth config param>.];
86
+ * $oauth2 = new OAuth2($config)
87
+ * $subscriber = new AuthTokenSubscriber($oauth2);
88
+ *
89
+ * $client = new Client([
90
+ * 'base_url' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
91
+ * 'defaults' => ['auth' => 'google_auth']
92
+ * ]);
93
+ * $client->getEmitter()->attach($subscriber);
94
+ *
95
+ * $res = $client->get('myproject/taskqueues/myqueue');
96
+ *
97
+ * @param BeforeEvent $event
98
+ */
99
+ public function onBefore(BeforeEvent $event)
100
+ {
101
+ // Requests using "auth"="google_auth" will be authorized.
102
+ $request = $event->getRequest();
103
+ if ($request->getConfig()['auth'] != 'google_auth') {
104
+ return;
105
+ }
106
+
107
+ // Fetch the auth token.
108
+ $auth_tokens = $this->fetcher->fetchAuthToken($this->httpHandler);
109
+ if (array_key_exists('access_token', $auth_tokens)) {
110
+ $request->setHeader('authorization', 'Bearer ' . $auth_tokens['access_token']);
111
+
112
+ // notify the callback if applicable
113
+ if ($this->tokenCallback) {
114
+ call_user_func($this->tokenCallback, $this->fetcher->getCacheKey(), $auth_tokens['access_token']);
115
+ }
116
+ }
117
+ }
118
+ }
vendor/google/auth/src/Subscriber/ScopedAccessTokenSubscriber.php ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Subscriber;
19
+
20
+ use Google\Auth\CacheTrait;
21
+ use GuzzleHttp\Event\BeforeEvent;
22
+ use GuzzleHttp\Event\RequestEvents;
23
+ use GuzzleHttp\Event\SubscriberInterface;
24
+ use Psr\Cache\CacheItemPoolInterface;
25
+
26
+ /**
27
+ * ScopedAccessTokenSubscriber is a Guzzle Subscriber that adds an Authorization
28
+ * header provided by a closure.
29
+ *
30
+ * The closure returns an access token, taking the scope, either a single
31
+ * string or an array of strings, as its value. If provided, a cache will be
32
+ * used to preserve the access token for a given lifetime.
33
+ *
34
+ * Requests will be accessed with the authorization header:
35
+ *
36
+ * 'authorization' 'Bearer <access token obtained from the closure>'
37
+ */
38
+ class ScopedAccessTokenSubscriber implements SubscriberInterface
39
+ {
40
+ use CacheTrait;
41
+
42
+ const DEFAULT_CACHE_LIFETIME = 1500;
43
+
44
+ /**
45
+ * @var CacheItemPoolInterface
46
+ */
47
+ private $cache;
48
+
49
+ /**
50
+ * @var callable The access token generator function
51
+ */
52
+ private $tokenFunc;
53
+
54
+ /**
55
+ * @var array|string The scopes used to generate the token
56
+ */
57
+ private $scopes;
58
+
59
+ /**
60
+ * @var array
61
+ */
62
+ private $cacheConfig;
63
+
64
+ /**
65
+ * Creates a new ScopedAccessTokenSubscriber.
66
+ *
67
+ * @param callable $tokenFunc a token generator function
68
+ * @param array|string $scopes the token authentication scopes
69
+ * @param array $cacheConfig configuration for the cache when it's present
70
+ * @param CacheItemPoolInterface $cache an implementation of CacheItemPoolInterface
71
+ */
72
+ public function __construct(
73
+ callable $tokenFunc,
74
+ $scopes,
75
+ array $cacheConfig = null,
76
+ CacheItemPoolInterface $cache = null
77
+ ) {
78
+ $this->tokenFunc = $tokenFunc;
79
+ if (!(is_string($scopes) || is_array($scopes))) {
80
+ throw new \InvalidArgumentException(
81
+ 'wants scope should be string or array');
82
+ }
83
+ $this->scopes = $scopes;
84
+
85
+ if (!is_null($cache)) {
86
+ $this->cache = $cache;
87
+ $this->cacheConfig = array_merge([
88
+ 'lifetime' => self::DEFAULT_CACHE_LIFETIME,
89
+ 'prefix' => '',
90
+ ], $cacheConfig);
91
+ }
92
+ }
93
+
94
+ /**
95
+ * @return array
96
+ */
97
+ public function getEvents()
98
+ {
99
+ return ['before' => ['onBefore', RequestEvents::SIGN_REQUEST]];
100
+ }
101
+
102
+ /**
103
+ * Updates the request with an Authorization header when auth is 'scoped'.
104
+ *
105
+ * E.g this could be used to authenticate using the AppEngine
106
+ * AppIdentityService.
107
+ *
108
+ * use google\appengine\api\app_identity\AppIdentityService;
109
+ * use Google\Auth\Subscriber\ScopedAccessTokenSubscriber;
110
+ * use GuzzleHttp\Client;
111
+ *
112
+ * $scope = 'https://www.googleapis.com/auth/taskqueue'
113
+ * $subscriber = new ScopedAccessToken(
114
+ * 'AppIdentityService::getAccessToken',
115
+ * $scope,
116
+ * ['prefix' => 'Google\Auth\ScopedAccessToken::'],
117
+ * $cache = new Memcache()
118
+ * );
119
+ *
120
+ * $client = new Client([
121
+ * 'base_url' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
122
+ * 'defaults' => ['auth' => 'scoped']
123
+ * ]);
124
+ * $client->getEmitter()->attach($subscriber);
125
+ *
126
+ * $res = $client->get('myproject/taskqueues/myqueue');
127
+ *
128
+ * @param BeforeEvent $event
129
+ */
130
+ public function onBefore(BeforeEvent $event)
131
+ {
132
+ // Requests using "auth"="scoped" will be authorized.
133
+ $request = $event->getRequest();
134
+ if ($request->getConfig()['auth'] != 'scoped') {
135
+ return;
136
+ }
137
+ $auth_header = 'Bearer ' . $this->fetchToken();
138
+ $request->setHeader('authorization', $auth_header);
139
+ }
140
+
141
+ /**
142
+ * @return string
143
+ */
144
+ private function getCacheKey()
145
+ {
146
+ $key = null;
147
+
148
+ if (is_string($this->scopes)) {
149
+ $key .= $this->scopes;
150
+ } elseif (is_array($this->scopes)) {
151
+ $key .= implode(':', $this->scopes);
152
+ }
153
+
154
+ return $key;
155
+ }
156
+
157
+ /**
158
+ * Determine if token is available in the cache, if not call tokenFunc to
159
+ * fetch it.
160
+ *
161
+ * @return string
162
+ */
163
+ private function fetchToken()
164
+ {
165
+ $cacheKey = $this->getCacheKey();
166
+ $cached = $this->getCachedValue($cacheKey);
167
+
168
+ if (!empty($cached)) {
169
+ return $cached;
170
+ }
171
+
172
+ $token = call_user_func($this->tokenFunc, $this->scopes);
173
+ $this->setCachedValue($cacheKey, $token);
174
+
175
+ return $token;
176
+ }
177
+ }
vendor/google/auth/src/Subscriber/SimpleSubscriber.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Subscriber;
19
+
20
+ use GuzzleHttp\Event\BeforeEvent;
21
+ use GuzzleHttp\Event\RequestEvents;
22
+ use GuzzleHttp\Event\SubscriberInterface;
23
+
24
+ /**
25
+ * SimpleSubscriber is a Guzzle Subscriber that implements Google's Simple API
26
+ * access.
27
+ *
28
+ * Requests are accessed using the Simple API access developer key.
29
+ */
30
+ class SimpleSubscriber implements SubscriberInterface
31
+ {
32
+ /**
33
+ * @var array
34
+ */
35
+ private $config;
36
+
37
+ /**
38
+ * Create a new Simple plugin.
39
+ *
40
+ * The configuration array expects one option
41
+ * - key: required, otherwise InvalidArgumentException is thrown
42
+ *
43
+ * @param array $config Configuration array
44
+ */
45
+ public function __construct(array $config)
46
+ {
47
+ if (!isset($config['key'])) {
48
+ throw new \InvalidArgumentException('requires a key to have been set');
49
+ }
50
+
51
+ $this->config = array_merge([], $config);
52
+ }
53
+
54
+ /**
55
+ * @return array
56
+ */
57
+ public function getEvents()
58
+ {
59
+ return ['before' => ['onBefore', RequestEvents::SIGN_REQUEST]];
60
+ }
61
+
62
+ /**
63
+ * Updates the request query with the developer key if auth is set to simple.
64
+ *
65
+ * use Google\Auth\Subscriber\SimpleSubscriber;
66
+ * use GuzzleHttp\Client;
67
+ *
68
+ * $my_key = 'is not the same as yours';
69
+ * $subscriber = new SimpleSubscriber(['key' => $my_key]);
70
+ *
71
+ * $client = new Client([
72
+ * 'base_url' => 'https://www.googleapis.com/discovery/v1/',
73
+ * 'defaults' => ['auth' => 'simple']
74
+ * ]);
75
+ * $client->getEmitter()->attach($subscriber);
76
+ *
77
+ * $res = $client->get('drive/v2/rest');
78
+ *
79
+ * @param BeforeEvent $event
80
+ */
81
+ public function onBefore(BeforeEvent $event)
82
+ {
83
+ // Requests using "auth"="simple" with the developer key.
84
+ $request = $event->getRequest();
85
+ if ($request->getConfig()['auth'] != 'simple') {
86
+ return;
87
+ }
88
+ $request->getQuery()->overwriteWith($this->config);
89
+ }
90
+ }
vendor/guzzlehttp/guzzle/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2011-2016 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
vendor/guzzlehttp/guzzle/src/Client.php ADDED
@@ -0,0 +1,414 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Cookie\CookieJar;
5
+ use GuzzleHttp\Promise;
6
+ use GuzzleHttp\Psr7;
7
+ use Psr\Http\Message\UriInterface;
8
+ use Psr\Http\Message\RequestInterface;
9
+ use Psr\Http\Message\ResponseInterface;
10
+
11
+ /**
12
+ * @method ResponseInterface get(string|UriInterface $uri, array $options = [])
13
+ * @method ResponseInterface head(string|UriInterface $uri, array $options = [])
14
+ * @method ResponseInterface put(string|UriInterface $uri, array $options = [])
15
+ * @method ResponseInterface post(string|UriInterface $uri, array $options = [])
16
+ * @method ResponseInterface patch(string|UriInterface $uri, array $options = [])
17
+ * @method ResponseInterface delete(string|UriInterface $uri, array $options = [])
18
+ * @method Promise\PromiseInterface getAsync(string|UriInterface $uri, array $options = [])
19
+ * @method Promise\PromiseInterface headAsync(string|UriInterface $uri, array $options = [])
20
+ * @method Promise\PromiseInterface putAsync(string|UriInterface $uri, array $options = [])
21
+ * @method Promise\PromiseInterface postAsync(string|UriInterface $uri, array $options = [])
22
+ * @method Promise\PromiseInterface patchAsync(string|UriInterface $uri, array $options = [])
23
+ * @method Promise\PromiseInterface deleteAsync(string|UriInterface $uri, array $options = [])
24
+ */
25
+ class Client implements ClientInterface
26
+ {
27
+ /** @var array Default request options */
28
+ private $config;
29
+
30
+ /**
31
+ * Clients accept an array of constructor parameters.
32
+ *
33
+ * Here's an example of creating a client using a base_uri and an array of
34
+ * default request options to apply to each request:
35
+ *
36
+ * $client = new Client([
37
+ * 'base_uri' => 'http://www.foo.com/1.0/',
38
+ * 'timeout' => 0,
39
+ * 'allow_redirects' => false,
40
+ * 'proxy' => '192.168.16.1:10'
41
+ * ]);
42
+ *
43
+ * Client configuration settings include the following options:
44
+ *
45
+ * - handler: (callable) Function that transfers HTTP requests over the
46
+ * wire. The function is called with a Psr7\Http\Message\RequestInterface
47
+ * and array of transfer options, and must return a
48
+ * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
49
+ * Psr7\Http\Message\ResponseInterface on success. "handler" is a
50
+ * constructor only option that cannot be overridden in per/request
51
+ * options. If no handler is provided, a default handler will be created
52
+ * that enables all of the request options below by attaching all of the
53
+ * default middleware to the handler.
54
+ * - base_uri: (string|UriInterface) Base URI of the client that is merged
55
+ * into relative URIs. Can be a string or instance of UriInterface.
56
+ * - **: any request option
57
+ *
58
+ * @param array $config Client configuration settings.
59
+ *
60
+ * @see \GuzzleHttp\RequestOptions for a list of available request options.
61
+ */
62
+ public function __construct(array $config = [])
63
+ {
64
+ if (!isset($config['handler'])) {
65
+ $config['handler'] = HandlerStack::create();
66
+ } elseif (!is_callable($config['handler'])) {
67
+ throw new \InvalidArgumentException('handler must be a callable');
68
+ }
69
+
70
+ // Convert the base_uri to a UriInterface
71
+ if (isset($config['base_uri'])) {
72
+ $config['base_uri'] = Psr7\uri_for($config['base_uri']);
73
+ }
74
+
75
+ $this->configureDefaults($config);
76
+ }
77
+
78
+ public function __call($method, $args)
79
+ {
80
+ if (count($args) < 1) {
81
+ throw new \InvalidArgumentException('Magic request methods require a URI and optional options array');
82
+ }
83
+
84
+ $uri = $args[0];
85
+ $opts = isset($args[1]) ? $args[1] : [];
86
+
87
+ return substr($method, -5) === 'Async'
88
+ ? $this->requestAsync(substr($method, 0, -5), $uri, $opts)
89
+ : $this->request($method, $uri, $opts);
90
+ }
91
+
92
+ public function sendAsync(RequestInterface $request, array $options = [])
93
+ {
94
+ // Merge the base URI into the request URI if needed.
95
+ $options = $this->prepareDefaults($options);
96
+
97
+ return $this->transfer(
98
+ $request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')),
99
+ $options
100
+ );
101
+ }
102
+
103
+ public function send(RequestInterface $request, array $options = [])
104
+ {
105
+ $options[RequestOptions::SYNCHRONOUS] = true;
106
+ return $this->sendAsync($request, $options)->wait();
107
+ }
108
+
109
+ public function requestAsync($method, $uri = '', array $options = [])
110
+ {
111
+ $options = $this->prepareDefaults($options);
112
+ // Remove request modifying parameter because it can be done up-front.
113
+ $headers = isset($options['headers']) ? $options['headers'] : [];
114
+ $body = isset($options['body']) ? $options['body'] : null;
115
+ $version = isset($options['version']) ? $options['version'] : '1.1';
116
+ // Merge the URI into the base URI.
117
+ $uri = $this->buildUri($uri, $options);
118
+ if (is_array($body)) {
119
+ $this->invalidBody();
120
+ }
121
+ $request = new Psr7\Request($method, $uri, $headers, $body, $version);
122
+ // Remove the option so that they are not doubly-applied.
123
+ unset($options['headers'], $options['body'], $options['version']);
124
+
125
+ return $this->transfer($request, $options);
126
+ }
127
+
128
+ public function request($method, $uri = '', array $options = [])
129
+ {
130
+ $options[RequestOptions::SYNCHRONOUS] = true;
131
+ return $this->requestAsync($method, $uri, $options)->wait();
132
+ }
133
+
134
+ public function getConfig($option = null)
135
+ {
136
+ return $option === null
137
+ ? $this->config
138
+ : (isset($this->config[$option]) ? $this->config[$option] : null);
139
+ }
140
+
141
+ private function buildUri($uri, array $config)
142
+ {
143
+ // for BC we accept null which would otherwise fail in uri_for
144
+ $uri = Psr7\uri_for($uri === null ? '' : $uri);
145
+
146
+ if (isset($config['base_uri'])) {
147
+ $uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri);
148
+ }
149
+
150
+ return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
151
+ }
152
+
153
+ /**
154
+ * Configures the default options for a client.
155
+ *
156
+ * @param array $config
157
+ */
158
+ private function configureDefaults(array $config)
159
+ {
160
+ $defaults = [
161
+ 'allow_redirects' => RedirectMiddleware::$defaultSettings,
162
+ 'http_errors' => true,
163
+ 'decode_content' => true,
164
+ 'verify' => true,
165
+ 'cookies' => false
166
+ ];
167
+
168
+ // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
169
+
170
+ // We can only trust the HTTP_PROXY environment variable in a CLI
171
+ // process due to the fact that PHP has no reliable mechanism to
172
+ // get environment variables that start with "HTTP_".
173
+ if (php_sapi_name() == 'cli' && getenv('HTTP_PROXY')) {
174
+ $defaults['proxy']['http'] = getenv('HTTP_PROXY');
175
+ }
176
+
177
+ if ($proxy = getenv('HTTPS_PROXY')) {
178
+ $defaults['proxy']['https'] = $proxy;
179
+ }
180
+
181
+ if ($noProxy = getenv('NO_PROXY')) {
182
+ $cleanedNoProxy = str_replace(' ', '', $noProxy);
183
+ $defaults['proxy']['no'] = explode(',', $cleanedNoProxy);
184
+ }
185
+
186
+ $this->config = $config + $defaults;
187
+
188
+ if (!empty($config['cookies']) && $config['cookies'] === true) {
189
+ $this->config['cookies'] = new CookieJar();
190
+ }
191
+
192
+ // Add the default user-agent header.
193
+ if (!isset($this->config['headers'])) {
194
+ $this->config['headers'] = ['User-Agent' => default_user_agent()];
195
+ } else {
196
+ // Add the User-Agent header if one was not already set.
197
+ foreach (array_keys($this->config['headers']) as $name) {
198
+ if (strtolower($name) === 'user-agent') {
199
+ return;
200
+ }
201
+ }
202
+ $this->config['headers']['User-Agent'] = default_user_agent();
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Merges default options into the array.
208
+ *
209
+ * @param array $options Options to modify by reference
210
+ *
211
+ * @return array
212
+ */
213
+ private function prepareDefaults($options)
214
+ {
215
+ $defaults = $this->config;
216
+
217
+ if (!empty($defaults['headers'])) {
218
+ // Default headers are only added if they are not present.
219
+ $defaults['_conditional'] = $defaults['headers'];
220
+ unset($defaults['headers']);
221
+ }
222
+
223
+ // Special handling for headers is required as they are added as
224
+ // conditional headers and as headers passed to a request ctor.
225
+ if (array_key_exists('headers', $options)) {
226
+ // Allows default headers to be unset.
227
+ if ($options['headers'] === null) {
228
+ $defaults['_conditional'] = null;
229
+ unset($options['headers']);
230
+ } elseif (!is_array($options['headers'])) {
231
+ throw new \InvalidArgumentException('headers must be an array');
232
+ }
233
+ }
234
+
235
+ // Shallow merge defaults underneath options.
236
+ $result = $options + $defaults;
237
+
238
+ // Remove null values.
239
+ foreach ($result as $k => $v) {
240
+ if ($v === null) {
241
+ unset($result[$k]);
242
+ }
243
+ }
244
+
245
+ return $result;
246
+ }
247
+
248
+ /**
249
+ * Transfers the given request and applies request options.
250
+ *
251
+ * The URI of the request is not modified and the request options are used
252
+ * as-is without merging in default options.
253
+ *
254
+ * @param RequestInterface $request
255
+ * @param array $options
256
+ *
257
+ * @return Promise\PromiseInterface
258
+ */
259
+ private function transfer(RequestInterface $request, array $options)
260
+ {
261
+ // save_to -> sink
262
+ if (isset($options['save_to'])) {
263
+ $options['sink'] = $options['save_to'];
264
+ unset($options['save_to']);
265
+ }
266
+
267
+ // exceptions -> http_errors
268
+ if (isset($options['exceptions'])) {
269
+ $options['http_errors'] = $options['exceptions'];
270
+ unset($options['exceptions']);
271
+ }
272
+
273
+ $request = $this->applyOptions($request, $options);
274
+ $handler = $options['handler'];
275
+
276
+ try {
277
+ return Promise\promise_for($handler($request, $options));
278
+ } catch (\Exception $e) {
279
+ return Promise\rejection_for($e);
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Applies the array of request options to a request.
285
+ *
286
+ * @param RequestInterface $request
287
+ * @param array $options
288
+ *
289
+ * @return RequestInterface
290
+ */
291
+ private function applyOptions(RequestInterface $request, array &$options)
292
+ {
293
+ $modify = [];
294
+
295
+ if (isset($options['form_params'])) {
296
+ if (isset($options['multipart'])) {
297
+ throw new \InvalidArgumentException('You cannot use '
298
+ . 'form_params and multipart at the same time. Use the '
299
+ . 'form_params option if you want to send application/'
300
+ . 'x-www-form-urlencoded requests, and the multipart '
301
+ . 'option to send multipart/form-data requests.');
302
+ }
303
+ $options['body'] = http_build_query($options['form_params'], '', '&');
304
+ unset($options['form_params']);
305
+ $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
306
+ }
307
+
308
+ if (isset($options['multipart'])) {
309
+ $options['body'] = new Psr7\MultipartStream($options['multipart']);
310
+ unset($options['multipart']);
311
+ }
312
+
313
+ if (isset($options['json'])) {
314
+ $options['body'] = \GuzzleHttp\json_encode($options['json']);
315
+ unset($options['json']);
316
+ $options['_conditional']['Content-Type'] = 'application/json';
317
+ }
318
+
319
+ if (!empty($options['decode_content'])
320
+ && $options['decode_content'] !== true
321
+ ) {
322
+ $modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
323
+ }
324
+
325
+ if (isset($options['headers'])) {
326
+ if (isset($modify['set_headers'])) {
327
+ $modify['set_headers'] = $options['headers'] + $modify['set_headers'];
328
+ } else {
329
+ $modify['set_headers'] = $options['headers'];
330
+ }
331
+ unset($options['headers']);
332
+ }
333
+
334
+ if (isset($options['body'])) {
335
+ if (is_array($options['body'])) {
336
+ $this->invalidBody();
337
+ }
338
+ $modify['body'] = Psr7\stream_for($options['body']);
339
+ unset($options['body']);
340
+ }
341
+
342
+ if (!empty($options['auth']) && is_array($options['auth'])) {
343
+ $value = $options['auth'];
344
+ $type = isset($value[2]) ? strtolower($value[2]) : 'basic';
345
+ switch ($type) {
346
+ case 'basic':
347
+ $modify['set_headers']['Authorization'] = 'Basic '
348
+ . base64_encode("$value[0]:$value[1]");
349
+ break;
350
+ case 'digest':
351
+ // @todo: Do not rely on curl
352
+ $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST;
353
+ $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
354
+ break;
355
+ case 'ntlm':
356
+ $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_NTLM;
357
+ $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
358
+ break;
359
+ }
360
+ }
361
+
362
+ if (isset($options['query'])) {
363
+ $value = $options['query'];
364
+ if (is_array($value)) {
365
+ $value = http_build_query($value, null, '&', PHP_QUERY_RFC3986);
366
+ }
367
+ if (!is_string($value)) {
368
+ throw new \InvalidArgumentException('query must be a string or array');
369
+ }
370
+ $modify['query'] = $value;
371
+ unset($options['query']);
372
+ }
373
+
374
+ // Ensure that sink is not an invalid value.
375
+ if (isset($options['sink'])) {
376
+ // TODO: Add more sink validation?
377
+ if (is_bool($options['sink'])) {
378
+ throw new \InvalidArgumentException('sink must not be a boolean');
379
+ }
380
+ }
381
+
382
+ $request = Psr7\modify_request($request, $modify);
383
+ if ($request->getBody() instanceof Psr7\MultipartStream) {
384
+ // Use a multipart/form-data POST if a Content-Type is not set.
385
+ $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
386
+ . $request->getBody()->getBoundary();
387
+ }
388
+
389
+ // Merge in conditional headers if they are not present.
390
+ if (isset($options['_conditional'])) {
391
+ // Build up the changes so it's in a single clone of the message.
392
+ $modify = [];
393
+ foreach ($options['_conditional'] as $k => $v) {
394
+ if (!$request->hasHeader($k)) {
395
+ $modify['set_headers'][$k] = $v;
396
+ }
397
+ }
398
+ $request = Psr7\modify_request($request, $modify);
399
+ // Don't pass this internal value along to middleware/handlers.
400
+ unset($options['_conditional']);
401
+ }
402
+
403
+ return $request;
404
+ }
405
+
406
+ private function invalidBody()
407
+ {
408
+ throw new \InvalidArgumentException('Passing in the "body" request '
409
+ . 'option as an array to send a POST request has been deprecated. '
410
+ . 'Please use the "form_params" request option to send a '
411
+ . 'application/x-www-form-urlencoded request, or the "multipart" '
412
+ . 'request option to send a multipart/form-data request.');
413
+ }
414
+ }
vendor/guzzlehttp/guzzle/src/ClientInterface.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Promise\PromiseInterface;
5
+ use GuzzleHttp\Exception\GuzzleException;
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
+ const VERSION = '6.2.1';
16
+
17
+ /**
18
+ * Send an HTTP request.
19
+ *
20
+ * @param RequestInterface $request Request to send
21
+ * @param array $options Request options to apply to the given
22
+ * request and to the transfer.
23
+ *
24
+ * @return ResponseInterface
25
+ * @throws GuzzleException
26
+ */
27
+ public function send(RequestInterface $request, array $options = []);
28
+
29
+ /**
30
+ * Asynchronously send an HTTP request.
31
+ *
32
+ * @param RequestInterface $request Request to send
33
+ * @param array $options Request options to apply to the given
34
+ * request and to the transfer.
35
+ *
36
+ * @return PromiseInterface
37
+ */
38
+ public function sendAsync(RequestInterface $request, array $options = []);
39
+
40
+ /**
41
+ * Create and send an HTTP request.
42
+ *
43
+ * Use an absolute path to override the base path of the client, or a
44
+ * relative path to append to the base path of the client. The URL can
45
+ * contain the query string as well.
46
+ *
47
+ * @param string $method HTTP method.
48
+ * @param string|UriInterface $uri URI object or string.
49
+ * @param array $options Request options to apply.
50
+ *
51
+ * @return ResponseInterface
52
+ * @throws GuzzleException
53
+ */
54
+ public function request($method, $uri, array $options = []);
55
+
56
+ /**
57
+ * Create and send an asynchronous HTTP request.
58
+ *
59
+ * Use an absolute path to override the base path of the client, or a
60
+ * relative path to append to the base path of the client. The URL can
61
+ * contain the query string as well. Use an array to provide a URL
62
+ * template and additional variables to use in the URL template expansion.
63
+ *
64
+ * @param string $method HTTP method
65
+ * @param string|UriInterface $uri URI object or string.
66
+ * @param array $options Request options to apply.
67
+ *
68
+ * @return PromiseInterface
69
+ */
70
+ public function requestAsync($method, $uri, array $options = []);
71
+
72
+ /**
73
+ * Get a client configuration option.
74
+ *
75
+ * These options include default request options of the client, a "handler"
76
+ * (if utilized by the concrete client), and a "base_uri" if utilized by
77
+ * the concrete client.
78
+ *
79
+ * @param string|null $option The config option to retrieve.
80
+ *
81
+ * @return mixed
82
+ */
83
+ public function getConfig($option = null);
84
+ }
vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php ADDED
@@ -0,0 +1,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 null name
98
+ if($name === null) {
99
+ return null;
100
+ }
101
+ foreach($this->cookies as $cookie) {
102
+ if($cookie->getName() !== null && strcasecmp($cookie->getName(), $name) === 0) {
103
+ return $cookie;
104
+ }
105
+ }
106
+ }
107
+
108
+ public function toArray()
109
+ {
110
+ return array_map(function (SetCookie $cookie) {
111
+ return $cookie->toArray();
112
+ }, $this->getIterator()->getArrayCopy());
113
+ }
114
+
115
+ public function clear($domain = null, $path = null, $name = null)
116
+ {
117
+ if (!$domain) {
118
+ $this->cookies = [];
119
+ return;
120
+ } elseif (!$path) {
121
+ $this->cookies = array_filter(
122
+ $this->cookies,
123
+ function (SetCookie $cookie) use ($path, $domain) {
124
+ return !$cookie->matchesDomain($domain);
125
+ }
126
+ );
127
+ } elseif (!$name) {
128
+ $this->cookies = array_filter(
129
+ $this->cookies,
130
+ function (SetCookie $cookie) use ($path, $domain) {
131
+ return !($cookie->matchesPath($path) &&
132
+ $cookie->matchesDomain($domain));
133
+ }
134
+ );
135
+ } else {
136
+ $this->cookies = array_filter(
137
+ $this->cookies,
138
+ function (SetCookie $cookie) use ($path, $domain, $name) {
139
+ return !($cookie->getName() == $name &&
140
+ $cookie->matchesPath($path) &&
141
+ $cookie->matchesDomain($domain));
142
+ }
143
+ );
144
+ }
145
+ }
146
+
147
+ public function clearSessionCookies()
148
+ {
149
+ $this->cookies = array_filter(
150
+ $this->cookies,
151
+ function (SetCookie $cookie) {
152
+ return !$cookie->getDiscard() && $cookie->getExpires();
153
+ }
154
+ );
155
+ }
156
+
157
+ public function setCookie(SetCookie $cookie)
158
+ {
159
+ // If the name string is empty (but not 0), ignore the set-cookie
160
+ // string entirely.
161
+ $name = $cookie->getName();
162
+ if (!$name && $name !== '0') {
163
+ return false;
164
+ }
165
+
166
+ // Only allow cookies with set and valid domain, name, value
167
+ $result = $cookie->validate();
168
+ if ($result !== true) {
169
+ if ($this->strictMode) {
170
+ throw new \RuntimeException('Invalid cookie: ' . $result);
171
+ } else {
172
+ $this->removeCookieIfEmpty($cookie);
173
+ return false;
174
+ }
175
+ }
176
+
177
+ // Resolve conflicts with previously set cookies
178
+ foreach ($this->cookies as $i => $c) {
179
+
180
+ // Two cookies are identical, when their path, and domain are
181
+ // identical.
182
+ if ($c->getPath() != $cookie->getPath() ||
183
+ $c->getDomain() != $cookie->getDomain() ||
184
+ $c->getName() != $cookie->getName()
185
+ ) {
186
+ continue;
187
+ }
188
+
189
+ // The previously set cookie is a discard cookie and this one is
190
+ // not so allow the new cookie to be set
191
+ if (!$cookie->getDiscard() && $c->getDiscard()) {
192
+ unset($this->cookies[$i]);
193
+ continue;
194
+ }
195
+
196
+ // If the new cookie's expiration is further into the future, then
197
+ // replace the old cookie
198
+ if ($cookie->getExpires() > $c->getExpires()) {
199
+ unset($this->cookies[$i]);
200
+ continue;
201
+ }
202
+
203
+ // If the value has changed, we better change it
204
+ if ($cookie->getValue() !== $c->getValue()) {
205
+ unset($this->cookies[$i]);
206
+ continue;
207
+ }
208
+
209
+ // The cookie exists, so no need to continue
210
+ return false;
211
+ }
212
+
213
+ $this->cookies[] = $cookie;
214
+
215
+ return true;
216
+ }
217
+
218
+ public function count()
219
+ {
220
+ return count($this->cookies);
221
+ }
222
+
223
+ public function getIterator()
224
+ {
225
+ return new \ArrayIterator(array_values($this->cookies));
226
+ }
227
+
228
+ public function extractCookies(
229
+ RequestInterface $request,
230
+ ResponseInterface $response
231
+ ) {
232
+ if ($cookieHeader = $response->getHeader('Set-Cookie')) {
233
+ foreach ($cookieHeader as $cookie) {
234
+ $sc = SetCookie::fromString($cookie);
235
+ if (!$sc->getDomain()) {
236
+ $sc->setDomain($request->getUri()->getHost());
237
+ }
238
+ if (0 !== strpos($sc->getPath(), '/')) {
239
+ $sc->setPath($this->getCookiePathFromRequest($request));
240
+ }
241
+ $this->setCookie($sc);
242
+ }
243
+ }
244
+ }
245
+
246
+ /**
247
+ * Computes cookie path following RFC 6265 section 5.1.4
248
+ *
249
+ * @link https://tools.ietf.org/html/rfc6265#section-5.1.4
250
+ *
251
+ * @param RequestInterface $request
252
+ * @return string
253
+ */
254
+ private function getCookiePathFromRequest(RequestInterface $request)
255
+ {
256
+ $uriPath = $request->getUri()->getPath();
257
+ if ('' === $uriPath) {
258
+ return '/';
259
+ }
260
+ if (0 !== strpos($uriPath, '/')) {
261
+ return '/';
262
+ }
263
+ if ('/' === $uriPath) {
264
+ return '/';
265
+ }
266
+ if (0 === $lastSlashPos = strrpos($uriPath, '/')) {
267
+ return '/';
268
+ }
269
+
270
+ return substr($uriPath, 0, $lastSlashPos);
271
+ }
272
+
273
+ public function withCookieHeader(RequestInterface $request)
274
+ {
275
+ $values = [];
276
+ $uri = $request->getUri();
277
+ $scheme = $uri->getScheme();
278
+ $host = $uri->getHost();
279
+ $path = $uri->getPath() ?: '/';
280
+
281
+ foreach ($this->cookies as $cookie) {
282
+ if ($cookie->matchesPath($path) &&
283
+ $cookie->matchesDomain($host) &&
284
+ !$cookie->isExpired() &&
285
+ (!$cookie->getSecure() || $scheme === 'https')
286
+ ) {
287
+ $values[] = $cookie->getName() . '='
288
+ . $cookie->getValue();
289
+ }
290
+ }
291
+
292
+ return $values
293
+ ? $request->withHeader('Cookie', implode('; ', $values))
294
+ : $request;
295
+ }
296
+
297
+ /**
298
+ * If a cookie already exists and the server asks to set it again with a
299
+ * null value, the cookie must be deleted.
300
+ *
301
+ * @param SetCookie $cookie
302
+ */
303
+ private function removeCookieIfEmpty(SetCookie $cookie)
304
+ {
305
+ $cookieValue = $cookie->getValue();
306
+ if ($cookieValue === null || $cookieValue === '') {
307
+ $this->clear(
308
+ $cookie->getDomain(),
309
+ $cookie->getPath(),
310
+ $cookie->getName()
311
+ );
312
+ }
313
+ }
314
+ }
vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php ADDED
@@ -0,0 +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
+ }
vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ /**
5
+ * Persists non-session cookies using a JSON formatted file
6
+ */
7
+ class FileCookieJar extends CookieJar
8
+ {
9
+ /** @var string filename */
10
+ private $filename;
11
+
12
+ /** @var bool Control whether to persist session cookies or not. */
13
+ private $storeSessionCookies;
14
+
15
+ /**
16
+ * Create a new FileCookieJar object
17
+ *
18
+ * @param string $cookieFile File to store the cookie data
19
+ * @param bool $storeSessionCookies Set to true to store session cookies
20
+ * in the cookie jar.
21
+ *
22
+ * @throws \RuntimeException if the file cannot be found or created
23
+ */
24
+ public function __construct($cookieFile, $storeSessionCookies = false)
25
+ {
26
+ $this->filename = $cookieFile;
27
+ $this->storeSessionCookies = $storeSessionCookies;
28
+
29
+ if (file_exists($cookieFile)) {
30
+ $this->load($cookieFile);
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Saves the file when shutting down
36
+ */
37
+ public function __destruct()
38
+ {
39
+ $this->save($this->filename);
40
+ }
41
+
42
+ /**
43
+ * Saves the cookies to a file.
44
+ *
45
+ * @param string $filename File to save
46
+ * @throws \RuntimeException if the file cannot be found or created
47
+ */
48
+ public function save($filename)
49
+ {
50
+ $json = [];
51
+ foreach ($this as $cookie) {
52
+ /** @var SetCookie $cookie */
53
+ if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
54
+ $json[] = $cookie->toArray();
55
+ }
56
+ }
57
+
58
+ $jsonStr = \GuzzleHttp\json_encode($json);
59
+ if (false === file_put_contents($filename, $jsonStr)) {
60
+ throw new \RuntimeException("Unable to save file {$filename}");
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Load cookies from a JSON formatted file.
66
+ *
67
+ * Old cookies are kept unless overwritten by newly loaded ones.
68
+ *
69
+ * @param string $filename Cookie file to load.
70
+ * @throws \RuntimeException if the file cannot be loaded.
71
+ */
72
+ public function load($filename)
73
+ {
74
+ $json = file_get_contents($filename);
75
+ if (false === $json) {
76
+ throw new \RuntimeException("Unable to load file {$filename}");
77
+ } elseif ($json === '') {
78
+ return;
79
+ }
80
+
81
+ $data = \GuzzleHttp\json_decode($json, true);
82
+ if (is_array($data)) {
83
+ foreach (json_decode($json, true) as $cookie) {
84
+ $this->setCookie(new SetCookie($cookie));
85
+ }
86
+ } elseif (strlen($data)) {
87
+ throw new \RuntimeException("Invalid cookie file: {$filename}");
88
+ }
89
+ }
90
+ }
vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ /**
5
+ * Persists cookies in the client session
6
+ */
7
+ class SessionCookieJar extends CookieJar
8
+ {
9
+ /** @var string session key */
10
+ private $sessionKey;
11
+
12
+ /** @var bool Control whether to persist session cookies or not. */
13
+ private $storeSessionCookies;
14
+
15
+ /**
16
+ * Create a new SessionCookieJar object
17
+ *
18
+ * @param string $sessionKey Session key name to store the cookie
19
+ * data in session
20
+ * @param bool $storeSessionCookies Set to true to store session cookies
21
+ * in the cookie jar.
22
+ */
23
+ public function __construct($sessionKey, $storeSessionCookies = false)
24
+ {
25
+ $this->sessionKey = $sessionKey;
26
+ $this->storeSessionCookies = $storeSessionCookies;
27
+ $this->load();
28
+ }
29
+
30
+ /**
31
+ * Saves cookies to session when shutting down
32
+ */
33
+ public function __destruct()
34
+ {
35
+ $this->save();
36
+ }
37
+
38
+ /**
39
+ * Save cookies to the client session
40
+ */
41
+ public function save()
42
+ {
43
+ $json = [];
44
+ foreach ($this as $cookie) {
45
+ /** @var SetCookie $cookie */
46
+ if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
47
+ $json[] = $cookie->toArray();
48
+ }
49
+ }
50
+
51
+ $_SESSION[$this->sessionKey] = json_encode($json);
52
+ }
53
+
54
+ /**
55
+ * Load the contents of the client session into the data array
56
+ */
57
+ protected function load()
58
+ {
59
+ if (!isset($_SESSION[$this->sessionKey])) {
60
+ return;
61
+ }
62
+ $data = json_decode($_SESSION[$this->sessionKey], true);
63
+ if (is_array($data)) {
64
+ foreach ($data as $cookie) {
65
+ $this->setCookie(new SetCookie($cookie));
66
+ }
67
+ } elseif (strlen($data)) {
68
+ throw new \RuntimeException("Invalid cookie data");
69
+ }
70
+ }
71
+ }
vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php ADDED
@@ -0,0 +1,404 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ /**
5
+ * Set-Cookie object
6
+ */
7
+ class SetCookie
8
+ {
9
+ /** @var array */
10
+ private static $defaults = [
11
+ 'Name' => null,
12
+ 'Value' => null,
13
+ 'Domain' => null,
14
+ 'Path' => '/',
15
+ 'Max-Age' => null,
16
+ 'Expires' => null,
17
+ 'Secure' => false,
18
+ 'Discard' => false,
19
+ 'HttpOnly' => false
20
+ ];
21
+
22
+ /** @var array Cookie data */
23
+ private $data;
24
+
25
+ /**
26
+ * Create a new SetCookie object from a string
27
+ *
28
+ * @param string $cookie Set-Cookie header string
29
+ *
30
+ * @return self
31
+ */
32
+ public static function fromString($cookie)
33
+ {
34
+ // Create the default return array
35
+ $data = self::$defaults;
36
+ // Explode the cookie string using a series of semicolons
37
+ $pieces = array_filter(array_map('trim', explode(';', $cookie)));
38
+ // The name of the cookie (first kvp) must include an equal sign.
39
+ if (empty($pieces) || !strpos($pieces[0], '=')) {
40
+ return new self($data);
41
+ }
42
+
43
+ // Add the cookie pieces into the parsed data array
44
+ foreach ($pieces as $part) {
45
+
46
+ $cookieParts = explode('=', $part, 2);
47
+ $key = trim($cookieParts[0]);
48
+ $value = isset($cookieParts[1])
49
+ ? trim($cookieParts[1], " \n\r\t\0\x0B")
50
+ : true;
51
+
52
+ // Only check for non-cookies when cookies have been found
53
+ if (empty($data['Name'])) {
54
+ $data['Name'] = $key;
55
+ $data['Value'] = $value;
56
+ } else {
57
+ foreach (array_keys(self::$defaults) as $search) {
58
+ if (!strcasecmp($search, $key)) {
59
+ $data[$search] = $value;
60
+ continue 2;
61
+ }
62
+ }
63
+ $data[$key] = $value;
64
+ }
65
+ }
66
+
67
+ return new self($data);
68
+ }
69
+
70
+ /**
71
+ * @param array $data Array of cookie data provided by a Cookie parser
72
+ */
73
+ public function __construct(array $data = [])
74
+ {
75
+ $this->data = array_replace(self::$defaults, $data);
76
+ // Extract the Expires value and turn it into a UNIX timestamp if needed
77
+ if (!$this->getExpires() && $this->getMaxAge()) {
78
+ // Calculate the Expires date
79
+ $this->setExpires(time() + $this->getMaxAge());
80
+ } elseif ($this->getExpires() && !is_numeric($this->getExpires())) {
81
+ $this->setExpires($this->getExpires());
82
+ }
83
+ }
84
+
85
+ public function __toString()
86
+ {
87
+ $str = $this->data['Name'] . '=' . $this->data['Value'] . '; ';
88
+ foreach ($this->data as $k => $v) {
89
+ if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) {
90
+ if ($k === 'Expires') {
91
+ $str .= 'Expires=' . gmdate('D, d M Y H:i:s \G\M\T', $v) . '; ';
92
+ } else {
93
+ $str .= ($v === true ? $k : "{$k}={$v}") . '; ';
94
+ }
95
+ }
96
+ }
97
+
98
+ return rtrim($str, '; ');
99
+ }
100
+
101
+ public function toArray()
102
+ {
103
+ return $this->data;
104
+ }
105
+
106
+ /**
107
+ * Get the cookie name
108
+ *
109
+ * @return string
110
+ */
111
+ public function getName()
112
+ {
113
+ return $this->data['Name'];
114
+ }
115
+
116
+ /**
117
+ * Set the cookie name
118
+ *
119
+ * @param string $name Cookie name
120
+ */
121
+ public function setName($name)
122
+ {
123
+ $this->data['Name'] = $name;
124
+ }
125
+
126
+ /**
127
+ * Get the cookie value
128
+ *
129
+ * @return string
130
+ */
131
+ public function getValue()
132
+ {
133
+ return $this->data['Value'];
134
+ }
135
+
136
+ /**
137
+ * Set the cookie value
138
+ *
139
+ * @param string $value Cookie value
140
+ */
141
+ public function setValue($value)
142
+ {
143
+ $this->data['Value'] = $value;
144
+ }
145
+
146
+ /**
147
+ * Get the domain
148
+ *
149
+ * @return string|null
150
+ */
151
+ public function getDomain()
152
+ {
153
+ return $this->data['Domain'];
154
+ }
155
+
156
+ /**
157
+ * Set the domain of the cookie
158
+ *
159
+ * @param string $domain
160
+ */
161
+ public function setDomain($domain)
162
+ {
163
+ $this->data['Domain'] = $domain;
164
+ }
165
+
166
+ /**
167
+ * Get the path
168
+ *
169
+ * @return string
170
+ */
171
+ public function getPath()
172
+ {
173
+ return $this->data['Path'];
174
+ }
175
+
176
+ /**
177
+ * Set the path of the cookie
178
+ *
179
+ * @param string $path Path of the cookie
180
+ */
181
+ public function setPath($path)
182
+ {
183
+ $this->data['Path'] = $path;
184
+ }
185
+
186
+ /**
187
+ * Maximum lifetime of the cookie in seconds
188
+ *
189
+ * @return int|null
190
+ */
191
+ public function getMaxAge()
192
+ {
193
+ return $this->data['Max-Age'];
194
+ }
195
+
196
+ /**
197
+ * Set the max-age of the cookie
198
+ *
199
+ * @param int $maxAge Max age of the cookie in seconds
200
+ */
201
+ public function setMaxAge($maxAge)
202
+ {
203
+ $this->data['Max-Age'] = $maxAge;
204
+ }
205
+
206
+ /**
207
+ * The UNIX timestamp when the cookie Expires
208
+ *
209
+ * @return mixed
210
+ */
211
+ public function getExpires()
212
+ {
213
+ return $this->data['Expires'];
214
+ }
215
+
216
+ /**
217
+ * Set the unix timestamp for which the cookie will expire
218
+ *
219
+ * @param int $timestamp Unix timestamp
220
+ */
221
+ public function setExpires($timestamp)
222
+ {
223
+ $this->data['Expires'] = is_numeric($timestamp)
224
+ ? (int) $timestamp
225
+ : strtotime($timestamp);
226
+ }
227
+
228
+ /**
229
+ * Get whether or not this is a secure cookie
230
+ *
231
+ * @return null|bool
232
+ */
233
+ public function getSecure()
234
+ {
235
+ return $this->data['Secure'];
236
+ }
237
+
238
+ /**
239
+ * Set whether or not the cookie is secure
240
+ *
241
+ * @param bool $secure Set to true or false if secure
242
+ */
243
+ public function setSecure($secure)
244
+ {
245
+ $this->data['Secure'] = $secure;
246
+ }
247
+
248
+ /**
249
+ * Get whether or not this is a session cookie
250
+ *
251
+ * @return null|bool
252
+ */
253
+ public function getDiscard()
254
+ {
255
+ return $this->data['Discard'];
256
+ }
257
+
258
+ /**
259
+ * Set whether or not this is a session cookie
260
+ *
261
+ * @param bool $discard Set to true or false if this is a session cookie
262
+ */
263
+ public function setDiscard($discard)
264
+ {
265
+ $this->data['Discard'] = $discard;
266
+ }
267
+
268
+ /**
269
+ * Get whether or not this is an HTTP only cookie
270
+ *
271
+ * @return bool
272
+ */
273
+ public function getHttpOnly()
274
+ {
275
+ return $this->data['HttpOnly'];
276
+ }
277
+
278
+ /**
279
+ * Set whether or not this is an HTTP only cookie
280
+ *
281
+ * @param bool $httpOnly Set to true or false if this is HTTP only
282
+ */
283
+ public function setHttpOnly($httpOnly)
284
+ {
285
+ $this->data['HttpOnly'] = $httpOnly;
286
+ }
287
+
288
+ /**
289
+ * Check if the cookie matches a path value.
290
+ *
291
+ * A request-path path-matches a given cookie-path if at least one of
292
+ * the following conditions holds:
293
+ *
294
+ * - The cookie-path and the request-path are identical.
295
+ * - The cookie-path is a prefix of the request-path, and the last
296
+ * character of the cookie-path is %x2F ("/").
297
+ * - The cookie-path is a prefix of the request-path, and the first
298
+ * character of the request-path that is not included in the cookie-
299
+ * path is a %x2F ("/") character.
300
+ *
301
+ * @param string $requestPath Path to check against
302
+ *
303
+ * @return bool
304
+ */
305
+ public function matchesPath($requestPath)
306
+ {
307
+ $cookiePath = $this->getPath();
308
+
309
+ // Match on exact matches or when path is the default empty "/"
310
+ if ($cookiePath === '/' || $cookiePath == $requestPath) {
311
+ return true;
312
+ }
313
+
314
+ // Ensure that the cookie-path is a prefix of the request path.
315
+ if (0 !== strpos($requestPath, $cookiePath)) {
316
+ return false;
317
+ }
318
+
319
+ // Match if the last character of the cookie-path is "/"
320
+ if (substr($cookiePath, -1, 1) === '/') {
321
+ return true;
322
+ }
323
+
324
+ // Match if the first character not included in cookie path is "/"
325
+ return substr($requestPath, strlen($cookiePath), 1) === '/';
326
+ }
327
+
328
+ /**
329
+ * Check if the cookie matches a domain value
330
+ *
331
+ * @param string $domain Domain to check against
332
+ *
333
+ * @return bool
334
+ */
335
+ public function matchesDomain($domain)
336
+ {
337
+ // Remove the leading '.' as per spec in RFC 6265.
338
+ // http://tools.ietf.org/html/rfc6265#section-5.2.3
339
+ $cookieDomain = ltrim($this->getDomain(), '.');
340
+
341
+ // Domain not set or exact match.
342
+ if (!$cookieDomain || !strcasecmp($domain, $cookieDomain)) {
343
+ return true;
344
+ }
345
+
346
+ // Matching the subdomain according to RFC 6265.
347
+ // http://tools.ietf.org/html/rfc6265#section-5.1.3
348
+ if (filter_var($domain, FILTER_VALIDATE_IP)) {
349
+ return false;
350
+ }
351
+
352
+ return (bool) preg_match('/\.' . preg_quote($cookieDomain) . '$/', $domain);
353
+ }
354
+
355
+ /**
356
+ * Check if the cookie is expired
357
+ *
358
+ * @return bool
359
+ */
360
+ public function isExpired()
361
+ {
362
+ return $this->getExpires() && time() > $this->getExpires();
363
+ }
364
+
365
+ /**
366
+ * Check if the cookie is valid according to RFC 6265
367
+ *
368
+ * @return bool|string Returns true if valid or an error message if invalid
369
+ */
370
+ public function validate()
371
+ {
372
+ // Names must not be empty, but can be 0
373
+ $name = $this->getName();
374
+ if (empty($name) && !is_numeric($name)) {
375
+ return 'The cookie name must not be empty';
376
+ }
377
+
378
+ // Check if any of the invalid characters are present in the cookie name
379
+ if (preg_match(
380
+ '/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/',
381
+ $name)
382
+ ) {
383
+ return 'Cookie name must not contain invalid characters: ASCII '
384
+ . 'Control characters (0-31;127), space, tab and the '
385
+ . 'following characters: ()<>@,;:\"/?={}';
386
+ }
387
+
388
+ // Value must not be empty, but can be 0
389
+ $value = $this->getValue();
390
+ if (empty($value) && !is_numeric($value)) {
391
+ return 'The cookie value must not be empty';
392
+ }
393
+
394
+ // Domains must not be empty, but can be 0
395
+ // A "0" is not a valid internet domain, but may be used as server name
396
+ // in a private network.
397
+ $domain = $this->getDomain();
398
+ if (empty($domain) && !is_numeric($domain)) {
399
+ return 'The cookie domain must not be empty';
400
+ }
401
+
402
+ return true;
403
+ }
404
+ }
vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+ use Psr\Http\Message\ResponseInterface;
6
+
7
+ /**
8
+ * Exception when an HTTP error occurs (4xx or 5xx error)
9
+ */
10
+ class BadResponseException extends RequestException
11
+ {
12
+ public function __construct(
13
+ $message,
14
+ RequestInterface $request,
15
+ ResponseInterface $response = null,
16
+ \Exception $previous = null,
17
+ array $handlerContext = []
18
+ ) {
19
+ if (null === $response) {
20
+ @trigger_error(
21
+ 'Instantiating the ' . __CLASS__ . ' class without a Response is deprecated since version 6.3 and will be removed in 7.0.',
22
+ E_USER_DEPRECATED
23
+ );
24
+ }
25
+ parent::__construct($message, $request, $response, $previous, $handlerContext);
26
+ }
27
+ }
vendor/guzzlehttp/guzzle/src/Exception/ClientException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ /**
5
+ * Exception when a client error is encountered (4xx codes)
6
+ */
7
+ class ClientException extends BadResponseException {}
vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+
6
+ /**
7
+ * Exception thrown when a connection cannot be established.
8
+ *
9
+ * Note that no response is present for a ConnectException
10
+ */
11
+ class ConnectException extends RequestException
12
+ {
13
+ public function __construct(
14
+ $message,
15
+ RequestInterface $request,
16
+ \Exception $previous = null,
17
+ array $handlerContext = []
18
+ ) {
19
+ parent::__construct($message, $request, null, $previous, $handlerContext);
20
+ }
21
+
22
+ /**
23
+ * @return null
24
+ */
25
+ public function getResponse()
26
+ {
27
+ return null;
28
+ }
29
+
30
+ /**
31
+ * @return bool
32
+ */
33
+ public function hasResponse()
34
+ {
35
+ return false;
36
+ }
37
+ }
vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ interface GuzzleException {}
vendor/guzzlehttp/guzzle/src/Exception/RequestException.php ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+ use Psr\Http\Message\ResponseInterface;
6
+ use GuzzleHttp\Promise\PromiseInterface;
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
+ $body = $response->getBody();
128
+
129
+ if (!$body->isSeekable()) {
130
+ return null;
131
+ }
132
+
133
+ $size = $body->getSize();
134
+
135
+ if ($size === 0) {
136
+ return null;
137
+ }
138
+
139
+ $summary = $body->read(120);
140
+ $body->rewind();
141
+
142
+ if ($size > 120) {
143
+ $summary .= ' (truncated...)';
144
+ }
145
+
146
+ // Matches any printable character, including unicode characters:
147
+ // letters, marks, numbers, punctuation, spacing, and separators.
148
+ if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) {
149
+ return null;
150
+ }
151
+
152
+ return $summary;
153
+ }
154
+
155
+ /**
156
+ * Obfuscates URI if there is an username and a password present
157
+ *
158
+ * @param UriInterface $uri
159
+ *
160
+ * @return UriInterface
161
+ */
162
+ private static function obfuscateUri($uri)
163
+ {
164
+ $userInfo = $uri->getUserInfo();
165
+
166
+ if (false !== ($pos = strpos($userInfo, ':'))) {
167
+ return $uri->withUserInfo(substr($userInfo, 0, $pos), '***');
168
+ }
169
+
170
+ return $uri;
171
+ }
172
+
173
+ /**
174
+ * Get the request that caused the exception
175
+ *
176
+ * @return RequestInterface
177
+ */
178
+ public function getRequest()
179
+ {
180
+ return $this->request;
181
+ }
182
+
183
+ /**
184
+ * Get the associated response
185
+ *
186
+ * @return ResponseInterface|null
187
+ */
188
+ public function getResponse()
189
+ {
190
+ return $this->response;
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
+ }
vendor/guzzlehttp/guzzle/src/Exception/SeekException.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Exception thrown when a seek fails on a stream.
8
+ */
9
+ class SeekException extends \RuntimeException implements GuzzleException
10
+ {
11
+ private $stream;
12
+
13
+ public function __construct(StreamInterface $stream, $pos = 0, $msg = '')
14
+ {
15
+ $this->stream = $stream;
16
+ $msg = $msg ?: 'Could not seek the stream to position ' . $pos;
17
+ parent::__construct($msg);
18
+ }
19
+
20
+ /**
21
+ * @return StreamInterface
22
+ */
23
+ public function getStream()
24
+ {
25
+ return $this->stream;
26
+ }
27
+ }
vendor/guzzlehttp/guzzle/src/Exception/ServerException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ /**
5
+ * Exception when a server error is encountered (5xx codes)
6
+ */
7
+ class ServerException extends BadResponseException {}
vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class TooManyRedirectsException extends RequestException {}
vendor/guzzlehttp/guzzle/src/Exception/TransferException.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class TransferException extends \RuntimeException implements GuzzleException {}
vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php ADDED
@@ -0,0 +1,559 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Exception\RequestException;
5
+ use GuzzleHttp\Exception\ConnectException;
6
+ use GuzzleHttp\Promise\FulfilledPromise;
7
+ use GuzzleHttp\Promise\RejectedPromise;
8
+ use GuzzleHttp\Psr7;
9
+ use GuzzleHttp\Psr7\LazyOpenStream;
10
+ use GuzzleHttp\TransferStats;
11
+ use Psr\Http\Message\RequestInterface;
12
+
13
+ /**
14
+ * Creates curl resources from a request
15
+ */
16
+ class CurlFactory implements CurlFactoryInterface
17
+ {
18
+ /** @var array */
19
+ private $handles = [];
20
+
21
+ /** @var int Total number of idle handles to keep in cache */
22
+ private $maxHandles;
23
+
24
+ /**
25
+ * @param int $maxHandles Maximum number of idle handles.
26
+ */
27
+ public function __construct($maxHandles)
28
+ {
29
+ $this->maxHandles = $maxHandles;
30
+ }
31
+
32
+ public function create(RequestInterface $request, array $options)
33
+ {
34
+ if (isset($options['curl']['body_as_string'])) {
35
+ $options['_body_as_string'] = $options['curl']['body_as_string'];
36
+ unset($options['curl']['body_as_string']);
37
+ }
38
+
39
+ $easy = new EasyHandle;
40
+ $easy->request = $request;
41
+ $easy->options = $options;
42
+ $conf = $this->getDefaultConf($easy);
43
+ $this->applyMethod($easy, $conf);
44
+ $this->applyHandlerOptions($easy, $conf);
45
+ $this->applyHeaders($easy, $conf);
46
+ unset($conf['_headers']);
47
+
48
+ // Add handler options from the request configuration options
49
+ if (isset($options['curl'])) {
50
+ $conf = array_replace($conf, $options['curl']);
51
+ }
52
+
53
+ $conf[CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
54
+ $easy->handle = $this->handles
55
+ ? array_pop($this->handles)
56
+ : curl_init();
57
+ curl_setopt_array($easy->handle, $conf);
58
+
59
+ return $easy;
60
+ }
61
+
62
+ public function release(EasyHandle $easy)
63
+ {
64
+ $resource = $easy->handle;
65
+ unset($easy->handle);
66
+
67
+ if (count($this->handles) >= $this->maxHandles) {
68
+ curl_close($resource);
69
+ } else {
70
+ // Remove all callback functions as they can hold onto references
71
+ // and are not cleaned up by curl_reset. Using curl_setopt_array
72
+ // does not work for some reason, so removing each one
73
+ // individually.
74
+ curl_setopt($resource, CURLOPT_HEADERFUNCTION, null);
75
+ curl_setopt($resource, CURLOPT_READFUNCTION, null);
76
+ curl_setopt($resource, CURLOPT_WRITEFUNCTION, null);
77
+ curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null);
78
+ curl_reset($resource);
79
+ $this->handles[] = $resource;
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Completes a cURL transaction, either returning a response promise or a
85
+ * rejected promise.
86
+ *
87
+ * @param callable $handler
88
+ * @param EasyHandle $easy
89
+ * @param CurlFactoryInterface $factory Dictates how the handle is released
90
+ *
91
+ * @return \GuzzleHttp\Promise\PromiseInterface
92
+ */
93
+ public static function finish(
94
+ callable $handler,
95
+ EasyHandle $easy,
96
+ CurlFactoryInterface $factory
97
+ ) {
98
+ if (isset($easy->options['on_stats'])) {
99
+ self::invokeStats($easy);
100
+ }
101
+
102
+ if (!$easy->response || $easy->errno) {
103
+ return self::finishError($handler, $easy, $factory);
104
+ }
105
+
106
+ // Return the response if it is present and there is no error.
107
+ $factory->release($easy);
108
+
109
+ // Rewind the body of the response if possible.
110
+ $body = $easy->response->getBody();
111
+ if ($body->isSeekable()) {
112
+ $body->rewind();
113
+ }
114
+
115
+ return new FulfilledPromise($easy->response);
116
+ }
117
+
118
+ private static function invokeStats(EasyHandle $easy)
119
+ {
120
+ $curlStats = curl_getinfo($easy->handle);
121
+ $stats = new TransferStats(
122
+ $easy->request,
123
+ $easy->response,
124
+ $curlStats['total_time'],
125
+ $easy->errno,
126
+ $curlStats
127
+ );
128
+ call_user_func($easy->options['on_stats'], $stats);
129
+ }
130
+
131
+ private static function finishError(
132
+ callable $handler,
133
+ EasyHandle $easy,
134
+ CurlFactoryInterface $factory
135
+ ) {
136
+ // Get error information and release the handle to the factory.
137
+ $ctx = [
138
+ 'errno' => $easy->errno,
139
+ 'error' => curl_error($easy->handle),
140
+ ] + curl_getinfo($easy->handle);
141
+ $factory->release($easy);
142
+
143
+ // Retry when nothing is present or when curl failed to rewind.
144
+ if (empty($easy->options['_err_message'])
145
+ && (!$easy->errno || $easy->errno == 65)
146
+ ) {
147
+ return self::retryFailedRewind($handler, $easy, $ctx);
148
+ }
149
+
150
+ return self::createRejection($easy, $ctx);
151
+ }
152
+
153
+ private static function createRejection(EasyHandle $easy, array $ctx)
154
+ {
155
+ static $connectionErrors = [
156
+ CURLE_OPERATION_TIMEOUTED => true,
157
+ CURLE_COULDNT_RESOLVE_HOST => true,
158
+ CURLE_COULDNT_CONNECT => true,
159
+ CURLE_SSL_CONNECT_ERROR => true,
160
+ CURLE_GOT_NOTHING => true,
161
+ ];
162
+
163
+ // If an exception was encountered during the onHeaders event, then
164
+ // return a rejected promise that wraps that exception.
165
+ if ($easy->onHeadersException) {
166
+ return \GuzzleHttp\Promise\rejection_for(
167
+ new RequestException(
168
+ 'An error was encountered during the on_headers event',
169
+ $easy->request,
170
+ $easy->response,
171
+ $easy->onHeadersException,
172
+ $ctx
173
+ )
174
+ );
175
+ }
176
+
177
+ $message = sprintf(
178
+ 'cURL error %s: %s (%s)',
179
+ $ctx['errno'],
180
+ $ctx['error'],
181
+ 'see http://curl.haxx.se/libcurl/c/libcurl-errors.html'
182
+ );
183
+
184
+ // Create a connection exception if it was a specific error code.
185
+ $error = isset($connectionErrors[$easy->errno])
186
+ ? new ConnectException($message, $easy->request, null, $ctx)
187
+ : new RequestException($message, $easy->request, $easy->response, null, $ctx);
188
+
189
+ return \GuzzleHttp\Promise\rejection_for($error);
190
+ }
191
+
192
+ private function getDefaultConf(EasyHandle $easy)
193
+ {
194
+ $conf = [
195
+ '_headers' => $easy->request->getHeaders(),
196
+ CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
197
+ CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''),
198
+ CURLOPT_RETURNTRANSFER => false,
199
+ CURLOPT_HEADER => false,
200
+ CURLOPT_CONNECTTIMEOUT => 150,
201
+ ];
202
+
203
+ if (defined('CURLOPT_PROTOCOLS')) {
204
+ $conf[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
205
+ }
206
+
207
+ $version = $easy->request->getProtocolVersion();
208
+ if ($version == 1.1) {
209
+ $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
210
+ } elseif ($version == 2.0) {
211
+ $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
212
+ } else {
213
+ $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
214
+ }
215
+
216
+ return $conf;
217
+ }
218
+
219
+ private function applyMethod(EasyHandle $easy, array &$conf)
220
+ {
221
+ $body = $easy->request->getBody();
222
+ $size = $body->getSize();
223
+
224
+ if ($size === null || $size > 0) {
225
+ $this->applyBody($easy->request, $easy->options, $conf);
226
+ return;
227
+ }
228
+
229
+ $method = $easy->request->getMethod();
230
+ if ($method === 'PUT' || $method === 'POST') {
231
+ // See http://tools.ietf.org/html/rfc7230#section-3.3.2
232
+ if (!$easy->request->hasHeader('Content-Length')) {
233
+ $conf[CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
234
+ }
235
+ } elseif ($method === 'HEAD') {
236
+ $conf[CURLOPT_NOBODY] = true;
237
+ unset(
238
+ $conf[CURLOPT_WRITEFUNCTION],
239
+ $conf[CURLOPT_READFUNCTION],
240
+ $conf[CURLOPT_FILE],
241
+ $conf[CURLOPT_INFILE]
242
+ );
243
+ }
244
+ }
245
+
246
+ private function applyBody(RequestInterface $request, array $options, array &$conf)
247
+ {
248
+ $size = $request->hasHeader('Content-Length')
249
+ ? (int) $request->getHeaderLine('Content-Length')
250
+ : null;
251
+
252
+ // Send the body as a string if the size is less than 1MB OR if the
253
+ // [curl][body_as_string] request value is set.
254
+ if (($size !== null && $size < 1000000) ||
255
+ !empty($options['_body_as_string'])
256
+ ) {
257
+ $conf[CURLOPT_POSTFIELDS] = (string) $request->getBody();
258
+ // Don't duplicate the Content-Length header
259
+ $this->removeHeader('Content-Length', $conf);
260
+ $this->removeHeader('Transfer-Encoding', $conf);
261
+ } else {
262
+ $conf[CURLOPT_UPLOAD] = true;
263
+ if ($size !== null) {
264
+ $conf[CURLOPT_INFILESIZE] = $size;
265
+ $this->removeHeader('Content-Length', $conf);
266
+ }
267
+ $body = $request->getBody();
268
+ if ($body->isSeekable()) {
269
+ $body->rewind();
270
+ }
271
+ $conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
272
+ return $body->read($length);
273
+ };
274
+ }
275
+
276
+ // If the Expect header is not present, prevent curl from adding it
277
+ if (!$request->hasHeader('Expect')) {
278
+ $conf[CURLOPT_HTTPHEADER][] = 'Expect:';
279
+ }
280
+
281
+ // cURL sometimes adds a content-type by default. Prevent this.
282
+ if (!$request->hasHeader('Content-Type')) {
283
+ $conf[CURLOPT_HTTPHEADER][] = 'Content-Type:';
284
+ }
285
+ }
286
+
287
+ private function applyHeaders(EasyHandle $easy, array &$conf)
288
+ {
289
+ foreach ($conf['_headers'] as $name => $values) {
290
+ foreach ($values as $value) {
291
+ $conf[CURLOPT_HTTPHEADER][] = "$name: $value";
292
+ }
293
+ }
294
+
295
+ // Remove the Accept header if one was not set
296
+ if (!$easy->request->hasHeader('Accept')) {
297
+ $conf[CURLOPT_HTTPHEADER][] = 'Accept:';
298
+ }
299
+ }
300
+
301
+ /**
302
+ * Remove a header from the options array.
303
+ *
304
+ * @param string $name Case-insensitive header to remove
305
+ * @param array $options Array of options to modify
306
+ */
307
+ private function removeHeader($name, array &$options)
308
+ {
309
+ foreach (array_keys($options['_headers']) as $key) {
310
+ if (!strcasecmp($key, $name)) {
311
+ unset($options['_headers'][$key]);
312
+ return;
313
+ }
314
+ }
315
+ }
316
+
317
+ private function applyHandlerOptions(EasyHandle $easy, array &$conf)
318
+ {
319
+ $options = $easy->options;
320
+ if (isset($options['verify'])) {
321
+ if ($options['verify'] === false) {
322
+ unset($conf[CURLOPT_CAINFO]);
323
+ $conf[CURLOPT_SSL_VERIFYHOST] = 0;
324
+ $conf[CURLOPT_SSL_VERIFYPEER] = false;
325
+ } else {
326
+ $conf[CURLOPT_SSL_VERIFYHOST] = 2;
327
+ $conf[CURLOPT_SSL_VERIFYPEER] = true;
328
+ if (is_string($options['verify'])) {
329
+ // Throw an error if the file/folder/link path is not valid or doesn't exist.
330
+ if (!file_exists($options['verify'])) {
331
+ throw new \InvalidArgumentException(
332
+ "SSL CA bundle not found: {$options['verify']}"
333
+ );
334
+ }
335
+ // If it's a directory or a link to a directory use CURLOPT_CAPATH.
336
+ // If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
337
+ if (is_dir($options['verify']) ||
338
+ (is_link($options['verify']) && is_dir(readlink($options['verify'])))) {
339
+ $conf[CURLOPT_CAPATH] = $options['verify'];
340
+ } else {
341
+ $conf[CURLOPT_CAINFO] = $options['verify'];
342
+ }
343
+ }
344
+ }
345
+ }
346
+
347
+ if (!empty($options['decode_content'])) {
348
+ $accept = $easy->request->getHeaderLine('Accept-Encoding');
349
+ if ($accept) {
350
+ $conf[CURLOPT_ENCODING] = $accept;
351
+ } else {
352
+ $conf[CURLOPT_ENCODING] = '';
353
+ // Don't let curl send the header over the wire
354
+ $conf[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
355
+ }
356
+ }
357
+
358
+ if (isset($options['sink'])) {
359
+ $sink = $options['sink'];
360
+ if (!is_string($sink)) {
361
+ $sink = \GuzzleHttp\Psr7\stream_for($sink);
362
+ } elseif (!is_dir(dirname($sink))) {
363
+ // Ensure that the directory exists before failing in curl.
364
+ throw new \RuntimeException(sprintf(
365
+ 'Directory %s does not exist for sink value of %s',
366
+ dirname($sink),
367
+ $sink
368
+ ));
369
+ } else {
370
+ $sink = new LazyOpenStream($sink, 'w+');
371
+ }
372
+ $easy->sink = $sink;
373
+ $conf[CURLOPT_WRITEFUNCTION] = function ($ch, $write) use ($sink) {
374
+ return $sink->write($write);
375
+ };
376
+ } else {
377
+ // Use a default temp stream if no sink was set.
378
+ $conf[CURLOPT_FILE] = fopen('php://temp', 'w+');
379
+ $easy->sink = Psr7\stream_for($conf[CURLOPT_FILE]);
380
+ }
381
+ $timeoutRequiresNoSignal = false;
382
+ if (isset($options['timeout'])) {
383
+ $timeoutRequiresNoSignal |= $options['timeout'] < 1;
384
+ $conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
385
+ }
386
+
387
+ // CURL default value is CURL_IPRESOLVE_WHATEVER
388
+ if (isset($options['force_ip_resolve'])) {
389
+ if ('v4' === $options['force_ip_resolve']) {
390
+ $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
391
+ } else if ('v6' === $options['force_ip_resolve']) {
392
+ $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V6;
393
+ }
394
+ }
395
+
396
+ if (isset($options['connect_timeout'])) {
397
+ $timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;
398
+ $conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
399
+ }
400
+
401
+ if ($timeoutRequiresNoSignal && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
402
+ $conf[CURLOPT_NOSIGNAL] = true;
403
+ }
404
+
405
+ if (isset($options['proxy'])) {
406
+ if (!is_array($options['proxy'])) {
407
+ $conf[CURLOPT_PROXY] = $options['proxy'];
408
+ } else {
409
+ $scheme = $easy->request->getUri()->getScheme();
410
+ if (isset($options['proxy'][$scheme])) {
411
+ $host = $easy->request->getUri()->getHost();
412
+ if (!isset($options['proxy']['no']) ||
413
+ !\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no'])
414
+ ) {
415
+ $conf[CURLOPT_PROXY] = $options['proxy'][$scheme];
416
+ }
417
+ }
418
+ }
419
+ }
420
+
421
+ if (isset($options['cert'])) {
422
+ $cert = $options['cert'];
423
+ if (is_array($cert)) {
424
+ $conf[CURLOPT_SSLCERTPASSWD] = $cert[1];
425
+ $cert = $cert[0];
426
+ }
427
+ if (!file_exists($cert)) {
428
+ throw new \InvalidArgumentException(
429
+ "SSL certificate not found: {$cert}"
430
+ );
431
+ }
432
+ $conf[CURLOPT_SSLCERT] = $cert;
433
+ }
434
+
435
+ if (isset($options['ssl_key'])) {
436
+ $sslKey = $options['ssl_key'];
437
+ if (is_array($sslKey)) {
438
+ $conf[CURLOPT_SSLKEYPASSWD] = $sslKey[1];
439
+ $sslKey = $sslKey[0];
440
+ }
441
+ if (!file_exists($sslKey)) {
442
+ throw new \InvalidArgumentException(
443
+ "SSL private key not found: {$sslKey}"
444
+ );
445
+ }
446
+ $conf[CURLOPT_SSLKEY] = $sslKey;
447
+ }
448
+
449
+ if (isset($options['progress'])) {
450
+ $progress = $options['progress'];
451
+ if (!is_callable($progress)) {
452
+ throw new \InvalidArgumentException(
453
+ 'progress client option must be callable'
454
+ );
455
+ }
456
+ $conf[CURLOPT_NOPROGRESS] = false;
457
+ $conf[CURLOPT_PROGRESSFUNCTION] = function () use ($progress) {
458
+ $args = func_get_args();
459
+ // PHP 5.5 pushed the handle onto the start of the args
460
+ if (is_resource($args[0])) {
461
+ array_shift($args);
462
+ }
463
+ call_user_func_array($progress, $args);
464
+ };
465
+ }
466
+
467
+ if (!empty($options['debug'])) {
468
+ $conf[CURLOPT_STDERR] = \GuzzleHttp\debug_resource($options['debug']);
469
+ $conf[CURLOPT_VERBOSE] = true;
470
+ }
471
+ }
472
+
473
+ /**
474
+ * This function ensures that a response was set on a transaction. If one
475
+ * was not set, then the request is retried if possible. This error
476
+ * typically means you are sending a payload, curl encountered a
477
+ * "Connection died, retrying a fresh connect" error, tried to rewind the
478
+ * stream, and then encountered a "necessary data rewind wasn't possible"
479
+ * error, causing the request to be sent through curl_multi_info_read()
480
+ * without an error status.
481
+ */
482
+ private static function retryFailedRewind(
483
+ callable $handler,
484
+ EasyHandle $easy,
485
+ array $ctx
486
+ ) {
487
+ try {
488
+ // Only rewind if the body has been read from.
489
+ $body = $easy->request->getBody();
490
+ if ($body->tell() > 0) {
491
+ $body->rewind();
492
+ }
493
+ } catch (\RuntimeException $e) {
494
+ $ctx['error'] = 'The connection unexpectedly failed without '
495
+ . 'providing an error. The request would have been retried, '
496
+ . 'but attempting to rewind the request body failed. '
497
+ . 'Exception: ' . $e;
498
+ return self::createRejection($easy, $ctx);
499
+ }
500
+
501
+ // Retry no more than 3 times before giving up.
502
+ if (!isset($easy->options['_curl_retries'])) {
503
+ $easy->options['_curl_retries'] = 1;
504
+ } elseif ($easy->options['_curl_retries'] == 2) {
505
+ $ctx['error'] = 'The cURL request was retried 3 times '
506
+ . 'and did not succeed. The most likely reason for the failure '
507
+ . 'is that cURL was unable to rewind the body of the request '
508
+ . 'and subsequent retries resulted in the same error. Turn on '
509
+ . 'the debug option to see what went wrong. See '
510
+ . 'https://bugs.php.net/bug.php?id=47204 for more information.';
511
+ return self::createRejection($easy, $ctx);
512
+ } else {
513
+ $easy->options['_curl_retries']++;
514
+ }
515
+
516
+ return $handler($easy->request, $easy->options);
517
+ }
518
+
519
+ private function createHeaderFn(EasyHandle $easy)
520
+ {
521
+ if (isset($easy->options['on_headers'])) {
522
+ $onHeaders = $easy->options['on_headers'];
523
+
524
+ if (!is_callable($onHeaders)) {
525
+ throw new \InvalidArgumentException('on_headers must be callable');
526
+ }
527
+ } else {
528
+ $onHeaders = null;
529
+ }
530
+
531
+ return function ($ch, $h) use (
532
+ $onHeaders,
533
+ $easy,
534
+ &$startingResponse
535
+ ) {
536
+ $value = trim($h);
537
+ if ($value === '') {
538
+ $startingResponse = true;
539
+ $easy->createResponse();
540
+ if ($onHeaders !== null) {
541
+ try {
542
+ $onHeaders($easy->response);
543
+ } catch (\Exception $e) {
544
+ // Associate the exception with the handle and trigger
545
+ // a curl header write error by returning 0.
546
+ $easy->onHeadersException = $e;
547
+ return -1;
548
+ }
549
+ }
550
+ } elseif ($startingResponse) {
551
+ $startingResponse = false;
552
+ $easy->headers = [$value];
553
+ } else {
554
+ $easy->headers[] = $value;
555
+ }
556
+ return strlen($h);
557
+ };
558
+ }
559
+ }
vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+
6
+ interface CurlFactoryInterface
7
+ {
8
+ /**
9
+ * Creates a cURL handle resource.
10
+ *
11
+ * @param RequestInterface $request Request
12
+ * @param array $options Transfer options
13
+ *
14
+ * @return EasyHandle
15
+ * @throws \RuntimeException when an option cannot be applied
16
+ */
17
+ public function create(RequestInterface $request, array $options);
18
+
19
+ /**
20
+ * Release an easy handle, allowing it to be reused or closed.
21
+ *
22
+ * This function must call unset on the easy handle's "handle" property.
23
+ *
24
+ * @param EasyHandle $easy
25
+ */
26
+ public function release(EasyHandle $easy);
27
+ }
vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Psr7;
5
+ use Psr\Http\Message\RequestInterface;
6
+
7
+ /**
8
+ * HTTP handler that uses cURL easy handles as a transport layer.
9
+ *
10
+ * When using the CurlHandler, custom curl options can be specified as an
11
+ * associative array of curl option constants mapping to values in the
12
+ * **curl** key of the "client" key of the request.
13
+ */
14
+ class CurlHandler
15
+ {
16
+ /** @var CurlFactoryInterface */
17
+ private $factory;
18
+
19
+ /**
20
+ * Accepts an associative array of options:
21
+ *
22
+ * - factory: Optional curl factory used to create cURL handles.
23
+ *
24
+ * @param array $options Array of options to use with the handler
25
+ */
26
+ public function __construct(array $options = [])
27
+ {
28
+ $this->factory = isset($options['handle_factory'])
29
+ ? $options['handle_factory']
30
+ : new CurlFactory(3);
31
+ }
32
+
33
+ public function __invoke(RequestInterface $request, array $options)
34
+ {
35
+ if (isset($options['delay'])) {
36
+ usleep($options['delay'] * 1000);
37
+ }
38
+
39
+ $easy = $this->factory->create($request, $options);
40
+ curl_exec($easy->handle);
41
+ $easy->errno = curl_errno($easy->handle);
42
+
43
+ return CurlFactory::finish($this, $easy, $this->factory);
44
+ }
45
+ }
vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Promise as P;
5
+ use GuzzleHttp\Promise\Promise;
6
+ use GuzzleHttp\Psr7;
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
+ * This handler accepts the following options:
29
+ *
30
+ * - handle_factory: An optional factory used to create curl handles
31
+ * - select_timeout: Optional timeout (in seconds) to block before timing
32
+ * out while selecting curl handles. Defaults to 1 second.
33
+ *
34
+ * @param array $options
35
+ */
36
+ public function __construct(array $options = [])
37
+ {
38
+ $this->factory = isset($options['handle_factory'])
39
+ ? $options['handle_factory'] : new CurlFactory(50);
40
+ $this->selectTimeout = isset($options['select_timeout'])
41
+ ? $options['select_timeout'] : 1;
42
+ }
43
+
44
+ public function __get($name)
45
+ {
46
+ if ($name === '_mh') {
47
+ return $this->_mh = curl_multi_init();
48
+ }
49
+
50
+ throw new \BadMethodCallException();
51
+ }
52
+
53
+ public function __destruct()
54
+ {
55
+ if (isset($this->_mh)) {
56
+ curl_multi_close($this->_mh);
57
+ unset($this->_mh);
58
+ }
59
+ }
60
+
61
+ public function __invoke(RequestInterface $request, array $options)
62
+ {
63
+ $easy = $this->factory->create($request, $options);
64
+ $id = (int) $easy->handle;
65
+
66
+ $promise = new Promise(
67
+ [$this, 'execute'],
68
+ function () use ($id) { return $this->cancel($id); }
69
+ );
70
+
71
+ $this->addRequest(['easy' => $easy, 'deferred' => $promise]);
72
+
73
+ return $promise;
74
+ }
75
+
76
+ /**
77
+ * Ticks the curl event loop.
78
+ */
79
+ public function tick()
80
+ {
81
+ // Add any delayed handles if needed.
82
+ if ($this->delays) {
83
+ $currentTime = microtime(true);
84
+ foreach ($this->delays as $id => $delay) {
85
+ if ($currentTime >= $delay) {
86
+ unset($this->delays[$id]);
87
+ curl_multi_add_handle(
88
+ $this->_mh,
89
+ $this->handles[$id]['easy']->handle
90
+ );
91
+ }
92
+ }
93
+ }
94
+
95
+ // Step through the task queue which may add additional requests.
96
+ P\queue()->run();
97
+
98
+ if ($this->active &&
99
+ curl_multi_select($this->_mh, $this->selectTimeout) === -1
100
+ ) {
101
+ // Perform a usleep if a select returns -1.
102
+ // See: https://bugs.php.net/bug.php?id=61141
103
+ usleep(250);
104
+ }
105
+
106
+ while (curl_multi_exec($this->_mh, $this->active) === CURLM_CALL_MULTI_PERFORM);
107
+
108
+ $this->processMessages();
109
+ }
110
+
111
+ /**
112
+ * Runs until all outstanding connections have completed.
113
+ */
114
+ public function execute()
115
+ {
116
+ $queue = P\queue();
117
+
118
+ while ($this->handles || !$queue->isEmpty()) {
119
+ // If there are no transfers, then sleep for the next delay
120
+ if (!$this->active && $this->delays) {
121
+ usleep($this->timeToNext());
122
+ }
123
+ $this->tick();
124
+ }
125
+ }
126
+
127
+ private function addRequest(array $entry)
128
+ {
129
+ $easy = $entry['easy'];
130
+ $id = (int) $easy->handle;
131
+ $this->handles[$id] = $entry;
132
+ if (empty($easy->options['delay'])) {
133
+ curl_multi_add_handle($this->_mh, $easy->handle);
134
+ } else {
135
+ $this->delays[$id] = microtime(true) + ($easy->options['delay'] / 1000);
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Cancels a handle from sending and removes references to it.
141
+ *
142
+ * @param int $id Handle ID to cancel and remove.
143
+ *
144
+ * @return bool True on success, false on failure.
145
+ */
146
+ private function cancel($id)
147
+ {
148
+ // Cannot cancel if it has been processed.
149
+ if (!isset($this->handles[$id])) {
150
+ return false;
151
+ }
152
+
153
+ $handle = $this->handles[$id]['easy']->handle;
154
+ unset($this->delays[$id], $this->handles[$id]);
155
+ curl_multi_remove_handle($this->_mh, $handle);
156
+ curl_close($handle);
157
+
158
+ return true;
159
+ }
160
+
161
+ private function processMessages()
162
+ {
163
+ while ($done = curl_multi_info_read($this->_mh)) {
164
+ $id = (int) $done['handle'];
165
+ curl_multi_remove_handle($this->_mh, $done['handle']);
166
+
167
+ if (!isset($this->handles[$id])) {
168
+ // Probably was cancelled.
169
+ continue;
170
+ }
171
+
172
+ $entry = $this->handles[$id];
173
+ unset($this->handles[$id], $this->delays[$id]);
174
+ $entry['easy']->errno = $done['result'];
175
+ $entry['deferred']->resolve(
176
+ CurlFactory::finish(
177
+ $this,
178
+ $entry['easy'],
179
+ $this->factory
180
+ )
181
+ );
182
+ }
183
+ }
184
+
185
+ private function timeToNext()
186
+ {
187
+ $currentTime = microtime(true);
188
+ $nextTime = PHP_INT_MAX;
189
+ foreach ($this->delays as $time) {
190
+ if ($time < $nextTime) {
191
+ $nextTime = $time;
192
+ }
193
+ }
194
+
195
+ return max(0, $nextTime - $currentTime) * 1000000;
196
+ }
197
+ }
vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Psr7\Response;
5
+ use Psr\Http\Message\RequestInterface;
6
+ use Psr\Http\Message\ResponseInterface;
7
+ use Psr\Http\Message\StreamInterface;
8
+
9
+ /**
10
+ * Represents a cURL easy handle and the data it populates.
11
+ *
12
+ * @internal
13
+ */
14
+ final class EasyHandle
15
+ {
16
+ /** @var resource cURL resource */
17
+ public $handle;
18
+
19
+ /** @var StreamInterface Where data is being written */
20
+ public $sink;
21
+
22
+ /** @var array Received HTTP headers so far */
23
+ public $headers = [];
24
+
25
+ /** @var ResponseInterface Received response (if any) */
26
+ public $response;
27
+
28
+ /** @var RequestInterface Request being sent */
29
+ public $request;
30
+
31
+ /** @var array Request options */
32
+ public $options = [];
33
+
34
+ /** @var int cURL error number (if any) */
35
+ public $errno = 0;
36
+
37
+ /** @var \Exception Exception during on_headers (if any) */
38
+ public $onHeadersException;
39
+
40
+ /**
41
+ * Attach a response to the easy handle based on the received headers.
42
+ *
43
+ * @throws \RuntimeException if no headers have been received.
44
+ */
45
+ public function createResponse()
46
+ {
47
+ if (empty($this->headers)) {
48
+ throw new \RuntimeException('No headers have been received');
49
+ }
50
+
51
+ // HTTP-version SP status-code SP reason-phrase
52
+ $startLine = explode(' ', array_shift($this->headers), 3);
53
+ $headers = \GuzzleHttp\headers_from_lines($this->headers);
54
+ $normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
55
+
56
+ if (!empty($this->options['decode_content'])
57
+ && isset($normalizedKeys['content-encoding'])
58
+ ) {
59
+ $headers['x-encoded-content-encoding']
60
+ = $headers[$normalizedKeys['content-encoding']];
61
+ unset($headers[$normalizedKeys['content-encoding']]);
62
+ if (isset($normalizedKeys['content-length'])) {
63
+ $headers['x-encoded-content-length']
64
+ = $headers[$normalizedKeys['content-length']];
65
+
66
+ $bodyLength = (int) $this->sink->getSize();
67
+ if ($bodyLength) {
68
+ $headers[$normalizedKeys['content-length']] = $bodyLength;
69
+ } else {
70
+ unset($headers[$normalizedKeys['content-length']]);
71
+ }
72
+ }
73
+ }
74
+
75
+ // Attach a response to the easy handle with the parsed headers.
76
+ $this->response = new Response(
77
+ $startLine[1],
78
+ $headers,
79
+ $this->sink,
80
+ substr($startLine[0], 5),
81
+ isset($startLine[2]) ? (string) $startLine[2] : null
82
+ );
83
+ }
84
+
85
+ public function __get($name)
86
+ {
87
+ $msg = $name === 'handle'
88
+ ? 'The EasyHandle has been released'
89
+ : 'Invalid property: ' . $name;
90
+ throw new \BadMethodCallException($msg);
91
+ }
92
+ }
vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ private function invokeStats(
179
+ RequestInterface $request,
180
+ array $options,
181
+ ResponseInterface $response = null,
182
+ $reason = null
183
+ ) {
184
+ if (isset($options['on_stats'])) {
185
+ $stats = new TransferStats($request, $response, 0, $reason);
186
+ call_user_func($options['on_stats'], $stats);
187
+ }
188
+ }
189
+ }
vendor/guzzlehttp/guzzle/src/Handler/Proxy.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\RequestOptions;
5
+ use Psr\Http\Message\RequestInterface;
6
+
7
+ /**
8
+ * Provides basic proxies for handlers.
9
+ */
10
+ class Proxy
11
+ {
12
+ /**
13
+ * Sends synchronous requests to a specific handler while sending all other
14
+ * requests to another handler.
15
+ *
16
+ * @param callable $default Handler used for normal responses
17
+ * @param callable $sync Handler used for synchronous responses.
18
+ *
19
+ * @return callable Returns the composed handler.
20
+ */
21
+ public static function wrapSync(
22
+ callable $default,
23
+ callable $sync
24
+ ) {
25
+ return function (RequestInterface $request, array $options) use ($default, $sync) {
26
+ return empty($options[RequestOptions::SYNCHRONOUS])
27
+ ? $default($request, $options)
28
+ : $sync($request, $options);
29
+ };
30
+ }
31
+
32
+ /**
33
+ * Sends streaming requests to a streaming compatible handler while sending
34
+ * all other requests to a default handler.
35
+ *
36
+ * This, for example, could be useful for taking advantage of the
37
+ * performance benefits of curl while still supporting true streaming
38
+ * through the StreamHandler.
39
+ *
40
+ * @param callable $default Handler used for non-streaming responses
41
+ * @param callable $streaming Handler used for streaming responses
42
+ *
43
+ * @return callable Returns the composed handler.
44
+ */
45
+ public static function wrapStreaming(
46
+ callable $default,
47
+ callable $streaming
48
+ ) {
49
+ return function (RequestInterface $request, array $options) use ($default, $streaming) {
50
+ return empty($options['stream'])
51
+ ? $default($request, $options)
52
+ : $streaming($request, $options);
53
+ };
54
+ }
55
+ }
vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php ADDED
@@ -0,0 +1,533 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Exception\RequestException;
5
+ use GuzzleHttp\Exception\ConnectException;
6
+ use GuzzleHttp\Promise\FulfilledPromise;
7
+ use GuzzleHttp\Promise\RejectedPromise;
8
+ use GuzzleHttp\Promise\PromiseInterface;
9
+ use GuzzleHttp\Psr7;
10
+ use GuzzleHttp\TransferStats;
11
+ use Psr\Http\Message\RequestInterface;
12
+ use Psr\Http\Message\ResponseInterface;
13
+ use Psr\Http\Message\StreamInterface;
14
+
15
+ /**
16
+ * HTTP handler that uses PHP's HTTP stream wrapper.
17
+ */
18
+ class StreamHandler
19
+ {
20
+ private $lastHeaders = [];
21
+
22
+ /**
23
+ * Sends an HTTP request.
24
+ *
25
+ * @param RequestInterface $request Request to send.
26
+ * @param array $options Request transfer options.
27
+ *
28
+ * @return PromiseInterface
29
+ */
30
+ public function __invoke(RequestInterface $request, array $options)
31
+ {
32
+ // Sleep if there is a delay specified.
33
+ if (isset($options['delay'])) {
34
+ usleep($options['delay'] * 1000);
35
+ }
36
+
37
+ $startTime = isset($options['on_stats']) ? microtime(true) : null;
38
+
39
+ try {
40
+ // Does not support the expect header.
41
+ $request = $request->withoutHeader('Expect');
42
+
43
+ // Append a content-length header if body size is zero to match
44
+ // cURL's behavior.
45
+ if (0 === $request->getBody()->getSize()) {
46
+ $request = $request->withHeader('Content-Length', 0);
47
+ }
48
+
49
+ return $this->createResponse(
50
+ $request,
51
+ $options,
52
+ $this->createStream($request, $options),
53
+ $startTime
54
+ );
55
+ } catch (\InvalidArgumentException $e) {
56
+ throw $e;
57
+ } catch (\Exception $e) {
58
+ // Determine if the error was a networking error.
59
+ $message = $e->getMessage();
60
+ // This list can probably get more comprehensive.
61
+ if (strpos($message, 'getaddrinfo') // DNS lookup failed
62
+ || strpos($message, 'Connection refused')
63
+ || strpos($message, "couldn't connect to host") // error on HHVM
64
+ ) {
65
+ $e = new ConnectException($e->getMessage(), $request, $e);
66
+ }
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
+ microtime(true) - $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, $options);
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
+
311
+ throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
312
+ }
313
+
314
+ $uri = $this->resolveHost($request, $options);
315
+
316
+ $context = $this->createResource(
317
+ function () use ($context, $params) {
318
+ return stream_context_create($context, $params);
319
+ }
320
+ );
321
+
322
+ return $this->createResource(
323
+ function () use ($uri, &$http_response_header, $context, $options) {
324
+ $resource = fopen((string) $uri, 'r', null, $context);
325
+ $this->lastHeaders = $http_response_header;
326
+
327
+ if (isset($options['read_timeout'])) {
328
+ $readTimeout = $options['read_timeout'];
329
+ $sec = (int) $readTimeout;
330
+ $usec = ($readTimeout - $sec) * 100000;
331
+ stream_set_timeout($resource, $sec, $usec);
332
+ }
333
+
334
+ return $resource;
335
+ }
336
+ );
337
+ }
338
+
339
+ private function resolveHost(RequestInterface $request, array $options)
340
+ {
341
+ $uri = $request->getUri();
342
+
343
+ if (isset($options['force_ip_resolve']) && !filter_var($uri->getHost(), FILTER_VALIDATE_IP)) {
344
+ if ('v4' === $options['force_ip_resolve']) {
345
+ $records = dns_get_record($uri->getHost(), DNS_A);
346
+ if (!isset($records[0]['ip'])) {
347
+ throw new ConnectException(sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request);
348
+ }
349
+ $uri = $uri->withHost($records[0]['ip']);
350
+ } elseif ('v6' === $options['force_ip_resolve']) {
351
+ $records = dns_get_record($uri->getHost(), DNS_AAAA);
352
+ if (!isset($records[0]['ipv6'])) {
353
+ throw new ConnectException(sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request);
354
+ }
355
+ $uri = $uri->withHost('[' . $records[0]['ipv6'] . ']');
356
+ }
357
+ }
358
+
359
+ return $uri;
360
+ }
361
+
362
+ private function getDefaultContext(RequestInterface $request)
363
+ {
364
+ $headers = '';
365
+ foreach ($request->getHeaders() as $name => $value) {
366
+ foreach ($value as $val) {
367
+ $headers .= "$name: $val\r\n";
368
+ }
369
+ }
370
+
371
+ $context = [
372
+ 'http' => [
373
+ 'method' => $request->getMethod(),
374
+ 'header' => $headers,
375
+ 'protocol_version' => $request->getProtocolVersion(),
376
+ 'ignore_errors' => true,
377
+ 'follow_location' => 0,
378
+ ],
379
+ ];
380
+
381
+ $body = (string) $request->getBody();
382
+
383
+ if (!empty($body)) {
384
+ $context['http']['content'] = $body;
385
+ // Prevent the HTTP handler from adding a Content-Type header.
386
+ if (!$request->hasHeader('Content-Type')) {
387
+ $context['http']['header'] .= "Content-Type:\r\n";
388
+ }
389
+ }
390
+
391
+ $context['http']['header'] = rtrim($context['http']['header']);
392
+
393
+ return $context;
394
+ }
395
+
396
+ private function add_proxy(RequestInterface $request, &$options, $value, &$params)
397
+ {
398
+ if (!is_array($value)) {
399
+ $options['http']['proxy'] = $value;
400
+ } else {
401
+ $scheme = $request->getUri()->getScheme();
402
+ if (isset($value[$scheme])) {
403
+ if (!isset($value['no'])
404
+ || !\GuzzleHttp\is_host_in_noproxy(
405
+ $request->getUri()->getHost(),
406
+ $value['no']
407
+ )
408
+ ) {
409
+ $options['http']['proxy'] = $value[$scheme];
410
+ }
411
+ }
412
+ }
413
+ }
414
+
415
+ private function add_timeout(RequestInterface $request, &$options, $value, &$params)
416
+ {
417
+ if ($value > 0) {
418
+ $options['http']['timeout'] = $value;
419
+ }
420
+ }
421
+
422
+ private function add_verify(RequestInterface $request, &$options, $value, &$params)
423
+ {
424
+ if ($value === true) {
425
+ // PHP 5.6 or greater will find the system cert by default. When
426
+ // < 5.6, use the Guzzle bundled cacert.
427
+ if (PHP_VERSION_ID < 50600) {
428
+ $options['ssl']['cafile'] = \GuzzleHttp\default_ca_bundle();
429
+ }
430
+ } elseif (is_string($value)) {
431
+ $options['ssl']['cafile'] = $value;
432
+ if (!file_exists($value)) {
433
+ throw new \RuntimeException("SSL CA bundle not found: $value");
434
+ }
435
+ } elseif ($value === false) {
436
+ $options['ssl']['verify_peer'] = false;
437
+ $options['ssl']['verify_peer_name'] = false;
438
+ return;
439
+ } else {
440
+ throw new \InvalidArgumentException('Invalid verify request option');
441
+ }
442
+
443
+ $options['ssl']['verify_peer'] = true;
444
+ $options['ssl']['verify_peer_name'] = true;
445
+ $options['ssl']['allow_self_signed'] = false;
446
+ }
447
+
448
+ private function add_cert(RequestInterface $request, &$options, $value, &$params)
449
+ {
450
+ if (is_array($value)) {
451
+ $options['ssl']['passphrase'] = $value[1];
452
+ $value = $value[0];
453
+ }
454
+
455
+ if (!file_exists($value)) {
456
+ throw new \RuntimeException("SSL certificate not found: {$value}");
457
+ }
458
+
459
+ $options['ssl']['local_cert'] = $value;
460
+ }
461
+
462
+ private function add_progress(RequestInterface $request, &$options, $value, &$params)
463
+ {
464
+ $this->addNotification(
465
+ $params,
466
+ function ($code, $a, $b, $c, $transferred, $total) use ($value) {
467
+ if ($code == STREAM_NOTIFY_PROGRESS) {
468
+ $value($total, $transferred, null, null);
469
+ }
470
+ }
471
+ );
472
+ }
473
+
474
+ private function add_debug(RequestInterface $request, &$options, $value, &$params)
475
+ {
476
+ if ($value === false) {
477
+ return;
478
+ }
479
+
480
+ static $map = [
481
+ STREAM_NOTIFY_CONNECT => 'CONNECT',
482
+ STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
483
+ STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
484
+ STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
485
+ STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
486
+ STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
487
+ STREAM_NOTIFY_PROGRESS => 'PROGRESS',
488
+ STREAM_NOTIFY_FAILURE => 'FAILURE',
489
+ STREAM_NOTIFY_COMPLETED => 'COMPLETED',
490
+ STREAM_NOTIFY_RESOLVE => 'RESOLVE',
491
+ ];
492
+ static $args = ['severity', 'message', 'message_code',
493
+ 'bytes_transferred', 'bytes_max'];
494
+
495
+ $value = \GuzzleHttp\debug_resource($value);
496
+ $ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');
497
+ $this->addNotification(
498
+ $params,
499
+ function () use ($ident, $value, $map, $args) {
500
+ $passed = func_get_args();
501
+ $code = array_shift($passed);
502
+ fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
503
+ foreach (array_filter($passed) as $i => $v) {
504
+ fwrite($value, $args[$i] . ': "' . $v . '" ');
505
+ }
506
+ fwrite($value, "\n");
507
+ }
508
+ );
509
+ }
510
+
511
+ private function addNotification(array &$params, callable $notify)
512
+ {
513
+ // Wrap the existing function if needed.
514
+ if (!isset($params['notification'])) {
515
+ $params['notification'] = $notify;
516
+ } else {
517
+ $params['notification'] = $this->callArray([
518
+ $params['notification'],
519
+ $notify
520
+ ]);
521
+ }
522
+ }
523
+
524
+ private function callArray(array $functions)
525
+ {
526
+ return function () use ($functions) {
527
+ $args = func_get_args();
528
+ foreach ($functions as $fn) {
529
+ call_user_func_array($fn, $args);
530
+ }
531
+ };
532
+ }
533
+ }
vendor/guzzlehttp/guzzle/src/HandlerStack.php ADDED
@@ -0,0 +1,273 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+
6
+ /**
7
+ * Creates a composed Guzzle handler function by stacking middlewares on top of
8
+ * an HTTP handler function.
9
+ */
10
+ class HandlerStack
11
+ {
12
+ /** @var callable */
13
+ private $handler;
14
+
15
+ /** @var array */
16
+ private $stack = [];
17
+
18
+ /** @var callable|null */
19
+ private $cached;
20
+
21
+ /**
22
+ * Creates a default handler stack that can be used by clients.
23
+ *
24
+ * The returned handler will wrap the provided handler or use the most
25
+ * appropriate default handler for you system. The returned HandlerStack has
26
+ * support for cookies, redirects, HTTP error exceptions, and preparing a body
27
+ * before sending.
28
+ *
29
+ * The returned handler stack can be passed to a client in the "handler"
30
+ * option.
31
+ *
32
+ * @param callable $handler HTTP handler function to use with the stack. If no
33
+ * handler is provided, the best handler for your
34
+ * system will be utilized.
35
+ *
36
+ * @return HandlerStack
37
+ */
38
+ public static function create(callable $handler = null)
39
+ {
40
+ $stack = new self($handler ?: choose_handler());
41
+ $stack->push(Middleware::httpErrors(), 'http_errors');
42
+ $stack->push(Middleware::redirect(), 'allow_redirects');
43
+ $stack->push(Middleware::cookies(), 'cookies');
44
+ $stack->push(Middleware::prepareBody(), 'prepare_body');
45
+
46
+ return $stack;
47
+ }
48
+
49
+ /**
50
+ * @param callable $handler Underlying HTTP handler.
51
+ */
52
+ public function __construct(callable $handler = null)
53
+ {
54
+ $this->handler = $handler;
55
+ }
56
+
57
+ /**
58
+ * Invokes the handler stack as a composed handler
59
+ *
60
+ * @param RequestInterface $request
61
+ * @param array $options
62
+ */
63
+ public function __invoke(RequestInterface $request, array $options)
64
+ {
65
+ $handler = $this->resolve();
66
+
67
+ return $handler($request, $options);
68
+ }
69
+
70
+ /**
71
+ * Dumps a string representation of the stack.
72
+ *
73
+ * @return string
74
+ */
75
+ public function __toString()
76
+ {
77
+ $depth = 0;
78
+ $stack = [];
79
+ if ($this->handler) {
80
+ $stack[] = "0) Handler: " . $this->debugCallable($this->handler);
81
+ }
82
+
83
+ $result = '';
84
+ foreach (array_reverse($this->stack) as $tuple) {
85
+ $depth++;
86
+ $str = "{$depth}) Name: '{$tuple[1]}', ";
87
+ $str .= "Function: " . $this->debugCallable($tuple[0]);
88
+ $result = "> {$str}\n{$result}";
89
+ $stack[] = $str;
90
+ }
91
+
92
+ foreach (array_keys($stack) as $k) {
93
+ $result .= "< {$stack[$k]}\n";
94
+ }
95
+
96
+ return $result;
97
+ }
98
+
99
+ /**
100
+ * Set the HTTP handler that actually returns a promise.
101
+ *
102
+ * @param callable $handler Accepts a request and array of options and
103
+ * returns a Promise.
104
+ */
105
+ public function setHandler(callable $handler)
106
+ {
107
+ $this->handler = $handler;
108
+ $this->cached = null;
109
+ }
110
+
111
+ /**
112
+ * Returns true if the builder has a handler.
113
+ *
114
+ * @return bool
115
+ */
116
+ public function hasHandler()
117
+ {
118
+ return (bool) $this->handler;
119
+ }
120
+
121
+ /**
122
+ * Unshift a middleware to the bottom of the stack.
123
+ *
124
+ * @param callable $middleware Middleware function
125
+ * @param string $name Name to register for this middleware.
126
+ */
127
+ public function unshift(callable $middleware, $name = null)
128
+ {
129
+ array_unshift($this->stack, [$middleware, $name]);
130
+ $this->cached = null;
131
+ }
132
+
133
+ /**
134
+ * Push a middleware to the top of the stack.
135
+ *
136
+ * @param callable $middleware Middleware function
137
+ * @param string $name Name to register for this middleware.
138
+ */
139
+ public function push(callable $middleware, $name = '')
140
+ {
141
+ $this->stack[] = [$middleware, $name];
142
+ $this->cached = null;
143
+ }
144
+
145
+ /**
146
+ * Add a middleware before another middleware by name.
147
+ *
148
+ * @param string $findName Middleware to find
149
+ * @param callable $middleware Middleware function
150
+ * @param string $withName Name to register for this middleware.
151
+ */
152
+ public function before($findName, callable $middleware, $withName = '')
153
+ {
154
+ $this->splice($findName, $withName, $middleware, true);
155
+ }
156
+
157
+ /**
158
+ * Add a middleware after another middleware by name.
159
+ *
160
+ * @param string $findName Middleware to find
161
+ * @param callable $middleware Middleware function
162
+ * @param string $withName Name to register for this middleware.
163
+ */
164
+ public function after($findName, callable $middleware, $withName = '')
165
+ {
166
+ $this->splice($findName, $withName, $middleware, false);
167
+ }
168
+
169
+ /**
170
+ * Remove a middleware by instance or name from the stack.
171
+ *
172
+ * @param callable|string $remove Middleware to remove by instance or name.
173
+ */
174
+ public function remove($remove)
175
+ {
176
+ $this->cached = null;
177
+ $idx = is_callable($remove) ? 0 : 1;
178
+ $this->stack = array_values(array_filter(
179
+ $this->stack,
180
+ function ($tuple) use ($idx, $remove) {
181
+ return $tuple[$idx] !== $remove;
182
+ }
183
+ ));
184
+ }
185
+
186
+ /**
187
+ * Compose the middleware and handler into a single callable function.
188
+ *
189
+ * @return callable
190
+ */
191
+ public function resolve()
192
+ {
193
+ if (!$this->cached) {
194
+ if (!($prev = $this->handler)) {
195
+ throw new \LogicException('No handler has been specified');
196
+ }
197
+
198
+ foreach (array_reverse($this->stack) as $fn) {
199
+ $prev = $fn[0]($prev);
200
+ }
201
+
202
+ $this->cached = $prev;
203
+ }
204
+
205
+ return $this->cached;
206
+ }
207
+
208
+ /**
209
+ * @param $name
210
+ * @return int
211
+ */
212
+ private function findByName($name)
213
+ {
214
+ foreach ($this->stack as $k => $v) {
215
+ if ($v[1] === $name) {
216
+ return $k;
217
+ }
218
+ }
219
+
220
+ throw new \InvalidArgumentException("Middleware not found: $name");
221
+ }
222
+
223
+ /**
224
+ * Splices a function into the middleware list at a specific position.
225
+ *
226
+ * @param $findName
227
+ * @param $withName
228
+ * @param callable $middleware
229
+ * @param $before
230
+ */
231
+ private function splice($findName, $withName, callable $middleware, $before)
232
+ {
233
+ $this->cached = null;
234
+ $idx = $this->findByName($findName);
235
+ $tuple = [$middleware, $withName];
236
+
237
+ if ($before) {
238
+ if ($idx === 0) {
239
+ array_unshift($this->stack, $tuple);
240
+ } else {
241
+ $replacement = [$tuple, $this->stack[$idx]];
242
+ array_splice($this->stack, $idx, 1, $replacement);
243
+ }
244
+ } elseif ($idx === count($this->stack) - 1) {
245
+ $this->stack[] = $tuple;
246
+ } else {
247
+ $replacement = [$this->stack[$idx], $tuple];
248
+ array_splice($this->stack, $idx, 1, $replacement);
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Provides a debug string for a given callable.
254
+ *
255
+ * @param array|callable $fn Function to write as a string.
256
+ *
257
+ * @return string
258
+ */
259
+ private function debugCallable($fn)
260
+ {
261
+ if (is_string($fn)) {
262
+ return "callable({$fn})";
263
+ }
264
+
265
+ if (is_array($fn)) {
266
+ return is_string($fn[0])
267
+ ? "callable({$fn[0]}::{$fn[1]})"
268
+ : "callable(['" . get_class($fn[0]) . "', '{$fn[1]}'])";
269
+ }
270
+
271
+ return 'callable(' . spl_object_hash($fn) . ')';
272
+ }
273
+ }
vendor/guzzlehttp/guzzle/src/MessageFormatter.php ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * - {host}: Host of the request
23
+ * - {version}: Protocol version
24
+ * - {target}: Request target of the request (path + query + fragment)
25
+ * - {hostname}: Hostname of the machine that sent the request
26
+ * - {code}: Status code of the response (if available)
27
+ * - {phrase}: Reason phrase of the response (if available)
28
+ * - {error}: Any error messages (if available)
29
+ * - {req_header_*}: Replace `*` with the lowercased name of a request header to add to the message
30
+ * - {res_header_*}: Replace `*` with the lowercased name of a response header to add to the message
31
+ * - {req_headers}: Request headers
32
+ * - {res_headers}: Response headers
33
+ * - {req_body}: Request body
34
+ * - {res_body}: Response body
35
+ */
36
+ class MessageFormatter
37
+ {
38
+ /**
39
+ * Apache Common Log Format.
40
+ * @link http://httpd.apache.org/docs/2.4/logs.html#common
41
+ * @var string
42
+ */
43
+ const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
44
+ const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
45
+ const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
46
+
47
+ /** @var string Template used to format log messages */
48
+ private $template;
49
+
50
+ /**
51
+ * @param string $template Log message template
52
+ */
53
+ public function __construct($template = self::CLF)
54
+ {
55
+ $this->template = $template ?: self::CLF;
56
+ }
57
+
58
+ /**
59
+ * Returns a formatted message string.
60
+ *
61
+ * @param RequestInterface $request Request that was sent
62
+ * @param ResponseInterface $response Response that was received
63
+ * @param \Exception $error Exception that was received
64
+ *
65
+ * @return string
66
+ */
67
+ public function format(
68
+ RequestInterface $request,
69
+ ResponseInterface $response = null,
70
+ \Exception $error = null
71
+ ) {
72
+ $cache = [];
73
+
74
+ return preg_replace_callback(
75
+ '/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
76
+ function (array $matches) use ($request, $response, $error, &$cache) {
77
+
78
+ if (isset($cache[$matches[1]])) {
79
+ return $cache[$matches[1]];
80
+ }
81
+
82
+ $result = '';
83
+ switch ($matches[1]) {
84
+ case 'request':
85
+ $result = Psr7\str($request);
86
+ break;
87
+ case 'response':
88
+ $result = $response ? Psr7\str($response) : '';
89
+ break;
90
+ case 'req_headers':
91
+ $result = trim($request->getMethod()
92
+ . ' ' . $request->getRequestTarget())
93
+ . ' HTTP/' . $request->getProtocolVersion() . "\r\n"
94
+ . $this->headers($request);
95
+ break;
96
+ case 'res_headers':
97
+ $result = $response ?
98
+ sprintf(
99
+ 'HTTP/%s %d %s',
100
+ $response->getProtocolVersion(),
101
+ $response->getStatusCode(),
102
+ $response->getReasonPhrase()
103
+ ) . "\r\n" . $this->headers($response)
104
+ : 'NULL';
105
+ break;
106
+ case 'req_body':
107
+ $result = $request->getBody();
108
+ break;
109
+ case 'res_body':
110
+ $result = $response ? $response->getBody() : 'NULL';
111
+ break;
112
+ case 'ts':
113
+ case 'date_iso_8601':
114
+ $result = gmdate('c');
115
+ break;
116
+ case 'date_common_log':
117
+ $result = date('d/M/Y:H:i:s O');
118
+ break;
119
+ case 'method':
120
+ $result = $request->getMethod();
121
+ break;
122
+ case 'version':
123
+ $result = $request->getProtocolVersion();
124
+ break;
125
+ case 'uri':
126
+ case 'url':
127
+ $result = $request->getUri();
128
+ break;
129
+ case 'target':
130
+ $result = $request->getRequestTarget();
131
+ break;
132
+ case 'req_version':
133
+ $result = $request->getProtocolVersion();
134
+ break;
135
+ case 'res_version':
136
+ $result = $response
137
+ ? $response->getProtocolVersion()
138
+ : 'NULL';
139
+ break;
140
+ case 'host':
141
+ $result = $request->getHeaderLine('Host');
142
+ break;
143
+ case 'hostname':
144
+ $result = gethostname();
145
+ break;
146
+ case 'code':
147
+ $result = $response ? $response->getStatusCode() : 'NULL';
148
+ break;
149
+ case 'phrase':
150
+ $result = $response ? $response->getReasonPhrase() : 'NULL';
151
+ break;
152
+ case 'error':
153
+ $result = $error ? $error->getMessage() : 'NULL';
154
+ break;
155
+ default:
156
+ // handle prefixed dynamic headers
157
+ if (strpos($matches[1], 'req_header_') === 0) {
158
+ $result = $request->getHeaderLine(substr($matches[1], 11));
159
+ } elseif (strpos($matches[1], 'res_header_') === 0) {
160
+ $result = $response
161
+ ? $response->getHeaderLine(substr($matches[1], 11))
162
+ : 'NULL';
163
+ }
164
+ }
165
+
166
+ $cache[$matches[1]] = $result;
167
+ return $result;
168
+ },
169
+ $this->template
170
+ );
171
+ }
172
+
173
+ private function headers(MessageInterface $message)
174
+ {
175
+ $result = '';
176
+ foreach ($message->getHeaders() as $name => $values) {
177
+ $result .= $name . ': ' . implode(', ', $values) . "\r\n";
178
+ }
179
+
180
+ return trim($result);
181
+ }
182
+ }
vendor/guzzlehttp/guzzle/src/Middleware.php ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Cookie\CookieJarInterface;
5
+ use GuzzleHttp\Exception\RequestException;
6
+ use GuzzleHttp\Promise\RejectedPromise;
7
+ use GuzzleHttp\Psr7;
8
+ use Psr\Http\Message\ResponseInterface;
9
+ use Psr\Log\LoggerInterface;
10
+ use Psr\Log\LogLevel;
11
+
12
+ /**
13
+ * Functions used to create and wrap handlers with handler middleware.
14
+ */
15
+ final class Middleware
16
+ {
17
+ /**
18
+ * Middleware that adds cookies to requests.
19
+ *
20
+ * The options array must be set to a CookieJarInterface in order to use
21
+ * cookies. This is typically handled for you by a client.
22
+ *
23
+ * @return callable Returns a function that accepts the next handler.
24
+ */
25
+ public static function cookies()
26
+ {
27
+ return function (callable $handler) {
28
+ return function ($request, array $options) use ($handler) {
29
+ if (empty($options['cookies'])) {
30
+ return $handler($request, $options);
31
+ } elseif (!($options['cookies'] instanceof CookieJarInterface)) {
32
+ throw new \InvalidArgumentException('cookies must be an instance of GuzzleHttp\Cookie\CookieJarInterface');
33
+ }
34
+ $cookieJar = $options['cookies'];
35
+ $request = $cookieJar->withCookieHeader($request);
36
+ return $handler($request, $options)
37
+ ->then(function ($response) use ($cookieJar, $request) {
38
+ $cookieJar->extractCookies($request, $response);
39
+ return $response;
40
+ }
41
+ );
42
+ };
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Middleware that throws exceptions for 4xx or 5xx responses when the
48
+ * "http_error" request option is set to true.
49
+ *
50
+ * @return callable Returns a function that accepts the next handler.
51
+ */
52
+ public static function httpErrors()
53
+ {
54
+ return function (callable $handler) {
55
+ return function ($request, array $options) use ($handler) {
56
+ if (empty($options['http_errors'])) {
57
+ return $handler($request, $options);
58
+ }
59
+ return $handler($request, $options)->then(
60
+ function (ResponseInterface $response) use ($request, $handler) {
61
+ $code = $response->getStatusCode();
62
+ if ($code < 400) {
63
+ return $response;
64
+ }
65
+ throw RequestException::create($request, $response);
66
+ }
67
+ );
68
+ };
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Middleware that pushes history data to an ArrayAccess container.
74
+ *
75
+ * @param array $container Container to hold the history (by reference).
76
+ *
77
+ * @return callable Returns a function that accepts the next handler.
78
+ * @throws \InvalidArgumentException if container is not an array or ArrayAccess.
79
+ */
80
+ public static function history(&$container)
81
+ {
82
+ if (!is_array($container) && !$container instanceof \ArrayAccess) {
83
+ throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess');
84
+ }
85
+
86
+ return function (callable $handler) use (&$container) {
87
+ return function ($request, array $options) use ($handler, &$container) {
88
+ return $handler($request, $options)->then(
89
+ function ($value) use ($request, &$container, $options) {
90
+ $container[] = [
91
+ 'request' => $request,
92
+ 'response' => $value,
93
+ 'error' => null,
94
+ 'options' => $options
95
+ ];
96
+ return $value;
97
+ },
98
+ function ($reason) use ($request, &$container, $options) {
99
+ $container[] = [
100
+ 'request' => $request,
101
+ 'response' => null,
102
+ 'error' => $reason,
103
+ 'options' => $options
104
+ ];
105
+ return \GuzzleHttp\Promise\rejection_for($reason);
106
+ }
107
+ );
108
+ };
109
+ };
110
+ }
111
+
112
+ /**
113
+ * Middleware that invokes a callback before and after sending a request.
114
+ *
115
+ * The provided listener cannot modify or alter the response. It simply
116
+ * "taps" into the chain to be notified before returning the promise. The
117
+ * before listener accepts a request and options array, and the after
118
+ * listener accepts a request, options array, and response promise.
119
+ *
120
+ * @param callable $before Function to invoke before forwarding the request.
121
+ * @param callable $after Function invoked after forwarding.
122
+ *
123
+ * @return callable Returns a function that accepts the next handler.
124
+ */
125
+ public static function tap(callable $before = null, callable $after = null)
126
+ {
127
+ return function (callable $handler) use ($before, $after) {
128
+ return function ($request, array $options) use ($handler, $before, $after) {
129
+ if ($before) {
130
+ $before($request, $options);
131
+ }
132
+ $response = $handler($request, $options);
133
+ if ($after) {
134
+ $after($request, $options, $response);
135
+ }
136
+ return $response;
137
+ };
138
+ };
139
+ }
140
+
141
+ /**
142
+ * Middleware that handles request redirects.
143
+ *
144
+ * @return callable Returns a function that accepts the next handler.
145
+ */
146
+ public static function redirect()
147
+ {
148
+ return function (callable $handler) {
149
+ return new RedirectMiddleware($handler);
150
+ };
151
+ }
152
+
153
+ /**
154
+ * Middleware that retries requests based on the boolean result of
155
+ * invoking the provided "decider" function.
156
+ *
157
+ * If no delay function is provided, a simple implementation of exponential
158
+ * backoff will be utilized.
159
+ *
160
+ * @param callable $decider Function that accepts the number of retries,
161
+ * a request, [response], and [exception] and
162
+ * returns true if the request is to be retried.
163
+ * @param callable $delay Function that accepts the number of retries and
164
+ * returns the number of milliseconds to delay.
165
+ *
166
+ * @return callable Returns a function that accepts the next handler.
167
+ */
168
+ public static function retry(callable $decider, callable $delay = null)
169
+ {
170
+ return function (callable $handler) use ($decider, $delay) {
171
+ return new RetryMiddleware($decider, $handler, $delay);
172
+ };
173
+ }
174
+
175
+ /**
176
+ * Middleware that logs requests, responses, and errors using a message
177
+ * formatter.
178
+ *
179
+ * @param LoggerInterface $logger Logs messages.
180
+ * @param MessageFormatter $formatter Formatter used to create message strings.
181
+ * @param string $logLevel Level at which to log requests.
182
+ *
183
+ * @return callable Returns a function that accepts the next handler.
184
+ */
185
+ public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO)
186
+ {
187
+ return function (callable $handler) use ($logger, $formatter, $logLevel) {
188
+ return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) {
189
+ return $handler($request, $options)->then(
190
+ function ($response) use ($logger, $request, $formatter, $logLevel) {
191
+ $message = $formatter->format($request, $response);
192
+ $logger->log($logLevel, $message);
193
+ return $response;
194
+ },
195
+ function ($reason) use ($logger, $request, $formatter) {
196
+ $response = $reason instanceof RequestException
197
+ ? $reason->getResponse()
198
+ : null;
199
+ $message = $formatter->format($request, $response, $reason);
200
+ $logger->notice($message);
201
+ return \GuzzleHttp\Promise\rejection_for($reason);
202
+ }
203
+ );
204
+ };
205
+ };
206
+ }
207
+
208
+ /**
209
+ * This middleware adds a default content-type if possible, a default
210
+ * content-length or transfer-encoding header, and the expect header.
211
+ *
212
+ * @return callable
213
+ */
214
+ public static function prepareBody()
215
+ {
216
+ return function (callable $handler) {
217
+ return new PrepareBodyMiddleware($handler);
218
+ };
219
+ }
220
+
221
+ /**
222
+ * Middleware that applies a map function to the request before passing to
223
+ * the next handler.
224
+ *
225
+ * @param callable $fn Function that accepts a RequestInterface and returns
226
+ * a RequestInterface.
227
+ * @return callable
228
+ */
229
+ public static function mapRequest(callable $fn)
230
+ {
231
+ return function (callable $handler) use ($fn) {
232
+ return function ($request, array $options) use ($handler, $fn) {
233
+ return $handler($fn($request), $options);
234
+ };
235
+ };
236
+ }
237
+
238
+ /**
239
+ * Middleware that applies a map function to the resolved promise's
240
+ * response.
241
+ *
242
+ * @param callable $fn Function that accepts a ResponseInterface and
243
+ * returns a ResponseInterface.
244
+ * @return callable
245
+ */
246
+ public static function mapResponse(callable $fn)
247
+ {
248
+ return function (callable $handler) use ($fn) {
249
+ return function ($request, array $options) use ($handler, $fn) {
250
+ return $handler($request, $options)->then($fn);
251
+ };
252
+ };
253
+ }
254
+ }
vendor/guzzlehttp/guzzle/src/Pool.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Promise\PromisorInterface;
5
+ use Psr\Http\Message\RequestInterface;
6
+ use GuzzleHttp\Promise\EachPromise;
7
+
8
+ /**
9
+ * Sends and 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
+ public function promise()
73
+ {
74
+ return $this->each->promise();
75
+ }
76
+
77
+ /**
78
+ * Sends multiple requests concurrently and returns an array of responses
79
+ * and exceptions that uses the same ordering as the provided requests.
80
+ *
81
+ * IMPORTANT: This method keeps every request and response in memory, and
82
+ * as such, is NOT recommended when sending a large number or an
83
+ * indeterminate number of requests concurrently.
84
+ *
85
+ * @param ClientInterface $client Client used to send the requests
86
+ * @param array|\Iterator $requests Requests to send concurrently.
87
+ * @param array $options Passes through the options available in
88
+ * {@see GuzzleHttp\Pool::__construct}
89
+ *
90
+ * @return array Returns an array containing the response or an exception
91
+ * in the same order that the requests were sent.
92
+ * @throws \InvalidArgumentException if the event format is incorrect.
93
+ */
94
+ public static function batch(
95
+ ClientInterface $client,
96
+ $requests,
97
+ array $options = []
98
+ ) {
99
+ $res = [];
100
+ self::cmpCallback($options, 'fulfilled', $res);
101
+ self::cmpCallback($options, 'rejected', $res);
102
+ $pool = new static($client, $requests, $options);
103
+ $pool->promise()->wait();
104
+ ksort($res);
105
+
106
+ return $res;
107
+ }
108
+
109
+ private static function cmpCallback(array &$options, $name, array &$results)
110
+ {
111
+ if (!isset($options[$name])) {
112
+ $options[$name] = function ($v, $k) use (&$results) {
113
+ $results[$k] = $v;
114
+ };
115
+ } else {
116
+ $currentFn = $options[$name];
117
+ $options[$name] = function ($v, $k) use (&$results, $currentFn) {
118
+ $currentFn($v, $k);
119
+ $results[$k] = $v;
120
+ };
121
+ }
122
+ }
123
+ }
vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php ADDED
@@ -0,0 +1,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
+ private function addExpectHeader(
70
+ RequestInterface $request,
71
+ array $options,
72
+ array &$modify
73
+ ) {
74
+ // Determine if the Expect header should be used
75
+ if ($request->hasHeader('Expect')) {
76
+ return;
77
+ }
78
+
79
+ $expect = isset($options['expect']) ? $options['expect'] : null;
80
+
81
+ // Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0
82
+ if ($expect === false || $request->getProtocolVersion() < 1.1) {
83
+ return;
84
+ }
85
+
86
+ // The expect header is unconditionally enabled
87
+ if ($expect === true) {
88
+ $modify['set_headers']['Expect'] = '100-Continue';
89
+ return;
90
+ }
91
+
92
+ // By default, send the expect header when the payload is > 1mb
93
+ if ($expect === null) {
94
+ $expect = 1048576;
95
+ }
96
+
97
+ // Always add if the body cannot be rewound, the size cannot be
98
+ // determined, or the size is greater than the cutoff threshold
99
+ $body = $request->getBody();
100
+ $size = $body->getSize();
101
+
102
+ if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {
103
+ $modify['set_headers']['Expect'] = '100-Continue';
104
+ }
105
+ }
106
+ }
vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php ADDED
@@ -0,0 +1,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|PromiseInterface $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
+ private function withTracking(PromiseInterface $promise, $uri, $statusCode)
122
+ {
123
+ return $promise->then(
124
+ function (ResponseInterface $response) use ($uri, $statusCode) {
125
+ // Note that we are pushing to the front of the list as this
126
+ // would be an earlier response than what is currently present
127
+ // in the history header.
128
+ $historyHeader = $response->getHeader(self::HISTORY_HEADER);
129
+ $statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER);
130
+ array_unshift($historyHeader, $uri);
131
+ array_unshift($statusHeader, $statusCode);
132
+ return $response->withHeader(self::HISTORY_HEADER, $historyHeader)
133
+ ->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader);
134
+ }
135
+ );
136
+ }
137
+
138
+ private function guardMax(RequestInterface $request, array &$options)
139
+ {
140
+ $current = isset($options['__redirect_count'])
141
+ ? $options['__redirect_count']
142
+ : 0;
143
+ $options['__redirect_count'] = $current + 1;
144
+ $max = $options['allow_redirects']['max'];
145
+
146
+ if ($options['__redirect_count'] > $max) {
147
+ throw new TooManyRedirectsException(
148
+ "Will not follow more than {$max} redirects",
149
+ $request
150
+ );
151
+ }
152
+ }
153
+
154
+ /**
155
+ * @param RequestInterface $request
156
+ * @param array $options
157
+ * @param ResponseInterface $response
158
+ *
159
+ * @return RequestInterface
160
+ */
161
+ public function modifyRequest(
162
+ RequestInterface $request,
163
+ array $options,
164
+ ResponseInterface $response
165
+ ) {
166
+ // Request modifications to apply.
167
+ $modify = [];
168
+ $protocols = $options['allow_redirects']['protocols'];
169
+
170
+ // Use a GET request if this is an entity enclosing request and we are
171
+ // not forcing RFC compliance, but rather emulating what all browsers
172
+ // would do.
173
+ $statusCode = $response->getStatusCode();
174
+ if ($statusCode == 303 ||
175
+ ($statusCode <= 302 && $request->getBody() && !$options['allow_redirects']['strict'])
176
+ ) {
177
+ $modify['method'] = 'GET';
178
+ $modify['body'] = '';
179
+ }
180
+
181
+ $modify['uri'] = $this->redirectUri($request, $response, $protocols);
182
+ Psr7\rewind_body($request);
183
+
184
+ // Add the Referer header if it is told to do so and only
185
+ // add the header if we are not redirecting from https to http.
186
+ if ($options['allow_redirects']['referer']
187
+ && $modify['uri']->getScheme() === $request->getUri()->getScheme()
188
+ ) {
189
+ $uri = $request->getUri()->withUserInfo('', '');
190
+ $modify['set_headers']['Referer'] = (string) $uri;
191
+ } else {
192
+ $modify['remove_headers'][] = 'Referer';
193
+ }
194
+
195
+ // Remove Authorization header if host is different.
196
+ if ($request->getUri()->getHost() !== $modify['uri']->getHost()) {
197
+ $modify['remove_headers'][] = 'Authorization';
198
+ }
199
+
200
+ return Psr7\modify_request($request, $modify);
201
+ }
202
+
203
+ /**
204
+ * Set the appropriate URL on the request based on the location header
205
+ *
206
+ * @param RequestInterface $request
207
+ * @param ResponseInterface $response
208
+ * @param array $protocols
209
+ *
210
+ * @return UriInterface
211
+ */
212
+ private function redirectUri(
213
+ RequestInterface $request,
214
+ ResponseInterface $response,
215
+ array $protocols
216
+ ) {
217
+ $location = Psr7\UriResolver::resolve(
218
+ $request->getUri(),
219
+ new Psr7\Uri($response->getHeaderLine('Location'))
220
+ );
221
+
222
+ // Ensure that the redirect URI is allowed based on the protocols.
223
+ if (!in_array($location->getScheme(), $protocols)) {
224
+ throw new BadResponseException(
225
+ sprintf(
226
+ 'Redirect URI, %s, does not use one of the allowed redirect protocols: %s',
227
+ $location,
228
+ implode(', ', $protocols)
229
+ ),
230
+ $request,
231
+ $response
232
+ );
233
+ }
234
+
235
+ return $location;
236
+ }
237
+ }
vendor/guzzlehttp/guzzle/src/RequestOptions.php ADDED
@@ -0,0 +1,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=true) Set to false to disable 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
+ * json: (mixed) Adds JSON data to a request. The provided value is JSON
137
+ * encoded and a Content-Type header of application/json will be added to
138
+ * the request if no Content-Type header is already present.
139
+ */
140
+ const JSON = 'json';
141
+
142
+ /**
143
+ * multipart: (array) Array of associative arrays, each containing a
144
+ * required "name" key mapping to the form field, name, a required
145
+ * "contents" key mapping to a StreamInterface|resource|string, an
146
+ * optional "headers" associative array of custom headers, and an
147
+ * optional "filename" key mapping to a string to send as the filename in
148
+ * the part. If no "filename" key is present, then no "filename" attribute
149
+ * will be added to the part.
150
+ */
151
+ const MULTIPART = 'multipart';
152
+
153
+ /**
154
+ * on_headers: (callable) A callable that is invoked when the HTTP headers
155
+ * of the response have been received but the body has not yet begun to
156
+ * download.
157
+ */
158
+ const ON_HEADERS = 'on_headers';
159
+
160
+ /**
161
+ * on_stats: (callable) allows you to get access to transfer statistics of
162
+ * a request and access the lower level transfer details of the handler
163
+ * associated with your client. ``on_stats`` is a callable that is invoked
164
+ * when a handler has finished sending a request. The callback is invoked
165
+ * with transfer statistics about the request, the response received, or
166
+ * the error encountered. Included in the data is the total amount of time
167
+ * taken to send the request.
168
+ */
169
+ const ON_STATS = 'on_stats';
170
+
171
+ /**
172
+ * progress: (callable) Defines a function to invoke when transfer
173
+ * progress is made. The function accepts the following positional
174
+ * arguments: the total number of bytes expected to be downloaded, the
175
+ * number of bytes downloaded so far, the number of bytes expected to be
176
+ * uploaded, the number of bytes uploaded so far.
177
+ */
178
+ const PROGRESS = 'progress';
179
+
180
+ /**
181
+ * proxy: (string|array) Pass a string to specify an HTTP proxy, or an
182
+ * array to specify different proxies for different protocols (where the
183
+ * key is the protocol and the value is a proxy string).
184
+ */
185
+ const PROXY = 'proxy';
186
+
187
+ /**
188
+ * query: (array|string) Associative array of query string values to add
189
+ * to the request. This option uses PHP's http_build_query() to create
190
+ * the string representation. Pass a string value if you need more
191
+ * control than what this method provides
192
+ */
193
+ const QUERY = 'query';
194
+
195
+ /**
196
+ * sink: (resource|string|StreamInterface) Where the data of the
197
+ * response is written to. Defaults to a PHP temp stream. Providing a
198
+ * string will write data to a file by the given name.
199
+ */
200
+ const SINK = 'sink';
201
+
202
+ /**
203
+ * synchronous: (bool) Set to true to inform HTTP handlers that you intend
204
+ * on waiting on the response. This can be useful for optimizations. Note
205
+ * that a promise is still returned if you are using one of the async
206
+ * client methods.
207
+ */
208
+ const SYNCHRONOUS = 'synchronous';
209
+
210
+ /**
211
+ * ssl_key: (array|string) Specify the path to a file containing a private
212
+ * SSL key in PEM format. If a password is required, then set to an array
213
+ * containing the path to the SSL key in the first array element followed
214
+ * by the password required for the certificate in the second element.
215
+ */
216
+ const SSL_KEY = 'ssl_key';
217
+
218
+ /**
219
+ * stream: Set to true to attempt to stream a response rather than
220
+ * download it all up-front.
221
+ */
222
+ const STREAM = 'stream';
223
+
224
+ /**
225
+ * verify: (bool|string, default=true) Describes the SSL certificate
226
+ * verification behavior of a request. Set to true to enable SSL
227
+ * certificate verification using the system CA bundle when available
228
+ * (the default). Set to false to disable certificate verification (this
229
+ * is insecure!). Set to a string to provide the path to a CA bundle on
230
+ * disk to enable verification using a custom certificate.
231
+ */
232
+ const VERIFY = 'verify';
233
+
234
+ /**
235
+ * timeout: (float, default=0) Float describing the timeout of the
236
+ * request in seconds. Use 0 to wait indefinitely (the default behavior).
237
+ */
238
+ const TIMEOUT = 'timeout';
239
+
240
+ /**
241
+ * read_timeout: (float, default=default_socket_timeout ini setting) Float describing
242
+ * the body read timeout, for stream requests.
243
+ */
244
+ const READ_TIMEOUT = 'read_timeout';
245
+
246
+ /**
247
+ * version: (float) Specifies the HTTP protocol version to attempt to use.
248
+ */
249
+ const VERSION = 'version';
250
+
251
+ /**
252
+ * force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol
253
+ */
254
+ const FORCE_IP_RESOLVE = 'force_ip_resolve';
255
+ }
vendor/guzzlehttp/guzzle/src/RetryMiddleware.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ /**
23
+ * @param callable $decider Function that accepts the number of retries,
24
+ * a request, [response], and [exception] and
25
+ * returns true if the request is to be
26
+ * retried.
27
+ * @param callable $nextHandler Next handler to invoke.
28
+ * @param callable $delay Function that accepts the number of retries
29
+ * and [response] and returns the number of
30
+ * milliseconds to delay.
31
+ */
32
+ public function __construct(
33
+ callable $decider,
34
+ callable $nextHandler,
35
+ callable $delay = null
36
+ ) {
37
+ $this->decider = $decider;
38
+ $this->nextHandler = $nextHandler;
39
+ $this->delay = $delay ?: __CLASS__ . '::exponentialDelay';
40
+ }
41
+
42
+ /**
43
+ * Default exponential backoff delay function.
44
+ *
45
+ * @param $retries
46
+ *
47
+ * @return int
48
+ */
49
+ public static function exponentialDelay($retries)
50
+ {
51
+ return (int) pow(2, $retries - 1);
52
+ }
53
+
54
+ /**
55
+ * @param RequestInterface $request
56
+ * @param array $options
57
+ *
58
+ * @return PromiseInterface
59
+ */
60
+ public function __invoke(RequestInterface $request, array $options)
61
+ {
62
+ if (!isset($options['retries'])) {
63
+ $options['retries'] = 0;
64
+ }
65
+
66
+ $fn = $this->nextHandler;
67
+ return $fn($request, $options)
68
+ ->then(
69
+ $this->onFulfilled($request, $options),
70
+ $this->onRejected($request, $options)
71
+ );
72
+ }
73
+
74
+ private function onFulfilled(RequestInterface $req, array $options)
75
+ {
76
+ return function ($value) use ($req, $options) {
77
+ if (!call_user_func(
78
+ $this->decider,
79
+ $options['retries'],
80
+ $req,
81
+ $value,
82
+ null
83
+ )) {
84
+ return $value;
85
+ }
86
+ return $this->doRetry($req, $options, $value);
87
+ };
88
+ }
89
+
90
+ private function onRejected(RequestInterface $req, array $options)
91
+ {
92
+ return function ($reason) use ($req, $options) {
93
+ if (!call_user_func(
94
+ $this->decider,
95
+ $options['retries'],
96
+ $req,
97
+ null,
98
+ $reason
99
+ )) {
100
+ return \GuzzleHttp\Promise\rejection_for($reason);
101
+ }
102
+ return $this->doRetry($req, $options);
103
+ };
104
+ }
105
+
106
+ private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null)
107
+ {
108
+ $options['delay'] = call_user_func($this->delay, ++$options['retries'], $response);
109
+
110
+ return $this($request, $options);
111
+ }
112
+ }
vendor/guzzlehttp/guzzle/src/TransferStats.php ADDED
@@ -0,0 +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 $request Request that was sent.
22
+ * @param ResponseInterface $response Response received (if any)
23
+ * @param 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 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/UriTemplate.php ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ /**
5
+ * Expands URI templates. Userland implementation of PECL uri_template.
6
+ *
7
+ * @link http://tools.ietf.org/html/rfc6570
8
+ */
9
+ class UriTemplate
10
+ {
11
+ /** @var string URI template */
12
+ private $template;
13
+
14
+ /** @var array Variables to use in the template expansion */
15
+ private $variables;
16
+
17
+ /** @var array Hash for quick operator lookups */
18
+ private static $operatorHash = [
19
+ '' => ['prefix' => '', 'joiner' => ',', 'query' => false],
20
+ '+' => ['prefix' => '', 'joiner' => ',', 'query' => false],
21
+ '#' => ['prefix' => '#', 'joiner' => ',', 'query' => false],
22
+ '.' => ['prefix' => '.', 'joiner' => '.', 'query' => false],
23
+ '/' => ['prefix' => '/', 'joiner' => '/', 'query' => false],
24
+ ';' => ['prefix' => ';', 'joiner' => ';', 'query' => true],
25
+ '?' => ['prefix' => '?', 'joiner' => '&', 'query' => true],
26
+ '&' => ['prefix' => '&', 'joiner' => '&', 'query' => true]
27
+ ];
28
+
29
+ /** @var array Delimiters */
30
+ private static $delims = [':', '/', '?', '#', '[', ']', '@', '!', '$',
31
+ '&', '\'', '(', ')', '*', '+', ',', ';', '='];
32
+
33
+ /** @var array Percent encoded delimiters */
34
+ private static $delimsPct = ['%3A', '%2F', '%3F', '%23', '%5B', '%5D',
35
+ '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C',
36
+ '%3B', '%3D'];
37
+
38
+ public function expand($template, array $variables)
39
+ {
40
+ if (false === strpos($template, '{')) {
41
+ return $template;
42
+ }
43
+
44
+ $this->template = $template;
45
+ $this->variables = $variables;
46
+
47
+ return preg_replace_callback(
48
+ '/\{([^\}]+)\}/',
49
+ [$this, 'expandMatch'],
50
+ $this->template
51
+ );
52
+ }
53
+
54
+ /**
55
+ * Parse an expression into parts
56
+ *
57
+ * @param string $expression Expression to parse
58
+ *
59
+ * @return array Returns an associative array of parts
60
+ */
61
+ private function parseExpression($expression)
62
+ {
63
+ $result = [];
64
+
65
+ if (isset(self::$operatorHash[$expression[0]])) {
66
+ $result['operator'] = $expression[0];
67
+ $expression = substr($expression, 1);
68
+ } else {
69
+ $result['operator'] = '';
70
+ }
71
+
72
+ foreach (explode(',', $expression) as $value) {
73
+ $value = trim($value);
74
+ $varspec = [];
75
+ if ($colonPos = strpos($value, ':')) {
76
+ $varspec['value'] = substr($value, 0, $colonPos);
77
+ $varspec['modifier'] = ':';
78
+ $varspec['position'] = (int) substr($value, $colonPos + 1);
79
+ } elseif (substr($value, -1) === '*') {
80
+ $varspec['modifier'] = '*';
81
+ $varspec['value'] = substr($value, 0, -1);
82
+ } else {
83
+ $varspec['value'] = (string) $value;
84
+ $varspec['modifier'] = '';
85
+ }
86
+ $result['values'][] = $varspec;
87
+ }
88
+
89
+ return $result;
90
+ }
91
+
92
+ /**
93
+ * Process an expansion
94
+ *
95
+ * @param array $matches Matches met in the preg_replace_callback
96
+ *
97
+ * @return string Returns the replacement string
98
+ */
99
+ private function expandMatch(array $matches)
100
+ {
101
+ static $rfc1738to3986 = ['+' => '%20', '%7e' => '~'];
102
+
103
+ $replacements = [];
104
+ $parsed = self::parseExpression($matches[1]);
105
+ $prefix = self::$operatorHash[$parsed['operator']]['prefix'];
106
+ $joiner = self::$operatorHash[$parsed['operator']]['joiner'];
107
+ $useQuery = self::$operatorHash[$parsed['operator']]['query'];
108
+
109
+ foreach ($parsed['values'] as $value) {
110
+
111
+ if (!isset($this->variables[$value['value']])) {
112
+ continue;
113
+ }
114
+
115
+ $variable = $this->variables[$value['value']];
116
+ $actuallyUseQuery = $useQuery;
117
+ $expanded = '';
118
+
119
+ if (is_array($variable)) {
120
+
121
+ $isAssoc = $this->isAssoc($variable);
122
+ $kvp = [];
123
+ foreach ($variable as $key => $var) {
124
+
125
+ if ($isAssoc) {
126
+ $key = rawurlencode($key);
127
+ $isNestedArray = is_array($var);
128
+ } else {
129
+ $isNestedArray = false;
130
+ }
131
+
132
+ if (!$isNestedArray) {
133
+ $var = rawurlencode($var);
134
+ if ($parsed['operator'] === '+' ||
135
+ $parsed['operator'] === '#'
136
+ ) {
137
+ $var = $this->decodeReserved($var);
138
+ }
139
+ }
140
+
141
+ if ($value['modifier'] === '*') {
142
+ if ($isAssoc) {
143
+ if ($isNestedArray) {
144
+ // Nested arrays must allow for deeply nested
145
+ // structures.
146
+ $var = strtr(
147
+ http_build_query([$key => $var]),
148
+ $rfc1738to3986
149
+ );
150
+ } else {
151
+ $var = $key . '=' . $var;
152
+ }
153
+ } elseif ($key > 0 && $actuallyUseQuery) {
154
+ $var = $value['value'] . '=' . $var;
155
+ }
156
+ }
157
+
158
+ $kvp[$key] = $var;
159
+ }
160
+
161
+ if (empty($variable)) {
162
+ $actuallyUseQuery = false;
163
+ } elseif ($value['modifier'] === '*') {
164
+ $expanded = implode($joiner, $kvp);
165
+ if ($isAssoc) {
166
+ // Don't prepend the value name when using the explode
167
+ // modifier with an associative array.
168
+ $actuallyUseQuery = false;
169
+ }
170
+ } else {
171
+ if ($isAssoc) {
172
+ // When an associative array is encountered and the
173
+ // explode modifier is not set, then the result must be
174
+ // a comma separated list of keys followed by their
175
+ // respective values.
176
+ foreach ($kvp as $k => &$v) {
177
+ $v = $k . ',' . $v;
178
+ }
179
+ }
180
+ $expanded = implode(',', $kvp);
181
+ }
182
+
183
+ } else {
184
+ if ($value['modifier'] === ':') {
185
+ $variable = substr($variable, 0, $value['position']);
186
+ }
187
+ $expanded = rawurlencode($variable);
188
+ if ($parsed['operator'] === '+' || $parsed['operator'] === '#') {
189
+ $expanded = $this->decodeReserved($expanded);
190
+ }
191
+ }
192
+
193
+ if ($actuallyUseQuery) {
194
+ if (!$expanded && $joiner !== '&') {
195
+ $expanded = $value['value'];
196
+ } else {
197
+ $expanded = $value['value'] . '=' . $expanded;
198
+ }
199
+ }
200
+
201
+ $replacements[] = $expanded;
202
+ }
203
+
204
+ $ret = implode($joiner, $replacements);
205
+ if ($ret && $prefix) {
206
+ return $prefix . $ret;
207
+ }
208
+
209
+ return $ret;
210
+ }
211
+
212
+ /**
213
+ * Determines if an array is associative.
214
+ *
215
+ * This makes the assumption that input arrays are sequences or hashes.
216
+ * This assumption is a tradeoff for accuracy in favor of speed, but it
217
+ * should work in almost every case where input is supplied for a URI
218
+ * template.
219
+ *
220
+ * @param array $array Array to check
221
+ *
222
+ * @return bool
223
+ */
224
+ private function isAssoc(array $array)
225
+ {
226
+ return $array && array_keys($array)[0] !== 0;
227
+ }
228
+
229
+ /**
230
+ * Removes percent encoding on reserved characters (used with + and #
231
+ * modifiers).
232
+ *
233
+ * @param string $string String to fix
234
+ *
235
+ * @return string
236
+ */
237
+ private function decodeReserved($string)
238
+ {
239
+ return str_replace(self::$delimsPct, self::$delims, $string);
240
+ }
241
+ }
vendor/guzzlehttp/guzzle/src/functions.php ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 array $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(<<< EOT
200
+ No system CA bundle could be found in any of the the common system locations.
201
+ PHP versions earlier than 5.6 are not properly configured to use the system's
202
+ CA bundle by default. In order to verify peer certificates, you will need to
203
+ supply the path on disk to a certificate bundle to the 'verify' request
204
+ option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not
205
+ need a specific certificate bundle, then Mozilla provides a commonly used CA
206
+ bundle which can be downloaded here (provided by the maintainer of cURL):
207
+ https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once
208
+ you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP
209
+ ini setting to point to the path to the file, allowing you to omit the 'verify'
210
+ request option. See http://curl.haxx.se/docs/sslcerts.html for more
211
+ information.
212
+ EOT
213
+ );
214
+ }
215
+
216
+ /**
217
+ * Creates an associative array of lowercase header names to the actual
218
+ * header casing.
219
+ *
220
+ * @param array $headers
221
+ *
222
+ * @return array
223
+ */
224
+ function normalize_header_keys(array $headers)
225
+ {
226
+ $result = [];
227
+ foreach (array_keys($headers) as $key) {
228
+ $result[strtolower($key)] = $key;
229
+ }
230
+
231
+ return $result;
232
+ }
233
+
234
+ /**
235
+ * Returns true if the provided host matches any of the no proxy areas.
236
+ *
237
+ * This method will strip a port from the host if it is present. Each pattern
238
+ * can be matched with an exact match (e.g., "foo.com" == "foo.com") or a
239
+ * partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" ==
240
+ * "baz.foo.com", but ".foo.com" != "foo.com").
241
+ *
242
+ * Areas are matched in the following cases:
243
+ * 1. "*" (without quotes) always matches any hosts.
244
+ * 2. An exact match.
245
+ * 3. The area starts with "." and the area is the last part of the host. e.g.
246
+ * '.mit.edu' will match any host that ends with '.mit.edu'.
247
+ *
248
+ * @param string $host Host to check against the patterns.
249
+ * @param array $noProxyArray An array of host patterns.
250
+ *
251
+ * @return bool
252
+ */
253
+ function is_host_in_noproxy($host, array $noProxyArray)
254
+ {
255
+ if (strlen($host) === 0) {
256
+ throw new \InvalidArgumentException('Empty host provided');
257
+ }
258
+
259
+ // Strip port if present.
260
+ if (strpos($host, ':')) {
261
+ $host = explode($host, ':', 2)[0];
262
+ }
263
+
264
+ foreach ($noProxyArray as $area) {
265
+ // Always match on wildcards.
266
+ if ($area === '*') {
267
+ return true;
268
+ } elseif (empty($area)) {
269
+ // Don't match on empty values.
270
+ continue;
271
+ } elseif ($area === $host) {
272
+ // Exact matches.
273
+ return true;
274
+ } else {
275
+ // Special match if the area when prefixed with ".". Remove any
276
+ // existing leading "." and add a new leading ".".
277
+ $area = '.' . ltrim($area, '.');
278
+ if (substr($host, -(strlen($area))) === $area) {
279
+ return true;
280
+ }
281
+ }
282
+ }
283
+
284
+ return false;
285
+ }
286
+
287
+ /**
288
+ * Wrapper for json_decode that throws when an error occurs.
289
+ *
290
+ * @param string $json JSON data to parse
291
+ * @param bool $assoc When true, returned objects will be converted
292
+ * into associative arrays.
293
+ * @param int $depth User specified recursion depth.
294
+ * @param int $options Bitmask of JSON decode options.
295
+ *
296
+ * @return mixed
297
+ * @throws \InvalidArgumentException if the JSON cannot be decoded.
298
+ * @link http://www.php.net/manual/en/function.json-decode.php
299
+ */
300
+ function json_decode($json, $assoc = false, $depth = 512, $options = 0)
301
+ {
302
+ $data = \json_decode($json, $assoc, $depth, $options);
303
+ if (JSON_ERROR_NONE !== json_last_error()) {
304
+ throw new \InvalidArgumentException(
305
+ 'json_decode error: ' . json_last_error_msg());
306
+ }
307
+
308
+ return $data;
309
+ }
310
+
311
+ /**
312
+ * Wrapper for JSON encoding that throws when an error occurs.
313
+ *
314
+ * @param mixed $value The value being encoded
315
+ * @param int $options JSON encode option bitmask
316
+ * @param int $depth Set the maximum depth. Must be greater than zero.
317
+ *
318
+ * @return string
319
+ * @throws \InvalidArgumentException if the JSON cannot be encoded.
320
+ * @link http://www.php.net/manual/en/function.json-encode.php
321
+ */
322
+ function json_encode($value, $options = 0, $depth = 512)
323
+ {
324
+ $json = \json_encode($value, $options, $depth);
325
+ if (JSON_ERROR_NONE !== json_last_error()) {
326
+ throw new \InvalidArgumentException(
327
+ 'json_encode error: ' . json_last_error_msg());
328
+ }
329
+
330
+ return $json;
331
+ }
vendor/guzzlehttp/guzzle/src/functions_include.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Don't redefine the functions if included multiple times.
4
+ if (!function_exists('GuzzleHttp\uri_template')) {
5
+ require __DIR__ . '/functions.php';
6
+ }
vendor/guzzlehttp/promises/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2015-2016 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
vendor/guzzlehttp/promises/src/AggregateException.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Promise;
3
+
4
+ /**
5
+ * Exception thrown when too many errors occur in the some() or any() methods.
6
+ */
7
+ class AggregateException extends RejectionException
8
+ {
9
+ public function __construct($msg, array $reasons)
10
+ {
11
+ parent::__construct(
12
+ $reasons,
13
+ sprintf('%s; %d rejected promises', $msg, count($reasons))
14
+ );
15
+ }
16
+ }
vendor/guzzlehttp/promises/src/CancellationException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Promise;
3
+
4
+ /**
5
+ * Exception that is set as the reason for a promise that has been cancelled.
6
+ */
7
+ class CancellationException extends RejectionException
8
+ {
9
+ }
vendor/guzzlehttp/promises/src/Coroutine.php ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Promise;
3
+
4
+ use Exception;
5
+ use Generator;
6
+ use Throwable;
7
+
8
+ /**
9
+ * Creates a promise that is resolved using a generator that yields values or
10
+ * promises (somewhat similar to C#'s async keyword).
11
+ *
12
+ * When called, the coroutine function will start an instance of the generator
13
+ * and returns a promise that is fulfilled with its final yielded value.
14
+ *
15
+ * Control is returned back to the generator when the yielded promise settles.
16
+ * This can lead to less verbose code when doing lots of sequential async calls
17
+ * with minimal processing in between.
18
+ *
19
+ * use GuzzleHttp\Promise;
20
+ *
21
+ * function createPromise($value) {
22
+ * return new Promise\FulfilledPromise($value);
23
+ * }
24
+ *
25
+ * $promise = Promise\coroutine(function () {
26
+ * $value = (yield createPromise('a'));
27
+ * try {
28
+ * $value = (yield createPromise($value . 'b'));
29
+ * } catch (\Exception $e) {
30
+ * // The promise was rejected.
31
+ * }
32
+ * yield $value . 'c';
33
+ * });
34
+ *
35
+ * // Outputs "abc"
36
+ * $promise->then(function ($v) { echo $v; });
37
+ *
38
+ * @param callable $generatorFn Generator function to wrap into a promise.
39
+ *
40
+ * @return Promise
41
+ * @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
42
+ */
43
+ final class Coroutine implements PromiseInterface
44
+ {
45
+ /**
46
+ * @var PromiseInterface|null
47
+ */
48
+ private $currentPromise;
49
+
50
+ /**
51
+ * @var Generator
52
+ */
53
+ private $generator;
54
+
55
+ /**
56
+ * @var Promise
57
+ */
58
+ private $result;
59
+
60
+ public function __construct(callable $generatorFn)
61
+ {
62
+ $this->generator = $generatorFn();
63
+ $this->result = new Promise(function () {
64
+ while (isset($this->currentPromise)) {
65
+ $this->currentPromise->wait();
66
+ }
67
+ });
68
+ $this->nextCoroutine($this->generator->current());
69
+ }
70
+
71
+ public function then(
72
+ callable $onFulfilled = null,
73
+ callable $onRejected = null
74
+ ) {
75
+ return $this->result->then($onFulfilled, $onRejected);
76
+ }
77
+
78
+ public function otherwise(callable $onRejected)
79
+ {
80
+ return $this->result->otherwise($onRejected);
81
+ }
82
+
83
+ public function wait($unwrap = true)
84
+ {
85
+ return $this->result->wait($unwrap);
86
+ }
87
+
88
+ public function getState()
89
+ {
90
+ return $this->result->getState();
91
+ }
92
+
93
+ public function resolve($value)
94
+ {
95
+ $this->result->resolve($value);
96
+ }
97
+
98
+ public function reject($reason)
99
+ {
100
+ $this->result->reject($reason);
101
+ }
102
+
103
+ public function cancel()
104
+ {
105
+ $this->currentPromise->cancel();
106
+ $this->result->cancel();
107
+ }
108
+
109
+ private function nextCoroutine($yielded)
110
+ {
111
+ $this->currentPromise = promise_for($yielded)
112
+ ->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
113
+ }
114
+
115
+ /**
116
+ * @internal
117
+ */
118
+ public function _handleSuccess($value)
119
+ {
120
+ unset($this->currentPromise);
121
+ try {
122
+ $next = $this->generator->send($value);
123
+ if ($this->generator->valid()) {
124
+ $this->nextCoroutine($next);
125
+ } else {
126
+ $this->result->resolve($value);
127
+ }
128
+ } catch (Exception $exception) {
129
+ $this->result->reject($exception);
130
+ } catch (Throwable $throwable) {
131
+ $this->result->reject($throwable);
132
+ }
133
+ }
134
+
135
+ /**
136
+ * @internal
137
+ */
138
+ public function _handleFailure($reason)
139
+ {
140
+ unset($this->currentPromise);
141
+ try {
142
+ $nextYield = $this->generator->throw(exception_for($reason));
143
+ // The throw was caught, so keep iterating on the coroutine
144
+ $this->nextCoroutine($nextYield);
145
+ } catch (Exception $exception) {
146
+ $this->result->reject($exception);
147
+ } catch (Throwable $throwable) {
148
+ $this->result->reject($throwable);
149
+ }
150
+ }
151
+ }
vendor/guzzlehttp/promises/src/EachPromise.php ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Promise;
3
+
4
+ /**
5
+ * Represents a promise that iterates over many promises and invokes
6
+ * side-effect functions in the process.
7
+ */
8
+ class EachPromise implements PromisorInterface
9
+ {
10
+ private $pending = [];
11
+
12
+ /** @var \Iterator */
13
+ private $iterable;
14
+
15
+ /** @var callable|int */
16
+ private $concurrency;
17
+
18
+ /** @var callable */
19
+ private $onFulfilled;
20
+
21
+ /** @var callable */
22
+ private $onRejected;
23
+
24
+ /** @var Promise */
25
+ private $aggregate;
26
+
27
+ /** @var bool */
28
+ private $mutex;
29
+
30
+ /**
31
+ * Configuration hash can include the following key value pairs:
32
+ *
33
+ * - fulfilled: (callable) Invoked when a promise fulfills. The function
34
+ * is invoked with three arguments: the fulfillment value, the index
35
+ * position from the iterable list of the promise, and the aggregate
36
+ * promise that manages all of the promises. The aggregate promise may
37
+ * be resolved from within the callback to short-circuit the promise.
38
+ * - rejected: (callable) Invoked when a promise is rejected. The
39
+ * function is invoked with three arguments: the rejection reason, the
40
+ * index position from the iterable list of the promise, and the
41
+ * aggregate promise that manages all of the promises. The aggregate
42
+ * promise may be resolved from within the callback to short-circuit
43
+ * the promise.
44
+ * - concurrency: (integer) Pass this configuration option to limit the
45
+ * allowed number of outstanding concurrently executing promises,
46
+ * creating a capped pool of promises. There is no limit by default.
47
+ *
48
+ * @param mixed $iterable Promises or values to iterate.
49
+ * @param array $config Configuration options
50
+ */
51
+ public function __construct($iterable, array $config = [])
52
+ {
53
+ $this->iterable = iter_for($iterable);
54
+
55
+ if (isset($config['concurrency'])) {
56
+ $this->concurrency = $config['concurrency'];
57
+ }
58
+
59
+ if (isset($config['fulfilled'])) {
60
+ $this->onFulfilled = $config['fulfilled'];
61
+ }
62
+
63
+ if (isset($config['rejected'])) {
64
+ $this->onRejected = $config['rejected'];
65
+ }
66
+ }
67
+
68
+ public function promise()
69
+ {
70
+ if ($this->aggregate) {
71
+ return $this->aggregate;
72
+ }
73
+
74
+ try {
75
+ $this->createPromise();
76
+ $this->iterable->rewind();
77
+ $this->refillPending();
78
+ } catch (\Throwable $e) {
79
+ $this->aggregate->reject($e);
80
+ } catch (\Exception $e) {
81
+ $this->aggregate->reject($e);
82
+ }
83
+
84
+ return $this->aggregate;
85
+ }
86
+
87
+ private function createPromise()
88
+ {
89
+ $this->mutex = false;
90
+ $this->aggregate = new Promise(function () {
91
+ reset($this->pending);
92
+ if (empty($this->pending) && !$this->iterable->valid()) {
93
+ $this->aggregate->resolve(null);
94
+ return;
95
+ }
96
+
97
+ // Consume a potentially fluctuating list of promises while
98
+ // ensuring that indexes are maintained (precluding array_shift).
99
+ while ($promise = current($this->pending)) {
100
+ next($this->pending);
101
+ $promise->wait();
102
+ if ($this->aggregate->getState() !== PromiseInterface::PENDING) {
103
+ return;
104
+ }
105
+ }
106
+ });
107
+
108
+ // Clear the references when the promise is resolved.
109
+ $clearFn = function () {
110
+ $this->iterable = $this->concurrency = $this->pending = null;
111
+ $this->onFulfilled = $this->onRejected = null;
112
+ };
113
+
114
+ $this->aggregate->then($clearFn, $clearFn);
115
+ }
116
+
117
+ private function refillPending()
118
+ {
119
+ if (!$this->concurrency) {
120
+ // Add all pending promises.
121
+ while ($this->addPending() && $this->advanceIterator());
122
+ return;
123
+ }
124
+
125
+ // Add only up to N pending promises.
126
+ $concurrency = is_callable($this->concurrency)
127
+ ? call_user_func($this->concurrency, count($this->pending))
128
+ : $this->concurrency;
129
+ $concurrency = max($concurrency - count($this->pending), 0);
130
+ // Concurrency may be set to 0 to disallow new promises.
131
+ if (!$concurrency) {
132
+ return;
133
+ }
134
+ // Add the first pending promise.
135
+ $this->addPending();
136
+ // Note this is special handling for concurrency=1 so that we do
137
+ // not advance the iterator after adding the first promise. This
138
+ // helps work around issues with generators that might not have the
139
+ // next value to yield until promise callbacks are called.
140
+ while (--$concurrency
141
+ && $this->advanceIterator()
142
+ && $this->addPending());
143
+ }
144
+
145
+ private function addPending()
146
+ {
147
+ if (!$this->iterable || !$this->iterable->valid()) {
148
+ return false;
149
+ }
150
+
151
+ $promise = promise_for($this->iterable->current());
152
+ $idx = $this->iterable->key();
153
+
154
+ $this->pending[$idx] = $promise->then(
155
+ function ($value) use ($idx) {
156
+ if ($this->onFulfilled) {
157
+ call_user_func(
158
+ $this->onFulfilled, $value, $idx, $this->aggregate
159
+ );
160
+ }
161
+ $this->step($idx);
162
+ },
163
+ function ($reason) use ($idx) {
164
+ if ($this->onRejected) {
165
+ call_user_func(
166
+ $this->onRejected, $reason, $idx, $this->aggregate
167
+ );
168
+ }
169
+ $this->step($idx);
170
+ }
171
+ );
172
+
173
+ return true;
174
+ }
175
+
176
+ private function advanceIterator()
177
+ {
178
+ // Place a lock on the iterator so that we ensure to not recurse,
179
+ // preventing fatal generator errors.
180
+ if ($this->mutex) {
181
+ return false;
182
+ }
183
+
184
+ $this->mutex = true;
185
+
186
+ try {
187
+ $this->iterable->next();
188
+ $this->mutex = false;
189
+ return true;
190
+ } catch (\Throwable $e) {
191
+ $this->aggregate->reject($e);
192
+ $this->mutex = false;
193
+ return false;
194
+ } catch (\Exception $e) {
195
+ $this->aggregate->reject($e);
196
+ $this->mutex = false;
197
+ return false;
198
+ }
199
+ }
200
+
201
+ private function step($idx)
202
+ {
203
+ // If the promise was already resolved, then ignore this step.
204
+ if ($this->aggregate->getState() !== PromiseInterface::PENDING) {
205
+ return;
206
+ }
207
+
208
+ unset($this->pending[$idx]);
209
+
210
+ // Only refill pending promises if we are not locked, preventing the
211
+ // EachPromise to recursively invoke the provided iterator, which
212
+ // cause a fatal error: "Cannot resume an already running generator"
213
+ if ($this->advanceIterator() && !$this->checkIfFinished()) {
214
+ // Add more pending promises if possible.
215
+ $this->refillPending();
216
+ }
217
+ }
218
+
219
+ private function checkIfFinished()
220
+ {
221
+ if (!$this->pending && !$this->iterable->valid()) {
222
+ // Resolve the promise if there's nothing left to do.
223
+ $this->aggregate->resolve(null);
224
+ return true;
225
+ }
226
+
227
+ return false;
228
+ }
229
+ }
vendor/guzzlehttp/promises/src/FulfilledPromise.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Promise;
3
+
4
+ /**
5
+ * A promise that has been fulfilled.
6
+ *
7
+ * Thenning off of this promise will invoke the onFulfilled callback
8
+ * immediately and ignore other callbacks.
9
+ */
10
+ class FulfilledPromise implements PromiseInterface
11
+ {
12
+ private $value;
13
+
14
+ public function __construct($value)
15
+ {
16
+ if (method_exists($value, 'then')) {
17
+ throw new \InvalidArgumentException(
18
+ 'You cannot create a FulfilledPromise with a promise.');
19
+ }
20
+
21
+ $this->value = $value;
22
+ }
23
+
24
+ public function then(
25
+ callable $onFulfilled = null,
26
+ callable $onRejected = null
27
+ ) {
28
+ // Return itself if there is no onFulfilled function.
29
+ if (!$onFulfilled) {
30
+ return $this;
31
+ }
32
+
33
+ $queue = queue();
34
+ $p = new Promise([$queue, 'run']);
35
+ $value = $this->value;
36
+ $queue->add(static function () use ($p, $value, $onFulfilled) {
37
+ if ($p->getState() === self::PENDING) {
38
+ try {
39
+ $p->resolve($onFulfilled($value));
40
+ } catch (\Throwable $e) {
41
+ $p->reject($e);
42
+ } catch (\Exception $e) {
43
+ $p->reject($e);
44
+ }
45
+ }
46
+ });
47
+
48
+ return $p;
49
+ }
50
+
51
+ public function otherwise(callable $onRejected)
52
+ {
53
+ return $this->then(null, $onRejected);
54
+ }
55
+
56
+ public function wait($unwrap = true, $defaultDelivery = null)
57
+ {
58
+ return $unwrap ? $this->value : null;
59
+ }
60
+
61
+ public function getState()
62
+ {
63
+ return self::FULFILLED;
64
+ }
65
+
66
+ public function resolve($value)
67
+ {
68
+ if ($value !== $this->value) {
69
+ throw new \LogicException("Cannot resolve a fulfilled promise");
70
+ }
71
+ }
72
+
73
+ public function reject($reason)
74
+ {
75
+ throw new \LogicException("Cannot reject a fulfilled promise");
76
+ }
77
+
78
+ public function cancel()
79
+ {
80
+ // pass
81
+ }
82
+ }
vendor/guzzlehttp/promises/src/Promise.php ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Promise;
3
+
4
+ /**
5
+ * Promises/A+ implementation that avoids recursion when possible.
6
+ *
7
+ * @link https://promisesaplus.com/
8
+ */
9
+ class Promise implements PromiseInterface
10
+ {
11
+ private $state = self::PENDING;
12
+ private $result;
13
+ private $cancelFn;
14
+ private $waitFn;
15
+ private $waitList;
16
+ private $handlers = [];
17
+
18
+ /**
19
+ * @param callable $waitFn Fn that when invoked resolves the promise.
20
+ * @param callable $cancelFn Fn that when invoked cancels the promise.
21
+ */
22
+ public function __construct(
23
+ callable $waitFn = null,
24
+ callable $cancelFn = null
25
+ ) {
26
+ $this->waitFn = $waitFn;
27
+ $this->cancelFn = $cancelFn;
28
+ }
29
+
30
+ public function then(
31
+ callable $onFulfilled = null,
32
+ callable $onRejected = null
33
+ ) {
34
+ if ($this->state === self::PENDING) {
35
+ $p = new Promise(null, [$this, 'cancel']);
36
+ $this->handlers[] = [$p, $onFulfilled, $onRejected];
37
+ $p->waitList = $this->waitList;
38
+ $p->waitList[] = $this;
39
+ return $p;
40
+ }
41
+
42
+ // Return a fulfilled promise and immediately invoke any callbacks.
43
+ if ($this->state === self::FULFILLED) {
44
+ return $onFulfilled
45
+ ? promise_for($this->result)->then($onFulfilled)
46
+ : promise_for($this->result);
47
+ }
48
+
49
+ // It's either cancelled or rejected, so return a rejected promise
50
+ // and immediately invoke any callbacks.
51
+ $rejection = rejection_for($this->result);
52
+ return $onRejected ? $rejection->then(null, $onRejected) : $rejection;
53
+ }
54
+
55
+ public function otherwise(callable $onRejected)
56
+ {
57
+ return $this->then(null, $onRejected);
58
+ }
59
+
60
+ public function wait($unwrap = true)
61
+ {
62
+ $this->waitIfPending();
63
+
64
+ $inner = $this->result instanceof PromiseInterface
65
+ ? $this->result->wait($unwrap)
66
+ : $this->result;
67
+
68
+ if ($unwrap) {
69
+ if ($this->result instanceof PromiseInterface
70
+ || $this->state === self::FULFILLED
71
+ ) {
72
+ return $inner;
73
+ } else {
74
+ // It's rejected so "unwrap" and throw an exception.
75
+ throw exception_for($inner);
76
+ }
77
+ }
78
+ }
79
+
80
+ public function getState()
81
+ {
82
+ return $this->state;
83
+ }
84
+
85
+ public function cancel()
86
+ {
87
+ if ($this->state !== self::PENDING) {
88
+ return;
89
+ }
90
+
91
+ $this->waitFn = $this->waitList = null;
92
+
93
+ if ($this->cancelFn) {
94
+ $fn = $this->cancelFn;
95
+ $this->cancelFn = null;
96
+ try {
97
+ $fn();
98
+ } catch (\Throwable $e) {
99
+ $this->reject($e);
100
+ } catch (\Exception $e) {
101
+ $this->reject($e);
102
+ }
103
+ }
104
+
105
+ // Reject the promise only if it wasn't rejected in a then callback.
106
+ if ($this->state === self::PENDING) {
107
+ $this->reject(new CancellationException('Promise has been cancelled'));
108
+ }
109
+ }
110
+
111
+ public function resolve($value)
112
+ {
113
+ $this->settle(self::FULFILLED, $value);
114
+ }
115
+
116
+ public function reject($reason)
117
+ {
118
+ $this->settle(self::REJECTED, $reason);
119
+ }
120
+
121
+ private function settle($state, $value)
122
+ {
123
+ if ($this->state !== self::PENDING) {
124
+ // Ignore calls with the same resolution.
125
+ if ($state === $this->state && $value === $this->result) {
126
+ return;
127
+ }
128
+ throw $this->state === $state
129
+ ? new \LogicException("The promise is already {$state}.")
130
+ : new \LogicException("Cannot change a {$this->state} promise to {$state}");
131
+ }
132
+
133
+ if ($value === $this) {
134
+ throw new \LogicException('Cannot fulfill or reject a promise with itself');
135
+ }
136
+
137
+ // Clear out the state of the promise but stash the handlers.
138
+ $this->state = $state;
139
+ $this->result = $value;
140
+ $handlers = $this->handlers;
141
+ $this->handlers = null;
142
+ $this->waitList = $this->waitFn = null;
143
+ $this->cancelFn = null;
144
+
145
+ if (!$handlers) {
146
+ return;
147
+ }
148
+
149
+ // If the value was not a settled promise or a thenable, then resolve
150
+ // it in the task queue using the correct ID.
151
+ if (!method_exists($value, 'then')) {
152
+ $id = $state === self::FULFILLED ? 1 : 2;
153
+ // It's a success, so resolve the handlers in the queue.
154
+ queue()->add(static function () use ($id, $value, $handlers) {
155
+ foreach ($handlers as $handler) {
156
+ self::callHandler($id, $value, $handler);
157
+ }
158
+ });
159
+ } elseif ($value instanceof Promise
160
+ && $value->getState() === self::PENDING
161
+ ) {
162
+ // We can just merge our handlers onto the next promise.
163
+ $value->handlers = array_merge($value->handlers, $handlers);
164
+ } else {
165
+ // Resolve the handlers when the forwarded promise is resolved.
166
+ $value->then(
167
+ static function ($value) use ($handlers) {
168
+ foreach ($handlers as $handler) {
169
+ self::callHandler(1, $value, $handler);
170
+ }
171
+ },
172
+ static function ($reason) use ($handlers) {
173
+ foreach ($handlers as $handler) {
174
+ self::callHandler(2, $reason, $handler);
175
+ }
176
+ }
177
+ );
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Call a stack of handlers using a specific callback index and value.
183
+ *
184
+ * @param int $index 1 (resolve) or 2 (reject).
185
+ * @param mixed $value Value to pass to the callback.
186
+ * @param array $handler Array of handler data (promise and callbacks).
187
+ *
188
+ * @return array Returns the next group to resolve.
189
+ */
190
+ private static function callHandler($index, $value, array $handler)
191
+ {
192
+ /** @var PromiseInterface $promise */
193
+ $promise = $handler[0];
194
+
195
+ // The promise may have been cancelled or resolved before placing
196
+ // this thunk in the queue.
197
+ if ($promise->getState() !== self::PENDING) {
198
+ return;
199
+ }
200
+
201
+ try {
202
+ if (isset($handler[$index])) {
203
+ $promise->resolve($handler[$index]($value));
204
+ } elseif ($index === 1) {
205
+ // Forward resolution values as-is.
206
+ $promise->resolve($value);
207
+ } else {
208
+ // Forward rejections down the chain.
209
+ $promise->reject($value);
210
+ }
211
+ } catch (\Throwable $reason) {
212
+ $promise->reject($reason);
213
+ } catch (\Exception $reason) {
214
+ $promise->reject($reason);
215
+ }
216
+ }
217
+
218
+ private function waitIfPending()
219
+ {
220
+ if ($this->state !== self::PENDING) {
221
+ return;
222
+ } elseif ($this->waitFn) {
223
+ $this->invokeWaitFn();
224
+ } elseif ($this->waitList) {
225
+ $this->invokeWaitList();
226
+ } else {
227
+ // If there's not wait function, then reject the promise.
228
+ $this->reject('Cannot wait on a promise that has '
229
+ . 'no internal wait function. You must provide a wait '
230
+ . 'function when constructing the promise to be able to '
231
+ . 'wait on a promise.');
232
+ }
233
+
234
+ queue()->run();
235
+
236
+ if ($this->state === self::PENDING) {
237
+ $this->reject('Invoking the wait callback did not resolve the promise');
238
+ }
239
+ }
240
+
241
+ private function invokeWaitFn()
242
+ {
243
+ try {
244
+ $wfn = $this->waitFn;
245
+ $this->waitFn = null;
246
+ $wfn(true);
247
+ } catch (\Exception $reason) {
248
+ if ($this->state === self::PENDING) {
249
+ // The promise has not been resolved yet, so reject the promise
250
+ // with the exception.
251
+ $this->reject($reason);
252
+ } else {
253
+ // The promise was already resolved, so there's a problem in
254
+ // the application.
255
+ throw $reason;
256
+ }
257
+ }
258
+ }
259
+
260
+ private function invokeWaitList()
261
+ {
262
+ $waitList = $this->waitList;
263
+ $this->waitList = null;
264
+
265
+ foreach ($waitList as $result) {
266
+ while (true) {
267
+ $result->waitIfPending();
268
+
269
+ if ($result->result instanceof Promise) {
270
+ $result = $result->result;
271
+ } else {
272
+ if ($result->result instanceof PromiseInterface) {
273
+ $result->result->wait(false);
274
+ }
275
+ break;
276
+ }
277
+ }
278
+ }
279
+ }
280
+ }
vendor/guzzlehttp/promises/src/PromiseInterface.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Promise;
3
+
4
+ /**
5
+ * A promise represents the eventual result of an asynchronous operation.
6
+ *
7
+ * The primary way of interacting with a promise is through its then method,
8
+ * which registers callbacks to receive either a promise’s eventual value or
9
+ * the reason why the promise cannot be fulfilled.
10
+ *
11
+ * @link https://promisesaplus.com/
12
+ */
13
+ interface PromiseInterface
14
+ {
15
+ const PENDING = 'pending';
16
+ const FULFILLED = 'fulfilled';
17
+ const REJECTED = 'rejected';
18
+
19
+ /**
20
+ * Appends fulfillment and rejection handlers to the promise, and returns
21
+ * a new promise resolving to the return value of the called handler.
22
+ *
23
+ * @param callable $onFulfilled Invoked when the promise fulfills.
24
+ * @param callable $onRejected Invoked when the promise is rejected.
25
+ *
26
+ * @return PromiseInterface
27
+ */
28
+ public function then(
29
+ callable $onFulfilled = null,
30
+ callable $onRejected = null
31
+ );
32
+
33
+ /**
34
+ * Appends a rejection handler callback to the promise, and returns a new
35
+ * promise resolving to the return value of the callback if it is called,
36
+ * or to its original fulfillment value if the promise is instead
37
+ * fulfilled.
38
+ *
39
+ * @param callable $onRejected Invoked when the promise is rejected.
40
+ *
41
+ * @return PromiseInterface
42
+ */
43
+ public function otherwise(callable $onRejected);
44
+
45
+ /**
46
+ * Get the state of the promise ("pending", "rejected", or "fulfilled").
47
+ *
48
+ * The three states can be checked against the constants defined on
49
+ * PromiseInterface: PENDING, FULFILLED, and REJECTED.
50
+ *
51
+ * @return string
52
+ */
53
+ public function getState();
54
+
55
+ /**
56
+ * Resolve the promise with the given value.
57
+ *
58
+ * @param mixed $value
59
+ * @throws \RuntimeException if the promise is already resolved.
60
+ */
61
+ public function resolve($value);
62
+
63
+ /**
64
+ * Reject the promise with the given reason.
65
+ *
66
+ * @param mixed $reason
67
+ * @throws \RuntimeException if the promise is already resolved.
68
+ */
69
+ public function reject($reason);
70
+
71
+ /**
72
+ * Cancels the promise if possible.
73
+ *
74
+ * @link https://github.com/promises-aplus/cancellation-spec/issues/7
75
+ */
76
+ public function cancel();
77
+
78
+ /**
79
+ * Waits until the promise completes if possible.
80
+ *
81
+ * Pass $unwrap as true to unwrap the result of the promise, either
82
+ * returning the resolved value or throwing the rejected exception.
83
+ *
84
+ * If the promise cannot be waited on, then the promise will be rejected.
85
+ *
86
+ * @param bool $unwrap
87
+ *
88
+ * @return mixed
89
+ * @throws \LogicException if the promise has no wait function or if the
90
+ * promise does not settle after waiting.
91
+ */
92
+ public function wait($unwrap = true);
93
+ }
vendor/guzzlehttp/promises/src/PromisorInterface.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Promise;
3
+
4
+ /**
5
+ * Interface used with classes that return a promise.
6
+ */
7
+ interface PromisorInterface
8
+ {
9
+ /**
10
+ * Returns a promise.
11
+ *
12
+ * @return PromiseInterface
13
+ */
14
+ public function promise();
15
+ }
vendor/guzzlehttp/promises/src/RejectedPromise.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Promise;
3
+
4
+ /**
5
+ * A promise that has been rejected.
6
+ *
7
+ * Thenning off of this promise will invoke the onRejected callback
8
+ * immediately and ignore other callbacks.
9
+ */
10
+ class RejectedPromise implements PromiseInterface
11
+ {
12
+ private $reason;
13
+
14
+ public function __construct($reason)
15
+ {
16
+ if (method_exists($reason, 'then')) {
17
+ throw new \InvalidArgumentException(
18
+ 'You cannot create a RejectedPromise with a promise.');
19
+ }
20
+
21
+ $this->reason = $reason;
22
+ }
23
+
24
+ public function then(
25
+ callable $onFulfilled = null,
26
+ callable $onRejected = null
27
+ ) {
28
+ // If there's no onRejected callback then just return self.
29
+ if (!$onRejected) {
30
+ return $this;
31
+ }
32
+
33
+ $queue = queue();
34
+ $reason = $this->reason;
35
+ $p = new Promise([$queue, 'run']);
36
+ $queue->add(static function () use ($p, $reason, $onRejected) {
37
+ if ($p->getState() === self::PENDING) {
38
+ try {
39
+ // Return a resolved promise if onRejected does not throw.
40
+ $p->resolve($onRejected($reason));
41
+ } catch (\Throwable $e) {
42
+ // onRejected threw, so return a rejected promise.
43
+ $p->reject($e);
44
+ } catch (\Exception $e) {
45
+ // onRejected threw, so return a rejected promise.
46
+ $p->reject($e);
47
+ }
48
+ }
49
+ });
50
+
51
+ return $p;
52
+ }
53
+
54
+ public function otherwise(callable $onRejected)
55
+ {
56
+ return $this->then(null, $onRejected);
57
+ }
58
+
59
+ public function wait($unwrap = true, $defaultDelivery = null)
60
+ {
61
+ if ($unwrap) {
62
+ throw exception_for($this->reason);
63
+ }
64
+ }
65
+
66
+ public function getState()
67
+ {
68
+ return self::REJECTED;
69
+ }
70
+
71
+ public function resolve($value)
72
+ {
73
+ throw new \LogicException("Cannot resolve a rejected promise");
74
+ }
75
+
76
+ public function reject($reason)
77
+ {
78
+ if ($reason !== $this->reason) {
79
+ throw new \LogicException("Cannot reject a rejected promise");
80
+ }
81
+ }
82
+
83
+ public function cancel()
84
+ {
85
+ // pass
86
+ }
87
+ }
vendor/guzzlehttp/promises/src/RejectionException.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Promise;
3
+
4
+ /**
5
+ * A special exception that is thrown when waiting on a rejected promise.
6
+ *
7
+ * The reason value is available via the getReason() method.
8
+ */
9
+ class RejectionException extends \RuntimeException
10
+ {
11
+ /** @var mixed Rejection reason. */
12
+ private $reason;
13
+
14
+ /**
15
+ * @param mixed $reason Rejection reason.
16
+ * @param string $description Optional description
17
+ */
18
+ public function __construct($reason, $description = null)
19
+ {
20
+ $this->reason = $reason;
21
+
22
+ $message = 'The promise was rejected';
23
+
24
+ if ($description) {
25
+ $message .= ' with reason: ' . $description;
26
+ } elseif (is_string($reason)
27
+ || (is_object($reason) && method_exists($reason, '__toString'))
28
+ ) {
29
+ $message .= ' with reason: ' . $this->reason;
30
+ } elseif ($reason instanceof \JsonSerializable) {
31
+ $message .= ' with reason: '
32
+ . json_encode($this->reason, JSON_PRETTY_PRINT);
33
+ }
34
+
35
+ parent::__construct($message);
36
+ }
37
+
38
+ /**
39
+ * Returns the rejection reason.
40
+ *
41
+ * @return mixed
42
+ */
43
+ public function getReason()
44
+ {
45
+ return $this->reason;
46
+ }
47
+ }
vendor/guzzlehttp/promises/src/TaskQueue.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Promise;
3
+
4
+ /**
5
+ * A task queue that executes tasks in a FIFO order.
6
+ *
7
+ * This task queue class is used to settle promises asynchronously and
8
+ * maintains a constant stack size. You can use the task queue asynchronously
9
+ * by calling the `run()` function of the global task queue in an event loop.
10
+ *
11
+ * GuzzleHttp\Promise\queue()->run();
12
+ */
13
+ class TaskQueue implements TaskQueueInterface
14
+ {
15
+ private $enableShutdown = true;
16
+ private $queue = [];
17
+
18
+ public function __construct($withShutdown = true)
19
+ {
20
+ if ($withShutdown) {
21
+ register_shutdown_function(function () {
22
+ if ($this->enableShutdown) {
23
+ // Only run the tasks if an E_ERROR didn't occur.
24
+ $err = error_get_last();
25
+ if (!$err || ($err['type'] ^ E_ERROR)) {
26
+ $this->run();
27
+ }
28
+ }
29
+ });
30
+ }
31
+ }
32
+
33
+ public function isEmpty()
34
+ {
35
+ return !$this->queue;
36
+ }
37
+
38
+ public function add(callable $task)
39
+ {
40
+ $this->queue[] = $task;
41
+ }
42
+
43
+ public function run()
44
+ {
45
+ /** @var callable $task */
46
+ while ($task = array_shift($this->queue)) {
47
+ $task();
48
+ }
49
+ }
50
+
51
+ /**
52
+ * The task queue will be run and exhausted by default when the process
53
+ * exits IFF the exit is not the result of a PHP E_ERROR error.
54
+ *
55
+ * You can disable running the automatic shutdown of the queue by calling
56
+ * this function. If you disable the task queue shutdown process, then you
57
+ * MUST either run the task queue (as a result of running your event loop
58
+ * or manually using the run() method) or wait on each outstanding promise.
59
+ *
60
+ * Note: This shutdown will occur before any destructors are triggered.
61
+ */
62
+ public function disableShutdown()
63
+ {
64
+ $this->enableShutdown = false;
65
+ }
66
+ }
vendor/guzzlehttp/promises/src/TaskQueueInterface.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Promise;
3
+
4
+ interface TaskQueueInterface
5
+ {
6
+ /**
7
+ * Returns true if the queue is empty.
8
+ *
9
+ * @return bool
10
+ */
11
+ public function isEmpty();
12
+
13
+ /**
14
+ * Adds a task to the queue that will be executed the next time run is
15
+ * called.
16
+ *
17
+ * @param callable $task
18
+ */
19
+ public function add(callable $task);
20
+
21
+ /**
22
+ * Execute all of the pending task in the queue.
23
+ */
24
+ public function run();
25
+ }
vendor/guzzlehttp/promises/src/functions.php ADDED
@@ -0,0 +1,457 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Promise;
3
+
4
+ /**
5
+ * Get the global task queue used for promise resolution.
6
+ *
7
+ * This task queue MUST be run in an event loop in order for promises to be
8
+ * settled asynchronously. It will be automatically run when synchronously
9
+ * waiting on a promise.
10
+ *
11
+ * <code>
12
+ * while ($eventLoop->isRunning()) {
13
+ * GuzzleHttp\Promise\queue()->run();
14
+ * }
15
+ * </code>
16
+ *
17
+ * @param TaskQueueInterface $assign Optionally specify a new queue instance.
18
+ *
19
+ * @return TaskQueueInterface
20
+ */
21
+ function queue(TaskQueueInterface $assign = null)
22
+ {
23
+ static $queue;
24
+
25
+ if ($assign) {
26
+ $queue = $assign;
27
+ } elseif (!$queue) {
28
+ $queue = new TaskQueue();
29
+ }
30
+
31
+ return $queue;
32
+ }
33
+
34
+ /**
35
+ * Adds a function to run in the task queue when it is next `run()` and returns
36
+ * a promise that is fulfilled or rejected with the result.
37
+ *
38
+ * @param callable $task Task function to run.
39
+ *
40
+ * @return PromiseInterface
41
+ */
42
+ function task(callable $task)
43
+ {
44
+ $queue = queue();
45
+ $promise = new Promise([$queue, 'run']);
46
+ $queue->add(function () use ($task, $promise) {
47
+ try {
48
+ $promise->resolve($task());
49
+ } catch (\Throwable $e) {
50
+ $promise->reject($e);
51
+ } catch (\Exception $e) {
52
+ $promise->reject($e);
53
+ }
54
+ });
55
+
56
+ return $promise;
57
+ }
58
+
59
+ /**
60
+ * Creates a promise for a value if the value is not a promise.
61
+ *
62
+ * @param mixed $value Promise or value.
63
+ *
64
+ * @return PromiseInterface
65
+ */
66
+ function promise_for($value)
67
+ {
68
+ if ($value instanceof PromiseInterface) {
69
+ return $value;
70
+ }
71
+
72
+ // Return a Guzzle promise that shadows the given promise.
73
+ if (method_exists($value, 'then')) {
74
+ $wfn = method_exists($value, 'wait') ? [$value, 'wait'] : null;
75
+ $cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null;
76
+ $promise = new Promise($wfn, $cfn);
77
+ $value->then([$promise, 'resolve'], [$promise, 'reject']);
78
+ return $promise;
79
+ }
80
+
81
+ return new FulfilledPromise($value);
82
+ }
83
+
84
+ /**
85
+ * Creates a rejected promise for a reason if the reason is not a promise. If
86
+ * the provided reason is a promise, then it is returned as-is.
87
+ *
88
+ * @param mixed $reason Promise or reason.
89
+ *
90
+ * @return PromiseInterface
91
+ */
92
+ function rejection_for($reason)
93
+ {
94
+ if ($reason instanceof PromiseInterface) {
95
+ return $reason;
96
+ }
97
+
98
+ return new RejectedPromise($reason);
99
+ }
100
+
101
+ /**
102
+ * Create an exception for a rejected promise value.
103
+ *
104
+ * @param mixed $reason
105
+ *
106
+ * @return \Exception|\Throwable
107
+ */
108
+ function exception_for($reason)
109
+ {
110
+ return $reason instanceof \Exception || $reason instanceof \Throwable
111
+ ? $reason
112
+ : new RejectionException($reason);
113
+ }
114
+
115
+ /**
116
+ * Returns an iterator for the given value.
117
+ *
118
+ * @param mixed $value
119
+ *
120
+ * @return \Iterator
121
+ */
122
+ function iter_for($value)
123
+ {
124
+ if ($value instanceof \Iterator) {
125
+ return $value;
126
+ } elseif (is_array($value)) {
127
+ return new \ArrayIterator($value);
128
+ } else {
129
+ return new \ArrayIterator([$value]);
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Synchronously waits on a promise to resolve and returns an inspection state
135
+ * array.
136
+ *
137
+ * Returns a state associative array containing a "state" key mapping to a
138
+ * valid promise state. If the state of the promise is "fulfilled", the array
139
+ * will contain a "value" key mapping to the fulfilled value of the promise. If
140
+ * the promise is rejected, the array will contain a "reason" key mapping to
141
+ * the rejection reason of the promise.
142
+ *
143
+ * @param PromiseInterface $promise Promise or value.
144
+ *
145
+ * @return array
146
+ */
147
+ function inspect(PromiseInterface $promise)
148
+ {
149
+ try {
150
+ return [
151
+ 'state' => PromiseInterface::FULFILLED,
152
+ 'value' => $promise->wait()
153
+ ];
154
+ } catch (RejectionException $e) {
155
+ return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()];
156
+ } catch (\Throwable $e) {
157
+ return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
158
+ } catch (\Exception $e) {
159
+ return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Waits on all of the provided promises, but does not unwrap rejected promises
165
+ * as thrown exception.
166
+ *
167
+ * Returns an array of inspection state arrays.
168
+ *
169
+ * @param PromiseInterface[] $promises Traversable of promises to wait upon.
170
+ *
171
+ * @return array
172
+ * @see GuzzleHttp\Promise\inspect for the inspection state array format.
173
+ */
174
+ function inspect_all($promises)
175
+ {
176
+ $results = [];
177
+ foreach ($promises as $key => $promise) {
178
+ $results[$key] = inspect($promise);
179
+ }
180
+
181
+ return $results;
182
+ }
183
+
184
+ /**
185
+ * Waits on all of the provided promises and returns the fulfilled values.
186
+ *
187
+ * Returns an array that contains the value of each promise (in the same order
188
+ * the promises were provided). An exception is thrown if any of the promises
189
+ * are rejected.
190
+ *
191
+ * @param mixed $promises Iterable of PromiseInterface objects to wait on.
192
+ *
193
+ * @return array
194
+ * @throws \Exception on error
195
+ * @throws \Throwable on error in PHP >=7
196
+ */
197
+ function unwrap($promises)
198
+ {
199
+ $results = [];
200
+ foreach ($promises as $key => $promise) {
201
+ $results[$key] = $promise->wait();
202
+ }
203
+
204
+ return $results;
205
+ }
206
+
207
+ /**
208
+ * Given an array of promises, return a promise that is fulfilled when all the
209
+ * items in the array are fulfilled.
210
+ *
211
+ * The promise's fulfillment value is an array with fulfillment values at
212
+ * respective positions to the original array. If any promise in the array
213
+ * rejects, the returned promise is rejected with the rejection reason.
214
+ *
215
+ * @param mixed $promises Promises or values.
216
+ *
217
+ * @return PromiseInterface
218
+ */
219
+ function all($promises)
220
+ {
221
+ $results = [];
222
+ return each(
223
+ $promises,
224
+ function ($value, $idx) use (&$results) {
225
+ $results[$idx] = $value;
226
+ },
227
+ function ($reason, $idx, Promise $aggregate) {
228
+ $aggregate->reject($reason);
229
+ }
230
+ )->then(function () use (&$results) {
231
+ ksort($results);
232
+ return $results;
233
+ });
234
+ }
235
+
236
+ /**
237
+ * Initiate a competitive race between multiple promises or values (values will
238
+ * become immediately fulfilled promises).
239
+ *
240
+ * When count amount of promises have been fulfilled, the returned promise is
241
+ * fulfilled with an array that contains the fulfillment values of the winners
242
+ * in order of resolution.
243
+ *
244
+ * This prommise is rejected with a {@see GuzzleHttp\Promise\AggregateException}
245
+ * if the number of fulfilled promises is less than the desired $count.
246
+ *
247
+ * @param int $count Total number of promises.
248
+ * @param mixed $promises Promises or values.
249
+ *
250
+ * @return PromiseInterface
251
+ */
252
+ function some($count, $promises)
253
+ {
254
+ $results = [];
255
+ $rejections = [];
256
+
257
+ return each(
258
+ $promises,
259
+ function ($value, $idx, PromiseInterface $p) use (&$results, $count) {
260
+ if ($p->getState() !== PromiseInterface::PENDING) {
261
+ return;
262
+ }
263
+ $results[$idx] = $value;
264
+ if (count($results) >= $count) {
265
+ $p->resolve(null);
266
+ }
267
+ },
268
+ function ($reason) use (&$rejections) {
269
+ $rejections[] = $reason;
270
+ }
271
+ )->then(
272
+ function () use (&$results, &$rejections, $count) {
273
+ if (count($results) !== $count) {
274
+ throw new AggregateException(
275
+ 'Not enough promises to fulfill count',
276
+ $rejections
277
+ );
278
+ }
279
+ ksort($results);
280
+ return array_values($results);
281
+ }
282
+ );
283
+ }
284
+
285
+ /**
286
+ * Like some(), with 1 as count. However, if the promise fulfills, the
287
+ * fulfillment value is not an array of 1 but the value directly.
288
+ *
289
+ * @param mixed $promises Promises or values.
290
+ *
291
+ * @return PromiseInterface
292
+ */
293
+ function any($promises)
294
+ {
295
+ return some(1, $promises)->then(function ($values) { return $values[0]; });
296
+ }
297
+
298
+ /**
299
+ * Returns a promise that is fulfilled when all of the provided promises have
300
+ * been fulfilled or rejected.
301
+ *
302
+ * The returned promise is fulfilled with an array of inspection state arrays.
303
+ *
304
+ * @param mixed $promises Promises or values.
305
+ *
306
+ * @return PromiseInterface
307
+ * @see GuzzleHttp\Promise\inspect for the inspection state array format.
308
+ */
309
+ function settle($promises)
310
+ {
311
+ $results = [];
312
+
313
+ return each(
314
+ $promises,
315
+ function ($value, $idx) use (&$results) {
316
+ $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value];
317
+ },
318
+ function ($reason, $idx) use (&$results) {
319
+ $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason];
320
+ }
321
+ )->then(function () use (&$results) {
322
+ ksort($results);
323
+ return $results;
324
+ });
325
+ }
326
+
327
+ /**
328
+ * Given an iterator that yields promises or values, returns a promise that is
329
+ * fulfilled with a null value when the iterator has been consumed or the
330
+ * aggregate promise has been fulfilled or rejected.
331
+ *
332
+ * $onFulfilled is a function that accepts the fulfilled value, iterator
333
+ * index, and the aggregate promise. The callback can invoke any necessary side
334
+ * effects and choose to resolve or reject the aggregate promise if needed.
335
+ *
336
+ * $onRejected is a function that accepts the rejection reason, iterator
337
+ * index, and the aggregate promise. The callback can invoke any necessary side
338
+ * effects and choose to resolve or reject the aggregate promise if needed.
339
+ *
340
+ * @param mixed $iterable Iterator or array to iterate over.
341
+ * @param callable $onFulfilled
342
+ * @param callable $onRejected
343
+ *
344
+ * @return PromiseInterface
345
+ */
346
+ function each(
347
+ $iterable,
348
+ callable $onFulfilled = null,
349
+ callable $onRejected = null
350
+ ) {
351
+ return (new EachPromise($iterable, [
352
+ 'fulfilled' => $onFulfilled,
353
+ 'rejected' => $onRejected
354
+ ]))->promise();
355
+ }
356
+
357
+ /**
358
+ * Like each, but only allows a certain number of outstanding promises at any
359
+ * given time.
360
+ *
361
+ * $concurrency may be an integer or a function that accepts the number of
362
+ * pending promises and returns a numeric concurrency limit value to allow for
363
+ * dynamic a concurrency size.
364
+ *
365
+ * @param mixed $iterable
366
+ * @param int|callable $concurrency
367
+ * @param callable $onFulfilled
368
+ * @param callable $onRejected
369
+ *
370
+ * @return PromiseInterface
371
+ */
372
+ function each_limit(
373
+ $iterable,
374
+ $concurrency,
375
+ callable $onFulfilled = null,
376
+ callable $onRejected = null
377
+ ) {
378
+ return (new EachPromise($iterable, [
379
+ 'fulfilled' => $onFulfilled,
380
+ 'rejected' => $onRejected,
381
+ 'concurrency' => $concurrency
382
+ ]))->promise();
383
+ }
384
+
385
+ /**
386
+ * Like each_limit, but ensures that no promise in the given $iterable argument
387
+ * is rejected. If any promise is rejected, then the aggregate promise is
388
+ * rejected with the encountered rejection.
389
+ *
390
+ * @param mixed $iterable
391
+ * @param int|callable $concurrency
392
+ * @param callable $onFulfilled
393
+ *
394
+ * @return PromiseInterface
395
+ */
396
+ function each_limit_all(
397
+ $iterable,
398
+ $concurrency,
399
+ callable $onFulfilled = null
400
+ ) {
401
+ return each_limit(
402
+ $iterable,
403
+ $concurrency,
404
+ $onFulfilled,
405
+ function ($reason, $idx, PromiseInterface $aggregate) {
406
+ $aggregate->reject($reason);
407
+ }
408
+ );
409
+ }
410
+
411
+ /**
412
+ * Returns true if a promise is fulfilled.
413
+ *
414
+ * @param PromiseInterface $promise
415
+ *
416
+ * @return bool
417
+ */
418
+ function is_fulfilled(PromiseInterface $promise)
419
+ {
420
+ return $promise->getState() === PromiseInterface::FULFILLED;
421
+ }
422
+
423
+ /**
424
+ * Returns true if a promise is rejected.
425
+ *
426
+ * @param PromiseInterface $promise
427
+ *
428
+ * @return bool
429
+ */
430
+ function is_rejected(PromiseInterface $promise)
431
+ {
432
+ return $promise->getState() === PromiseInterface::REJECTED;
433
+ }
434
+
435
+ /**
436
+ * Returns true if a promise is fulfilled or rejected.
437
+ *
438
+ * @param PromiseInterface $promise
439
+ *
440
+ * @return bool
441
+ */
442
+ function is_settled(PromiseInterface $promise)
443
+ {
444
+ return $promise->getState() !== PromiseInterface::PENDING;
445
+ }
446
+
447
+ /**
448
+ * @see Coroutine
449
+ *
450
+ * @param callable $generatorFn
451
+ *
452
+ * @return PromiseInterface
453
+ */
454
+ function coroutine(callable $generatorFn)
455
+ {
456
+ return new Coroutine($generatorFn);
457
+ }
vendor/guzzlehttp/promises/src/functions_include.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Don't redefine the functions if included multiple times.
4
+ if (!function_exists('GuzzleHttp\Promise\promise_for')) {
5
+ require __DIR__ . '/functions.php';
6
+ }
vendor/guzzlehttp/psr7/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2015 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
vendor/guzzlehttp/psr7/src/AppendStream.php ADDED
@@ -0,0 +1,233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Reads from multiple streams, one after the other.
8
+ *
9
+ * This is a read-only stream decorator.
10
+ */
11
+ class AppendStream implements StreamInterface
12
+ {
13
+ /** @var StreamInterface[] Streams being decorated */
14
+ private $streams = [];
15
+
16
+ private $seekable = true;
17
+ private $current = 0;
18
+ private $pos = 0;
19
+ private $detached = false;
20
+
21
+ /**
22
+ * @param StreamInterface[] $streams Streams to decorate. Each stream must
23
+ * be readable.
24
+ */
25
+ public function __construct(array $streams = [])
26
+ {
27
+ foreach ($streams as $stream) {
28
+ $this->addStream($stream);
29
+ }
30
+ }
31
+
32
+ public function __toString()
33
+ {
34
+ try {
35
+ $this->rewind();
36
+ return $this->getContents();
37
+ } catch (\Exception $e) {
38
+ return '';
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Add a stream to the AppendStream
44
+ *
45
+ * @param StreamInterface $stream Stream to append. Must be readable.
46
+ *
47
+ * @throws \InvalidArgumentException if the stream is not readable
48
+ */
49
+ public function addStream(StreamInterface $stream)
50
+ {
51
+ if (!$stream->isReadable()) {
52
+ throw new \InvalidArgumentException('Each stream must be readable');
53
+ }
54
+
55
+ // The stream is only seekable if all streams are seekable
56
+ if (!$stream->isSeekable()) {
57
+ $this->seekable = false;
58
+ }
59
+
60
+ $this->streams[] = $stream;
61
+ }
62
+
63
+ public function getContents()
64
+ {
65
+ return copy_to_string($this);
66
+ }
67
+
68
+ /**
69
+ * Closes each attached stream.
70
+ *
71
+ * {@inheritdoc}
72
+ */
73
+ public function close()
74
+ {
75
+ $this->pos = $this->current = 0;
76
+
77
+ foreach ($this->streams as $stream) {
78
+ $stream->close();
79
+ }
80
+
81
+ $this->streams = [];
82
+ }
83
+
84
+ /**
85
+ * Detaches each attached stream
86
+ *
87
+ * {@inheritdoc}
88
+ */
89
+ public function detach()
90
+ {
91
+ $this->close();
92
+ $this->detached = true;
93
+ }
94
+
95
+ public function tell()
96
+ {
97
+ return $this->pos;
98
+ }
99
+
100
+ /**
101
+ * Tries to calculate the size by adding the size of each stream.
102
+ *
103
+ * If any of the streams do not return a valid number, then the size of the
104
+ * append stream cannot be determined and null is returned.
105
+ *
106
+ * {@inheritdoc}
107
+ */
108
+ public function getSize()
109
+ {
110
+ $size = 0;
111
+
112
+ foreach ($this->streams as $stream) {
113
+ $s = $stream->getSize();
114
+ if ($s === null) {
115
+ return null;
116
+ }
117
+ $size += $s;
118
+ }
119
+
120
+ return $size;
121
+ }
122
+
123
+ public function eof()
124
+ {
125
+ return !$this->streams ||
126
+ ($this->current >= count($this->streams) - 1 &&
127
+ $this->streams[$this->current]->eof());
128
+ }
129
+
130
+ public function rewind()
131
+ {
132
+ $this->seek(0);
133
+ }
134
+
135
+ /**
136
+ * Attempts to seek to the given position. Only supports SEEK_SET.
137
+ *
138
+ * {@inheritdoc}
139
+ */
140
+ public function seek($offset, $whence = SEEK_SET)
141
+ {
142
+ if (!$this->seekable) {
143
+ throw new \RuntimeException('This AppendStream is not seekable');
144
+ } elseif ($whence !== SEEK_SET) {
145
+ throw new \RuntimeException('The AppendStream can only seek with SEEK_SET');
146
+ }
147
+
148
+ $this->pos = $this->current = 0;
149
+
150
+ // Rewind each stream
151
+ foreach ($this->streams as $i => $stream) {
152
+ try {
153
+ $stream->rewind();
154
+ } catch (\Exception $e) {
155
+ throw new \RuntimeException('Unable to seek stream '
156
+ . $i . ' of the AppendStream', 0, $e);
157
+ }
158
+ }
159
+
160
+ // Seek to the actual position by reading from each stream
161
+ while ($this->pos < $offset && !$this->eof()) {
162
+ $result = $this->read(min(8096, $offset - $this->pos));
163
+ if ($result === '') {
164
+ break;
165
+ }
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Reads from all of the appended streams until the length is met or EOF.
171
+ *
172
+ * {@inheritdoc}
173
+ */
174
+ public function read($length)
175
+ {
176
+ $buffer = '';
177
+ $total = count($this->streams) - 1;
178
+ $remaining = $length;
179
+ $progressToNext = false;
180
+
181
+ while ($remaining > 0) {
182
+
183
+ // Progress to the next stream if needed.
184
+ if ($progressToNext || $this->streams[$this->current]->eof()) {
185
+ $progressToNext = false;
186
+ if ($this->current === $total) {
187
+ break;
188
+ }
189
+ $this->current++;
190
+ }
191
+
192
+ $result = $this->streams[$this->current]->read($remaining);
193
+
194
+ // Using a loose comparison here to match on '', false, and null
195
+ if ($result == null) {
196
+ $progressToNext = true;
197
+ continue;
198
+ }
199
+
200
+ $buffer .= $result;
201
+ $remaining = $length - strlen($buffer);
202
+ }
203
+
204
+ $this->pos += strlen($buffer);
205
+
206
+ return $buffer;
207
+ }
208
+
209
+ public function isReadable()
210
+ {
211
+ return true;
212
+ }
213
+
214
+ public function isWritable()
215
+ {
216
+ return false;
217
+ }
218
+
219
+ public function isSeekable()
220
+ {
221
+ return $this->seekable;
222
+ }
223
+
224
+ public function write($string)
225
+ {
226
+ throw new \RuntimeException('Cannot write to an AppendStream');
227
+ }
228
+
229
+ public function getMetadata($key = null)
230
+ {
231
+ return $key ? null : [];
232
+ }
233
+ }
vendor/guzzlehttp/psr7/src/BufferStream.php ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Provides a buffer stream that can be written to to fill a buffer, and read
8
+ * from to remove bytes from the buffer.
9
+ *
10
+ * This stream returns a "hwm" metadata value that tells upstream consumers
11
+ * what the configured high water mark of the stream is, or the maximum
12
+ * preferred size of the buffer.
13
+ */
14
+ class BufferStream implements StreamInterface
15
+ {
16
+ private $hwm;
17
+ private $buffer = '';
18
+
19
+ /**
20
+ * @param int $hwm High water mark, representing the preferred maximum
21
+ * buffer size. If the size of the buffer exceeds the high
22
+ * water mark, then calls to write will continue to succeed
23
+ * but will return false to inform writers to slow down
24
+ * until the buffer has been drained by reading from it.
25
+ */
26
+ public function __construct($hwm = 16384)
27
+ {
28
+ $this->hwm = $hwm;
29
+ }
30
+
31
+ public function __toString()
32
+ {
33
+ return $this->getContents();
34
+ }
35
+
36
+ public function getContents()
37
+ {
38
+ $buffer = $this->buffer;
39
+ $this->buffer = '';
40
+
41
+ return $buffer;
42
+ }
43
+
44
+ public function close()
45
+ {
46
+ $this->buffer = '';
47
+ }
48
+
49
+ public function detach()
50
+ {
51
+ $this->close();
52
+ }
53
+
54
+ public function getSize()
55
+ {
56
+ return strlen($this->buffer);
57
+ }
58
+
59
+ public function isReadable()
60
+ {
61
+ return true;
62
+ }
63
+
64
+ public function isWritable()
65
+ {
66
+ return true;
67
+ }
68
+
69
+ public function isSeekable()
70
+ {
71
+ return false;
72
+ }
73
+
74
+ public function rewind()
75
+ {
76
+ $this->seek(0);
77
+ }
78
+
79
+ public function seek($offset, $whence = SEEK_SET)
80
+ {
81
+ throw new \RuntimeException('Cannot seek a BufferStream');
82
+ }
83
+
84
+ public function eof()
85
+ {
86
+ return strlen($this->buffer) === 0;
87
+ }
88
+
89
+ public function tell()
90
+ {
91
+ throw new \RuntimeException('Cannot determine the position of a BufferStream');
92
+ }
93
+
94
+ /**
95
+ * Reads data from the buffer.
96
+ */
97
+ public function read($length)
98
+ {
99
+ $currentLength = strlen($this->buffer);
100
+
101
+ if ($length >= $currentLength) {
102
+ // No need to slice the buffer because we don't have enough data.
103
+ $result = $this->buffer;
104
+ $this->buffer = '';
105
+ } else {
106
+ // Slice up the result to provide a subset of the buffer.
107
+ $result = substr($this->buffer, 0, $length);
108
+ $this->buffer = substr($this->buffer, $length);
109
+ }
110
+
111
+ return $result;
112
+ }
113
+
114
+ /**
115
+ * Writes data to the buffer.
116
+ */
117
+ public function write($string)
118
+ {
119
+ $this->buffer .= $string;
120
+
121
+ // TODO: What should happen here?
122
+ if (strlen($this->buffer) >= $this->hwm) {
123
+ return false;
124
+ }
125
+
126
+ return strlen($string);
127
+ }
128
+
129
+ public function getMetadata($key = null)
130
+ {
131
+ if ($key == 'hwm') {
132
+ return $this->hwm;
133
+ }
134
+
135
+ return $key ? null : [];
136
+ }
137
+ }
vendor/guzzlehttp/psr7/src/CachingStream.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Stream decorator that can cache previously read bytes from a sequentially
8
+ * read stream.
9
+ */
10
+ class CachingStream implements StreamInterface
11
+ {
12
+ use StreamDecoratorTrait;
13
+
14
+ /** @var StreamInterface Stream being wrapped */
15
+ private $remoteStream;
16
+
17
+ /** @var int Number of bytes to skip reading due to a write on the buffer */
18
+ private $skipReadBytes = 0;
19
+
20
+ /**
21
+ * We will treat the buffer object as the body of the stream
22
+ *
23
+ * @param StreamInterface $stream Stream to cache
24
+ * @param StreamInterface $target Optionally specify where data is cached
25
+ */
26
+ public function __construct(
27
+ StreamInterface $stream,
28
+ StreamInterface $target = null
29
+ ) {
30
+ $this->remoteStream = $stream;
31
+ $this->stream = $target ?: new Stream(fopen('php://temp', 'r+'));
32
+ }
33
+
34
+ public function getSize()
35
+ {
36
+ return max($this->stream->getSize(), $this->remoteStream->getSize());
37
+ }
38
+
39
+ public function rewind()
40
+ {
41
+ $this->seek(0);
42
+ }
43
+
44
+ public function seek($offset, $whence = SEEK_SET)
45
+ {
46
+ if ($whence == SEEK_SET) {
47
+ $byte = $offset;
48
+ } elseif ($whence == SEEK_CUR) {
49
+ $byte = $offset + $this->tell();
50
+ } elseif ($whence == SEEK_END) {
51
+ $size = $this->remoteStream->getSize();
52
+ if ($size === null) {
53
+ $size = $this->cacheEntireStream();
54
+ }
55
+ $byte = $size + $offset;
56
+ } else {
57
+ throw new \InvalidArgumentException('Invalid whence');
58
+ }
59
+
60
+ $diff = $byte - $this->stream->getSize();
61
+
62
+ if ($diff > 0) {
63
+ // Read the remoteStream until we have read in at least the amount
64
+ // of bytes requested, or we reach the end of the file.
65
+ while ($diff > 0 && !$this->remoteStream->eof()) {
66
+ $this->read($diff);
67
+ $diff = $byte - $this->stream->getSize();
68
+ }
69
+ } else {
70
+ // We can just do a normal seek since we've already seen this byte.
71
+ $this->stream->seek($byte);
72
+ }
73
+ }
74
+
75
+ public function read($length)
76
+ {
77
+ // Perform a regular read on any previously read data from the buffer
78
+ $data = $this->stream->read($length);
79
+ $remaining = $length - strlen($data);
80
+
81
+ // More data was requested so read from the remote stream
82
+ if ($remaining) {
83
+ // If data was written to the buffer in a position that would have
84
+ // been filled from the remote stream, then we must skip bytes on
85
+ // the remote stream to emulate overwriting bytes from that
86
+ // position. This mimics the behavior of other PHP stream wrappers.
87
+ $remoteData = $this->remoteStream->read(
88
+ $remaining + $this->skipReadBytes
89
+ );
90
+
91
+ if ($this->skipReadBytes) {
92
+ $len = strlen($remoteData);
93
+ $remoteData = substr($remoteData, $this->skipReadBytes);
94
+ $this->skipReadBytes = max(0, $this->skipReadBytes - $len);
95
+ }
96
+
97
+ $data .= $remoteData;
98
+ $this->stream->write($remoteData);
99
+ }
100
+
101
+ return $data;
102
+ }
103
+
104
+ public function write($string)
105
+ {
106
+ // When appending to the end of the currently read stream, you'll want
107
+ // to skip bytes from being read from the remote stream to emulate
108
+ // other stream wrappers. Basically replacing bytes of data of a fixed
109
+ // length.
110
+ $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell();
111
+ if ($overflow > 0) {
112
+ $this->skipReadBytes += $overflow;
113
+ }
114
+
115
+ return $this->stream->write($string);
116
+ }
117
+
118
+ public function eof()
119
+ {
120
+ return $this->stream->eof() && $this->remoteStream->eof();
121
+ }
122
+
123
+ /**
124
+ * Close both the remote stream and buffer stream
125
+ */
126
+ public function close()
127
+ {
128
+ $this->remoteStream->close() && $this->stream->close();
129
+ }
130
+
131
+ private function cacheEntireStream()
132
+ {
133
+ $target = new FnStream(['write' => 'strlen']);
134
+ copy_to_stream($this, $target);
135
+
136
+ return $this->tell();
137
+ }
138
+ }
vendor/guzzlehttp/psr7/src/DroppingStream.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Stream decorator that begins dropping data once the size of the underlying
8
+ * stream becomes too full.
9
+ */
10
+ class DroppingStream implements StreamInterface
11
+ {
12
+ use StreamDecoratorTrait;
13
+
14
+ private $maxLength;
15
+
16
+ /**
17
+ * @param StreamInterface $stream Underlying stream to decorate.
18
+ * @param int $maxLength Maximum size before dropping data.
19
+ */
20
+ public function __construct(StreamInterface $stream, $maxLength)
21
+ {
22
+ $this->stream = $stream;
23
+ $this->maxLength = $maxLength;
24
+ }
25
+
26
+ public function write($string)
27
+ {
28
+ $diff = $this->maxLength - $this->stream->getSize();
29
+
30
+ // Begin returning 0 when the underlying stream is too large.
31
+ if ($diff <= 0) {
32
+ return 0;
33
+ }
34
+
35
+ // Write the stream or a subset of the stream if needed.
36
+ if (strlen($string) < $diff) {
37
+ return $this->stream->write($string);
38
+ }
39
+
40
+ return $this->stream->write(substr($string, 0, $diff));
41
+ }
42
+ }
vendor/guzzlehttp/psr7/src/FnStream.php ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Compose stream implementations based on a hash of functions.
8
+ *
9
+ * Allows for easy testing and extension of a provided stream without needing
10
+ * to create a concrete class for a simple extension point.
11
+ */
12
+ class FnStream implements StreamInterface
13
+ {
14
+ /** @var array */
15
+ private $methods;
16
+
17
+ /** @var array Methods that must be implemented in the given array */
18
+ private static $slots = ['__toString', 'close', 'detach', 'rewind',
19
+ 'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write',
20
+ 'isReadable', 'read', 'getContents', 'getMetadata'];
21
+
22
+ /**
23
+ * @param array $methods Hash of method name to a callable.
24
+ */
25
+ public function __construct(array $methods)
26
+ {
27
+ $this->methods = $methods;
28
+
29
+ // Create the functions on the class
30
+ foreach ($methods as $name => $fn) {
31
+ $this->{'_fn_' . $name} = $fn;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Lazily determine which methods are not implemented.
37
+ * @throws \BadMethodCallException
38
+ */
39
+ public function __get($name)
40
+ {
41
+ throw new \BadMethodCallException(str_replace('_fn_', '', $name)
42
+ . '() is not implemented in the FnStream');
43
+ }
44
+
45
+ /**
46
+ * The close method is called on the underlying stream only if possible.
47
+ */
48
+ public function __destruct()
49
+ {
50
+ if (isset($this->_fn_close)) {
51
+ call_user_func($this->_fn_close);
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Adds custom functionality to an underlying stream by intercepting
57
+ * specific method calls.
58
+ *
59
+ * @param StreamInterface $stream Stream to decorate
60
+ * @param array $methods Hash of method name to a closure
61
+ *
62
+ * @return FnStream
63
+ */
64
+ public static function decorate(StreamInterface $stream, array $methods)
65
+ {
66
+ // If any of the required methods were not provided, then simply
67
+ // proxy to the decorated stream.
68
+ foreach (array_diff(self::$slots, array_keys($methods)) as $diff) {
69
+ $methods[$diff] = [$stream, $diff];
70
+ }
71
+
72
+ return new self($methods);
73
+ }
74
+
75
+ public function __toString()
76
+ {
77
+ return call_user_func($this->_fn___toString);
78
+ }
79
+
80
+ public function close()
81
+ {
82
+ return call_user_func($this->_fn_close);
83
+ }
84
+
85
+ public function detach()
86
+ {
87
+ return call_user_func($this->_fn_detach);
88
+ }
89
+
90
+ public function getSize()
91
+ {
92
+ return call_user_func($this->_fn_getSize);
93
+ }
94
+
95
+ public function tell()
96
+ {
97
+ return call_user_func($this->_fn_tell);
98
+ }
99
+
100
+ public function eof()
101
+ {
102
+ return call_user_func($this->_fn_eof);
103
+ }
104
+
105
+ public function isSeekable()
106
+ {
107
+ return call_user_func($this->_fn_isSeekable);
108
+ }
109
+
110
+ public function rewind()
111
+ {
112
+ call_user_func($this->_fn_rewind);
113
+ }
114
+
115
+ public function seek($offset, $whence = SEEK_SET)
116
+ {
117
+ call_user_func($this->_fn_seek, $offset, $whence);
118
+ }
119
+
120
+ public function isWritable()
121
+ {
122
+ return call_user_func($this->_fn_isWritable);
123
+ }
124
+
125
+ public function write($string)
126
+ {
127
+ return call_user_func($this->_fn_write, $string);
128
+ }
129
+
130
+ public function isReadable()
131
+ {
132
+ return call_user_func($this->_fn_isReadable);
133
+ }
134
+
135
+ public function read($length)
136
+ {
137
+ return call_user_func($this->_fn_read, $length);
138
+ }
139
+
140
+ public function getContents()
141
+ {
142
+ return call_user_func($this->_fn_getContents);
143
+ }
144
+
145
+ public function getMetadata($key = null)
146
+ {
147
+ return call_user_func($this->_fn_getMetadata, $key);
148
+ }
149
+ }
vendor/guzzlehttp/psr7/src/InflateStream.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Uses PHP's zlib.inflate filter to inflate deflate or gzipped content.
8
+ *
9
+ * This stream decorator skips the first 10 bytes of the given stream to remove
10
+ * the gzip header, converts the provided stream to a PHP stream resource,
11
+ * then appends the zlib.inflate filter. The stream is then converted back
12
+ * to a Guzzle stream resource to be used as a Guzzle stream.
13
+ *
14
+ * @link http://tools.ietf.org/html/rfc1952
15
+ * @link http://php.net/manual/en/filters.compression.php
16
+ */
17
+ class InflateStream implements StreamInterface
18
+ {
19
+ use StreamDecoratorTrait;
20
+
21
+ public function __construct(StreamInterface $stream)
22
+ {
23
+ // read the first 10 bytes, ie. gzip header
24
+ $header = $stream->read(10);
25
+ $filenameHeaderLength = $this->getLengthOfPossibleFilenameHeader($stream, $header);
26
+ // Skip the header, that is 10 + length of filename + 1 (nil) bytes
27
+ $stream = new LimitStream($stream, -1, 10 + $filenameHeaderLength);
28
+ $resource = StreamWrapper::getResource($stream);
29
+ stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ);
30
+ $this->stream = new Stream($resource);
31
+ }
32
+
33
+ /**
34
+ * @param StreamInterface $stream
35
+ * @param $header
36
+ * @return int
37
+ */
38
+ private function getLengthOfPossibleFilenameHeader(StreamInterface $stream, $header)
39
+ {
40
+ $filename_header_length = 0;
41
+
42
+ if (substr(bin2hex($header), 6, 2) === '08') {
43
+ // we have a filename, read until nil
44
+ $filename_header_length = 1;
45
+ while ($stream->read(1) !== chr(0)) {
46
+ $filename_header_length++;
47
+ }
48
+ }
49
+
50
+ return $filename_header_length;
51
+ }
52
+ }
vendor/guzzlehttp/psr7/src/LazyOpenStream.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Lazily reads or writes to a file that is opened only after an IO operation
8
+ * take place on the stream.
9
+ */
10
+ class LazyOpenStream implements StreamInterface
11
+ {
12
+ use StreamDecoratorTrait;
13
+
14
+ /** @var string File to open */
15
+ private $filename;
16
+
17
+ /** @var string $mode */
18
+ private $mode;
19
+
20
+ /**
21
+ * @param string $filename File to lazily open
22
+ * @param string $mode fopen mode to use when opening the stream
23
+ */
24
+ public function __construct($filename, $mode)
25
+ {
26
+ $this->filename = $filename;
27
+ $this->mode = $mode;
28
+ }
29
+
30
+ /**
31
+ * Creates the underlying stream lazily when required.
32
+ *
33
+ * @return StreamInterface
34
+ */
35
+ protected function createStream()
36
+ {
37
+ return stream_for(try_fopen($this->filename, $this->mode));
38
+ }
39
+ }
vendor/guzzlehttp/psr7/src/LimitStream.php ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+
7
+ /**
8
+ * Decorator used to return only a subset of a stream
9
+ */
10
+ class LimitStream implements StreamInterface
11
+ {
12
+ use StreamDecoratorTrait;
13
+
14
+ /** @var int Offset to start reading from */
15
+ private $offset;
16
+
17
+ /** @var int Limit the number of bytes that can be read */
18
+ private $limit;
19
+
20
+ /**
21
+ * @param StreamInterface $stream Stream to wrap
22
+ * @param int $limit Total number of bytes to allow to be read
23
+ * from the stream. Pass -1 for no limit.
24
+ * @param int $offset Position to seek to before reading (only
25
+ * works on seekable streams).
26
+ */
27
+ public function __construct(
28
+ StreamInterface $stream,
29
+ $limit = -1,
30
+ $offset = 0
31
+ ) {
32
+ $this->stream = $stream;
33
+ $this->setLimit($limit);
34
+ $this->setOffset($offset);
35
+ }
36
+
37
+ public function eof()
38
+ {
39
+ // Always return true if the underlying stream is EOF
40
+ if ($this->stream->eof()) {
41
+ return true;
42
+ }
43
+
44
+ // No limit and the underlying stream is not at EOF
45
+ if ($this->limit == -1) {
46
+ return false;
47
+ }
48
+
49
+ return $this->stream->tell() >= $this->offset + $this->limit;
50
+ }
51
+
52
+ /**
53
+ * Returns the size of the limited subset of data
54
+ * {@inheritdoc}
55
+ */
56
+ public function getSize()
57
+ {
58
+ if (null === ($length = $this->stream->getSize())) {
59
+ return null;
60
+ } elseif ($this->limit == -1) {
61
+ return $length - $this->offset;
62
+ } else {
63
+ return min($this->limit, $length - $this->offset);
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Allow for a bounded seek on the read limited stream
69
+ * {@inheritdoc}
70
+ */
71
+ public function seek($offset, $whence = SEEK_SET)
72
+ {
73
+ if ($whence !== SEEK_SET || $offset < 0) {
74
+ throw new \RuntimeException(sprintf(
75
+ 'Cannot seek to offset % with whence %s',
76
+ $offset,
77
+ $whence
78
+ ));
79
+ }
80
+
81
+ $offset += $this->offset;
82
+
83
+ if ($this->limit !== -1) {
84
+ if ($offset > $this->offset + $this->limit) {
85
+ $offset = $this->offset + $this->limit;
86
+ }
87
+ }
88
+
89
+ $this->stream->seek($offset);
90
+ }
91
+
92
+ /**
93
+ * Give a relative tell()
94
+ * {@inheritdoc}
95
+ */
96
+ public function tell()
97
+ {
98
+ return $this->stream->tell() - $this->offset;
99
+ }
100
+
101
+ /**
102
+ * Set the offset to start limiting from
103
+ *
104
+ * @param int $offset Offset to seek to and begin byte limiting from
105
+ *
106
+ * @throws \RuntimeException if the stream cannot be seeked.
107
+ */
108
+ public function setOffset($offset)
109
+ {
110
+ $current = $this->stream->tell();
111
+
112
+ if ($current !== $offset) {
113
+ // If the stream cannot seek to the offset position, then read to it
114
+ if ($this->stream->isSeekable()) {
115
+ $this->stream->seek($offset);
116
+ } elseif ($current > $offset) {
117
+ throw new \RuntimeException("Could not seek to stream offset $offset");
118
+ } else {
119
+ $this->stream->read($offset - $current);
120
+ }
121
+ }
122
+
123
+ $this->offset = $offset;
124
+ }
125
+
126
+ /**
127
+ * Set the limit of bytes that the decorator allows to be read from the
128
+ * stream.
129
+ *
130
+ * @param int $limit Number of bytes to allow to be read from the stream.
131
+ * Use -1 for no limit.
132
+ */
133
+ public function setLimit($limit)
134
+ {
135
+ $this->limit = $limit;
136
+ }
137
+
138
+ public function read($length)
139
+ {
140
+ if ($this->limit == -1) {
141
+ return $this->stream->read($length);
142
+ }
143
+
144
+ // Check if the current position is less than the total allowed
145
+ // bytes + original offset
146
+ $remaining = ($this->offset + $this->limit) - $this->stream->tell();
147
+ if ($remaining > 0) {
148
+ // Only return the amount of requested data, ensuring that the byte
149
+ // limit is not exceeded
150
+ return $this->stream->read(min($remaining, $length));
151
+ }
152
+
153
+ return '';
154
+ }
155
+ }
vendor/guzzlehttp/psr7/src/MessageTrait.php ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Trait implementing functionality common to requests and responses.
8
+ */
9
+ trait MessageTrait
10
+ {
11
+ /** @var array Map of all registered headers, as original name => array of values */
12
+ private $headers = [];
13
+
14
+ /** @var array Map of lowercase header name => original name at registration */
15
+ private $headerNames = [];
16
+
17
+ /** @var string */
18
+ private $protocol = '1.1';
19
+
20
+ /** @var StreamInterface */
21
+ private $stream;
22
+
23
+ public function getProtocolVersion()
24
+ {
25
+ return $this->protocol;
26
+ }
27
+
28
+ public function withProtocolVersion($version)
29
+ {
30
+ if ($this->protocol === $version) {
31
+ return $this;
32
+ }
33
+
34
+ $new = clone $this;
35
+ $new->protocol = $version;
36
+ return $new;
37
+ }
38
+
39
+ public function getHeaders()
40
+ {
41
+ return $this->headers;
42
+ }
43
+
44
+ public function hasHeader($header)
45
+ {
46
+ return isset($this->headerNames[strtolower($header)]);
47
+ }
48
+
49
+ public function getHeader($header)
50
+ {
51
+ $header = strtolower($header);
52
+
53
+ if (!isset($this->headerNames[$header])) {
54
+ return [];
55
+ }
56
+
57
+ $header = $this->headerNames[$header];
58
+
59
+ return $this->headers[$header];
60
+ }
61
+
62
+ public function getHeaderLine($header)
63
+ {
64
+ return implode(', ', $this->getHeader($header));
65
+ }
66
+
67
+ public function withHeader($header, $value)
68
+ {
69
+ if (!is_array($value)) {
70
+ $value = [$value];
71
+ }
72
+
73
+ $value = $this->trimHeaderValues($value);
74
+ $normalized = strtolower($header);
75
+
76
+ $new = clone $this;
77
+ if (isset($new->headerNames[$normalized])) {
78
+ unset($new->headers[$new->headerNames[$normalized]]);
79
+ }
80
+ $new->headerNames[$normalized] = $header;
81
+ $new->headers[$header] = $value;
82
+
83
+ return $new;
84
+ }
85
+
86
+ public function withAddedHeader($header, $value)
87
+ {
88
+ if (!is_array($value)) {
89
+ $value = [$value];
90
+ }
91
+
92
+ $value = $this->trimHeaderValues($value);
93
+ $normalized = strtolower($header);
94
+
95
+ $new = clone $this;
96
+ if (isset($new->headerNames[$normalized])) {
97
+ $header = $this->headerNames[$normalized];
98
+ $new->headers[$header] = array_merge($this->headers[$header], $value);
99
+ } else {
100
+ $new->headerNames[$normalized] = $header;
101
+ $new->headers[$header] = $value;
102
+ }
103
+
104
+ return $new;
105
+ }
106
+
107
+ public function withoutHeader($header)
108
+ {
109
+ $normalized = strtolower($header);
110
+
111
+ if (!isset($this->headerNames[$normalized])) {
112
+ return $this;
113
+ }
114
+
115
+ $header = $this->headerNames[$normalized];
116
+
117
+ $new = clone $this;
118
+ unset($new->headers[$header], $new->headerNames[$normalized]);
119
+
120
+ return $new;
121
+ }
122
+
123
+ public function getBody()
124
+ {
125
+ if (!$this->stream) {
126
+ $this->stream = stream_for('');
127
+ }
128
+
129
+ return $this->stream;
130
+ }
131
+
132
+ public function withBody(StreamInterface $body)
133
+ {
134
+ if ($body === $this->stream) {
135
+ return $this;
136
+ }
137
+
138
+ $new = clone $this;
139
+ $new->stream = $body;
140
+ return $new;
141
+ }
142
+
143
+ private function setHeaders(array $headers)
144
+ {
145
+ $this->headerNames = $this->headers = [];
146
+ foreach ($headers as $header => $value) {
147
+ if (!is_array($value)) {
148
+ $value = [$value];
149
+ }
150
+
151
+ $value = $this->trimHeaderValues($value);
152
+ $normalized = strtolower($header);
153
+ if (isset($this->headerNames[$normalized])) {
154
+ $header = $this->headerNames[$normalized];
155
+ $this->headers[$header] = array_merge($this->headers[$header], $value);
156
+ } else {
157
+ $this->headerNames[$normalized] = $header;
158
+ $this->headers[$header] = $value;
159
+ }
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Trims whitespace from the header values.
165
+ *
166
+ * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field.
167
+ *
168
+ * header-field = field-name ":" OWS field-value OWS
169
+ * OWS = *( SP / HTAB )
170
+ *
171
+ * @param string[] $values Header values
172
+ *
173
+ * @return string[] Trimmed header values
174
+ *
175
+ * @see https://tools.ietf.org/html/rfc7230#section-3.2.4
176
+ */
177
+ private function trimHeaderValues(array $values)
178
+ {
179
+ return array_map(function ($value) {
180
+ return trim($value, " \t");
181
+ }, $values);
182
+ }
183
+ }
vendor/guzzlehttp/psr7/src/MultipartStream.php ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Stream that when read returns bytes for a streaming multipart or
8
+ * multipart/form-data stream.
9
+ */
10
+ class MultipartStream implements StreamInterface
11
+ {
12
+ use StreamDecoratorTrait;
13
+
14
+ private $boundary;
15
+
16
+ /**
17
+ * @param array $elements Array of associative arrays, each containing a
18
+ * required "name" key mapping to the form field,
19
+ * name, a required "contents" key mapping to a
20
+ * StreamInterface/resource/string, an optional
21
+ * "headers" associative array of custom headers,
22
+ * and an optional "filename" key mapping to a
23
+ * string to send as the filename in the part.
24
+ * @param string $boundary You can optionally provide a specific boundary
25
+ *
26
+ * @throws \InvalidArgumentException
27
+ */
28
+ public function __construct(array $elements = [], $boundary = null)
29
+ {
30
+ $this->boundary = $boundary ?: sha1(uniqid('', true));
31
+ $this->stream = $this->createStream($elements);
32
+ }
33
+
34
+ /**
35
+ * Get the boundary
36
+ *
37
+ * @return string
38
+ */
39
+ public function getBoundary()
40
+ {
41
+ return $this->boundary;
42
+ }
43
+
44
+ public function isWritable()
45
+ {
46
+ return false;
47
+ }
48
+
49
+ /**
50
+ * Get the headers needed before transferring the content of a POST file
51
+ */
52
+ private function getHeaders(array $headers)
53
+ {
54
+ $str = '';
55
+ foreach ($headers as $key => $value) {
56
+ $str .= "{$key}: {$value}\r\n";
57
+ }
58
+
59
+ return "--{$this->boundary}\r\n" . trim($str) . "\r\n\r\n";
60
+ }
61
+
62
+ /**
63
+ * Create the aggregate stream that will be used to upload the POST data
64
+ */
65
+ protected function createStream(array $elements)
66
+ {
67
+ $stream = new AppendStream();
68
+
69
+ foreach ($elements as $element) {
70
+ $this->addElement($stream, $element);
71
+ }
72
+
73
+ // Add the trailing boundary with CRLF
74
+ $stream->addStream(stream_for("--{$this->boundary}--\r\n"));
75
+
76
+ return $stream;
77
+ }
78
+
79
+ private function addElement(AppendStream $stream, array $element)
80
+ {
81
+ foreach (['contents', 'name'] as $key) {
82
+ if (!array_key_exists($key, $element)) {
83
+ throw new \InvalidArgumentException("A '{$key}' key is required");
84
+ }
85
+ }
86
+
87
+ $element['contents'] = stream_for($element['contents']);
88
+
89
+ if (empty($element['filename'])) {
90
+ $uri = $element['contents']->getMetadata('uri');
91
+ if (substr($uri, 0, 6) !== 'php://') {
92
+ $element['filename'] = $uri;
93
+ }
94
+ }
95
+
96
+ list($body, $headers) = $this->createElement(
97
+ $element['name'],
98
+ $element['contents'],
99
+ isset($element['filename']) ? $element['filename'] : null,
100
+ isset($element['headers']) ? $element['headers'] : []
101
+ );
102
+
103
+ $stream->addStream(stream_for($this->getHeaders($headers)));
104
+ $stream->addStream($body);
105
+ $stream->addStream(stream_for("\r\n"));
106
+ }
107
+
108
+ /**
109
+ * @return array
110
+ */
111
+ private function createElement($name, StreamInterface $stream, $filename, array $headers)
112
+ {
113
+ // Set a default content-disposition header if one was no provided
114
+ $disposition = $this->getHeader($headers, 'content-disposition');
115
+ if (!$disposition) {
116
+ $headers['Content-Disposition'] = ($filename === '0' || $filename)
117
+ ? sprintf('form-data; name="%s"; filename="%s"',
118
+ $name,
119
+ basename($filename))
120
+ : "form-data; name=\"{$name}\"";
121
+ }
122
+
123
+ // Set a default content-length header if one was no provided
124
+ $length = $this->getHeader($headers, 'content-length');
125
+ if (!$length) {
126
+ if ($length = $stream->getSize()) {
127
+ $headers['Content-Length'] = (string) $length;
128
+ }
129
+ }
130
+
131
+ // Set a default Content-Type if one was not supplied
132
+ $type = $this->getHeader($headers, 'content-type');
133
+ if (!$type && ($filename === '0' || $filename)) {
134
+ if ($type = mimetype_from_filename($filename)) {
135
+ $headers['Content-Type'] = $type;
136
+ }
137
+ }
138
+
139
+ return [$stream, $headers];
140
+ }
141
+
142
+ private function getHeader(array $headers, $key)
143
+ {
144
+ $lowercaseHeader = strtolower($key);
145
+ foreach ($headers as $k => $v) {
146
+ if (strtolower($k) === $lowercaseHeader) {
147
+ return $v;
148
+ }
149
+ }
150
+
151
+ return null;
152
+ }
153
+ }
vendor/guzzlehttp/psr7/src/NoSeekStream.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Stream decorator that prevents a stream from being seeked
8
+ */
9
+ class NoSeekStream implements StreamInterface
10
+ {
11
+ use StreamDecoratorTrait;
12
+
13
+ public function seek($offset, $whence = SEEK_SET)
14
+ {
15
+ throw new \RuntimeException('Cannot seek a NoSeekStream');
16
+ }
17
+
18
+ public function isSeekable()
19
+ {
20
+ return false;
21
+ }
22
+ }
vendor/guzzlehttp/psr7/src/PumpStream.php ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Provides a read only stream that pumps data from a PHP callable.
8
+ *
9
+ * When invoking the provided callable, the PumpStream will pass the amount of
10
+ * data requested to read to the callable. The callable can choose to ignore
11
+ * this value and return fewer or more bytes than requested. Any extra data
12
+ * returned by the provided callable is buffered internally until drained using
13
+ * the read() function of the PumpStream. The provided callable MUST return
14
+ * false when there is no more data to read.
15
+ */
16
+ class PumpStream implements StreamInterface
17
+ {
18
+ /** @var callable */
19
+ private $source;
20
+
21
+ /** @var int */
22
+ private $size;
23
+
24
+ /** @var int */
25
+ private $tellPos = 0;
26
+
27
+ /** @var array */
28
+ private $metadata;
29
+
30
+ /** @var BufferStream */
31
+ private $buffer;
32
+
33
+ /**
34
+ * @param callable $source Source of the stream data. The callable MAY
35
+ * accept an integer argument used to control the
36
+ * amount of data to return. The callable MUST
37
+ * return a string when called, or false on error
38
+ * or EOF.
39
+ * @param array $options Stream options:
40
+ * - metadata: Hash of metadata to use with stream.
41
+ * - size: Size of the stream, if known.
42
+ */
43
+ public function __construct(callable $source, array $options = [])
44
+ {
45
+ $this->source = $source;
46
+ $this->size = isset($options['size']) ? $options['size'] : null;
47
+ $this->metadata = isset($options['metadata']) ? $options['metadata'] : [];
48
+ $this->buffer = new BufferStream();
49
+ }
50
+
51
+ public function __toString()
52
+ {
53
+ try {
54
+ return copy_to_string($this);
55
+ } catch (\Exception $e) {
56
+ return '';
57
+ }
58
+ }
59
+
60
+ public function close()
61
+ {
62
+ $this->detach();
63
+ }
64
+
65
+ public function detach()
66
+ {
67
+ $this->tellPos = false;
68
+ $this->source = null;
69
+ }
70
+
71
+ public function getSize()
72
+ {
73
+ return $this->size;
74
+ }
75
+
76
+ public function tell()
77
+ {
78
+ return $this->tellPos;
79
+ }
80
+
81
+ public function eof()
82
+ {
83
+ return !$this->source;
84
+ }
85
+
86
+ public function isSeekable()
87
+ {
88
+ return false;
89
+ }
90
+
91
+ public function rewind()
92
+ {
93
+ $this->seek(0);
94
+ }
95
+
96
+ public function seek($offset, $whence = SEEK_SET)
97
+ {
98
+ throw new \RuntimeException('Cannot seek a PumpStream');
99
+ }
100
+
101
+ public function isWritable()
102
+ {
103
+ return false;
104
+ }
105
+
106
+ public function write($string)
107
+ {
108
+ throw new \RuntimeException('Cannot write to a PumpStream');
109
+ }
110
+
111
+ public function isReadable()
112
+ {
113
+ return true;
114
+ }
115
+
116
+ public function read($length)
117
+ {
118
+ $data = $this->buffer->read($length);
119
+ $readLen = strlen($data);
120
+ $this->tellPos += $readLen;
121
+ $remaining = $length - $readLen;
122
+
123
+ if ($remaining) {
124
+ $this->pump($remaining);
125
+ $data .= $this->buffer->read($remaining);
126
+ $this->tellPos += strlen($data) - $readLen;
127
+ }
128
+
129
+ return $data;
130
+ }
131
+
132
+ public function getContents()
133
+ {
134
+ $result = '';
135
+ while (!$this->eof()) {
136
+ $result .= $this->read(1000000);
137
+ }
138
+
139
+ return $result;
140
+ }
141
+
142
+ public function getMetadata($key = null)
143
+ {
144
+ if (!$key) {
145
+ return $this->metadata;
146
+ }
147
+
148
+ return isset($this->metadata[$key]) ? $this->metadata[$key] : null;
149
+ }
150
+
151
+ private function pump($length)
152
+ {
153
+ if ($this->source) {
154
+ do {
155
+ $data = call_user_func($this->source, $length);
156
+ if ($data === false || $data === null) {
157
+ $this->source = null;
158
+ return;
159
+ }
160
+ $this->buffer->write($data);
161
+ $length -= strlen($data);
162
+ } while ($length > 0);
163
+ }
164
+ }
165
+ }
vendor/guzzlehttp/psr7/src/Request.php ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use InvalidArgumentException;
5
+ use Psr\Http\Message\RequestInterface;
6
+ use Psr\Http\Message\StreamInterface;
7
+ use Psr\Http\Message\UriInterface;
8
+
9
+ /**
10
+ * PSR-7 request implementation.
11
+ */
12
+ class Request implements RequestInterface
13
+ {
14
+ use MessageTrait;
15
+
16
+ /** @var string */
17
+ private $method;
18
+
19
+ /** @var null|string */
20
+ private $requestTarget;
21
+
22
+ /** @var UriInterface */
23
+ private $uri;
24
+
25
+ /**
26
+ * @param string $method HTTP method
27
+ * @param string|UriInterface $uri URI
28
+ * @param array $headers Request headers
29
+ * @param string|null|resource|StreamInterface $body Request body
30
+ * @param string $version Protocol version
31
+ */
32
+ public function __construct(
33
+ $method,
34
+ $uri,
35
+ array $headers = [],
36
+ $body = null,
37
+ $version = '1.1'
38
+ ) {
39
+ if (!($uri instanceof UriInterface)) {
40
+ $uri = new Uri($uri);
41
+ }
42
+
43
+ $this->method = strtoupper($method);
44
+ $this->uri = $uri;
45
+ $this->setHeaders($headers);
46
+ $this->protocol = $version;
47
+
48
+ if (!$this->hasHeader('Host')) {
49
+ $this->updateHostFromUri();
50
+ }
51
+
52
+ if ($body !== '' && $body !== null) {
53
+ $this->stream = stream_for($body);
54
+ }
55
+ }
56
+
57
+ public function getRequestTarget()
58
+ {
59
+ if ($this->requestTarget !== null) {
60
+ return $this->requestTarget;
61
+ }
62
+
63
+ $target = $this->uri->getPath();
64
+ if ($target == '') {
65
+ $target = '/';
66
+ }
67
+ if ($this->uri->getQuery() != '') {
68
+ $target .= '?' . $this->uri->getQuery();
69
+ }
70
+
71
+ return $target;
72
+ }
73
+
74
+ public function withRequestTarget($requestTarget)
75
+ {
76
+ if (preg_match('#\s#', $requestTarget)) {
77
+ throw new InvalidArgumentException(
78
+ 'Invalid request target provided; cannot contain whitespace'
79
+ );
80
+ }
81
+
82
+ $new = clone $this;
83
+ $new->requestTarget = $requestTarget;
84
+ return $new;
85
+ }
86
+
87
+ public function getMethod()
88
+ {
89
+ return $this->method;
90
+ }
91
+
92
+ public function withMethod($method)
93
+ {
94
+ $new = clone $this;
95
+ $new->method = strtoupper($method);
96
+ return $new;
97
+ }
98
+
99
+ public function getUri()
100
+ {
101
+ return $this->uri;
102
+ }
103
+
104
+ public function withUri(UriInterface $uri, $preserveHost = false)
105
+ {
106
+ if ($uri === $this->uri) {
107
+ return $this;
108
+ }
109
+
110
+ $new = clone $this;
111
+ $new->uri = $uri;
112
+
113
+ if (!$preserveHost) {
114
+ $new->updateHostFromUri();
115
+ }
116
+
117
+ return $new;
118
+ }
119
+
120
+ private function updateHostFromUri()
121
+ {
122
+ $host = $this->uri->getHost();
123
+
124
+ if ($host == '') {
125
+ return;
126
+ }
127
+
128
+ if (($port = $this->uri->getPort()) !== null) {
129
+ $host .= ':' . $port;
130
+ }
131
+
132
+ if (isset($this->headerNames['host'])) {
133
+ $header = $this->headerNames['host'];
134
+ } else {
135
+ $header = 'Host';
136
+ $this->headerNames['host'] = 'Host';
137
+ }
138
+ // Ensure Host is the first header.
139
+ // See: http://tools.ietf.org/html/rfc7230#section-5.4
140
+ $this->headers = [$header => [$host]] + $this->headers;
141
+ }
142
+ }
vendor/guzzlehttp/psr7/src/Response.php ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\ResponseInterface;
5
+ use Psr\Http\Message\StreamInterface;
6
+
7
+ /**
8
+ * PSR-7 response implementation.
9
+ */
10
+ class Response implements ResponseInterface
11
+ {
12
+ use MessageTrait;
13
+
14
+ /** @var array Map of standard HTTP status code/reason phrases */
15
+ private static $phrases = [
16
+ 100 => 'Continue',
17
+ 101 => 'Switching Protocols',
18
+ 102 => 'Processing',
19
+ 200 => 'OK',
20
+ 201 => 'Created',
21
+ 202 => 'Accepted',
22
+ 203 => 'Non-Authoritative Information',
23
+ 204 => 'No Content',
24
+ 205 => 'Reset Content',
25
+ 206 => 'Partial Content',
26
+ 207 => 'Multi-status',
27
+ 208 => 'Already Reported',
28
+ 300 => 'Multiple Choices',
29
+ 301 => 'Moved Permanently',
30
+ 302 => 'Found',
31
+ 303 => 'See Other',
32
+ 304 => 'Not Modified',
33
+ 305 => 'Use Proxy',
34
+ 306 => 'Switch Proxy',
35
+ 307 => 'Temporary Redirect',
36
+ 400 => 'Bad Request',
37
+ 401 => 'Unauthorized',
38
+ 402 => 'Payment Required',
39
+ 403 => 'Forbidden',
40
+ 404 => 'Not Found',
41
+ 405 => 'Method Not Allowed',
42
+ 406 => 'Not Acceptable',
43
+ 407 => 'Proxy Authentication Required',
44
+ 408 => 'Request Time-out',
45
+ 409 => 'Conflict',
46
+ 410 => 'Gone',
47
+ 411 => 'Length Required',
48
+ 412 => 'Precondition Failed',
49
+ 413 => 'Request Entity Too Large',
50
+ 414 => 'Request-URI Too Large',
51
+ 415 => 'Unsupported Media Type',
52
+ 416 => 'Requested range not satisfiable',
53
+ 417 => 'Expectation Failed',
54
+ 418 => 'I\'m a teapot',
55
+ 422 => 'Unprocessable Entity',
56
+ 423 => 'Locked',
57
+ 424 => 'Failed Dependency',
58
+ 425 => 'Unordered Collection',
59
+ 426 => 'Upgrade Required',
60
+ 428 => 'Precondition Required',
61
+ 429 => 'Too Many Requests',
62
+ 431 => 'Request Header Fields Too Large',
63
+ 451 => 'Unavailable For Legal Reasons',
64
+ 500 => 'Internal Server Error',
65
+ 501 => 'Not Implemented',
66
+ 502 => 'Bad Gateway',
67
+ 503 => 'Service Unavailable',
68
+ 504 => 'Gateway Time-out',
69
+ 505 => 'HTTP Version not supported',
70
+ 506 => 'Variant Also Negotiates',
71
+ 507 => 'Insufficient Storage',
72
+ 508 => 'Loop Detected',
73
+ 511 => 'Network Authentication Required',
74
+ ];
75
+
76
+ /** @var string */
77
+ private $reasonPhrase = '';
78
+
79
+ /** @var int */
80
+ private $statusCode = 200;
81
+
82
+ /**
83
+ * @param int $status Status code
84
+ * @param array $headers Response headers
85
+ * @param string|null|resource|StreamInterface $body Response body
86
+ * @param string $version Protocol version
87
+ * @param string|null $reason Reason phrase (when empty a default will be used based on the status code)
88
+ */
89
+ public function __construct(
90
+ $status = 200,
91
+ array $headers = [],
92
+ $body = null,
93
+ $version = '1.1',
94
+ $reason = null
95
+ ) {
96
+ $this->statusCode = (int) $status;
97
+
98
+ if ($body !== '' && $body !== null) {
99
+ $this->stream = stream_for($body);
100
+ }
101
+
102
+ $this->setHeaders($headers);
103
+ if ($reason == '' && isset(self::$phrases[$this->statusCode])) {
104
+ $this->reasonPhrase = self::$phrases[$this->statusCode];
105
+ } else {
106
+ $this->reasonPhrase = (string) $reason;
107
+ }
108
+
109
+ $this->protocol = $version;
110
+ }
111
+
112
+ public function getStatusCode()
113
+ {
114
+ return $this->statusCode;
115
+ }
116
+
117
+ public function getReasonPhrase()
118
+ {
119
+ return $this->reasonPhrase;
120
+ }
121
+
122
+ public function withStatus($code, $reasonPhrase = '')
123
+ {
124
+ $new = clone $this;
125
+ $new->statusCode = (int) $code;
126
+ if ($reasonPhrase == '' && isset(self::$phrases[$new->statusCode])) {
127
+ $reasonPhrase = self::$phrases[$new->statusCode];
128
+ }
129
+ $new->reasonPhrase = $reasonPhrase;
130
+ return $new;
131
+ }
132
+ }
vendor/guzzlehttp/psr7/src/ServerRequest.php ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Psr7;
4
+
5
+ use InvalidArgumentException;
6
+ use Psr\Http\Message\ServerRequestInterface;
7
+ use Psr\Http\Message\UriInterface;
8
+ use Psr\Http\Message\StreamInterface;
9
+ use Psr\Http\Message\UploadedFileInterface;
10
+
11
+ /**
12
+ * Server-side HTTP request
13
+ *
14
+ * Extends the Request definition to add methods for accessing incoming data,
15
+ * specifically server parameters, cookies, matched path parameters, query
16
+ * string arguments, body parameters, and upload file information.
17
+ *
18
+ * "Attributes" are discovered via decomposing the request (and usually
19
+ * specifically the URI path), and typically will be injected by the application.
20
+ *
21
+ * Requests are considered immutable; all methods that might change state are
22
+ * implemented such that they retain the internal state of the current
23
+ * message and return a new instance that contains the changed state.
24
+ */
25
+ class ServerRequest extends Request implements ServerRequestInterface
26
+ {
27
+ /**
28
+ * @var array
29
+ */
30
+ private $attributes = [];
31
+
32
+ /**
33
+ * @var array
34
+ */
35
+ private $cookieParams = [];
36
+
37
+ /**
38
+ * @var null|array|object
39
+ */
40
+ private $parsedBody;
41
+
42
+ /**
43
+ * @var array
44
+ */
45
+ private $queryParams = [];
46
+
47
+ /**
48
+ * @var array
49
+ */
50
+ private $serverParams;
51
+
52
+ /**
53
+ * @var array
54
+ */
55
+ private $uploadedFiles = [];
56
+
57
+ /**
58
+ * @param string $method HTTP method
59
+ * @param string|UriInterface $uri URI
60
+ * @param array $headers Request headers
61
+ * @param string|null|resource|StreamInterface $body Request body
62
+ * @param string $version Protocol version
63
+ * @param array $serverParams Typically the $_SERVER superglobal
64
+ */
65
+ public function __construct(
66
+ $method,
67
+ $uri,
68
+ array $headers = [],
69
+ $body = null,
70
+ $version = '1.1',
71
+ array $serverParams = []
72
+ ) {
73
+ $this->serverParams = $serverParams;
74
+
75
+ parent::__construct($method, $uri, $headers, $body, $version);
76
+ }
77
+
78
+ /**
79
+ * Return an UploadedFile instance array.
80
+ *
81
+ * @param array $files A array which respect $_FILES structure
82
+ * @throws InvalidArgumentException for unrecognized values
83
+ * @return array
84
+ */
85
+ public static function normalizeFiles(array $files)
86
+ {
87
+ $normalized = [];
88
+
89
+ foreach ($files as $key => $value) {
90
+ if ($value instanceof UploadedFileInterface) {
91
+ $normalized[$key] = $value;
92
+ } elseif (is_array($value) && isset($value['tmp_name'])) {
93
+ $normalized[$key] = self::createUploadedFileFromSpec($value);
94
+ } elseif (is_array($value)) {
95
+ $normalized[$key] = self::normalizeFiles($value);
96
+ continue;
97
+ } else {
98
+ throw new InvalidArgumentException('Invalid value in files specification');
99
+ }
100
+ }
101
+
102
+ return $normalized;
103
+ }
104
+
105
+ /**
106
+ * Create and return an UploadedFile instance from a $_FILES specification.
107
+ *
108
+ * If the specification represents an array of values, this method will
109
+ * delegate to normalizeNestedFileSpec() and return that return value.
110
+ *
111
+ * @param array $value $_FILES struct
112
+ * @return array|UploadedFileInterface
113
+ */
114
+ private static function createUploadedFileFromSpec(array $value)
115
+ {
116
+ if (is_array($value['tmp_name'])) {
117
+ return self::normalizeNestedFileSpec($value);
118
+ }
119
+
120
+ return new UploadedFile(
121
+ $value['tmp_name'],
122
+ (int) $value['size'],
123
+ (int) $value['error'],
124
+ $value['name'],
125
+ $value['type']
126
+ );
127
+ }
128
+
129
+ /**
130
+ * Normalize an array of file specifications.
131
+ *
132
+ * Loops through all nested files and returns a normalized array of
133
+ * UploadedFileInterface instances.
134
+ *
135
+ * @param array $files
136
+ * @return UploadedFileInterface[]
137
+ */
138
+ private static function normalizeNestedFileSpec(array $files = [])
139
+ {
140
+ $normalizedFiles = [];
141
+
142
+ foreach (array_keys($files['tmp_name']) as $key) {
143
+ $spec = [
144
+ 'tmp_name' => $files['tmp_name'][$key],
145
+ 'size' => $files['size'][$key],
146
+ 'error' => $files['error'][$key],
147
+ 'name' => $files['name'][$key],
148
+ 'type' => $files['type'][$key],
149
+ ];
150
+ $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec);
151
+ }
152
+
153
+ return $normalizedFiles;
154
+ }
155
+
156
+ /**
157
+ * Return a ServerRequest populated with superglobals:
158
+ * $_GET
159
+ * $_POST
160
+ * $_COOKIE
161
+ * $_FILES
162
+ * $_SERVER
163
+ *
164
+ * @return ServerRequestInterface
165
+ */
166
+ public static function fromGlobals()
167
+ {
168
+ $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
169
+ $headers = function_exists('getallheaders') ? getallheaders() : [];
170
+ $uri = self::getUriFromGlobals();
171
+ $body = new LazyOpenStream('php://input', 'r+');
172
+ $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1';
173
+
174
+ $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER);
175
+
176
+ return $serverRequest
177
+ ->withCookieParams($_COOKIE)
178
+ ->withQueryParams($_GET)
179
+ ->withParsedBody($_POST)
180
+ ->withUploadedFiles(self::normalizeFiles($_FILES));
181
+ }
182
+
183
+ /**
184
+ * Get a Uri populated with values from $_SERVER.
185
+ *
186
+ * @return UriInterface
187
+ */
188
+ public static function getUriFromGlobals() {
189
+ $uri = new Uri('');
190
+
191
+ $uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');
192
+
193
+ $hasPort = false;
194
+ if (isset($_SERVER['HTTP_HOST'])) {
195
+ $hostHeaderParts = explode(':', $_SERVER['HTTP_HOST']);
196
+ $uri = $uri->withHost($hostHeaderParts[0]);
197
+ if (isset($hostHeaderParts[1])) {
198
+ $hasPort = true;
199
+ $uri = $uri->withPort($hostHeaderParts[1]);
200
+ }
201
+ } elseif (isset($_SERVER['SERVER_NAME'])) {
202
+ $uri = $uri->withHost($_SERVER['SERVER_NAME']);
203
+ } elseif (isset($_SERVER['SERVER_ADDR'])) {
204
+ $uri = $uri->withHost($_SERVER['SERVER_ADDR']);
205
+ }
206
+
207
+ if (!$hasPort && isset($_SERVER['SERVER_PORT'])) {
208
+ $uri = $uri->withPort($_SERVER['SERVER_PORT']);
209
+ }
210
+
211
+ $hasQuery = false;
212
+ if (isset($_SERVER['REQUEST_URI'])) {
213
+ $requestUriParts = explode('?', $_SERVER['REQUEST_URI']);
214
+ $uri = $uri->withPath($requestUriParts[0]);
215
+ if (isset($requestUriParts[1])) {
216
+ $hasQuery = true;
217
+ $uri = $uri->withQuery($requestUriParts[1]);
218
+ }
219
+ }
220
+
221
+ if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) {
222
+ $uri = $uri->withQuery($_SERVER['QUERY_STRING']);
223
+ }
224
+
225
+ return $uri;
226
+ }
227
+
228
+
229
+ /**
230
+ * {@inheritdoc}
231
+ */
232
+ public function getServerParams()
233
+ {
234
+ return $this->serverParams;
235
+ }
236
+
237
+ /**
238
+ * {@inheritdoc}
239
+ */
240
+ public function getUploadedFiles()
241
+ {
242
+ return $this->uploadedFiles;
243
+ }
244
+
245
+ /**
246
+ * {@inheritdoc}
247
+ */
248
+ public function withUploadedFiles(array $uploadedFiles)
249
+ {
250
+ $new = clone $this;
251
+ $new->uploadedFiles = $uploadedFiles;
252
+
253
+ return $new;
254
+ }
255
+
256
+ /**
257
+ * {@inheritdoc}
258
+ */
259
+ public function getCookieParams()
260
+ {
261
+ return $this->cookieParams;
262
+ }
263
+
264
+ /**
265
+ * {@inheritdoc}
266
+ */
267
+ public function withCookieParams(array $cookies)
268
+ {
269
+ $new = clone $this;
270
+ $new->cookieParams = $cookies;
271
+
272
+ return $new;
273
+ }
274
+
275
+ /**
276
+ * {@inheritdoc}
277
+ */
278
+ public function getQueryParams()
279
+ {
280
+ return $this->queryParams;
281
+ }
282
+
283
+ /**
284
+ * {@inheritdoc}
285
+ */
286
+ public function withQueryParams(array $query)
287
+ {
288
+ $new = clone $this;
289
+ $new->queryParams = $query;
290
+
291
+ return $new;
292
+ }
293
+
294
+ /**
295
+ * {@inheritdoc}
296
+ */
297
+ public function getParsedBody()
298
+ {
299
+ return $this->parsedBody;
300
+ }
301
+
302
+ /**
303
+ * {@inheritdoc}
304
+ */
305
+ public function withParsedBody($data)
306
+ {
307
+ $new = clone $this;
308
+ $new->parsedBody = $data;
309
+
310
+ return $new;
311
+ }
312
+
313
+ /**
314
+ * {@inheritdoc}
315
+ */
316
+ public function getAttributes()
317
+ {
318
+ return $this->attributes;
319
+ }
320
+
321
+ /**
322
+ * {@inheritdoc}
323
+ */
324
+ public function getAttribute($attribute, $default = null)
325
+ {
326
+ if (false === array_key_exists($attribute, $this->attributes)) {
327
+ return $default;
328
+ }
329
+
330
+ return $this->attributes[$attribute];
331
+ }
332
+
333
+ /**
334
+ * {@inheritdoc}
335
+ */
336
+ public function withAttribute($attribute, $value)
337
+ {
338
+ $new = clone $this;
339
+ $new->attributes[$attribute] = $value;
340
+
341
+ return $new;
342
+ }
343
+
344
+ /**
345
+ * {@inheritdoc}
346
+ */
347
+ public function withoutAttribute($attribute)
348
+ {
349
+ if (false === array_key_exists($attribute, $this->attributes)) {
350
+ return $this;
351
+ }
352
+
353
+ $new = clone $this;
354
+ unset($new->attributes[$attribute]);
355
+
356
+ return $new;
357
+ }
358
+ }
vendor/guzzlehttp/psr7/src/Stream.php ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * PHP stream implementation.
8
+ *
9
+ * @var $stream
10
+ */
11
+ class Stream implements StreamInterface
12
+ {
13
+ private $stream;
14
+ private $size;
15
+ private $seekable;
16
+ private $readable;
17
+ private $writable;
18
+ private $uri;
19
+ private $customMetadata;
20
+
21
+ /** @var array Hash of readable and writable stream types */
22
+ private static $readWriteHash = [
23
+ 'read' => [
24
+ 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
25
+ 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
26
+ 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
27
+ 'x+t' => true, 'c+t' => true, 'a+' => true
28
+ ],
29
+ 'write' => [
30
+ 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
31
+ 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true,
32
+ 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
33
+ 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
34
+ ]
35
+ ];
36
+
37
+ /**
38
+ * This constructor accepts an associative array of options.
39
+ *
40
+ * - size: (int) If a read stream would otherwise have an indeterminate
41
+ * size, but the size is known due to foreknowledge, then you can
42
+ * provide that size, in bytes.
43
+ * - metadata: (array) Any additional metadata to return when the metadata
44
+ * of the stream is accessed.
45
+ *
46
+ * @param resource $stream Stream resource to wrap.
47
+ * @param array $options Associative array of options.
48
+ *
49
+ * @throws \InvalidArgumentException if the stream is not a stream resource
50
+ */
51
+ public function __construct($stream, $options = [])
52
+ {
53
+ if (!is_resource($stream)) {
54
+ throw new \InvalidArgumentException('Stream must be a resource');
55
+ }
56
+
57
+ if (isset($options['size'])) {
58
+ $this->size = $options['size'];
59
+ }
60
+
61
+ $this->customMetadata = isset($options['metadata'])
62
+ ? $options['metadata']
63
+ : [];
64
+
65
+ $this->stream = $stream;
66
+ $meta = stream_get_meta_data($this->stream);
67
+ $this->seekable = $meta['seekable'];
68
+ $this->readable = isset(self::$readWriteHash['read'][$meta['mode']]);
69
+ $this->writable = isset(self::$readWriteHash['write'][$meta['mode']]);
70
+ $this->uri = $this->getMetadata('uri');
71
+ }
72
+
73
+ public function __get($name)
74
+ {
75
+ if ($name == 'stream') {
76
+ throw new \RuntimeException('The stream is detached');
77
+ }
78
+
79
+ throw new \BadMethodCallException('No value for ' . $name);
80
+ }
81
+
82
+ /**
83
+ * Closes the stream when the destructed
84
+ */
85
+ public function __destruct()
86
+ {
87
+ $this->close();
88
+ }
89
+
90
+ public function __toString()
91
+ {
92
+ try {
93
+ $this->seek(0);
94
+ return (string) stream_get_contents($this->stream);
95
+ } catch (\Exception $e) {
96
+ return '';
97
+ }
98
+ }
99
+
100
+ public function getContents()
101
+ {
102
+ $contents = stream_get_contents($this->stream);
103
+
104
+ if ($contents === false) {
105
+ throw new \RuntimeException('Unable to read stream contents');
106
+ }
107
+
108
+ return $contents;
109
+ }
110
+
111
+ public function close()
112
+ {
113
+ if (isset($this->stream)) {
114
+ if (is_resource($this->stream)) {
115
+ fclose($this->stream);
116
+ }
117
+ $this->detach();
118
+ }
119
+ }
120
+
121
+ public function detach()
122
+ {
123
+ if (!isset($this->stream)) {
124
+ return null;
125
+ }
126
+
127
+ $result = $this->stream;
128
+ unset($this->stream);
129
+ $this->size = $this->uri = null;
130
+ $this->readable = $this->writable = $this->seekable = false;
131
+
132
+ return $result;
133
+ }
134
+
135
+ public function getSize()
136
+ {
137
+ if ($this->size !== null) {
138
+ return $this->size;
139
+ }
140
+
141
+ if (!isset($this->stream)) {
142
+ return null;
143
+ }
144
+
145
+ // Clear the stat cache if the stream has a URI
146
+ if ($this->uri) {
147
+ clearstatcache(true, $this->uri);
148
+ }
149
+
150
+ $stats = fstat($this->stream);
151
+ if (isset($stats['size'])) {
152
+ $this->size = $stats['size'];
153
+ return $this->size;
154
+ }
155
+
156
+ return null;
157
+ }
158
+
159
+ public function isReadable()
160
+ {
161
+ return $this->readable;
162
+ }
163
+
164
+ public function isWritable()
165
+ {
166
+ return $this->writable;
167
+ }
168
+
169
+ public function isSeekable()
170
+ {
171
+ return $this->seekable;
172
+ }
173
+
174
+ public function eof()
175
+ {
176
+ return !$this->stream || feof($this->stream);
177
+ }
178
+
179
+ public function tell()
180
+ {
181
+ $result = ftell($this->stream);
182
+
183
+ if ($result === false) {
184
+ throw new \RuntimeException('Unable to determine stream position');
185
+ }
186
+
187
+ return $result;
188
+ }
189
+
190
+ public function rewind()
191
+ {
192
+ $this->seek(0);
193
+ }
194
+
195
+ public function seek($offset, $whence = SEEK_SET)
196
+ {
197
+ if (!$this->seekable) {
198
+ throw new \RuntimeException('Stream is not seekable');
199
+ } elseif (fseek($this->stream, $offset, $whence) === -1) {
200
+ throw new \RuntimeException('Unable to seek to stream position '
201
+ . $offset . ' with whence ' . var_export($whence, true));
202
+ }
203
+ }
204
+
205
+ public function read($length)
206
+ {
207
+ if (!$this->readable) {
208
+ throw new \RuntimeException('Cannot read from non-readable stream');
209
+ }
210
+ if ($length < 0) {
211
+ throw new \RuntimeException('Length parameter cannot be negative');
212
+ }
213
+
214
+ if (0 === $length) {
215
+ return '';
216
+ }
217
+
218
+ $string = fread($this->stream, $length);
219
+ if (false === $string) {
220
+ throw new \RuntimeException('Unable to read from stream');
221
+ }
222
+
223
+ return $string;
224
+ }
225
+
226
+ public function write($string)
227
+ {
228
+ if (!$this->writable) {
229
+ throw new \RuntimeException('Cannot write to a non-writable stream');
230
+ }
231
+
232
+ // We can't know the size after writing anything
233
+ $this->size = null;
234
+ $result = fwrite($this->stream, $string);
235
+
236
+ if ($result === false) {
237
+ throw new \RuntimeException('Unable to write to stream');
238
+ }
239
+
240
+ return $result;
241
+ }
242
+
243
+ public function getMetadata($key = null)
244
+ {
245
+ if (!isset($this->stream)) {
246
+ return $key ? null : [];
247
+ } elseif (!$key) {
248
+ return $this->customMetadata + stream_get_meta_data($this->stream);
249
+ } elseif (isset($this->customMetadata[$key])) {
250
+ return $this->customMetadata[$key];
251
+ }
252
+
253
+ $meta = stream_get_meta_data($this->stream);
254
+
255
+ return isset($meta[$key]) ? $meta[$key] : null;
256
+ }
257
+ }
vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Stream decorator trait
8
+ * @property StreamInterface stream
9
+ */
10
+ trait StreamDecoratorTrait
11
+ {
12
+ /**
13
+ * @param StreamInterface $stream Stream to decorate
14
+ */
15
+ public function __construct(StreamInterface $stream)
16
+ {
17
+ $this->stream = $stream;
18
+ }
19
+
20
+ /**
21
+ * Magic method used to create a new stream if streams are not added in
22
+ * the constructor of a decorator (e.g., LazyOpenStream).
23
+ *
24
+ * @param string $name Name of the property (allows "stream" only).
25
+ *
26
+ * @return StreamInterface
27
+ */
28
+ public function __get($name)
29
+ {
30
+ if ($name == 'stream') {
31
+ $this->stream = $this->createStream();
32
+ return $this->stream;
33
+ }
34
+
35
+ throw new \UnexpectedValueException("$name not found on class");
36
+ }
37
+
38
+ public function __toString()
39
+ {
40
+ try {
41
+ if ($this->isSeekable()) {
42
+ $this->seek(0);
43
+ }
44
+ return $this->getContents();
45
+ } catch (\Exception $e) {
46
+ // Really, PHP? https://bugs.php.net/bug.php?id=53648
47
+ trigger_error('StreamDecorator::__toString exception: '
48
+ . (string) $e, E_USER_ERROR);
49
+ return '';
50
+ }
51
+ }
52
+
53
+ public function getContents()
54
+ {
55
+ return copy_to_string($this);
56
+ }
57
+
58
+ /**
59
+ * Allow decorators to implement custom methods
60
+ *
61
+ * @param string $method Missing method name
62
+ * @param array $args Method arguments
63
+ *
64
+ * @return mixed
65
+ */
66
+ public function __call($method, array $args)
67
+ {
68
+ $result = call_user_func_array([$this->stream, $method], $args);
69
+
70
+ // Always return the wrapped object if the result is a return $this
71
+ return $result === $this->stream ? $this : $result;
72
+ }
73
+
74
+ public function close()
75
+ {
76
+ $this->stream->close();
77
+ }
78
+
79
+ public function getMetadata($key = null)
80
+ {
81
+ return $this->stream->getMetadata($key);
82
+ }
83
+
84
+ public function detach()
85
+ {
86
+ return $this->stream->detach();
87
+ }
88
+
89
+ public function getSize()
90
+ {
91
+ return $this->stream->getSize();
92
+ }
93
+
94
+ public function eof()
95
+ {
96
+ return $this->stream->eof();
97
+ }
98
+
99
+ public function tell()
100
+ {
101
+ return $this->stream->tell();
102
+ }
103
+
104
+ public function isReadable()
105
+ {
106
+ return $this->stream->isReadable();
107
+ }
108
+
109
+ public function isWritable()
110
+ {
111
+ return $this->stream->isWritable();
112
+ }
113
+
114
+ public function isSeekable()
115
+ {
116
+ return $this->stream->isSeekable();
117
+ }
118
+
119
+ public function rewind()
120
+ {
121
+ $this->seek(0);
122
+ }
123
+
124
+ public function seek($offset, $whence = SEEK_SET)
125
+ {
126
+ $this->stream->seek($offset, $whence);
127
+ }
128
+
129
+ public function read($length)
130
+ {
131
+ return $this->stream->read($length);
132
+ }
133
+
134
+ public function write($string)
135
+ {
136
+ return $this->stream->write($string);
137
+ }
138
+
139
+ /**
140
+ * Implement in subclasses to dynamically create streams when requested.
141
+ *
142
+ * @return StreamInterface
143
+ * @throws \BadMethodCallException
144
+ */
145
+ protected function createStream()
146
+ {
147
+ throw new \BadMethodCallException('Not implemented');
148
+ }
149
+ }
vendor/guzzlehttp/psr7/src/StreamWrapper.php ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Converts Guzzle streams into PHP stream resources.
8
+ */
9
+ class StreamWrapper
10
+ {
11
+ /** @var resource */
12
+ public $context;
13
+
14
+ /** @var StreamInterface */
15
+ private $stream;
16
+
17
+ /** @var string r, r+, or w */
18
+ private $mode;
19
+
20
+ /**
21
+ * Returns a resource representing the stream.
22
+ *
23
+ * @param StreamInterface $stream The stream to get a resource for
24
+ *
25
+ * @return resource
26
+ * @throws \InvalidArgumentException if stream is not readable or writable
27
+ */
28
+ public static function getResource(StreamInterface $stream)
29
+ {
30
+ self::register();
31
+
32
+ if ($stream->isReadable()) {
33
+ $mode = $stream->isWritable() ? 'r+' : 'r';
34
+ } elseif ($stream->isWritable()) {
35
+ $mode = 'w';
36
+ } else {
37
+ throw new \InvalidArgumentException('The stream must be readable, '
38
+ . 'writable, or both.');
39
+ }
40
+
41
+ return fopen('guzzle://stream', $mode, null, stream_context_create([
42
+ 'guzzle' => ['stream' => $stream]
43
+ ]));
44
+ }
45
+
46
+ /**
47
+ * Registers the stream wrapper if needed
48
+ */
49
+ public static function register()
50
+ {
51
+ if (!in_array('guzzle', stream_get_wrappers())) {
52
+ stream_wrapper_register('guzzle', __CLASS__);
53
+ }
54
+ }
55
+
56
+ public function stream_open($path, $mode, $options, &$opened_path)
57
+ {
58
+ $options = stream_context_get_options($this->context);
59
+
60
+ if (!isset($options['guzzle']['stream'])) {
61
+ return false;
62
+ }
63
+
64
+ $this->mode = $mode;
65
+ $this->stream = $options['guzzle']['stream'];
66
+
67
+ return true;
68
+ }
69
+
70
+ public function stream_read($count)
71
+ {
72
+ return $this->stream->read($count);
73
+ }
74
+
75
+ public function stream_write($data)
76
+ {
77
+ return (int) $this->stream->write($data);
78
+ }
79
+
80
+ public function stream_tell()
81
+ {
82
+ return $this->stream->tell();
83
+ }
84
+
85
+ public function stream_eof()
86
+ {
87
+ return $this->stream->eof();
88
+ }
89
+
90
+ public function stream_seek($offset, $whence)
91
+ {
92
+ $this->stream->seek($offset, $whence);
93
+
94
+ return true;
95
+ }
96
+
97
+ public function stream_stat()
98
+ {
99
+ static $modeMap = [
100
+ 'r' => 33060,
101
+ 'r+' => 33206,
102
+ 'w' => 33188
103
+ ];
104
+
105
+ return [
106
+ 'dev' => 0,
107
+ 'ino' => 0,
108
+ 'mode' => $modeMap[$this->mode],
109
+ 'nlink' => 0,
110
+ 'uid' => 0,
111
+ 'gid' => 0,
112
+ 'rdev' => 0,
113
+ 'size' => $this->stream->getSize() ?: 0,
114
+ 'atime' => 0,
115
+ 'mtime' => 0,
116
+ 'ctime' => 0,
117
+ 'blksize' => 0,
118
+ 'blocks' => 0
119
+ ];
120
+ }
121
+ }
vendor/guzzlehttp/psr7/src/UploadedFile.php ADDED
@@ -0,0 +1,316 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use InvalidArgumentException;
5
+ use Psr\Http\Message\StreamInterface;
6
+ use Psr\Http\Message\UploadedFileInterface;
7
+ use RuntimeException;
8
+
9
+ class UploadedFile implements UploadedFileInterface
10
+ {
11
+ /**
12
+ * @var int[]
13
+ */
14
+ private static $errors = [
15
+ UPLOAD_ERR_OK,
16
+ UPLOAD_ERR_INI_SIZE,
17
+ UPLOAD_ERR_FORM_SIZE,
18
+ UPLOAD_ERR_PARTIAL,
19
+ UPLOAD_ERR_NO_FILE,
20
+ UPLOAD_ERR_NO_TMP_DIR,
21
+ UPLOAD_ERR_CANT_WRITE,
22
+ UPLOAD_ERR_EXTENSION,
23
+ ];
24
+
25
+ /**
26
+ * @var string
27
+ */
28
+ private $clientFilename;
29
+
30
+ /**
31
+ * @var string
32
+ */
33
+ private $clientMediaType;
34
+
35
+ /**
36
+ * @var int
37
+ */
38
+ private $error;
39
+
40
+ /**
41
+ * @var null|string
42
+ */
43
+ private $file;
44
+
45
+ /**
46
+ * @var bool
47
+ */
48
+ private $moved = false;
49
+
50
+ /**
51
+ * @var int
52
+ */
53
+ private $size;
54
+
55
+ /**
56
+ * @var StreamInterface|null
57
+ */
58
+ private $stream;
59
+
60
+ /**
61
+ * @param StreamInterface|string|resource $streamOrFile
62
+ * @param int $size
63
+ * @param int $errorStatus
64
+ * @param string|null $clientFilename
65
+ * @param string|null $clientMediaType
66
+ */
67
+ public function __construct(
68
+ $streamOrFile,
69
+ $size,
70
+ $errorStatus,
71
+ $clientFilename = null,
72
+ $clientMediaType = null
73
+ ) {
74
+ $this->setError($errorStatus);
75
+ $this->setSize($size);
76
+ $this->setClientFilename($clientFilename);
77
+ $this->setClientMediaType($clientMediaType);
78
+
79
+ if ($this->isOk()) {
80
+ $this->setStreamOrFile($streamOrFile);
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Depending on the value set file or stream variable
86
+ *
87
+ * @param mixed $streamOrFile
88
+ * @throws InvalidArgumentException
89
+ */
90
+ private function setStreamOrFile($streamOrFile)
91
+ {
92
+ if (is_string($streamOrFile)) {
93
+ $this->file = $streamOrFile;
94
+ } elseif (is_resource($streamOrFile)) {
95
+ $this->stream = new Stream($streamOrFile);
96
+ } elseif ($streamOrFile instanceof StreamInterface) {
97
+ $this->stream = $streamOrFile;
98
+ } else {
99
+ throw new InvalidArgumentException(
100
+ 'Invalid stream or file provided for UploadedFile'
101
+ );
102
+ }
103
+ }
104
+
105
+ /**
106
+ * @param int $error
107
+ * @throws InvalidArgumentException
108
+ */
109
+ private function setError($error)
110
+ {
111
+ if (false === is_int($error)) {
112
+ throw new InvalidArgumentException(
113
+ 'Upload file error status must be an integer'
114
+ );
115
+ }
116
+
117
+ if (false === in_array($error, UploadedFile::$errors)) {
118
+ throw new InvalidArgumentException(
119
+ 'Invalid error status for UploadedFile'
120
+ );
121
+ }
122
+
123
+ $this->error = $error;
124
+ }
125
+
126
+ /**
127
+ * @param int $size
128
+ * @throws InvalidArgumentException
129
+ */
130
+ private function setSize($size)
131
+ {
132
+ if (false === is_int($size)) {
133
+ throw new InvalidArgumentException(
134
+ 'Upload file size must be an integer'
135
+ );
136
+ }
137
+
138
+ $this->size = $size;
139
+ }
140
+
141
+ /**
142
+ * @param mixed $param
143
+ * @return boolean
144
+ */
145
+ private function isStringOrNull($param)
146
+ {
147
+ return in_array(gettype($param), ['string', 'NULL']);
148
+ }
149
+
150
+ /**
151
+ * @param mixed $param
152
+ * @return boolean
153
+ */
154
+ private function isStringNotEmpty($param)
155
+ {
156
+ return is_string($param) && false === empty($param);
157
+ }
158
+
159
+ /**
160
+ * @param string|null $clientFilename
161
+ * @throws InvalidArgumentException
162
+ */
163
+ private function setClientFilename($clientFilename)
164
+ {
165
+ if (false === $this->isStringOrNull($clientFilename)) {
166
+ throw new InvalidArgumentException(
167
+ 'Upload file client filename must be a string or null'
168
+ );
169
+ }
170
+
171
+ $this->clientFilename = $clientFilename;
172
+ }
173
+
174
+ /**
175
+ * @param string|null $clientMediaType
176
+ * @throws InvalidArgumentException
177
+ */
178
+ private function setClientMediaType($clientMediaType)
179
+ {
180
+ if (false === $this->isStringOrNull($clientMediaType)) {
181
+ throw new InvalidArgumentException(
182
+ 'Upload file client media type must be a string or null'
183
+ );
184
+ }
185
+
186
+ $this->clientMediaType = $clientMediaType;
187
+ }
188
+
189
+ /**
190
+ * Return true if there is no upload error
191
+ *
192
+ * @return boolean
193
+ */
194
+ private function isOk()
195
+ {
196
+ return $this->error === UPLOAD_ERR_OK;
197
+ }
198
+
199
+ /**
200
+ * @return boolean
201
+ */
202
+ public function isMoved()
203
+ {
204
+ return $this->moved;
205
+ }
206
+
207
+ /**
208
+ * @throws RuntimeException if is moved or not ok
209
+ */
210
+ private function validateActive()
211
+ {
212
+ if (false === $this->isOk()) {
213
+ throw new RuntimeException('Cannot retrieve stream due to upload error');
214
+ }
215
+
216
+ if ($this->isMoved()) {
217
+ throw new RuntimeException('Cannot retrieve stream after it has already been moved');
218
+ }
219
+ }
220
+
221
+ /**
222
+ * {@inheritdoc}
223
+ * @throws RuntimeException if the upload was not successful.
224
+ */
225
+ public function getStream()
226
+ {
227
+ $this->validateActive();
228
+
229
+ if ($this->stream instanceof StreamInterface) {
230
+ return $this->stream;
231
+ }
232
+
233
+ return new LazyOpenStream($this->file, 'r+');
234
+ }
235
+
236
+ /**
237
+ * {@inheritdoc}
238
+ *
239
+ * @see http://php.net/is_uploaded_file
240
+ * @see http://php.net/move_uploaded_file
241
+ * @param string $targetPath Path to which to move the uploaded file.
242
+ * @throws RuntimeException if the upload was not successful.
243
+ * @throws InvalidArgumentException if the $path specified is invalid.
244
+ * @throws RuntimeException on any error during the move operation, or on
245
+ * the second or subsequent call to the method.
246
+ */
247
+ public function moveTo($targetPath)
248
+ {
249
+ $this->validateActive();
250
+
251
+ if (false === $this->isStringNotEmpty($targetPath)) {
252
+ throw new InvalidArgumentException(
253
+ 'Invalid path provided for move operation; must be a non-empty string'
254
+ );
255
+ }
256
+
257
+ if ($this->file) {
258
+ $this->moved = php_sapi_name() == 'cli'
259
+ ? rename($this->file, $targetPath)
260
+ : move_uploaded_file($this->file, $targetPath);
261
+ } else {
262
+ copy_to_stream(
263
+ $this->getStream(),
264
+ new LazyOpenStream($targetPath, 'w')
265
+ );
266
+
267
+ $this->moved = true;
268
+ }
269
+
270
+ if (false === $this->moved) {
271
+ throw new RuntimeException(
272
+ sprintf('Uploaded file could not be moved to %s', $targetPath)
273
+ );
274
+ }
275
+ }
276
+
277
+ /**
278
+ * {@inheritdoc}
279
+ *
280
+ * @return int|null The file size in bytes or null if unknown.
281
+ */
282
+ public function getSize()
283
+ {
284
+ return $this->size;
285
+ }
286
+
287
+ /**
288
+ * {@inheritdoc}
289
+ *
290
+ * @see http://php.net/manual/en/features.file-upload.errors.php
291
+ * @return int One of PHP's UPLOAD_ERR_XXX constants.
292
+ */
293
+ public function getError()
294
+ {
295
+ return $this->error;
296
+ }
297
+
298
+ /**
299
+ * {@inheritdoc}
300
+ *
301
+ * @return string|null The filename sent by the client or null if none
302
+ * was provided.
303
+ */
304
+ public function getClientFilename()
305
+ {
306
+ return $this->clientFilename;
307
+ }
308
+
309
+ /**
310
+ * {@inheritdoc}
311
+ */
312
+ public function getClientMediaType()
313
+ {
314
+ return $this->clientMediaType;
315
+ }
316
+ }
vendor/guzzlehttp/psr7/src/Uri.php ADDED
@@ -0,0 +1,702 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\UriInterface;
5
+
6
+ /**
7
+ * PSR-7 URI implementation.
8
+ *
9
+ * @author Michael Dowling
10
+ * @author Tobias Schultze
11
+ * @author Matthew Weier O'Phinney
12
+ */
13
+ class Uri implements UriInterface
14
+ {
15
+ /**
16
+ * Absolute http and https URIs require a host per RFC 7230 Section 2.7
17
+ * but in generic URIs the host can be empty. So for http(s) URIs
18
+ * we apply this default host when no host is given yet to form a
19
+ * valid URI.
20
+ */
21
+ const HTTP_DEFAULT_HOST = 'localhost';
22
+
23
+ private static $defaultPorts = [
24
+ 'http' => 80,
25
+ 'https' => 443,
26
+ 'ftp' => 21,
27
+ 'gopher' => 70,
28
+ 'nntp' => 119,
29
+ 'news' => 119,
30
+ 'telnet' => 23,
31
+ 'tn3270' => 23,
32
+ 'imap' => 143,
33
+ 'pop' => 110,
34
+ 'ldap' => 389,
35
+ ];
36
+
37
+ private static $charUnreserved = 'a-zA-Z0-9_\-\.~';
38
+ private static $charSubDelims = '!\$&\'\(\)\*\+,;=';
39
+ private static $replaceQuery = ['=' => '%3D', '&' => '%26'];
40
+
41
+ /** @var string Uri scheme. */
42
+ private $scheme = '';
43
+
44
+ /** @var string Uri user info. */
45
+ private $userInfo = '';
46
+
47
+ /** @var string Uri host. */
48
+ private $host = '';
49
+
50
+ /** @var int|null Uri port. */
51
+ private $port;
52
+
53
+ /** @var string Uri path. */
54
+ private $path = '';
55
+
56
+ /** @var string Uri query string. */
57
+ private $query = '';
58
+
59
+ /** @var string Uri fragment. */
60
+ private $fragment = '';
61
+
62
+ /**
63
+ * @param string $uri URI to parse
64
+ */
65
+ public function __construct($uri = '')
66
+ {
67
+ // weak type check to also accept null until we can add scalar type hints
68
+ if ($uri != '') {
69
+ $parts = parse_url($uri);
70
+ if ($parts === false) {
71
+ throw new \InvalidArgumentException("Unable to parse URI: $uri");
72
+ }
73
+ $this->applyParts($parts);
74
+ }
75
+ }
76
+
77
+ public function __toString()
78
+ {
79
+ return self::composeComponents(
80
+ $this->scheme,
81
+ $this->getAuthority(),
82
+ $this->path,
83
+ $this->query,
84
+ $this->fragment
85
+ );
86
+ }
87
+
88
+ /**
89
+ * Composes a URI reference string from its various components.
90
+ *
91
+ * Usually this method does not need to be called manually but instead is used indirectly via
92
+ * `Psr\Http\Message\UriInterface::__toString`.
93
+ *
94
+ * PSR-7 UriInterface treats an empty component the same as a missing component as
95
+ * getQuery(), getFragment() etc. always return a string. This explains the slight
96
+ * difference to RFC 3986 Section 5.3.
97
+ *
98
+ * Another adjustment is that the authority separator is added even when the authority is missing/empty
99
+ * for the "file" scheme. This is because PHP stream functions like `file_get_contents` only work with
100
+ * `file:///myfile` but not with `file:/myfile` although they are equivalent according to RFC 3986. But
101
+ * `file:///` is the more common syntax for the file scheme anyway (Chrome for example redirects to
102
+ * that format).
103
+ *
104
+ * @param string $scheme
105
+ * @param string $authority
106
+ * @param string $path
107
+ * @param string $query
108
+ * @param string $fragment
109
+ *
110
+ * @return string
111
+ *
112
+ * @link https://tools.ietf.org/html/rfc3986#section-5.3
113
+ */
114
+ public static function composeComponents($scheme, $authority, $path, $query, $fragment)
115
+ {
116
+ $uri = '';
117
+
118
+ // weak type checks to also accept null until we can add scalar type hints
119
+ if ($scheme != '') {
120
+ $uri .= $scheme . ':';
121
+ }
122
+
123
+ if ($authority != ''|| $scheme === 'file') {
124
+ $uri .= '//' . $authority;
125
+ }
126
+
127
+ $uri .= $path;
128
+
129
+ if ($query != '') {
130
+ $uri .= '?' . $query;
131
+ }
132
+
133
+ if ($fragment != '') {
134
+ $uri .= '#' . $fragment;
135
+ }
136
+
137
+ return $uri;
138
+ }
139
+
140
+ /**
141
+ * Whether the URI has the default port of the current scheme.
142
+ *
143
+ * `Psr\Http\Message\UriInterface::getPort` may return null or the standard port. This method can be used
144
+ * independently of the implementation.
145
+ *
146
+ * @param UriInterface $uri
147
+ *
148
+ * @return bool
149
+ */
150
+ public static function isDefaultPort(UriInterface $uri)
151
+ {
152
+ return $uri->getPort() === null
153
+ || (isset(self::$defaultPorts[$uri->getScheme()]) && $uri->getPort() === self::$defaultPorts[$uri->getScheme()]);
154
+ }
155
+
156
+ /**
157
+ * Whether the URI is absolute, i.e. it has a scheme.
158
+ *
159
+ * An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true
160
+ * if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative
161
+ * to another URI, the base URI. Relative references can be divided into several forms:
162
+ * - network-path references, e.g. '//example.com/path'
163
+ * - absolute-path references, e.g. '/path'
164
+ * - relative-path references, e.g. 'subpath'
165
+ *
166
+ * @param UriInterface $uri
167
+ *
168
+ * @return bool
169
+ * @see Uri::isNetworkPathReference
170
+ * @see Uri::isAbsolutePathReference
171
+ * @see Uri::isRelativePathReference
172
+ * @link https://tools.ietf.org/html/rfc3986#section-4
173
+ */
174
+ public static function isAbsolute(UriInterface $uri)
175
+ {
176
+ return $uri->getScheme() !== '';
177
+ }
178
+
179
+ /**
180
+ * Whether the URI is a network-path reference.
181
+ *
182
+ * A relative reference that begins with two slash characters is termed an network-path reference.
183
+ *
184
+ * @param UriInterface $uri
185
+ *
186
+ * @return bool
187
+ * @link https://tools.ietf.org/html/rfc3986#section-4.2
188
+ */
189
+ public static function isNetworkPathReference(UriInterface $uri)
190
+ {
191
+ return $uri->getScheme() === '' && $uri->getAuthority() !== '';
192
+ }
193
+
194
+ /**
195
+ * Whether the URI is a absolute-path reference.
196
+ *
197
+ * A relative reference that begins with a single slash character is termed an absolute-path reference.
198
+ *
199
+ * @param UriInterface $uri
200
+ *
201
+ * @return bool
202
+ * @link https://tools.ietf.org/html/rfc3986#section-4.2
203
+ */
204
+ public static function isAbsolutePathReference(UriInterface $uri)
205
+ {
206
+ return $uri->getScheme() === ''
207
+ && $uri->getAuthority() === ''
208
+ && isset($uri->getPath()[0])
209
+ && $uri->getPath()[0] === '/';
210
+ }
211
+
212
+ /**
213
+ * Whether the URI is a relative-path reference.
214
+ *
215
+ * A relative reference that does not begin with a slash character is termed a relative-path reference.
216
+ *
217
+ * @param UriInterface $uri
218
+ *
219
+ * @return bool
220
+ * @link https://tools.ietf.org/html/rfc3986#section-4.2
221
+ */
222
+ public static function isRelativePathReference(UriInterface $uri)
223
+ {
224
+ return $uri->getScheme() === ''
225
+ && $uri->getAuthority() === ''
226
+ && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/');
227
+ }
228
+
229
+ /**
230
+ * Whether the URI is a same-document reference.
231
+ *
232
+ * A same-document reference refers to a URI that is, aside from its fragment
233
+ * component, identical to the base URI. When no base URI is given, only an empty
234
+ * URI reference (apart from its fragment) is considered a same-document reference.
235
+ *
236
+ * @param UriInterface $uri The URI to check
237
+ * @param UriInterface|null $base An optional base URI to compare against
238
+ *
239
+ * @return bool
240
+ * @link https://tools.ietf.org/html/rfc3986#section-4.4
241
+ */
242
+ public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null)
243
+ {
244
+ if ($base !== null) {
245
+ $uri = UriResolver::resolve($base, $uri);
246
+
247
+ return ($uri->getScheme() === $base->getScheme())
248
+ && ($uri->getAuthority() === $base->getAuthority())
249
+ && ($uri->getPath() === $base->getPath())
250
+ && ($uri->getQuery() === $base->getQuery());
251
+ }
252
+
253
+ return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === '';
254
+ }
255
+
256
+ /**
257
+ * Removes dot segments from a path and returns the new path.
258
+ *
259
+ * @param string $path
260
+ *
261
+ * @return string
262
+ *
263
+ * @deprecated since version 1.4. Use UriResolver::removeDotSegments instead.
264
+ * @see UriResolver::removeDotSegments
265
+ */
266
+ public static function removeDotSegments($path)
267
+ {
268
+ return UriResolver::removeDotSegments($path);
269
+ }
270
+
271
+ /**
272
+ * Converts the relative URI into a new URI that is resolved against the base URI.
273
+ *
274
+ * @param UriInterface $base Base URI
275
+ * @param string|UriInterface $rel Relative URI
276
+ *
277
+ * @return UriInterface
278
+ *
279
+ * @deprecated since version 1.4. Use UriResolver::resolve instead.
280
+ * @see UriResolver::resolve
281
+ */
282
+ public static function resolve(UriInterface $base, $rel)
283
+ {
284
+ if (!($rel instanceof UriInterface)) {
285
+ $rel = new self($rel);
286
+ }
287
+
288
+ return UriResolver::resolve($base, $rel);
289
+ }
290
+
291
+ /**
292
+ * Creates a new URI with a specific query string value removed.
293
+ *
294
+ * Any existing query string values that exactly match the provided key are
295
+ * removed.
296
+ *
297
+ * @param UriInterface $uri URI to use as a base.
298
+ * @param string $key Query string key to remove.
299
+ *
300
+ * @return UriInterface
301
+ */
302
+ public static function withoutQueryValue(UriInterface $uri, $key)
303
+ {
304
+ $current = $uri->getQuery();
305
+ if ($current === '') {
306
+ return $uri;
307
+ }
308
+
309
+ $decodedKey = rawurldecode($key);
310
+ $result = array_filter(explode('&', $current), function ($part) use ($decodedKey) {
311
+ return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
312
+ });
313
+
314
+ return $uri->withQuery(implode('&', $result));
315
+ }
316
+
317
+ /**
318
+ * Creates a new URI with a specific query string value.
319
+ *
320
+ * Any existing query string values that exactly match the provided key are
321
+ * removed and replaced with the given key value pair.
322
+ *
323
+ * A value of null will set the query string key without a value, e.g. "key"
324
+ * instead of "key=value".
325
+ *
326
+ * @param UriInterface $uri URI to use as a base.
327
+ * @param string $key Key to set.
328
+ * @param string|null $value Value to set
329
+ *
330
+ * @return UriInterface
331
+ */
332
+ public static function withQueryValue(UriInterface $uri, $key, $value)
333
+ {
334
+ $current = $uri->getQuery();
335
+
336
+ if ($current === '') {
337
+ $result = [];
338
+ } else {
339
+ $decodedKey = rawurldecode($key);
340
+ $result = array_filter(explode('&', $current), function ($part) use ($decodedKey) {
341
+ return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
342
+ });
343
+ }
344
+
345
+ // Query string separators ("=", "&") within the key or value need to be encoded
346
+ // (while preventing double-encoding) before setting the query string. All other
347
+ // chars that need percent-encoding will be encoded by withQuery().
348
+ $key = strtr($key, self::$replaceQuery);
349
+
350
+ if ($value !== null) {
351
+ $result[] = $key . '=' . strtr($value, self::$replaceQuery);
352
+ } else {
353
+ $result[] = $key;
354
+ }
355
+
356
+ return $uri->withQuery(implode('&', $result));
357
+ }
358
+
359
+ /**
360
+ * Creates a URI from a hash of `parse_url` components.
361
+ *
362
+ * @param array $parts
363
+ *
364
+ * @return UriInterface
365
+ * @link http://php.net/manual/en/function.parse-url.php
366
+ *
367
+ * @throws \InvalidArgumentException If the components do not form a valid URI.
368
+ */
369
+ public static function fromParts(array $parts)
370
+ {
371
+ $uri = new self();
372
+ $uri->applyParts($parts);
373
+ $uri->validateState();
374
+
375
+ return $uri;
376
+ }
377
+
378
+ public function getScheme()
379
+ {
380
+ return $this->scheme;
381
+ }
382
+
383
+ public function getAuthority()
384
+ {
385
+ $authority = $this->host;
386
+ if ($this->userInfo !== '') {
387
+ $authority = $this->userInfo . '@' . $authority;
388
+ }
389
+
390
+ if ($this->port !== null) {
391
+ $authority .= ':' . $this->port;
392
+ }
393
+
394
+ return $authority;
395
+ }
396
+
397
+ public function getUserInfo()
398
+ {
399
+ return $this->userInfo;
400
+ }
401
+
402
+ public function getHost()
403
+ {
404
+ return $this->host;
405
+ }
406
+
407
+ public function getPort()
408
+ {
409
+ return $this->port;
410
+ }
411
+
412
+ public function getPath()
413
+ {
414
+ return $this->path;
415
+ }
416
+
417
+ public function getQuery()
418
+ {
419
+ return $this->query;
420
+ }
421
+
422
+ public function getFragment()
423
+ {
424
+ return $this->fragment;
425
+ }
426
+
427
+ public function withScheme($scheme)
428
+ {
429
+ $scheme = $this->filterScheme($scheme);
430
+
431
+ if ($this->scheme === $scheme) {
432
+ return $this;
433
+ }
434
+
435
+ $new = clone $this;
436
+ $new->scheme = $scheme;
437
+ $new->removeDefaultPort();
438
+ $new->validateState();
439
+
440
+ return $new;
441
+ }
442
+
443
+ public function withUserInfo($user, $password = null)
444
+ {
445
+ $info = $user;
446
+ if ($password != '') {
447
+ $info .= ':' . $password;
448
+ }
449
+
450
+ if ($this->userInfo === $info) {
451
+ return $this;
452
+ }
453
+
454
+ $new = clone $this;
455
+ $new->userInfo = $info;
456
+ $new->validateState();
457
+
458
+ return $new;
459
+ }
460
+
461
+ public function withHost($host)
462
+ {
463
+ $host = $this->filterHost($host);
464
+
465
+ if ($this->host === $host) {
466
+ return $this;
467
+ }
468
+
469
+ $new = clone $this;
470
+ $new->host = $host;
471
+ $new->validateState();
472
+
473
+ return $new;
474
+ }
475
+
476
+ public function withPort($port)
477
+ {
478
+ $port = $this->filterPort($port);
479
+
480
+ if ($this->port === $port) {
481
+ return $this;
482
+ }
483
+
484
+ $new = clone $this;
485
+ $new->port = $port;
486
+ $new->removeDefaultPort();
487
+ $new->validateState();
488
+
489
+ return $new;
490
+ }
491
+
492
+ public function withPath($path)
493
+ {
494
+ $path = $this->filterPath($path);
495
+
496
+ if ($this->path === $path) {
497
+ return $this;
498
+ }
499
+
500
+ $new = clone $this;
501
+ $new->path = $path;
502
+ $new->validateState();
503
+
504
+ return $new;
505
+ }
506
+
507
+ public function withQuery($query)
508
+ {
509
+ $query = $this->filterQueryAndFragment($query);
510
+
511
+ if ($this->query === $query) {
512
+ return $this;
513
+ }
514
+
515
+ $new = clone $this;
516
+ $new->query = $query;
517
+
518
+ return $new;
519
+ }
520
+
521
+ public function withFragment($fragment)
522
+ {
523
+ $fragment = $this->filterQueryAndFragment($fragment);
524
+
525
+ if ($this->fragment === $fragment) {
526
+ return $this;
527
+ }
528
+
529
+ $new = clone $this;
530
+ $new->fragment = $fragment;
531
+
532
+ return $new;
533
+ }
534
+
535
+ /**
536
+ * Apply parse_url parts to a URI.
537
+ *
538
+ * @param array $parts Array of parse_url parts to apply.
539
+ */
540
+ private function applyParts(array $parts)
541
+ {
542
+ $this->scheme = isset($parts['scheme'])
543
+ ? $this->filterScheme($parts['scheme'])
544
+ : '';
545
+ $this->userInfo = isset($parts['user']) ? $parts['user'] : '';
546
+ $this->host = isset($parts['host'])
547
+ ? $this->filterHost($parts['host'])
548
+ : '';
549
+ $this->port = isset($parts['port'])
550
+ ? $this->filterPort($parts['port'])
551
+ : null;
552
+ $this->path = isset($parts['path'])
553
+ ? $this->filterPath($parts['path'])
554
+ : '';
555
+ $this->query = isset($parts['query'])
556
+ ? $this->filterQueryAndFragment($parts['query'])
557
+ : '';
558
+ $this->fragment = isset($parts['fragment'])
559
+ ? $this->filterQueryAndFragment($parts['fragment'])
560
+ : '';
561
+ if (isset($parts['pass'])) {
562
+ $this->userInfo .= ':' . $parts['pass'];
563
+ }
564
+
565
+ $this->removeDefaultPort();
566
+ }
567
+
568
+ /**
569
+ * @param string $scheme
570
+ *
571
+ * @return string
572
+ *
573
+ * @throws \InvalidArgumentException If the scheme is invalid.
574
+ */
575
+ private function filterScheme($scheme)
576
+ {
577
+ if (!is_string($scheme)) {
578
+ throw new \InvalidArgumentException('Scheme must be a string');
579
+ }
580
+
581
+ return strtolower($scheme);
582
+ }
583
+
584
+ /**
585
+ * @param string $host
586
+ *
587
+ * @return string
588
+ *
589
+ * @throws \InvalidArgumentException If the host is invalid.
590
+ */
591
+ private function filterHost($host)
592
+ {
593
+ if (!is_string($host)) {
594
+ throw new \InvalidArgumentException('Host must be a string');
595
+ }
596
+
597
+ return strtolower($host);
598
+ }
599
+
600
+ /**
601
+ * @param int|null $port
602
+ *
603
+ * @return int|null
604
+ *
605
+ * @throws \InvalidArgumentException If the port is invalid.
606
+ */
607
+ private function filterPort($port)
608
+ {
609
+ if ($port === null) {
610
+ return null;
611
+ }
612
+
613
+ $port = (int) $port;
614
+ if (1 > $port || 0xffff < $port) {
615
+ throw new \InvalidArgumentException(
616
+ sprintf('Invalid port: %d. Must be between 1 and 65535', $port)
617
+ );
618
+ }
619
+
620
+ return $port;
621
+ }
622
+
623
+ private function removeDefaultPort()
624
+ {
625
+ if ($this->port !== null && self::isDefaultPort($this)) {
626
+ $this->port = null;
627
+ }
628
+ }
629
+
630
+ /**
631
+ * Filters the path of a URI
632
+ *
633
+ * @param string $path
634
+ *
635
+ * @return string
636
+ *
637
+ * @throws \InvalidArgumentException If the path is invalid.
638
+ */
639
+ private function filterPath($path)
640
+ {
641
+ if (!is_string($path)) {
642
+ throw new \InvalidArgumentException('Path must be a string');
643
+ }
644
+
645
+ return preg_replace_callback(
646
+ '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/]++|%(?![A-Fa-f0-9]{2}))/',
647
+ [$this, 'rawurlencodeMatchZero'],
648
+ $path
649
+ );
650
+ }
651
+
652
+ /**
653
+ * Filters the query string or fragment of a URI.
654
+ *
655
+ * @param string $str
656
+ *
657
+ * @return string
658
+ *
659
+ * @throws \InvalidArgumentException If the query or fragment is invalid.
660
+ */
661
+ private function filterQueryAndFragment($str)
662
+ {
663
+ if (!is_string($str)) {
664
+ throw new \InvalidArgumentException('Query and fragment must be a string');
665
+ }
666
+
667
+ return preg_replace_callback(
668
+ '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/',
669
+ [$this, 'rawurlencodeMatchZero'],
670
+ $str
671
+ );
672
+ }
673
+
674
+ private function rawurlencodeMatchZero(array $match)
675
+ {
676
+ return rawurlencode($match[0]);
677
+ }
678
+
679
+ private function validateState()
680
+ {
681
+ if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) {
682
+ $this->host = self::HTTP_DEFAULT_HOST;
683
+ }
684
+
685
+ if ($this->getAuthority() === '') {
686
+ if (0 === strpos($this->path, '//')) {
687
+ throw new \InvalidArgumentException('The path of a URI without an authority must not start with two slashes "//"');
688
+ }
689
+ if ($this->scheme === '' && false !== strpos(explode('/', $this->path, 2)[0], ':')) {
690
+ throw new \InvalidArgumentException('A relative URI must not have a path beginning with a segment containing a colon');
691
+ }
692
+ } elseif (isset($this->path[0]) && $this->path[0] !== '/') {
693
+ @trigger_error(
694
+ 'The path of a URI with an authority must start with a slash "/" or be empty. Automagically fixing the URI ' .
695
+ 'by adding a leading slash to the path is deprecated since version 1.4 and will throw an exception instead.',
696
+ E_USER_DEPRECATED
697
+ );
698
+ $this->path = '/'. $this->path;
699
+ //throw new \InvalidArgumentException('The path of a URI with an authority must start with a slash "/" or be empty');
700
+ }
701
+ }
702
+ }
vendor/guzzlehttp/psr7/src/UriNormalizer.php ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Psr7;
3
+
4
+ use Psr\Http\Message\UriInterface;
5
+
6
+ /**
7
+ * Provides methods to normalize and compare URIs.
8
+ *
9
+ * @author Tobias Schultze
10
+ *
11
+ * @link https://tools.ietf.org/html/rfc3986#section-6
12
+ */
13
+ final class UriNormalizer
14
+ {
15
+ /**
16
+ * Default normalizations which only include the ones that preserve semantics.
17
+ *
18
+ * self::CAPITALIZE_PERCENT_ENCODING | self::DECODE_UNRESERVED_CHARACTERS | self::CONVERT_EMPTY_PATH |
19
+ * self::REMOVE_DEFAULT_HOST | self::REMOVE_DEFAULT_PORT | self::REMOVE_DOT_SEGMENTS
20
+ */
21
+ const PRESERVING_NORMALIZATIONS = 63;
22
+
23
+ /**
24
+ * All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized.
25
+ *
26
+ * Example: http://example.org/a%c2%b1b → http://example.org/a%C2%B1b
27
+ */
28
+ const CAPITALIZE_PERCENT_ENCODING = 1;
29
+
30
+ /**
31
+ * Decodes percent-encoded octets of unreserved characters.
32
+ *
33
+ * For consistency, percent-encoded octets in the ranges of ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39),
34
+ * hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should not be created by URI producers and,
35
+ * when found in a URI, should be decoded to their corresponding unreserved characters by URI normalizers.
36
+ *
37
+ * Example: http://example.org/%7Eusern%61me/ → http://example.org/~username/
38
+ */
39
+ const DECODE_UNRESERVED_CHARACTERS = 2;
40
+
41
+ /**
42
+ * Converts the empty path to "/" for http and https URIs.
43
+ *
44
+ * Example: http://example.org → http://example.org/
45
+ */
46
+ const CONVERT_EMPTY_PATH = 4;
47
+
48
+ /**
49
+ * Removes the default host of the given URI scheme from the URI.
50
+ *
51
+ * Only the "file" scheme defines the default host "localhost".
52
+ * All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile`
53
+ * are equivalent according to RFC 3986. The first format is not accepted
54
+ * by PHPs stream functions and thus already normalized implicitly to the
55
+ * se