PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/internal/Mageplaza/SocialLogin/Facebook/FacebookBatchRequest.php

https://bitbucket.org/leminhtamboy/wisi
PHP | 301 lines | 147 code | 35 blank | 119 comment | 12 complexity | 0215ae57b381d86a0f5d62b2c47c3536 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0
  1. <?php
  2. /**
  3. * Copyright 2017 Facebook, Inc.
  4. *
  5. * You are hereby granted a non-exclusive, worldwide, royalty-free license to
  6. * use, copy, modify, and distribute this software in source code or binary
  7. * form for use in connection with the web services and APIs provided by
  8. * Facebook.
  9. *
  10. * As with any software that integrates with the Facebook platform, your use
  11. * of this software is subject to the Facebook Developer Principles and
  12. * Policies [http://developers.facebook.com/policy/]. This copyright notice
  13. * shall be included in all copies or substantial portions of the software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21. * DEALINGS IN THE SOFTWARE.
  22. *
  23. */
  24. namespace Facebook;
  25. use ArrayIterator;
  26. use IteratorAggregate;
  27. use ArrayAccess;
  28. use Facebook\Authentication\AccessToken;
  29. use Facebook\Exceptions\FacebookSDKException;
  30. /**
  31. * Class BatchRequest
  32. *
  33. * @package Facebook
  34. */
  35. class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, ArrayAccess
  36. {
  37. /**
  38. * @var array An array of FacebookRequest entities to send.
  39. */
  40. protected $requests;
  41. /**
  42. * @var array An array of files to upload.
  43. */
  44. protected $attachedFiles;
  45. /**
  46. * Creates a new Request entity.
  47. *
  48. * @param FacebookApp|null $app
  49. * @param array $requests
  50. * @param AccessToken|string|null $accessToken
  51. * @param string|null $graphVersion
  52. */
  53. public function __construct(FacebookApp $app = null, array $requests = [], $accessToken = null, $graphVersion = null)
  54. {
  55. parent::__construct($app, $accessToken, 'POST', '', [], null, $graphVersion);
  56. $this->add($requests);
  57. }
  58. /**
  59. * A a new request to the array.
  60. *
  61. * @param FacebookRequest|array $request
  62. * @param string|null $name
  63. *
  64. * @return FacebookBatchRequest
  65. *
  66. * @throws \InvalidArgumentException
  67. */
  68. public function add($request, $name = null)
  69. {
  70. if (is_array($request)) {
  71. foreach ($request as $key => $req) {
  72. $this->add($req, $key);
  73. }
  74. return $this;
  75. }
  76. if (!$request instanceof FacebookRequest) {
  77. throw new \InvalidArgumentException('Argument for add() must be of type array or FacebookRequest.');
  78. }
  79. $this->addFallbackDefaults($request);
  80. $requestToAdd = [
  81. 'name' => $name,
  82. 'request' => $request,
  83. ];
  84. // File uploads
  85. $attachedFiles = $this->extractFileAttachments($request);
  86. if ($attachedFiles) {
  87. $requestToAdd['attached_files'] = $attachedFiles;
  88. }
  89. $this->requests[] = $requestToAdd;
  90. return $this;
  91. }
  92. /**
  93. * Ensures that the FacebookApp and access token fall back when missing.
  94. *
  95. * @param FacebookRequest $request
  96. *
  97. * @throws FacebookSDKException
  98. */
  99. public function addFallbackDefaults(FacebookRequest $request)
  100. {
  101. if (!$request->getApp()) {
  102. $app = $this->getApp();
  103. if (!$app) {
  104. throw new FacebookSDKException('Missing FacebookApp on FacebookRequest and no fallback detected on FacebookBatchRequest.');
  105. }
  106. $request->setApp($app);
  107. }
  108. if (!$request->getAccessToken()) {
  109. $accessToken = $this->getAccessToken();
  110. if (!$accessToken) {
  111. throw new FacebookSDKException('Missing access token on FacebookRequest and no fallback detected on FacebookBatchRequest.');
  112. }
  113. $request->setAccessToken($accessToken);
  114. }
  115. }
  116. /**
  117. * Extracts the files from a request.
  118. *
  119. * @param FacebookRequest $request
  120. *
  121. * @return string|null
  122. *
  123. * @throws FacebookSDKException
  124. */
  125. public function extractFileAttachments(FacebookRequest $request)
  126. {
  127. if (!$request->containsFileUploads()) {
  128. return null;
  129. }
  130. $files = $request->getFiles();
  131. $fileNames = [];
  132. foreach ($files as $file) {
  133. $fileName = uniqid();
  134. $this->addFile($fileName, $file);
  135. $fileNames[] = $fileName;
  136. }
  137. $request->resetFiles();
  138. // @TODO Does Graph support multiple uploads on one endpoint?
  139. return implode(',', $fileNames);
  140. }
  141. /**
  142. * Return the FacebookRequest entities.
  143. *
  144. * @return array
  145. */
  146. public function getRequests()
  147. {
  148. return $this->requests;
  149. }
  150. /**
  151. * Prepares the requests to be sent as a batch request.
  152. */
  153. public function prepareRequestsForBatch()
  154. {
  155. $this->validateBatchRequestCount();
  156. $params = [
  157. 'batch' => $this->convertRequestsToJson(),
  158. 'include_headers' => true,
  159. ];
  160. $this->setParams($params);
  161. }
  162. /**
  163. * Converts the requests into a JSON(P) string.
  164. *
  165. * @return string
  166. */
  167. public function convertRequestsToJson()
  168. {
  169. $requests = [];
  170. foreach ($this->requests as $request) {
  171. $attachedFiles = isset($request['attached_files']) ? $request['attached_files'] : null;
  172. $requests[] = $this->requestEntityToBatchArray($request['request'], $request['name'], $attachedFiles);
  173. }
  174. return json_encode($requests);
  175. }
  176. /**
  177. * Validate the request count before sending them as a batch.
  178. *
  179. * @throws FacebookSDKException
  180. */
  181. public function validateBatchRequestCount()
  182. {
  183. $batchCount = count($this->requests);
  184. if ($batchCount === 0) {
  185. throw new FacebookSDKException('There are no batch requests to send.');
  186. } elseif ($batchCount > 50) {
  187. // Per: https://developers.facebook.com/docs/graph-api/making-multiple-requests#limits
  188. throw new FacebookSDKException('You cannot send more than 50 batch requests at a time.');
  189. }
  190. }
  191. /**
  192. * Converts a Request entity into an array that is batch-friendly.
  193. *
  194. * @param FacebookRequest $request The request entity to convert.
  195. * @param string|null $requestName The name of the request.
  196. * @param string|null $attachedFiles Names of files associated with the request.
  197. *
  198. * @return array
  199. */
  200. public function requestEntityToBatchArray(FacebookRequest $request, $requestName = null, $attachedFiles = null)
  201. {
  202. $compiledHeaders = [];
  203. $headers = $request->getHeaders();
  204. foreach ($headers as $name => $value) {
  205. $compiledHeaders[] = $name . ': ' . $value;
  206. }
  207. $batch = [
  208. 'headers' => $compiledHeaders,
  209. 'method' => $request->getMethod(),
  210. 'relative_url' => $request->getUrl(),
  211. ];
  212. // Since file uploads are moved to the root request of a batch request,
  213. // the child requests will always be URL-encoded.
  214. $body = $request->getUrlEncodedBody()->getBody();
  215. if ($body) {
  216. $batch['body'] = $body;
  217. }
  218. if (isset($requestName)) {
  219. $batch['name'] = $requestName;
  220. }
  221. if (isset($attachedFiles)) {
  222. $batch['attached_files'] = $attachedFiles;
  223. }
  224. // @TODO Add support for "omit_response_on_success"
  225. // @TODO Add support for "depends_on"
  226. // @TODO Add support for JSONP with "callback"
  227. return $batch;
  228. }
  229. /**
  230. * Get an iterator for the items.
  231. *
  232. * @return ArrayIterator
  233. */
  234. public function getIterator()
  235. {
  236. return new ArrayIterator($this->requests);
  237. }
  238. /**
  239. * @inheritdoc
  240. */
  241. public function offsetSet($offset, $value)
  242. {
  243. $this->add($value, $offset);
  244. }
  245. /**
  246. * @inheritdoc
  247. */
  248. public function offsetExists($offset)
  249. {
  250. return isset($this->requests[$offset]);
  251. }
  252. /**
  253. * @inheritdoc
  254. */
  255. public function offsetUnset($offset)
  256. {
  257. unset($this->requests[$offset]);
  258. }
  259. /**
  260. * @inheritdoc
  261. */
  262. public function offsetGet($offset)
  263. {
  264. return isset($this->requests[$offset]) ? $this->requests[$offset] : null;
  265. }
  266. }