PHP 30
FacebookBatchRequest Guest on 25th April 2021 12:03:42 AM
  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.  
  26. use ArrayIterator;
  27. use IteratorAggregate;
  28. use ArrayAccess;
  29. use Facebook\Authentication\AccessToken;
  30. use Facebook\Exceptions\FacebookSDKException;
  31.  
  32. /**
  33.  * Class BatchRequest
  34.  *
  35.  * @package Facebook
  36.  */
  37. class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, ArrayAccess
  38. {
  39.     /**
  40.      * @var array An array of FacebookRequest entities to send.
  41.      */
  42.     protected $requests = [];
  43.  
  44.     /**
  45.      * @var array An array of files to upload.
  46.      */
  47.     protected $attachedFiles;
  48.  
  49.     /**
  50.      * Creates a new Request entity.
  51.      *
  52.      * @param FacebookApp|null        $app
  53.      * @param array                   $requests
  54.      * @param AccessToken|string|null $accessToken
  55.      * @param string|null             $graphVersion
  56.      */
  57.     public function __construct(FacebookApp $app = null, array $requests = [], $accessToken = null, $graphVersion = null)
  58.     {
  59.         parent::__construct($app, $accessToken, 'POST', '', [], null, $graphVersion);
  60.  
  61.         $this->add($requests);
  62.     }
  63.  
  64.     /**
  65.      * Adds a new request to the array.
  66.      *
  67.      * @param FacebookRequest|array $request
  68.      * @param string|null|array     $options Array of batch request options e.g. 'name', 'omit_response_on_success'.
  69.      *                                       If a string is given, it is the value of the 'name' option.
  70.      *
  71.      * @return FacebookBatchRequest
  72.      *
  73.      * @throws \InvalidArgumentException
  74.      */
  75.     public function add($request, $options = null)
  76.     {
  77.         if (is_array($request)) {
  78.             foreach ($request as $key => $req) {
  79.                 $this->add($req, $key);
  80.             }
  81.  
  82.             return $this;
  83.         }
  84.  
  85.         if (!$request instanceof FacebookRequest) {
  86.             throw new \InvalidArgumentException('Argument for add() must be of type array or FacebookRequest.');
  87.         }
  88.  
  89.         if (null === $options) {
  90.             $options = [];
  91.         } elseif (!is_array($options)) {
  92.             $options = ['name' => $options];
  93.         }
  94.  
  95.         $this->addFallbackDefaults($request);
  96.  
  97.         // File uploads
  98.         $attachedFiles = $this->extractFileAttachments($request);
  99.  
  100.         $name = isset($options['name']) ? $options['name'] : null;
  101.  
  102.         unset($options['name']);
  103.  
  104.         $requestToAdd = [
  105.             'name' => $name,
  106.             'request' => $request,
  107.             'options' => $options,
  108.             'attached_files' => $attachedFiles,
  109.         ];
  110.  
  111.         $this->requests[] = $requestToAdd;
  112.  
  113.         return $this;
  114.     }
  115.  
  116.     /**
  117.      * Ensures that the FacebookApp and access token fall back when missing.
  118.      *
  119.      * @param FacebookRequest $request
  120.      *
  121.      * @throws FacebookSDKException
  122.      */
  123.     public function addFallbackDefaults(FacebookRequest $request)
  124.     {
  125.         if (!$request->getApp()) {
  126.             $app = $this->getApp();
  127.             if (!$app) {
  128.                 throw new FacebookSDKException('Missing FacebookApp on FacebookRequest and no fallback detected on FacebookBatchRequest.');
  129.             }
  130.             $request->setApp($app);
  131.         }
  132.  
  133.         if (!$request->getAccessToken()) {
  134.             $accessToken = $this->getAccessToken();
  135.             if (!$accessToken) {
  136.                 throw new FacebookSDKException('Missing access token on FacebookRequest and no fallback detected on FacebookBatchRequest.');
  137.             }
  138.             $request->setAccessToken($accessToken);
  139.         }
  140.     }
  141.  
  142.     /**
  143.      * Extracts the files from a request.
  144.      *
  145.      * @param FacebookRequest $request
  146.      *
  147.      * @return string|null
  148.      *
  149.      * @throws FacebookSDKException
  150.      */
  151.     public function extractFileAttachments(FacebookRequest $request)
  152.     {
  153.         if (!$request->containsFileUploads()) {
  154.             return null;
  155.         }
  156.  
  157.         $files = $request->getFiles();
  158.         $fileNames = [];
  159.         foreach ($files as $file) {
  160.             $fileName = uniqid();
  161.             $this->addFile($fileName, $file);
  162.             $fileNames[] = $fileName;
  163.         }
  164.  
  165.         $request->resetFiles();
  166.  
  167.         // @TODO Does Graph support multiple uploads on one endpoint?
  168.         return implode(',', $fileNames);
  169.     }
  170.  
  171.     /**
  172.      * Return the FacebookRequest entities.
  173.      *
  174.      * @return array
  175.      */
  176.     public function getRequests()
  177.     {
  178.         return $this->requests;
  179.     }
  180.  
  181.     /**
  182.      * Prepares the requests to be sent as a batch request.
  183.      */
  184.     public function prepareRequestsForBatch()
  185.     {
  186.         $this->validateBatchRequestCount();
  187.  
  188.         $params = [
  189.             'batch' => $this->convertRequestsToJson(),
  190.             'include_headers' => true,
  191.         ];
  192.         $this->setParams($params);
  193.     }
  194.  
  195.     /**
  196.      * Converts the requests into a JSON(P) string.
  197.      *
  198.      * @return string
  199.      */
  200.     public function convertRequestsToJson()
  201.     {
  202.         $requests = [];
  203.         foreach ($this->requests as $request) {
  204.             $options = [];
  205.  
  206.             if (null !== $request['name']) {
  207.                 $options['name'] = $request['name'];
  208.             }
  209.  
  210.             $options += $request['options'];
  211.  
  212.             $requests[] = $this->requestEntityToBatchArray($request['request'], $options, $request['attached_files']);
  213.         }
  214.  
  215.         return json_encode($requests);
  216.     }
  217.  
  218.     /**
  219.      * Validate the request count before sending them as a batch.
  220.      *
  221.      * @throws FacebookSDKException
  222.      */
  223.     public function validateBatchRequestCount()
  224.     {
  225.         $batchCount = count($this->requests);
  226.         if ($batchCount === 0) {
  227.             throw new FacebookSDKException('There are no batch requests to send.');
  228.         } elseif ($batchCount > 50) {
  229.             // Per: https://developers.facebook.com/docs/graph-api/making-multiple-requests#limits
  230.             throw new FacebookSDKException('You cannot send more than 50 batch requests at a time.');
  231.         }
  232.     }
  233.  
  234.     /**
  235.      * Converts a Request entity into an array that is batch-friendly.
  236.      *
  237.      * @param FacebookRequest   $request       The request entity to convert.
  238.      * @param string|null|array $options       Array of batch request options e.g. 'name', 'omit_response_on_success'.
  239.      *                                         If a string is given, it is the value of the 'name' option.
  240.      * @param string|null       $attachedFiles Names of files associated with the request.
  241.      *
  242.      * @return array
  243.      */
  244.     public function requestEntityToBatchArray(FacebookRequest $request, $options = null, $attachedFiles = null)
  245.     {
  246.  
  247.         if (null === $options) {
  248.             $options = [];
  249.         } elseif (!is_array($options)) {
  250.             $options = ['name' => $options];
  251.         }
  252.  
  253.         $compiledHeaders = [];
  254.         $headers = $request->getHeaders();
  255.         foreach ($headers as $name => $value) {
  256.             $compiledHeaders[] = $name . ': ' . $value;
  257.         }
  258.  
  259.         $batch = [
  260.             'headers' => $compiledHeaders,
  261.             'method' => $request->getMethod(),
  262.             'relative_url' => $request->getUrl(),
  263.         ];
  264.  
  265.         // Since file uploads are moved to the root request of a batch request,
  266.         // the child requests will always be URL-encoded.
  267.         $body = $request->getUrlEncodedBody()->getBody();
  268.         if ($body) {
  269.             $batch['body'] = $body;
  270.         }
  271.  
  272.         $batch += $options;
  273.  
  274.         if (null !== $attachedFiles) {
  275.             $batch['attached_files'] = $attachedFiles;
  276.         }
  277.  
  278.         return $batch;
  279.     }
  280.  
  281.     /**
  282.      * Get an iterator for the items.
  283.      *
  284.      * @return ArrayIterator
  285.      */
  286.     public function getIterator()
  287.     {
  288.         return new ArrayIterator($this->requests);
  289.     }
  290.  
  291.     /**
  292.      * @inheritdoc
  293.      */
  294.     public function offsetSet($offset, $value)
  295.     {
  296.         $this->add($value, $offset);
  297.     }
  298.  
  299.     /**
  300.      * @inheritdoc
  301.      */
  302.     public function offsetExists($offset)
  303.     {
  304.         return isset($this->requests[$offset]);
  305.     }
  306.  
  307.     /**
  308.      * @inheritdoc
  309.      */
  310.     public function offsetUnset($offset)
  311.     {
  312.         unset($this->requests[$offset]);
  313.     }
  314.  
  315.     /**
  316.      * @inheritdoc
  317.      */
  318.     public function offsetGet($offset)
  319.     {
  320.         return isset($this->requests[$offset]) ? $this->requests[$offset] : null;
  321.     }
  322. }

Paste-bin is for source code and general debugging text.

Login or Register to edit, delete and keep track of your pastes and more.

Raw Paste

Login or Register to edit or fork this paste. It's free.