| 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 |
} |
| 146 |
|