Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.

Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]

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