PluginProbe
Media Cloud Sync / 1.1.1
Media Cloud Sync v1.1.1
1.4.2 1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 All 36 releases
media-cloud-sync / includes / sdk / google / google / cloud-storage / src / StorageObject.php

StorageObject.php in Media Cloud Sync 1.1.1, at includes/sdk/google/google/cloud-storage/src/StorageObject.php

1,136 lines 53.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Copyright 2015 Google Inc. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 namespace Dudlewebs\WPMCS\Google\Cloud\Storage;
19
20 use Dudlewebs\WPMCS\Google\Cloud\Core\ArrayTrait;
21 use Dudlewebs\WPMCS\Google\Cloud\Core\Exception\NotFoundException;
22 use Dudlewebs\WPMCS\Google\Cloud\Core\Timestamp;
23 use Dudlewebs\WPMCS\Google\Cloud\Core\Upload\SignedUrlUploader;
24 use Dudlewebs\WPMCS\Google\Cloud\Storage\Connection\ConnectionInterface;
25 use Dudlewebs\WPMCS\GuzzleHttp\Promise\PromiseInterface;
26 use Dudlewebs\WPMCS\GuzzleHttp\Psr7\Utils;
27 use Dudlewebs\WPMCS\Psr\Http\Message\StreamInterface;
28 /**
29 * Objects are the individual pieces of data that you store in Google Cloud
30 * Storage.
31 *
32 * Example:
33 * ```
34 * use Google\Cloud\Storage\StorageClient;
35 *
36 * $storage = new StorageClient();
37 *
38 * $bucket = $storage->bucket('my-bucket');
39 * $object = $bucket->object('my-object');
40 * ```
41 */
42 class StorageObject
43 {
44 use ArrayTrait;
45 use EncryptionTrait;
46 /**
47 * @deprecated
48 */
49 const DEFAULT_DOWNLOAD_URL = SigningHelper::DEFAULT_DOWNLOAD_HOST;
50 /**
51 * @var Acl ACL for the object.
52 */
53 private $acl;
54 /**
55 * @var ConnectionInterface Represents a connection to Cloud Storage.
56 * @internal
57 */
58 protected $connection;
59 /**
60 * @var array|null The object's encryption data.
61 */
62 private $encryptionData;
63 /**
64 * @var array The object's identity.
65 */
66 private $identity;
67 /**
68 * @var array|null The object's metadata.
69 */
70 private $info;
71 /**
72 * @param ConnectionInterface $connection Represents a connection to Cloud
73 * Storage. This object is created by StorageClient,
74 * and should not be instantiated outside of this client.
75 * @param string $name The object's name.
76 * @param string $bucket The name of the bucket the object is contained in.
77 * @param string $generation [optional] The generation of the object.
78 * @param array $info [optional] The object's metadata.
79 * @param string $encryptionKey [optional] An AES-256 customer-supplied
80 * encryption key.
81 * @param string $encryptionKeySHA256 [optional] The SHA256 hash of the
82 * customer-supplied encryption key.
83 */
84 public function __construct(ConnectionInterface $connection, $name, $bucket, $generation = null, array $info = [], $encryptionKey = null, $encryptionKeySHA256 = null)
85 {
86 $this->connection = $connection;
87 $this->info = $info;
88 $this->encryptionData = ['encryptionKey' => $encryptionKey, 'encryptionKeySHA256' => $encryptionKeySHA256];
89 $this->identity = ['bucket' => $bucket, 'object' => $name, 'generation' => $generation, 'userProject' => $this->pluck('requesterProjectId', $info, \false)];
90 $this->acl = new Acl($this->connection, 'objectAccessControls', $this->identity);
91 }
92 /**
93 * Configure ACL for this object.
94 *
95 * Example:
96 * ```
97 * $acl = $object->acl();
98 * ```
99 *
100 * @see https://cloud.google.com/storage/docs/access-control More about Access Control Lists
101 *
102 * @return Acl
103 */
104 public function acl()
105 {
106 return $this->acl;
107 }
108 /**
109 * Check whether or not the object exists.
110 *
111 * Example:
112 * ```
113 * if ($object->exists()) {
114 * echo 'Object exists!';
115 * }
116 * ```
117 *
118 * @param array $options [optional] Configuration options.
119 * @return bool
120 */
121 public function exists(array $options = [])
122 {
123 try {
124 $this->connection->getObject($this->identity + $options + ['fields' => 'name']);
125 } catch (NotFoundException $ex) {
126 return \false;
127 }
128 return \true;
129 }
130 /**
131 * Delete the object.
132 *
133 * Example:
134 * ```
135 * $object->delete();
136 * ```
137 *
138 * @see https://cloud.google.com/storage/docs/json_api/v1/objects/delete Objects delete API documentation.
139 *
140 * @param array $options [optional] {
141 * Configuration options.
142 *
143 * @type string $ifGenerationMatch Makes the operation conditional on
144 * whether the object's current generation matches the given
145 * value.
146 * @type string $ifGenerationNotMatch Makes the operation conditional on
147 * whether the object's current generation does not match the
148 * given value.
149 * @type string $ifMetagenerationMatch Makes the operation conditional
150 * on whether the object's current metageneration matches the
151 * given value.
152 * @type string $ifMetagenerationNotMatch Makes the operation
153 * conditional on whether the object's current metageneration does
154 * not match the given value.
155 * }
156 * @return void
157 */
158 public function delete(array $options = [])
159 {
160 $this->connection->deleteObject($options + array_filter($this->identity));
161 }
162 /**
163 * Update the object. Upon receiving a result the local object's data will
164 * be updated.
165 *
166 * Example:
167 * ```
168 * // Add custom metadata to an existing object.
169 * $object->update([
170 * 'metadata' => [
171 * 'albumType' => 'family'
172 * ]
173 * ]);
174 * ```
175 *
176 * @see https://cloud.google.com/storage/docs/json_api/v1/objects/patch Objects patch API documentation.
177 *
178 * @param array $metadata The available options for metadata are outlined
179 * at the [JSON API docs](https://cloud.google.com/storage/docs/json_api/v1/objects#resource)
180 * @param array $options [optional] {
181 * Configuration options.
182 *
183 * @type string $ifGenerationMatch Makes the operation conditional on
184 * whether the object's current generation matches the given
185 * value.
186 * @type string $ifGenerationNotMatch Makes the operation conditional on
187 * whether the object's current generation does not match the
188 * given value.
189 * @type string $ifMetagenerationMatch Makes the operation conditional
190 * on whether the object's current metageneration matches the
191 * given value.
192 * @type string $ifMetagenerationNotMatch Makes the operation
193 * conditional on whether the object's current metageneration does
194 * not match the given value.
195 * @type string $predefinedAcl Predefined ACL to apply to the object.
196 * Acceptable values include, `"authenticatedRead"`,
197 * `"bucketOwnerFullControl"`, `"bucketOwnerRead"`, `"private"`,
198 * `"projectPrivate"`, and `"publicRead"`.
199 * @type array $retention The full list of available options are outlined
200 * at the [JSON API docs](https://cloud.google.com/storage/docs/json_api/v1/objects/update#request-body).
201 * @type string $retention.retainUntilTime The earliest time in RFC 3339
202 * UTC "Zulu" format that the object can be deleted or replaced.
203 * This is the retention configuration set for this object.
204 * @type string $retention.mode The mode of the retention configuration,
205 * which can be either `"Unlocked"` or `"Locked"`.
206 * @type bool $overrideUnlockedRetention Applicable for objects that
207 * have an unlocked retention configuration. Required to be set to
208 * `true` if the operation includes a retention property that
209 * changes the mode to `Locked`, reduces the `retainUntilTime`, or
210 * removes the retention configuration from the object.
211 * @type string $projection Determines which properties to return. May
212 * be either 'full' or 'noAcl'.
213 * @type string $fields Selector which will cause the response to only
214 * return the specified fields.
215 * }
216 * @return array
217 */
218 public function update(array $metadata, array $options = [])
219 {
220 $options += $metadata;
221 // can only set predefinedAcl or acl
222 if (isset($options['predefinedAcl'])) {
223 $options['acl'] = null;
224 }
225 return $this->info = $this->connection->patchObject($options + array_filter($this->identity));
226 }
227 /**
228 * Copy the object to a destination bucket.
229 *
230 * Please note that if the destination bucket is the same as the source
231 * bucket and a new name is not provided the source object will be replaced
232 * with the copy of itself.
233 *
234 * Example:
235 * ```
236 * // Provide your destination bucket as a string and retain the source
237 * // object's name.
238 * $copiedObject = $object->copy('otherBucket');
239 * ```
240 *
241 * ```
242 * // Provide your destination bucket as a bucket object and choose a new
243 * // name for the copied object.
244 * $otherBucket = $storage->bucket('otherBucket');
245 * $copiedObject = $object->copy($otherBucket, [
246 * 'name' => 'newFile.txt'
247 * ]);
248 * ```
249 *
250 * @see https://cloud.google.com/storage/docs/json_api/v1/objects/copy Objects copy API documentation.
251 *
252 * @param Bucket|string $destination The destination bucket.
253 * @param array $options [optional] {
254 * Configuration options.
255 *
256 * @type string $name The name of the destination object. **Defaults
257 * to** the name of the source object.
258 * @type string $predefinedAcl Predefined ACL to apply to the object.
259 * Acceptable values include, `"authenticatedRead"`,
260 * `"bucketOwnerFullControl"`, `"bucketOwnerRead"`, `"private"`,
261 * `"projectPrivate"`, and `"publicRead"`.
262 * @type string $encryptionKey A base64 encoded AES-256 customer-supplied
263 * encryption key. It will be neccesary to provide this when a key
264 * was used during the object's creation.
265 * @type string $encryptionKeySHA256 Base64 encoded SHA256 hash of the
266 * customer-supplied encryption key. This value will be calculated
267 * from the `encryptionKey` on your behalf if not provided, but
268 * for best performance it is recommended to pass in a cached
269 * version of the already calculated SHA.
270 * @type string $ifGenerationMatch Makes the operation conditional on
271 * whether the destination object's current generation matches the
272 * given value.
273 * @type string $ifGenerationNotMatch Makes the operation conditional on
274 * whether the destination object's current generation does not
275 * match the given value.
276 * @type string $ifMetagenerationMatch Makes the operation conditional
277 * on whether the destination object's current metageneration
278 * matches the given value.
279 * @type string $ifMetagenerationNotMatch Makes the operation
280 * conditional on whether the destination object's current
281 * metageneration does not match the given value.
282 * @type string $ifSourceGenerationMatch Makes the operation conditional
283 * on whether the source object's current generation matches the
284 * given value.
285 * @type string $ifSourceGenerationNotMatch Makes the operation
286 * conditional on whether the source object's current generation
287 * does not match the given value.
288 * @type string $ifSourceMetagenerationMatch Makes the operation
289 * conditional on whether the source object's current
290 * metageneration matches the given value.
291 * @type string $ifSourceMetagenerationNotMatch Makes the operation
292 * conditional on whether the source object's current
293 * metageneration does not match the given value.
294 * }
295 * @return StorageObject
296 */
297 public function copy($destination, array $options = [])
298 {
299 $key = $options['encryptionKey'] ?? null;
300 $keySHA256 = $options['encryptionKeySHA256'] ?? null;
301 $response = $this->connection->copyObject($this->formatDestinationRequest($destination, $options));
302 return new StorageObject($this->connection, $response['name'], $response['bucket'], $response['generation'], $response + ['requesterProjectId' => $this->identity['userProject']], $key, $keySHA256);
303 }
304 /**
305 * Rewrite the object to a destination bucket.
306 *
307 * This method copies data using multiple requests so large objects can be
308 * copied with a normal length timeout per request rather than one very long
309 * timeout for a single request.
310 *
311 * Please note that if the destination bucket is the same as the source
312 * bucket and a new name is not provided the source object will be replaced
313 * with the copy of itself.
314 *
315 * Example:
316 * ```
317 * // Provide your destination bucket as a string and retain the source
318 * // object's name.
319 * $rewrittenObject = $object->rewrite('otherBucket');
320 * ```
321 *
322 * ```
323 * // Provide your destination bucket as a bucket object and choose a new
324 * // name for the copied object.
325 * $otherBucket = $storage->bucket('otherBucket');
326 * $rewrittenObject = $object->rewrite($otherBucket, [
327 * 'name' => 'newFile.txt'
328 * ]);
329 * ```
330 *
331 * ```
332 * // Rotate customer-supplied encryption keys.
333 * $key = file_get_contents(__DIR__ . '/key.txt');
334 * $destinationKey = base64_encode(openssl_random_pseudo_bytes(32)); // Make sure to remember your key.
335 *
336 * $rewrittenObject = $object->rewrite('otherBucket', [
337 * 'encryptionKey' => $key,
338 * 'destinationEncryptionKey' => $destinationKey
339 * ]);
340 * ```
341 *
342 * @see https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite Objects rewrite API documentation.
343 * @see https://cloud.google.com/storage/docs/encryption#customer-supplied Customer-supplied encryption keys.
344 *
345 * @param Bucket|string $destination The destination bucket.
346 * @param array $options [optional] {
347 * Configuration options.
348 *
349 * @type string $name The name of the destination object. **Defaults
350 * to** the name of the source object.
351 * @type string $predefinedAcl Predefined ACL to apply to the object.
352 * Acceptable values include, `"authenticatedRead"`,
353 * `"bucketOwnerFullControl"`, `"bucketOwnerRead"`, `"private"`,
354 * `"projectPrivate"`, and `"publicRead"`.
355 * @type string $maxBytesRewrittenPerCall The maximum number of bytes
356 * that will be rewritten per rewrite request. Most callers
357 * shouldn't need to specify this parameter - it is primarily in
358 * place to support testing. If specified the value must be an
359 * integral multiple of 1 MiB (1048576). Also, this only applies
360 * to requests where the source and destination span locations
361 * and/or storage classes.
362 * @type string $encryptionKey A base64 encoded AES-256 customer-supplied
363 * encryption key. It will be neccesary to provide this when a key
364 * was used during the object's creation.
365 * @type string $encryptionKeySHA256 Base64 encoded SHA256 hash of the
366 * customer-supplied encryption key. This value will be calculated
367 * from the `encryptionKey` on your behalf if not provided, but
368 * for best performance it is recommended to pass in a cached
369 * version of the already calculated SHA.
370 * @type string $destinationEncryptionKey A base64 encoded AES-256
371 * customer-supplied encryption key that will be used to encrypt
372 * the rewritten object.
373 * @type string $destinationEncryptionKeySHA256 Base64 encoded SHA256
374 * hash of the customer-supplied destination encryption key. This
375 * value will be calculated from the `destinationEncryptionKey` on
376 * your behalf if not provided, but for best performance it is
377 * recommended to pass in a cached version of the already
378 * calculated SHA.
379 * @type string $destinationKmsKeyName Name of the Cloud KMS key that
380 * will be used to encrypt the object. Should be in the format
381 * `projects/my-project/locations/kr-location/keyRings/my-kr/cryptoKeys/my-key`.
382 * Please note the KMS key ring must use the same location as the
383 * destination bucket.
384 * @type string $ifGenerationMatch Makes the operation conditional on
385 * whether the destination object's current generation matches the
386 * given value.
387 * @type string $ifGenerationNotMatch Makes the operation conditional on
388 * whether the destination object's current generation does not
389 * match the given value.
390 * @type string $ifMetagenerationMatch Makes the operation conditional
391 * on whether the destination object's current metageneration
392 * matches the given value.
393 * @type string $ifMetagenerationNotMatch Makes the operation
394 * conditional on whether the destination object's current
395 * metageneration does not match the given value.
396 * @type string $ifSourceGenerationMatch Makes the operation conditional
397 * on whether the source object's current generation matches the
398 * given value.
399 * @type string $ifSourceGenerationNotMatch Makes the operation
400 * conditional on whether the source object's current generation
401 * does not match the given value.
402 * @type string $ifSourceMetagenerationMatch Makes the operation
403 * conditional on whether the source object's current
404 * metageneration matches the given value.
405 * @type string $ifSourceMetagenerationNotMatch Makes the operation
406 * conditional on whether the source object's current
407 * metageneration does not match the given value.
408 * }
409 * @return StorageObject
410 * @throws \InvalidArgumentException
411 */
412 public function rewrite($destination, array $options = [])
413 {
414 $options['useCopySourceHeaders'] = \true;
415 $destinationKey = $options['destinationEncryptionKey'] ?? null;
416 $destinationKeySHA256 = $options['destinationEncryptionKeySHA256'] ?? null;
417 $options = $this->formatDestinationRequest($destination, $options);
418 do {
419 $response = $this->connection->rewriteObject($options);
420 $options['rewriteToken'] = $response['rewriteToken'] ?? null;
421 } while ($options['rewriteToken']);
422 return new StorageObject($this->connection, $response['resource']['name'], $response['resource']['bucket'], $response['resource']['generation'], $response['resource'] + ['requesterProjectId' => $this->identity['userProject']], $destinationKey, $destinationKeySHA256);
423 }
424 /**
425 * Renames the object.
426 *
427 * Please note that there is no atomic rename provided by the Storage API.
428 * This method is for convenience and is a set of sequential calls to copy
429 * and delete. Upon success the source object's metadata will be cleared,
430 * please use the returned object instead.
431 *
432 * Example:
433 * ```
434 * $object2 = $object->rename('object2.txt');
435 * echo $object2->name();
436 * ```
437 *
438 * @param string $name The new name.
439 * @param array $options [optional] {
440 * Configuration options.
441 *
442 * @type string $predefinedAcl Predefined ACL to apply to the object.
443 * Acceptable values include, `"authenticatedRead"`,
444 * `"bucketOwnerFullControl"`, `"bucketOwnerRead"`, `"private"`,
445 * `"projectPrivate"`, and `"publicRead"`.
446 * @type string $encryptionKey A base64 encoded AES-256 customer-supplied
447 * encryption key. It will be neccesary to provide this when a key
448 * was used during the object's creation.
449 * @type string $encryptionKeySHA256 Base64 encoded SHA256 hash of the
450 * customer-supplied encryption key. This value will be calculated
451 * from the `encryptionKey` on your behalf if not provided, but
452 * for best performance it is recommended to pass in a cached
453 * version of the already calculated SHA.
454 * @type string $ifGenerationMatch Makes the operation conditional on
455 * whether the destination object's current generation matches the
456 * given value.
457 * @type string $ifGenerationNotMatch Makes the operation conditional on
458 * whether the destination object's current generation does not
459 * match the given value.
460 * @type string $ifMetagenerationMatch Makes the operation conditional
461 * on whether the destination object's current metageneration
462 * matches the given value.
463 * @type string $ifMetagenerationNotMatch Makes the operation
464 * conditional on whether the destination object's current
465 * metageneration does not match the given value.
466 * @type string $ifSourceGenerationMatch Makes the operation conditional
467 * on whether the source object's current generation matches the
468 * given value.
469 * @type string $ifSourceGenerationNotMatch Makes the operation
470 * conditional on whether the source object's current generation
471 * does not match the given value.
472 * @type string $ifSourceMetagenerationMatch Makes the operation
473 * conditional on whether the source object's current
474 * metageneration matches the given value.
475 * @type string $ifSourceMetagenerationNotMatch Makes the operation
476 * conditional on whether the source object's current
477 * metageneration does not match the given value.
478 * @type string $destinationBucket Will move to this bucket if set. If
479 * not set, will default to the same bucket.
480 * }
481 * @return StorageObject The renamed object.
482 */
483 public function rename($name, array $options = [])
484 {
485 $destinationBucket = $options['destinationBucket'] ?? $this->identity['bucket'];
486 unset($options['destinationBucket']);
487 $copiedObject = $this->copy($destinationBucket, ['name' => $name] + $options);
488 $this->delete(array_intersect_key($options, ['restOptions' => null, 'retries' => null]));
489 $this->info = [];
490 return $copiedObject;
491 }
492 /**
493 * Download an object as a string.
494 *
495 * For an example of setting the range header to download a subrange of the
496 * object please see {@see StorageObject::downloadAsStream()}.
497 *
498 * Example:
499 * ```
500 * $string = $object->downloadAsString();
501 * echo $string;
502 * ```
503 *
504 * @see https://cloud.google.com/storage/docs/json_api/v1/objects/get Objects get API documentation.
505 * @see https://cloud.google.com/storage/docs/json_api/v1/parameters#range Learn more about the Range header.
506 *
507 * @param array $options [optional] {
508 * Configuration Options.
509 *
510 * @type string $encryptionKey An AES-256 customer-supplied encryption
511 * key. It will be neccesary to provide this when a key was used
512 * during the object's creation. If provided one must also include
513 * an `encryptionKeySHA256`.
514 * @type string $encryptionKeySHA256 The SHA256 hash of the
515 * customer-supplied encryption key. It will be neccesary to
516 * provide this when a key was used during the object's creation.
517 * If provided one must also include an `encryptionKey`.
518 * }
519 * @return string
520 */
521 public function downloadAsString(array $options = [])
522 {
523 return (string) $this->downloadAsStream($options);
524 }
525 /**
526 * Download an object to a specified location.
527 *
528 * For an example of setting the range header to download a subrange of the
529 * object please see {@see StorageObject::downloadAsStream()}.
530 *
531 * Example:
532 * ```
533 * $stream = $object->downloadToFile(__DIR__ . '/my-file.txt');
534 * ```
535 *
536 * @see https://cloud.google.com/storage/docs/json_api/v1/objects/get Objects get API documentation.
537 * @see https://cloud.google.com/storage/docs/json_api/v1/parameters#range Learn more about the Range header.
538 *
539 * @param string $path Path to download the file to.
540 * @param array $options [optional] {
541 * Configuration Options.
542 *
543 * @type string $encryptionKey An AES-256 customer-supplied encryption
544 * key. It will be neccesary to provide this when a key was used
545 * during the object's creation. If provided one must also include
546 * an `encryptionKeySHA256`.
547 * @type string $encryptionKeySHA256 The SHA256 hash of the
548 * customer-supplied encryption key. It will be neccesary to
549 * provide this when a key was used during the object's creation.
550 * If provided one must also include an `encryptionKey`.
551 * }
552 * @return StreamInterface
553 */
554 public function downloadToFile($path, array $options = [])
555 {
556 $source = $this->downloadAsStream($options);
557 $destination = Utils::streamFor(fopen($path, 'w'));
558 Utils::copyToStream($source, $destination);
559 $destination->seek(0);
560 return $destination;
561 }
562 /**
563 * Download an object as a stream. The library will attempt to resume the download
564 * if a retry-able error is thrown. An attempt to fetch the remaining file will
565 * be made only if the user has not supplied a custom retry
566 * function of their own.
567 *
568 * Please note Google Cloud Storage respects the Range header as specified
569 * by [RFC7233](https://tools.ietf.org/html/rfc7233#section-3.1). See below
570 * for an example of this in action.
571 *
572 * Example:
573 * ```
574 * $stream = $object->downloadAsStream();
575 * echo $stream->getContents();
576 * ```
577 *
578 * ```
579 * // Set the Range header in order to download a subrange of the object. For more examples of
580 * // setting the Range header, please see [RFC7233](https://tools.ietf.org/html/rfc7233#section-3.1).
581 * $firstFiveBytes = '0-4'; // Get the first 5 bytes.
582 * $fromFifthByteToLastByte = '4-'; // Get the bytes starting with the 5th to the last.
583 * $lastFiveBytes = '-5'; // Get the last 5 bytes.
584 *
585 * $stream = $object->downloadAsStream([
586 * 'restOptions' => [
587 * 'headers' => [
588 * 'Range' => "bytes=$firstFiveBytes"
589 * ]
590 * ]
591 * ]);
592 * ```
593 *
594 * @see https://cloud.google.com/storage/docs/json_api/v1/objects/get Objects get API documentation.
595 * @see https://cloud.google.com/storage/docs/json_api/v1/parameters#range Learn more about the Range header.
596 *
597 * @param array $options [optional] {
598 * Configuration Options.
599 *
600 * @type string $encryptionKey An AES-256 customer-supplied encryption
601 * key. It will be neccesary to provide this when a key was used
602 * during the object's creation. If provided one must also include
603 * an `encryptionKeySHA256`.
604 * @type string $encryptionKeySHA256 The SHA256 hash of the
605 * customer-supplied encryption key. It will be neccesary to
606 * provide this when a key was used during the object's creation.
607 * If provided one must also include an `encryptionKey`.
608 * }
609 * @return StreamInterface
610 */
611 public function downloadAsStream(array $options = [])
612 {
613 return $this->connection->downloadObject($this->formatEncryptionHeaders($options + $this->encryptionData + array_filter($this->identity)));
614 }
615 /**
616 * Asynchronously download an object as a stream.
617 *
618 * For an example of setting the range header to download a subrange of the
619 * object please see {@see StorageObject::downloadAsStream()}.
620 *
621 * Example:
622 * ```
623 * use Psr\Http\Message\StreamInterface;
624 *
625 * $promise = $object->downloadAsStreamAsync()
626 * ->then(function (StreamInterface $data) {
627 * echo $data->getContents();
628 * });
629 *
630 * $promise->wait();
631 * ```
632 *
633 * ```
634 * // Download all objects in a bucket asynchronously.
635 * use GuzzleHttp\Promise\Utils;
636 * use Psr\Http\Message\StreamInterface;
637 *
638 * $promises = [];
639 *
640 * foreach ($bucket->objects() as $object) {
641 * $promises[] = $object->downloadAsStreamAsync()
642 * ->then(function (StreamInterface $data) {
643 * echo $data->getContents();
644 * });
645 * }
646 *
647 * Utils::unwrap($promises);
648 * ```
649 *
650 * @see https://cloud.google.com/storage/docs/json_api/v1/objects/get Objects get API documentation.
651 * @see https://cloud.google.com/storage/docs/json_api/v1/parameters#range Learn more about the Range header.
652 * @see https://github.com/guzzle/promises Learn more about Guzzle Promises
653 *
654 * @param array $options [optional] {
655 * Configuration Options.
656 *
657 * @type string $encryptionKey An AES-256 customer-supplied encryption
658 * key. It will be neccesary to provide this when a key was used
659 * during the object's creation. If provided one must also include
660 * an `encryptionKeySHA256`.
661 * @type string $encryptionKeySHA256 The SHA256 hash of the
662 * customer-supplied encryption key. It will be neccesary to
663 * provide this when a key was used during the object's creation.
664 * If provided one must also include an `encryptionKey`.
665 * }
666 * @return PromiseInterface<StreamInterface>
667 * @experimental The experimental flag means that while we believe this method
668 * or class is ready for use, it may change before release in backwards-
669 * incompatible ways. Please use with caution, and test thoroughly when
670 * upgrading.
671 */
672 public function downloadAsStreamAsync(array $options = [])
673 {
674 return $this->connection->downloadObjectAsync($this->formatEncryptionHeaders($options + $this->encryptionData + array_filter($this->identity)));
675 }
676 /**
677 * Create a Signed URL for this object.
678 *
679 * Signed URLs can be complex, and it is strongly recommended you read and
680 * understand the [documentation](https://cloud.google.com/storage/docs/access-control/signed-urls).
681 *
682 * In cases where a keyfile is available, signing is accomplished in the
683 * client using your Service Account private key. In Google Compute Engine,
684 * signing is accomplished using
685 * [IAM signBlob](https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/signBlob).
686 * Signing using IAM requires that your service account be granted the
687 * `iam.serviceAccounts.signBlob` permission, part of the "Service Account
688 * Token Creator" IAM role.
689 *
690 * Additionally, signing using IAM requires different scopes. When creating
691 * an instance of {@see StorageClient}, provide the
692 * `https://www.googleapis.com/auth/cloud-platform` scopein `$options.scopes`.
693 * This scope may be used entirely in place of the scopes provided in
694 * {@see StorageClient}.
695 *
696 * App Engine and Compute Engine will attempt to sign URLs using IAM.
697 *
698 * Example:
699 * ```
700 * $url = $object->signedUrl(new \DateTime('tomorrow'));
701 * ```
702 *
703 * ```
704 * // Create a signed URL allowing updates to the object.
705 * $url = $object->signedUrl(new \DateTime('tomorrow'), [
706 * 'method' => 'PUT'
707 * ]);
708 * ```
709 *
710 * ```
711 * // Use Signed URLs v4
712 * $url = $object->signedUrl(new \DateTime('tomorrow'), [
713 * 'version' => 'v4'
714 * ]);
715 * ```
716 *
717 * ```
718 * // Using Bucket-Bound hostnames
719 * // By default, a custom bucket-bound hostname will use `http` as the schema rather than `https`.
720 * // In order to get an https URI, we need to specify the proper scheme.
721 * $url = $object->signedUrl(new \DateTime('tomorrow'), [
722 * 'version' => 'v4',
723 * 'bucketBoundHostname' => 'cdn.example.com',
724 * 'scheme' => 'https'
725 * ]);
726 * ```
727 *
728 * ```
729 * // Using virtual hosted style URIs
730 * // When true, returns a URL with the hostname `<bucket>.storage.googleapis.com`.
731 * $url = $object->signedUrl(new \DateTime('tomorrow'), [
732 * 'virtualHostedStyle' => true
733 * ]);
734 * ````
735 *
736 * @see https://cloud.google.com/storage/docs/access-control/signed-urls Signed URLs
737 *
738 * @param Timestamp|\DateTimeInterface|int $expires Specifies when the URL
739 * will expire. May provide an instance of {@see \Google\Cloud\Core\Timestamp},
740 * [http://php.net/datetimeimmutable](`\DateTimeImmutable`), or a
741 * UNIX timestamp as an integer.
742 * @param array $options {
743 * Configuration Options.
744 *
745 * @type string $bucketBoundHostname The hostname for the bucket, for
746 * instance `cdn.example.com`. May be used for Google Cloud Load
747 * Balancers or for custom bucket CNAMEs. **Defaults to**
748 * `storage.googleapis.com`.
749 * @type string $contentMd5 The MD5 digest value in base64. If you
750 * provide this, the client must provide this HTTP header with
751 * this same value in its request. If provided, take care to
752 * always provide this value as a base64 encoded string.
753 * @type string $contentType If you provide this value, the client must
754 * provide this HTTP header set to the same value.
755 * @type bool $forceOpenssl If true, OpenSSL will be used regardless of
756 * whether phpseclib is available. **Defaults to** `false`.
757 * @type array $headers If additional headers are provided, the server
758 * will check to make sure that the client provides matching
759 * values. Provide headers as a key/value array, where the key is
760 * the header name, and the value is an array of header values.
761 * Headers with multiple values may provide values as a simple
762 * array, or a comma-separated string. For a reference of allowed
763 * headers, see [Reference Headers](https://cloud.google.com/storage/docs/xml-api/reference-headers).
764 * Header values will be trimmed of leading and trailing spaces,
765 * multiple spaces within values will be collapsed to a single
766 * space, and line breaks will be replaced by an empty string.
767 * V2 Signed URLs may not provide `x-goog-encryption-key` or
768 * `x-goog-encryption-key-sha256` headers.
769 * @type array $keyFile Keyfile data to use in place of the keyfile with
770 * which the client was constructed. If `$options.keyFilePath` is
771 * set, this option is ignored.
772 * @type string $keyFilePath A path to a valid Keyfile to use in place
773 * of the keyfile with which the client was constructed.
774 * @type string $method One of `GET`, `PUT` or `DELETE`.
775 * **Defaults to** `GET`.
776 * @type string $responseDisposition The
777 * [`response-content-disposition`](http://www.iana.org/assignments/cont-disp/cont-disp.xhtml)
778 * parameter of the signed url.
779 * @type string $responseType The `response-content-type` parameter of the
780 * signed url. When the server contentType is `null`, this option
781 * may be used to control the content type of the response.
782 * @type string $saveAsName The filename to prompt the user to save the
783 * file as when the signed url is accessed. This is ignored if
784 * `$options.responseDisposition` is set.
785 * @type string $scheme Either `http` or `https`. Only used if a custom
786 * hostname is provided via `$options.bucketBoundHostname`. If a
787 * custom bucketBoundHostname is provided, **defaults to** `http`.
788 * In all other cases, **defaults to** `https`.
789 * @type string|array $scopes One or more authentication scopes to be
790 * used with a key file. This option is ignored unless
791 * `$options.keyFile` or `$options.keyFilePath` is set.
792 * @type array $queryParams Additional query parameters to be included
793 * as part of the signed URL query string. For allowed values,
794 * see [Reference Headers](https://cloud.google.com/storage/docs/xml-api/reference-headers#query).
795 * @type string $version One of "v2" or "v4". **Defaults to** `"v2"`.
796 * @type bool $virtualHostedStyle If `true`, URL will be of form
797 * `mybucket.storage.googleapis.com`. If `false`,
798 * `storage.googleapis.com/mybucket`. **Defaults to** `false`.
799 * }
800 * @return string
801 * @throws \InvalidArgumentException If the given expiration is invalid or in the past.
802 * @throws \InvalidArgumentException If the given `$options.method` is not valid.
803 * @throws \InvalidArgumentException If the given `$options.keyFilePath` is not valid.
804 * @throws \InvalidArgumentException If the given custom headers are invalid.
805 * @throws \InvalidArgumentException If the keyfile does not contain the required information.
806 * @throws \RuntimeException If the credentials provided cannot be used for signing strings.
807 */
808 public function signedUrl($expires, array $options = [])
809 {
810 // May be overridden for testing.
811 $signingHelper = $this->pluck('helper', $options, \false) ?: SigningHelper::getHelper();
812 $resource = sprintf('/%s/%s', $this->identity['bucket'], $this->identity['object']);
813 return $signingHelper->sign($this->connection, $expires, $resource, $this->identity['generation'], $options);
814 }
815 /**
816 * Create a Signed Upload URL for this object.
817 *
818 * This method differs from {@see StorageObject::signedUrl()}
819 * in that it allows you to initiate a new resumable upload session. This
820 * can be used to allow non-authenticated users to insert an object into a
821 * bucket.
822 *
823 * In order to upload data, a session URI must be
824 * obtained by sending an HTTP POST request to the URL returned from this
825 * method. See the [Cloud Storage Documentation](https://goo.gl/b1ZiZm) for
826 * more information.
827 *
828 * If you prefer to skip this initial step, you may find
829 * {@see StorageObject::beginSignedUploadSession()} to
830 * fit your needs. Note that `beginSignedUploadSession()` cannot be used
831 * with Google Cloud PHP's Signed URL Uploader, and does not support a
832 * configurable expiration date.
833 *
834 * Example:
835 * ```
836 * $url = $object->signedUploadUrl(new \DateTime('tomorrow'));
837 * ```
838 *
839 * ```
840 * // Use Signed URLs v4
841 * $url = $object->signedUploadUrl(new \DateTime('tomorrow'), [
842 * 'version' => 'v4'
843 * ]);
844 * ```
845 *
846 * @param Timestamp|\DateTimeInterface|int $expires Specifies when the URL
847 * will expire. May provide an instance of {@see \Google\Cloud\Core\Timestamp},
848 * [http://php.net/datetimeimmutable](`\DateTimeImmutable`), or a
849 * UNIX timestamp as an integer.
850 * @param array $options {
851 * Configuration Options.
852 *
853 * @type string $contentMd5 The MD5 digest value in base64. If you
854 * provide this, the client must provide this HTTP header with
855 * this same value in its request. If provided, take care to
856 * always provide this value as a base64 encoded string.
857 * @type string $contentType If you provide this value, the client must
858 * provide this HTTP header set to the same value.
859 * @type bool $forceOpenssl If true, OpenSSL will be used regardless of
860 * whether phpseclib is available. **Defaults to** `false`.
861 * @type array $headers If additional headers are provided, the server
862 * will check to make sure that the client provides matching
863 * values. Provide headers as a key/value array, where the key is
864 * the header name, and the value is an array of header values.
865 * Headers with multiple values may provide values as a simple
866 * array, or a comma-separated string. For a reference of allowed
867 * headers, see [Reference Headers](https://cloud.google.com/storage/docs/xml-api/reference-headers).
868 * Header values will be trimmed of leading and trailing spaces,
869 * multiple spaces within values will be collapsed to a single
870 * space, and line breaks will be replaced by an empty string.
871 * V2 Signed URLs may not provide `x-goog-encryption-key` or
872 * `x-goog-encryption-key-sha256` headers.
873 * @type array $keyFile Keyfile data to use in place of the keyfile with
874 * which the client was constructed. If `$options.keyFilePath` is
875 * set, this option is ignored.
876 * @type string $keyFilePath A path to a valid Keyfile to use in place
877 * of the keyfile with which the client was constructed.
878 * @type string $responseDisposition The
879 * [`response-content-disposition`](http://www.iana.org/assignments/cont-disp/cont-disp.xhtml)
880 * parameter of the signed url.
881 * @type string $responseType The `response-content-type` parameter of the
882 * signed url. When the server contentType is `null`, this option
883 * may be used to control the content type of the response.
884 * @type string $saveAsName The filename to prompt the user to save the
885 * file as when the signed url is accessed. This is ignored if
886 * `$options.responseDisposition` is set.
887 * @type string $scheme Either `http` or `https`. Only used if a custom
888 * hostname is provided via `$options.bucketBoundHostname`. In all
889 * other cases, `https` is used. When a custom bucketBoundHostname
890 * is provided, **defaults to** `http`.
891 * @type string|array $scopes One or more authentication scopes to be
892 * used with a key file. This option is ignored unless
893 * `$options.keyFile` or `$options.keyFilePath` is set.
894 * @type array $queryParams Additional query parameters to be included
895 * as part of the signed URL query string. For allowed values,
896 * see [Reference Headers](https://cloud.google.com/storage/docs/xml-api/reference-headers#query).
897 * @type string $version One of "v2" or "v4". **Defaults to** `"v2"`.
898 * }
899 * @return string
900 */
901 public function signedUploadUrl($expires, array $options = [])
902 {
903 $options += ['headers' => []];
904 $options['headers']['x-goog-resumable'] = 'start';
905 unset($options['cname'], $options['bucketBoundHostname'], $options['saveAsName'], $options['responseDisposition'], $options['responseType'], $options['virtualHostedStyle']);
906 return $this->signedUrl($expires, ['method' => 'POST', 'allowPost' => \true] + $options);
907 }
908 /**
909 * Create a signed URL upload session.
910 *
911 * The returned URL differs from the return value of
912 * {@see StorageObject::signedUploadUrl()} in that it
913 * is ready to accept upload data immediately via an HTTP PUT request.
914 *
915 * Because an upload session is created by the client, the expiration date
916 * is not configurable. The URL generated by this method is valid for one
917 * week.
918 *
919 * Example:
920 * ```
921 * $url = $object->beginSignedUploadSession();
922 * ```
923 *
924 * ```
925 * // Use Signed URLs v4
926 * $url = $object->beginSignedUploadSession([
927 * 'version' => 'v4'
928 * ]);
929 * ```
930 *
931 * @see https://cloud.google.com/storage/docs/xml-api/resumable-upload#practices Resumable Upload Best Practices
932 *
933 * @param array $options {
934 * Configuration Options.
935 *
936 * @type string $contentMd5 The MD5 digest value in base64. If you
937 * provide this, the client must provide this HTTP header with
938 * this same value in its request. If provided, take care to
939 * always provide this value as a base64 encoded string.
940 * @type string $contentType If you provide this value, the client must
941 * provide this HTTP header set to the same value.
942 * @type bool $forceOpenssl If true, OpenSSL will be used regardless of
943 * whether phpseclib is available. **Defaults to** `false`.
944 * @type array $headers If additional headers are provided, the server
945 * will check to make sure that the client provides matching
946 * values. Provide headers as a key/value array, where the key is
947 * the header name, and the value is an array of header values.
948 * Headers with multiple values may provide values as a simple
949 * array, or a comma-separated string. For a reference of allowed
950 * headers, see [Reference Headers](https://cloud.google.com/storage/docs/xml-api/reference-headers).
951 * Header values will be trimmed of leading and trailing spaces,
952 * multiple spaces within values will be collapsed to a single
953 * space, and line breaks will be replaced by an empty string.
954 * V2 Signed URLs may not provide `x-goog-encryption-key` or
955 * `x-goog-encryption-key-sha256` headers.
956 * @type array $keyFile Keyfile data to use in place of the keyfile with
957 * which the client was constructed. If `$options.keyFilePath` is
958 * set, this option is ignored.
959 * @type string $keyFilePath A path to a valid Keyfile to use in place
960 * of the keyfile with which the client was constructed.
961 * @type string $origin Value of CORS header
962 * "Access-Control-Allow-Origin". **Defaults to** `"*"`.
963 * @type string|array $scopes One or more authentication scopes to be
964 * used with a key file. This option is ignored unless
965 * `$options.keyFile` or `$options.keyFilePath` is set.
966 * @type array $queryParams Additional query parameters to be included
967 * as part of the signed URL query string. For allowed values,
968 * see [Reference Headers](https://cloud.google.com/storage/docs/xml-api/reference-headers#query).
969 * @type string $version One of "v2" or "v4". **Defaults to** `"v2"`.
970 * }
971 * @return string
972 */
973 public function beginSignedUploadSession(array $options = [])
974 {
975 $expires = new \DateTimeImmutable('+1 minute');
976 $startUri = $this->signedUploadUrl($expires, $options);
977 $uploaderOptions = $this->pluckArray(['contentType', 'origin'], $options);
978 if (!isset($uploaderOptions['origin'])) {
979 $uploaderOptions['origin'] = '*';
980 }
981 $uploader = new SignedUrlUploader($this->connection->requestWrapper(), '', $startUri, $uploaderOptions);
982 return $uploader->getResumeUri();
983 }
984 /**
985 * Retrieves the object's details. If no object data is cached a network
986 * request will be made to retrieve it.
987 *
988 * Example:
989 * ```
990 * $info = $object->info();
991 * echo $info['size'];
992 * ```
993 *
994 * @see https://cloud.google.com/storage/docs/json_api/v1/objects/get Objects get API documentation.
995 *
996 * @param array $options [optional] {
997 * Configuration options.
998 *
999 * @type string $encryptionKey An AES-256 customer-supplied encryption
1000 * key. It will be neccesary to provide this when a key was used
1001 * during the object's creation in order to retrieve the MD5 hash
1002 * and CRC32C checksum. If provided one must also include an
1003 * `encryptionKeySHA256`.
1004 * @type string $encryptionKeySHA256 The SHA256 hash of the
1005 * customer-supplied encryption key. It will be neccesary to
1006 * provide this when a key was used during the object's creation
1007 * in order to retrieve the MD5 hash and CRC32C checksum. If
1008 * provided one must also include an `encryptionKey`.
1009 * @type string $ifGenerationMatch Makes the operation conditional on
1010 * whether the object's current generation matches the given
1011 * value.
1012 * @type string $ifGenerationNotMatch Makes the operation conditional on
1013 * whether the object's current generation does not match the
1014 * given value.
1015 * @type string $ifMetagenerationMatch Makes the operation conditional
1016 * on whether the object's current metageneration matches the
1017 * given value.
1018 * @type string $ifMetagenerationNotMatch Makes the operation
1019 * conditional on whether the object's current metageneration does
1020 * not match the given value.
1021 * @type string $projection Determines which properties to return. May
1022 * be either 'full' or 'noAcl'.
1023 * }
1024 * @return array
1025 */
1026 public function info(array $options = [])
1027 {
1028 return $this->info ?: $this->reload($options);
1029 }
1030 /**
1031 * Triggers a network request to reload the object's details.
1032 *
1033 * Example:
1034 * ```
1035 * $object->reload();
1036 * $info = $object->info();
1037 * echo $info['location'];
1038 * ```
1039 *
1040 * @see https://cloud.google.com/storage/docs/json_api/v1/objects/get Objects get API documentation.
1041 *
1042 * @param array $options [optional] {
1043 * Configuration options.
1044 *
1045 * @type string $encryptionKey A base64 encoded AES-256 customer-supplied
1046 * encryption key. It will be neccesary to provide this when a key
1047 * was used during the object's creation.
1048 * @type string $encryptionKeySHA256 Base64 encoded SHA256 hash of the
1049 * customer-supplied encryption key. This value will be calculated
1050 * from the `encryptionKey` on your behalf if not provided, but
1051 * for best performance it is recommended to pass in a cached
1052 * version of the already calculated SHA.
1053 * @type string $ifGenerationMatch Makes the operation conditional on
1054 * whether the object's current generation matches the given
1055 * value.
1056 * @type string $ifGenerationNotMatch Makes the operation conditional on
1057 * whether the object's current generation does not match the
1058 * given value.
1059 * @type string $ifMetagenerationMatch Makes the operation conditional
1060 * on whether the object's current metageneration matches the
1061 * given value.
1062 * @type string $ifMetagenerationNotMatch Makes the operation
1063 * conditional on whether the object's current metageneration does
1064 * not match the given value.
1065 * @type string $projection Determines which properties to return. May
1066 * be either 'full' or 'noAcl'.
1067 * }
1068 * @return array
1069 */
1070 public function reload(array $options = [])
1071 {
1072 return $this->info = $this->connection->getObject($this->formatEncryptionHeaders($options + $this->encryptionData + array_filter($this->identity)));
1073 }
1074 /**
1075 * Retrieves the object's name.
1076 *
1077 * Example:
1078 * ```
1079 * echo $object->name();
1080 * ```
1081 *
1082 * @return string
1083 */
1084 public function name()
1085 {
1086 return $this->identity['object'];
1087 }
1088 /**
1089 * Retrieves the object's identity.
1090 *
1091 * Example:
1092 * ```
1093 * echo $object->identity()['object'];
1094 * ```
1095 *
1096 * @return array
1097 */
1098 public function identity()
1099 {
1100 return $this->identity;
1101 }
1102 /**
1103 * Formats the object as a string in the following format:
1104 * `gs://{bucket-name}/{object-name}`.
1105 *
1106 * Example:
1107 * ```
1108 * echo $object->gcsUri();
1109 * ```
1110 *
1111 * @return string
1112 */
1113 public function gcsUri()
1114 {
1115 return sprintf('gs://%s/%s', $this->identity['bucket'], $this->identity['object']);
1116 }
1117 /**
1118 * Formats a destination based request, such as copy or rewrite.
1119 *
1120 * @param string|Bucket $destination The destination bucket.
1121 * @param array $options Options to configure.
1122 * @return array
1123 */
1124 private function formatDestinationRequest($destination, array $options)
1125 {
1126 if (!is_string($destination) && !$destination instanceof Bucket) {
1127 throw new \InvalidArgumentException('$destination must be either a string or an instance of Bucket.');
1128 }
1129 $destAcl = $options['predefinedAcl'] ?? null;
1130 $destObject = $options['name'] ?? $this->identity['object'];
1131 unset($options['name']);
1132 unset($options['predefinedAcl']);
1133 return array_filter(['destinationBucket' => $destination instanceof Bucket ? $destination->name() : $destination, 'destinationObject' => $destObject, 'destinationPredefinedAcl' => $destAcl, 'sourceBucket' => $this->identity['bucket'], 'sourceObject' => $this->identity['object'], 'sourceGeneration' => $this->identity['generation'], 'userProject' => $this->identity['userProject']]) + $this->formatEncryptionHeaders($options + $this->encryptionData);
1134 }
1135 }
1136