summaryrefslogtreecommitdiff
path: root/lib/facebook-graph-sdk/src/Facebook/FacebookBatchRequest.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/facebook-graph-sdk/src/Facebook/FacebookBatchRequest.php')
-rw-r--r--lib/facebook-graph-sdk/src/Facebook/FacebookBatchRequest.php303
1 files changed, 303 insertions, 0 deletions
diff --git a/lib/facebook-graph-sdk/src/Facebook/FacebookBatchRequest.php b/lib/facebook-graph-sdk/src/Facebook/FacebookBatchRequest.php
new file mode 100644
index 0000000..33c489c
--- /dev/null
+++ b/lib/facebook-graph-sdk/src/Facebook/FacebookBatchRequest.php
@@ -0,0 +1,303 @@
+<?php
+/**
+ * Copyright 2014 Facebook, Inc.
+ *
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
+ * use, copy, modify, and distribute this software in source code or binary
+ * form for use in connection with the web services and APIs provided by
+ * Facebook.
+ *
+ * As with any software that integrates with the Facebook platform, your use
+ * of this software is subject to the Facebook Developer Principles and
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
+ * shall be included in all copies or substantial portions of the software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+namespace Facebook;
+
+use ArrayIterator;
+use IteratorAggregate;
+use ArrayAccess;
+use Facebook\Authentication\AccessToken;
+use Facebook\Exceptions\FacebookSDKException;
+
+/**
+ * Class BatchRequest
+ *
+ * @package Facebook
+ */
+class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, ArrayAccess
+{
+ /**
+ * @var array An array of FacebookRequest entities to send.
+ */
+ protected $requests;
+
+ /**
+ * @var array An array of files to upload.
+ */
+ protected $attachedFiles;
+
+ /**
+ * Creates a new Request entity.
+ *
+ * @param FacebookApp|null $app
+ * @param array $requests
+ * @param AccessToken|string|null $accessToken
+ * @param string|null $graphVersion
+ */
+ public function __construct(FacebookApp $app = null, array $requests = [], $accessToken = null, $graphVersion = null)
+ {
+ parent::__construct($app, $accessToken, 'POST', '', [], null, $graphVersion);
+
+ $this->add($requests);
+ }
+
+ /**
+ * A a new request to the array.
+ *
+ * @param FacebookRequest|array $request
+ * @param string|null $name
+ *
+ * @return FacebookBatchRequest
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function add($request, $name = null)
+ {
+ if (is_array($request)) {
+ foreach ($request as $key => $req) {
+ $this->add($req, $key);
+ }
+
+ return $this;
+ }
+
+ if (!$request instanceof FacebookRequest) {
+ throw new \InvalidArgumentException('Argument for add() must be of type array or FacebookRequest.');
+ }
+
+ $this->addFallbackDefaults($request);
+ $requestToAdd = [
+ 'name' => $name,
+ 'request' => $request,
+ ];
+
+ // File uploads
+ $attachedFiles = $this->extractFileAttachments($request);
+ if ($attachedFiles) {
+ $requestToAdd['attached_files'] = $attachedFiles;
+ }
+ $this->requests[] = $requestToAdd;
+
+ return $this;
+ }
+
+ /**
+ * Ensures that the FacebookApp and access token fall back when missing.
+ *
+ * @param FacebookRequest $request
+ *
+ * @throws FacebookSDKException
+ */
+ public function addFallbackDefaults(FacebookRequest $request)
+ {
+ if (!$request->getApp()) {
+ $app = $this->getApp();
+ if (!$app) {
+ throw new FacebookSDKException('Missing FacebookApp on FacebookRequest and no fallback detected on FacebookBatchRequest.');
+ }
+ $request->setApp($app);
+ }
+
+ if (!$request->getAccessToken()) {
+ $accessToken = $this->getAccessToken();
+ if (!$accessToken) {
+ throw new FacebookSDKException('Missing access token on FacebookRequest and no fallback detected on FacebookBatchRequest.');
+ }
+ $request->setAccessToken($accessToken);
+ }
+ }
+
+ /**
+ * Extracts the files from a request.
+ *
+ * @param FacebookRequest $request
+ *
+ * @return string|null
+ *
+ * @throws FacebookSDKException
+ */
+ public function extractFileAttachments(FacebookRequest $request)
+ {
+ if (!$request->containsFileUploads()) {
+ return null;
+ }
+
+ $files = $request->getFiles();
+ $fileNames = [];
+ foreach ($files as $file) {
+ $fileName = uniqid();
+ $this->addFile($fileName, $file);
+ $fileNames[] = $fileName;
+ }
+
+ $request->resetFiles();
+
+ // @TODO Does Graph support multiple uploads on one endpoint?
+ return implode(',', $fileNames);
+ }
+
+ /**
+ * Return the FacebookRequest entities.
+ *
+ * @return array
+ */
+ public function getRequests()
+ {
+ return $this->requests;
+ }
+
+ /**
+ * Prepares the requests to be sent as a batch request.
+ *
+ * @return string
+ */
+ public function prepareRequestsForBatch()
+ {
+ $this->validateBatchRequestCount();
+
+ $params = [
+ 'batch' => $this->convertRequestsToJson(),
+ 'include_headers' => true,
+ ];
+ $this->setParams($params);
+ }
+
+ /**
+ * Converts the requests into a JSON(P) string.
+ *
+ * @return string
+ */
+ public function convertRequestsToJson()
+ {
+ $requests = [];
+ foreach ($this->requests as $request) {
+ $attachedFiles = isset($request['attached_files']) ? $request['attached_files'] : null;
+ $requests[] = $this->requestEntityToBatchArray($request['request'], $request['name'], $attachedFiles);
+ }
+
+ return json_encode($requests);
+ }
+
+ /**
+ * Validate the request count before sending them as a batch.
+ *
+ * @throws FacebookSDKException
+ */
+ public function validateBatchRequestCount()
+ {
+ $batchCount = count($this->requests);
+ if ($batchCount === 0) {
+ throw new FacebookSDKException('There are no batch requests to send.');
+ } elseif ($batchCount > 50) {
+ // Per: https://developers.facebook.com/docs/graph-api/making-multiple-requests#limits
+ throw new FacebookSDKException('You cannot send more than 50 batch requests at a time.');
+ }
+ }
+
+ /**
+ * Converts a Request entity into an array that is batch-friendly.
+ *
+ * @param FacebookRequest $request The request entity to convert.
+ * @param string|null $requestName The name of the request.
+ * @param string|null $attachedFiles Names of files associated with the request.
+ *
+ * @return array
+ */
+ public function requestEntityToBatchArray(FacebookRequest $request, $requestName = null, $attachedFiles = null)
+ {
+ $compiledHeaders = [];
+ $headers = $request->getHeaders();
+ foreach ($headers as $name => $value) {
+ $compiledHeaders[] = $name . ': ' . $value;
+ }
+
+ $batch = [
+ 'headers' => $compiledHeaders,
+ 'method' => $request->getMethod(),
+ 'relative_url' => $request->getUrl(),
+ ];
+
+ // Since file uploads are moved to the root request of a batch request,
+ // the child requests will always be URL-encoded.
+ $body = $request->getUrlEncodedBody()->getBody();
+ if ($body) {
+ $batch['body'] = $body;
+ }
+
+ if (isset($requestName)) {
+ $batch['name'] = $requestName;
+ }
+
+ if (isset($attachedFiles)) {
+ $batch['attached_files'] = $attachedFiles;
+ }
+
+ // @TODO Add support for "omit_response_on_success"
+ // @TODO Add support for "depends_on"
+ // @TODO Add support for JSONP with "callback"
+
+ return $batch;
+ }
+
+ /**
+ * Get an iterator for the items.
+ *
+ * @return ArrayIterator
+ */
+ public function getIterator()
+ {
+ return new ArrayIterator($this->requests);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function offsetSet($offset, $value)
+ {
+ $this->add($value, $offset);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function offsetExists($offset)
+ {
+ return isset($this->requests[$offset]);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function offsetUnset($offset)
+ {
+ unset($this->requests[$offset]);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function offsetGet($offset)
+ {
+ return isset($this->requests[$offset]) ? $this->requests[$offset] : null;
+ }
+}