From 10f5d6fd0b6721bf94c056d305143eb2e657b166 Mon Sep 17 00:00:00 2001 From: salilg-eng Date: Mon, 13 Apr 2026 10:45:29 +0000 Subject: [PATCH 1/5] Object Contexts Sample --- storage/src/list_storage_object_contexts.php | 52 ++++++++++++++++ storage/src/set_storage_object_contexts.php | 64 ++++++++++++++++++++ storage/src/view_storage_object_contexts.php | 57 +++++++++++++++++ storage/test/storageTest.php | 63 ++++++++++++++++--- 4 files changed, 226 insertions(+), 10 deletions(-) create mode 100644 storage/src/list_storage_object_contexts.php create mode 100644 storage/src/set_storage_object_contexts.php create mode 100644 storage/src/view_storage_object_contexts.php diff --git a/storage/src/list_storage_object_contexts.php b/storage/src/list_storage_object_contexts.php new file mode 100644 index 000000000..95065455f --- /dev/null +++ b/storage/src/list_storage_object_contexts.php @@ -0,0 +1,52 @@ +bucket($bucketName); + + // Example filter: find objects where department is finance + $options = [ + 'filter' => 'contexts.custom.department.value="finance"' + ]; + foreach ($bucket->objects($options) as $object) { + printf('Found object: %s' . PHP_EOL, $object->name()); + } +} +# [END storage_list_object_contexts] + +// The following 2 lines are only needed to run the samples +require_once __DIR__ . '/../../testing/sample_helpers.php'; +\Google\Cloud\Samples\execute_sample(__FILE__, __NAMESPACE__, $argv); diff --git a/storage/src/set_storage_object_contexts.php b/storage/src/set_storage_object_contexts.php new file mode 100644 index 000000000..9ae7c7f94 --- /dev/null +++ b/storage/src/set_storage_object_contexts.php @@ -0,0 +1,64 @@ +bucket($bucketName); + $object = $bucket->object($objectName); + + // Contexts are defined under the 'custom' key; keys/values must start with an alphanumeric and avoid quotes/slashes. + $object->update([ + 'contexts' => [ + 'custom' => [ + 'department' => ['value' => 'finance'], + 'priority' => ['value' => 'high'] + ] + ] + ]); + $info = $object->info(); + if (isset($info['contexts']['custom'])) { + printf('Contexts for object %s were updated:' . PHP_EOL, $objectName); + foreach ($info['contexts']['custom'] as $key => $data) { + printf(' - Key: %s, Value: %s' . PHP_EOL, $key, $data['value']); + } + } +} +# [END storage_set_object_contexts] + +// The following 2 lines are only needed to run the samples +require_once __DIR__ . '/../../testing/sample_helpers.php'; +\Google\Cloud\Samples\execute_sample(__FILE__, __NAMESPACE__, $argv); diff --git a/storage/src/view_storage_object_contexts.php b/storage/src/view_storage_object_contexts.php new file mode 100644 index 000000000..e82a596b7 --- /dev/null +++ b/storage/src/view_storage_object_contexts.php @@ -0,0 +1,57 @@ +bucket($bucketName); + $object = $bucket->object($objectName); + + $info = $object->info(); + if (isset($info['contexts']['custom'])) { + printf('Contexts for object %s were updated:' . PHP_EOL, $objectName); + foreach ($info['contexts']['custom'] as $key => $data) { + printf(' - Key: %s, Value: %s' . PHP_EOL, $key, $data['value']); + printf(' - Created: %s' . PHP_EOL, $data['createTime']); + printf(' - Updated: %s' . PHP_EOL, $data['updateTime']); + } + } +} +# [END storage_get_object_contexts] + +// The following 2 lines are only needed to run the samples +require_once __DIR__ . '/../../testing/sample_helpers.php'; +\Google\Cloud\Samples\execute_sample(__FILE__, __NAMESPACE__, $argv); diff --git a/storage/test/storageTest.php b/storage/test/storageTest.php index c71e30e9c..20c92da8b 100644 --- a/storage/test/storageTest.php +++ b/storage/test/storageTest.php @@ -35,6 +35,7 @@ class storageTest extends TestCase private static $storage; private static $tempBucket; private static $objectRetentionBucketName; + private static $objectContextBucketName; public static function setUpBeforeClass(): void { @@ -49,6 +50,12 @@ public static function setUpBeforeClass(): void self::$projectId, time() ); + + self::$objectContextBucketName = sprintf( + '%s_object_contexts-%s', + self::$projectId, + time() + ); } public static function tearDownAfterClass(): void @@ -57,17 +64,20 @@ public static function tearDownAfterClass(): void $object->delete(); } self::$tempBucket->delete(); - - $objectRetentionBucket = self::$storage->bucket(self::$objectRetentionBucketName); - foreach ($objectRetentionBucket->objects() as $object) { - // Disable object retention before delete - $object->update([ - 'retention' => [], - 'overrideUnlockedRetention' => true - ]); - $object->delete(); + if (isset(self::$objectRetentionBucketName)) { + $objectRetentionBucket = self::$storage->bucket(self::$objectRetentionBucketName); + if ($objectRetentionBucket->exists()) { + foreach ($objectRetentionBucket->objects() as $object) { + // Disable object retention before delete + $object->update([ + 'retention' => [], + 'overrideUnlockedRetention' => true + ]); + $object->delete(); + } + $objectRetentionBucket->delete(); + } } - $objectRetentionBucket->delete(); } public function testBucketAcl() @@ -226,6 +236,39 @@ public function testSetObjectRetentionPolicy() ); } + public function testObjectContexts() + { + $bucketName = self::$objectContextBucketName; + self::runFunctionSnippet('create_bucket', [ $bucketName]); + $objectContextsBucket = self::$storage->bucket($bucketName); + $objectName = $this->requireEnv('GOOGLE_STORAGE_OBJECT') . '.ObjectContexts'; + $object = $objectContextsBucket->upload('test', [ + 'name' => $objectName, + ]); + $objectName = $object->info()['name']; + $setOutput = $this->runFunctionSnippet('set_storage_object_contexts', [ + self::$objectContextBucketName, + $objectName, + ]); + + $this->assertStringContainsString("Contexts for object $objectName were updated", $setOutput); + + $getOutput = $this->runFunctionSnippet('view_storage_object_contexts', [ + self::$objectContextBucketName, + $objectName + ]); + + $this->assertStringContainsString('Key: department, Value: finance', $getOutput); + $this->assertStringContainsString('Key: priority, Value: high', $getOutput); + + sleep(2); + + $listOutput = $this->runFunctionSnippet('list_storage_object_contexts', [ + self::$objectContextBucketName + ]); + $this->assertStringContainsString("Found object: $objectName", $listOutput); + } + public function testGetBucketClassAndLocation() { $output = $this->runFunctionSnippet( From 3083a8357f901ba2a2a2542a48a9bb0b755ddc3c Mon Sep 17 00:00:00 2001 From: salilg-eng Date: Fri, 17 Apr 2026 05:44:45 +0000 Subject: [PATCH 2/5] Final code --- ...t_contexts.php => get_object_contexts.php} | 2 +- ..._contexts.php => list_object_contexts.php} | 4 +- ...t_contexts.php => set_object_contexts.php} | 2 +- storage/test/storageTest.php | 71 ++++++++++++------- 4 files changed, 51 insertions(+), 28 deletions(-) rename storage/src/{view_storage_object_contexts.php => get_object_contexts.php} (95%) rename storage/src/{list_storage_object_contexts.php => list_object_contexts.php} (92%) rename storage/src/{set_storage_object_contexts.php => set_object_contexts.php} (96%) diff --git a/storage/src/view_storage_object_contexts.php b/storage/src/get_object_contexts.php similarity index 95% rename from storage/src/view_storage_object_contexts.php rename to storage/src/get_object_contexts.php index e82a596b7..63d299553 100644 --- a/storage/src/view_storage_object_contexts.php +++ b/storage/src/get_object_contexts.php @@ -34,7 +34,7 @@ * @param string $objectName The name of your Cloud Storage object. * (e.g. 'my-object') */ -function view_storage_object_contexts(string $bucketName, string $objectName): void +function get_object_contexts(string $bucketName, string $objectName): void { $storage = new StorageClient(); $bucket = $storage->bucket($bucketName); diff --git a/storage/src/list_storage_object_contexts.php b/storage/src/list_object_contexts.php similarity index 92% rename from storage/src/list_storage_object_contexts.php rename to storage/src/list_object_contexts.php index 95065455f..7f9e975a7 100644 --- a/storage/src/list_storage_object_contexts.php +++ b/storage/src/list_object_contexts.php @@ -32,14 +32,14 @@ * @param string $bucketName The name of your Cloud Storage bucket. * (e.g. 'my-bucket') */ -function list_storage_object_contexts(string $bucketName): void +function list_object_contexts(string $bucketName): void { $storage = new StorageClient(); $bucket = $storage->bucket($bucketName); // Example filter: find objects where department is finance $options = [ - 'filter' => 'contexts.custom.department.value="finance"' + 'filter' => 'contexts."department"="finance"' ]; foreach ($bucket->objects($options) as $object) { printf('Found object: %s' . PHP_EOL, $object->name()); diff --git a/storage/src/set_storage_object_contexts.php b/storage/src/set_object_contexts.php similarity index 96% rename from storage/src/set_storage_object_contexts.php rename to storage/src/set_object_contexts.php index 9ae7c7f94..7f341cd87 100644 --- a/storage/src/set_storage_object_contexts.php +++ b/storage/src/set_object_contexts.php @@ -34,7 +34,7 @@ * @param string $objectName The name of your Cloud Storage object. * (e.g. 'my-object') */ -function set_storage_object_contexts(string $bucketName, string $objectName): void +function set_object_contexts(string $bucketName, string $objectName): void { $storage = new StorageClient(); $bucket = $storage->bucket($bucketName); diff --git a/storage/test/storageTest.php b/storage/test/storageTest.php index 20c92da8b..fc9400f23 100644 --- a/storage/test/storageTest.php +++ b/storage/test/storageTest.php @@ -64,20 +64,17 @@ public static function tearDownAfterClass(): void $object->delete(); } self::$tempBucket->delete(); - if (isset(self::$objectRetentionBucketName)) { - $objectRetentionBucket = self::$storage->bucket(self::$objectRetentionBucketName); - if ($objectRetentionBucket->exists()) { - foreach ($objectRetentionBucket->objects() as $object) { - // Disable object retention before delete - $object->update([ - 'retention' => [], - 'overrideUnlockedRetention' => true - ]); - $object->delete(); - } - $objectRetentionBucket->delete(); - } + + $objectRetentionBucket = self::$storage->bucket(self::$objectRetentionBucketName); + foreach ($objectRetentionBucket->objects() as $object) { + // Disable object retention before delete + $object->update([ + 'retention' => [], + 'overrideUnlockedRetention' => true + ]); + $object->delete(); } + $objectRetentionBucket->delete(); } public function testBucketAcl() @@ -238,35 +235,61 @@ public function testSetObjectRetentionPolicy() public function testObjectContexts() { - $bucketName = self::$objectContextBucketName; - self::runFunctionSnippet('create_bucket', [ $bucketName]); + $bucketName = self::$bucketName; $objectContextsBucket = self::$storage->bucket($bucketName); - $objectName = $this->requireEnv('GOOGLE_STORAGE_OBJECT') . '.ObjectContexts'; + $objectName = 'object-contexts-'.uniqid(); $object = $objectContextsBucket->upload('test', [ 'name' => $objectName, ]); $objectName = $object->info()['name']; - $setOutput = $this->runFunctionSnippet('set_storage_object_contexts', [ - self::$objectContextBucketName, + + // Set Object Contexts + $setOutput = $this->runFunctionSnippet('set_object_contexts', [ + $bucketName, $objectName, ]); $this->assertStringContainsString("Contexts for object $objectName were updated", $setOutput); - $getOutput = $this->runFunctionSnippet('view_storage_object_contexts', [ - self::$objectContextBucketName, + // Get Object Contexts + $getOutput = $this->runFunctionSnippet('get_object_contexts', [ + $bucketName, $objectName ]); $this->assertStringContainsString('Key: department, Value: finance', $getOutput); $this->assertStringContainsString('Key: priority, Value: high', $getOutput); - sleep(2); - - $listOutput = $this->runFunctionSnippet('list_storage_object_contexts', [ - self::$objectContextBucketName + // List Object Contexts using filter + $listOutput = $this->runFunctionSnippet('list_object_contexts', [ + $bucketName ]); $this->assertStringContainsString("Found object: $objectName", $listOutput); + + // Clear all contexts on the object. + $object->update([ + 'contexts' => [ + 'custom' => [], + ], + ]); + $object->reload(); + + $clearedGetOutput = $this->runFunctionSnippet('get_object_contexts', [ + $bucketName, + $objectName + ]); + + $this->assertStringNotContainsString('Key: department, Value: finance', $clearedGetOutput); + $this->assertStringNotContainsString('Key: priority, Value: high', $clearedGetOutput); + + $clearedInfo = $object->info(); + $this->assertTrue(empty($clearedInfo['contexts']['custom'] ?? [])); + + // List again with filter after clearing contexts. + $clearedListOutput = $this->runFunctionSnippet('list_object_contexts', [ + $bucketName + ]); + $this->assertEmpty(trim($clearedListOutput)); } public function testGetBucketClassAndLocation() From d1c784bc60c485f03c007e5ecb1c70ea6cf1fb1c Mon Sep 17 00:00:00 2001 From: salilg-eng Date: Fri, 17 Apr 2026 05:46:29 +0000 Subject: [PATCH 3/5] Final code --- storage/test/storageTest.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/storage/test/storageTest.php b/storage/test/storageTest.php index fc9400f23..2d63d0a55 100644 --- a/storage/test/storageTest.php +++ b/storage/test/storageTest.php @@ -50,12 +50,6 @@ public static function setUpBeforeClass(): void self::$projectId, time() ); - - self::$objectContextBucketName = sprintf( - '%s_object_contexts-%s', - self::$projectId, - time() - ); } public static function tearDownAfterClass(): void From 9cf15304c6406b395cdf0daa0ad0033448151738 Mon Sep 17 00:00:00 2001 From: salilg-eng Date: Fri, 17 Apr 2026 05:47:13 +0000 Subject: [PATCH 4/5] Final code --- storage/test/storageTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/storage/test/storageTest.php b/storage/test/storageTest.php index 2d63d0a55..dd70c7c00 100644 --- a/storage/test/storageTest.php +++ b/storage/test/storageTest.php @@ -35,7 +35,6 @@ class storageTest extends TestCase private static $storage; private static $tempBucket; private static $objectRetentionBucketName; - private static $objectContextBucketName; public static function setUpBeforeClass(): void { From e0611291b1cdc99442f9426e81958b4e63274846 Mon Sep 17 00:00:00 2001 From: salilg-eng Date: Fri, 17 Apr 2026 06:01:55 +0000 Subject: [PATCH 5/5] Final code --- storage/src/get_object_contexts.php | 4 ++-- storage/src/list_object_contexts.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/storage/src/get_object_contexts.php b/storage/src/get_object_contexts.php index 63d299553..874e1e52a 100644 --- a/storage/src/get_object_contexts.php +++ b/storage/src/get_object_contexts.php @@ -27,7 +27,7 @@ use Google\Cloud\Storage\StorageClient; /** - * Attach or modify contexts to an existing object. + * Retrieve contexts for an existing object. * * @param string $bucketName The name of your Cloud Storage bucket. * (e.g. 'my-bucket') @@ -42,7 +42,7 @@ function get_object_contexts(string $bucketName, string $objectName): void $info = $object->info(); if (isset($info['contexts']['custom'])) { - printf('Contexts for object %s were updated:' . PHP_EOL, $objectName); + printf('Contexts for object %s:' . PHP_EOL, $objectName); foreach ($info['contexts']['custom'] as $key => $data) { printf(' - Key: %s, Value: %s' . PHP_EOL, $key, $data['value']); printf(' - Created: %s' . PHP_EOL, $data['createTime']); diff --git a/storage/src/list_object_contexts.php b/storage/src/list_object_contexts.php index 7f9e975a7..58a82d8b8 100644 --- a/storage/src/list_object_contexts.php +++ b/storage/src/list_object_contexts.php @@ -27,7 +27,7 @@ use Google\Cloud\Storage\StorageClient; /** - * Attach or modify contexts to an existing object. + * List objects with a filter based on contexts. * * @param string $bucketName The name of your Cloud Storage bucket. * (e.g. 'my-bucket')