PluginProbe
WP-Stateless – Google Cloud Storage / 3.0.3
WP-Stateless – Google Cloud Storage v3.0.3
4.4.3 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.3.0 2.3.1 2.3.2 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 All 62 releases
wp-stateless / lib / Google / vendor / google / cloud-storage / src / Connection / Rest.php

Rest.php in WP-Stateless – Google Cloud Storage 3.0.3, at lib/Google/vendor/google/cloud-storage/src/Connection/Rest.php

600 lines 14.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Copyright 2015 Google Inc. All Rights Reserved.
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 namespace Google\Cloud\Storage\Connection;
19
20 use Google\Cloud\Core\RequestBuilder;
21 use Google\Cloud\Core\RequestWrapper;
22 use Google\Cloud\Core\RestTrait;
23 use Google\Cloud\Core\Upload\AbstractUploader;
24 use Google\Cloud\Core\Upload\MultipartUploader;
25 use Google\Cloud\Core\Upload\ResumableUploader;
26 use Google\Cloud\Core\Upload\StreamableUploader;
27 use Google\Cloud\Core\UriTrait;
28 use Google\Cloud\Storage\Connection\ConnectionInterface;
29 use Google\Cloud\Storage\StorageClient;
30 use Google\CRC32\Builtin;
31 use Google\CRC32\CRC32;
32 use GuzzleHttp\Psr7;
33 use GuzzleHttp\Psr7\Request;
34 use Psr\Http\Message\ResponseInterface;
35 use Psr\Http\Message\StreamInterface;
36
37 /**
38 * Implementation of the
39 * [Google Cloud Storage JSON API](https://cloud.google.com/storage/docs/json_api/).
40 */
41 class Rest implements ConnectionInterface
42 {
43 use RestTrait;
44 use UriTrait;
45
46 /**
47 * @deprecated
48 */
49 const BASE_URI = 'https://storage.googleapis.com/storage/v1/';
50
51 const DEFAULT_API_ENDPOINT = 'https://storage.googleapis.com';
52
53 /**
54 * @deprecated
55 */
56 const UPLOAD_URI = 'https://storage.googleapis.com/upload/storage/v1/b/{bucket}/o{?query*}';
57
58 const UPLOAD_PATH = 'upload/storage/v1/b/{bucket}/o{?query*}';
59
60 /**
61 * @deprecated
62 */
63 const DOWNLOAD_URI = 'https://storage.googleapis.com/storage/v1/b/{bucket}/o/{object}{?query*}';
64
65 const DOWNLOAD_PATH = 'storage/v1/b/{bucket}/o/{object}{?query*}';
66
67 /**
68 * @var string
69 */
70 private $projectId;
71
72 /**
73 * @var string
74 */
75 private $apiEndpoint;
76
77 /**
78 * @param array $config
79 */
80 public function __construct(array $config = [])
81 {
82 $config += [
83 'serviceDefinitionPath' => __DIR__ . '/ServiceDefinition/storage-v1.json',
84 'componentVersion' => StorageClient::VERSION,
85 'apiEndpoint' => self::DEFAULT_API_ENDPOINT
86 ];
87
88 $this->apiEndpoint = $this->getApiEndpoint(self::DEFAULT_API_ENDPOINT, $config);
89
90 $this->setRequestWrapper(new RequestWrapper($config));
91 $this->setRequestBuilder(new RequestBuilder(
92 $config['serviceDefinitionPath'],
93 $this->apiEndpoint
94 ));
95
96 $this->projectId = $this->pluck('projectId', $config, false);
97 }
98
99 /**
100 * @return string
101 */
102 public function projectId()
103 {
104 return $this->projectId;
105 }
106
107 /**
108 * @param array $args
109 */
110 public function deleteAcl(array $args = [])
111 {
112 return $this->send($args['type'], 'delete', $args);
113 }
114
115 /**
116 * @param array $args
117 */
118 public function getAcl(array $args = [])
119 {
120 return $this->send($args['type'], 'get', $args);
121 }
122
123 /**
124 * @param array $args
125 */
126 public function listAcl(array $args = [])
127 {
128 return $this->send($args['type'], 'list', $args);
129 }
130
131 /**
132 * @param array $args
133 */
134 public function insertAcl(array $args = [])
135 {
136 return $this->send($args['type'], 'insert', $args);
137 }
138
139 /**
140 * @param array $args
141 */
142 public function patchAcl(array $args = [])
143 {
144 return $this->send($args['type'], 'patch', $args);
145 }
146
147 /**
148 * @param array $args
149 */
150 public function deleteBucket(array $args = [])
151 {
152 return $this->send('buckets', 'delete', $args);
153 }
154
155 /**
156 * @param array $args
157 */
158 public function getBucket(array $args = [])
159 {
160 return $this->send('buckets', 'get', $args);
161 }
162
163 /**
164 * @param array $args
165 */
166 public function listBuckets(array $args = [])
167 {
168 return $this->send('buckets', 'list', $args);
169 }
170
171 /**
172 * @param array $args
173 */
174 public function insertBucket(array $args = [])
175 {
176 return $this->send('buckets', 'insert', $args);
177 }
178
179 /**
180 * @param array $args
181 */
182 public function patchBucket(array $args = [])
183 {
184 return $this->send('buckets', 'patch', $args);
185 }
186
187 /**
188 * @param array $args
189 */
190 public function deleteObject(array $args = [])
191 {
192 return $this->send('objects', 'delete', $args);
193 }
194
195 /**
196 * @param array $args
197 */
198 public function copyObject(array $args = [])
199 {
200 return $this->send('objects', 'copy', $args);
201 }
202
203 /**
204 * @param array $args
205 */
206 public function rewriteObject(array $args = [])
207 {
208 return $this->send('objects', 'rewrite', $args);
209 }
210
211 /**
212 * @param array $args
213 */
214 public function composeObject(array $args = [])
215 {
216 return $this->send('objects', 'compose', $args);
217 }
218
219 /**
220 * @param array $args
221 */
222 public function getObject(array $args = [])
223 {
224 return $this->send('objects', 'get', $args);
225 }
226
227 /**
228 * @param array $args
229 */
230 public function listObjects(array $args = [])
231 {
232 return $this->send('objects', 'list', $args);
233 }
234
235 /**
236 * @param array $args
237 */
238 public function patchObject(array $args = [])
239 {
240 return $this->send('objects', 'patch', $args);
241 }
242
243 /**
244 * @param array $args
245 */
246 public function downloadObject(array $args = [])
247 {
248 list($request, $requestOptions) = $this->buildDownloadObjectParams($args);
249
250 return $this->requestWrapper->send(
251 $request,
252 $requestOptions
253 )->getBody();
254 }
255
256 /**
257 * @param array $args
258 * @experimental The experimental flag means that while we believe this method
259 * or class is ready for use, it may change before release in backwards-
260 * incompatible ways. Please use with caution, and test thoroughly when
261 * upgrading.
262 */
263 public function downloadObjectAsync(array $args = [])
264 {
265 list($request, $requestOptions) = $this->buildDownloadObjectParams($args);
266
267 return $this->requestWrapper->sendAsync(
268 $request,
269 $requestOptions
270 )->then(function (ResponseInterface $response) {
271 return $response->getBody();
272 });
273 }
274
275 /**
276 * @param array $args
277 */
278 public function insertObject(array $args = [])
279 {
280 $args = $this->resolveUploadOptions($args);
281
282 $uploadType = AbstractUploader::UPLOAD_TYPE_RESUMABLE;
283 if ($args['streamable']) {
284 $uploaderClass = StreamableUploader::class;
285 } elseif ($args['resumable']) {
286 $uploaderClass = ResumableUploader::class;
287 } else {
288 $uploaderClass = MultipartUploader::class;
289 $uploadType = AbstractUploader::UPLOAD_TYPE_MULTIPART;
290 }
291
292 $uriParams = [
293 'bucket' => $args['bucket'],
294 'query' => [
295 'predefinedAcl' => $args['predefinedAcl'],
296 'uploadType' => $uploadType,
297 'userProject' => $args['userProject']
298 ]
299 ];
300
301 return new $uploaderClass(
302 $this->requestWrapper,
303 $args['data'],
304 $this->expandUri($this->apiEndpoint . self::UPLOAD_PATH, $uriParams),
305 $args['uploaderOptions']
306 );
307 }
308
309 /**
310 * @param array $args
311 */
312 private function resolveUploadOptions(array $args)
313 {
314 $args += [
315 'bucket' => null,
316 'name' => null,
317 'validate' => true,
318 'resumable' => null,
319 'streamable' => null,
320 'predefinedAcl' => null,
321 'metadata' => [],
322 'userProject' => null,
323 ];
324
325 $args['data'] = Psr7\stream_for($args['data']);
326
327 if ($args['resumable'] === null) {
328 $args['resumable'] = $args['data']->getSize() > AbstractUploader::RESUMABLE_LIMIT;
329 }
330
331 if (!$args['name']) {
332 $args['name'] = basename($args['data']->getMetadata('uri'));
333 }
334
335 $validate = $this->chooseValidationMethod($args);
336 if ($validate === 'md5') {
337 $args['metadata']['md5Hash'] = base64_encode(Psr7\hash($args['data'], 'md5', true));
338 } elseif ($validate === 'crc32') {
339 $args['metadata']['crc32c'] = $this->crcFromStream($args['data']);
340 }
341
342 $args['metadata']['name'] = $args['name'];
343 unset($args['name']);
344 $args['contentType'] = isset($args['metadata']['contentType'])
345 ? $args['metadata']['contentType']
346 : Psr7\mimetype_from_filename($args['metadata']['name']);
347
348 $uploaderOptionKeys = [
349 'restOptions',
350 'retries',
351 'requestTimeout',
352 'chunkSize',
353 'contentType',
354 'metadata',
355 'uploadProgressCallback'
356 ];
357
358 $args['uploaderOptions'] = array_intersect_key($args, array_flip($uploaderOptionKeys));
359 $args = array_diff_key($args, array_flip($uploaderOptionKeys));
360
361 return $args;
362 }
363
364 /**
365 * @param array $args
366 */
367 public function getBucketIamPolicy(array $args)
368 {
369 return $this->send('buckets', 'getIamPolicy', $args);
370 }
371
372 /**
373 * @param array $args
374 */
375 public function setBucketIamPolicy(array $args)
376 {
377 return $this->send('buckets', 'setIamPolicy', $args);
378 }
379
380 /**
381 * @param array $args
382 */
383 public function testBucketIamPermissions(array $args)
384 {
385 return $this->send('buckets', 'testIamPermissions', $args);
386 }
387
388 /**
389 * @param array $args
390 */
391 public function getNotification(array $args = [])
392 {
393 return $this->send('notifications', 'get', $args);
394 }
395
396 /**
397 * @param array $args
398 */
399 public function deleteNotification(array $args = [])
400 {
401 return $this->send('notifications', 'delete', $args);
402 }
403
404 /**
405 * @param array $args
406 */
407 public function insertNotification(array $args = [])
408 {
409 return $this->send('notifications', 'insert', $args);
410 }
411
412 /**
413 * @param array $args
414 */
415 public function listNotifications(array $args = [])
416 {
417 return $this->send('notifications', 'list', $args);
418 }
419
420 /**
421 * @param array $args
422 */
423 public function getServiceAccount(array $args = [])
424 {
425 return $this->send('projects.resources.serviceAccount', 'get', $args);
426 }
427
428 /**
429 * @param array $args
430 */
431 public function lockRetentionPolicy(array $args = [])
432 {
433 return $this->send('buckets', 'lockRetentionPolicy', $args);
434 }
435
436 /**
437 * @param array $args
438 */
439 public function createHmacKey(array $args = [])
440 {
441 return $this->send('projects.resources.hmacKeys', 'create', $args);
442 }
443
444 /**
445 * @param array $args
446 */
447 public function deleteHmacKey(array $args = [])
448 {
449 return $this->send('projects.resources.hmacKeys', 'delete', $args);
450 }
451
452 /**
453 * @param array $args
454 */
455 public function getHmacKey(array $args = [])
456 {
457 return $this->send('projects.resources.hmacKeys', 'get', $args);
458 }
459
460 /**
461 * @param array $args
462 */
463 public function updateHmacKey(array $args = [])
464 {
465 return $this->send('projects.resources.hmacKeys', 'update', $args);
466 }
467
468 /**
469 * @param array $args
470 */
471 public function listHmacKeys(array $args = [])
472 {
473 return $this->send('projects.resources.hmacKeys', 'list', $args);
474 }
475
476 /**
477 * @param array $args
478 * @return array
479 */
480 private function buildDownloadObjectParams(array $args)
481 {
482 $args += [
483 'bucket' => null,
484 'object' => null,
485 'generation' => null,
486 'userProject' => null
487 ];
488
489 $requestOptions = array_intersect_key($args, [
490 'restOptions' => null,
491 'retries' => null,
492 'restRetryFunction' => null,
493 'restCalcDelayFunction' => null,
494 'restDelayFunction' => null
495 ]);
496
497 $uri = $this->expandUri($this->apiEndpoint . self::DOWNLOAD_PATH, [
498 'bucket' => $args['bucket'],
499 'object' => $args['object'],
500 'query' => [
501 'generation' => $args['generation'],
502 'alt' => 'media',
503 'userProject' => $args['userProject']
504 ]
505 ]);
506
507 return [
508 new Request('GET', Psr7\uri_for($uri)),
509 $requestOptions
510 ];
511 }
512
513 /**
514 * Choose a upload validation method based on user input and platform
515 * requirements.
516 *
517 * @param array $args
518 * @return bool|string
519 */
520 private function chooseValidationMethod(array $args)
521 {
522 // If the user provided a hash, skip hashing.
523 if (isset($args['metadata']['md5Hash']) || isset($args['metadata']['crc32c'])) {
524 return false;
525 }
526
527 $validate = $args['validate'];
528 if (in_array($validate, [false, 'crc32', 'md5'], true)) {
529 return $validate;
530 }
531
532 // not documented, but the feature is called crc32c, so let's accept that as input anyways.
533 if ($validate === 'crc32c') {
534 return 'crc32';
535 }
536
537 // is the extension loaded?
538 if ($this->crc32cExtensionLoaded()) {
539 return 'crc32';
540 }
541
542 // is crc32c available in `hash()`?
543 if ($this->supportsBuiltinCrc32c()) {
544 return 'crc32';
545 }
546
547 return 'md5';
548 }
549
550 /**
551 * Generate a CRC32c checksum from a stream.
552 *
553 * @param StreamInterface $data
554 * @return string
555 */
556 private function crcFromStream(StreamInterface $data)
557 {
558 $pos = $data->tell();
559
560 if ($pos > 0) {
561 $data->rewind();
562 }
563
564 $crc32c = CRC32::create(CRC32::CASTAGNOLI);
565
566 $data->rewind();
567 while (!$data->eof()) {
568 $crc32c->update($data->read(1048576));
569 }
570
571 $data->seek($pos);
572
573 return base64_encode($crc32c->hash(true));
574 }
575
576 /**
577 * Check if the crc32c extension is available.
578 *
579 * Protected access for unit testing.
580 *
581 * @return bool
582 */
583 protected function crc32cExtensionLoaded()
584 {
585 return extension_loaded('crc32c');
586 }
587
588 /**
589 * Check if hash() supports crc32c.
590 *
591 * Protected access for unit testing.
592 *
593 * @return bool
594 */
595 protected function supportsBuiltinCrc32c()
596 {
597 return Builtin::supports(CRC32::CASTAGNOLI);
598 }
599 }
600