Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 311 and 402] [Versions 311 and 403]

   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  if (!class_exists('Google_Client')) {
  19    require_once dirname(__FILE__) . '/../autoload.php';
  20  }
  21  
  22  /**
  23   * Class to handle batched requests to the Google API service.
  24   */
  25  class Google_Http_Batch
  26  {
  27    /** @var string Multipart Boundary. */
  28    private $boundary;
  29  
  30    /** @var array service requests to be executed. */
  31    private $requests = array();
  32  
  33    /** @var Google_Client */
  34    private $client;
  35  
  36    private $expected_classes = array();
  37  
  38    private $root_url;
  39  
  40    private $batch_path;
  41  
  42    public function __construct(Google_Client $client, $boundary = false, $rootUrl = '', $batchPath = '')
  43    {
  44      $this->client = $client;
  45      $this->root_url = rtrim($rootUrl ? $rootUrl : $this->client->getBasePath(), '/');
  46      $this->batch_path = $batchPath ? $batchPath : 'batch';
  47      $this->expected_classes = array();
  48      $boundary = (false == $boundary) ? mt_rand() : $boundary;
  49      $this->boundary = str_replace('"', '', $boundary);
  50    }
  51  
  52    public function add(Google_Http_Request $request, $key = false)
  53    {
  54      if (false == $key) {
  55        $key = mt_rand();
  56      }
  57  
  58      $this->requests[$key] = $request;
  59    }
  60  
  61    public function execute()
  62    {
  63      $body = '';
  64  
  65      /** @var Google_Http_Request $req */
  66      foreach ($this->requests as $key => $req) {
  67        $body .= "--{$this->boundary}\n";
  68        $body .= $req->toBatchString($key) . "\n\n";
  69        $this->expected_classes["response-" . $key] = $req->getExpectedClass();
  70      }
  71  
  72      $body .= "--{$this->boundary}--";
  73  
  74      $url = $this->root_url . '/' . $this->batch_path;
  75      $httpRequest = new Google_Http_Request($url, 'POST');
  76      $httpRequest->setRequestHeaders(
  77          array('Content-Type' => 'multipart/mixed; boundary=' . $this->boundary)
  78      );
  79  
  80      $httpRequest->setPostBody($body);
  81      $response = $this->client->getIo()->makeRequest($httpRequest);
  82  
  83      return $this->parseResponse($response);
  84    }
  85  
  86    public function parseResponse(Google_Http_Request $response)
  87    {
  88      $contentType = $response->getResponseHeader('content-type');
  89      $contentType = explode(';', $contentType);
  90      $boundary = false;
  91      foreach ($contentType as $part) {
  92        $part = (explode('=', $part, 2));
  93        if (isset($part[0]) && 'boundary' == trim($part[0])) {
  94          $boundary = $part[1];
  95        }
  96      }
  97  
  98      $body = $response->getResponseBody();
  99      if ($body) {
 100        $body = str_replace("--$boundary--", "--$boundary", $body);
 101        $parts = explode("--$boundary", $body);
 102        $responses = array();
 103  
 104        foreach ($parts as $part) {
 105          $part = trim($part);
 106          if (!empty($part)) {
 107            list($metaHeaders, $part) = explode("\r\n\r\n", $part, 2);
 108            $metaHeaders = $this->client->getIo()->getHttpResponseHeaders($metaHeaders);
 109  
 110            $status = substr($part, 0, strpos($part, "\n"));
 111            $status = explode(" ", $status);
 112            $status = $status[1];
 113  
 114            list($partHeaders, $partBody) = $this->client->getIo()->ParseHttpResponse($part, false);
 115            $response = new Google_Http_Request("");
 116            $response->setResponseHttpCode($status);
 117            $response->setResponseHeaders($partHeaders);
 118            $response->setResponseBody($partBody);
 119  
 120            // Need content id.
 121            $key = $metaHeaders['content-id'];
 122  
 123            if (isset($this->expected_classes[$key]) &&
 124                strlen($this->expected_classes[$key]) > 0) {
 125              $class = $this->expected_classes[$key];
 126              $response->setExpectedClass($class);
 127            }
 128  
 129            try {
 130              $response = Google_Http_REST::decodeHttpResponse($response, $this->client);
 131              $responses[$key] = $response;
 132            } catch (Google_Service_Exception $e) {
 133              // Store the exception as the response, so successful responses
 134              // can be processed.
 135              $responses[$key] = $e;
 136            }
 137          }
 138        }
 139  
 140        return $responses;
 141      }
 142  
 143      return null;
 144    }
 145  }