SS4 Yaml Config Injection - how to inject function call from dynamically injected class

Silverstripe Version: 4.x

Currently I am looking into possible other cloud storage providers besides Amazon S3. Theoretically this should be very easy to do now that SS4 uses flysystem. The only thing I am not sure how to figure out though is how to get a yaml config setup properly.

For example the flysystem S3 adapter, your base config is like the following -

$client = new S3Client([
    'credentials' => [
        'key'    => 'your-key',
        'secret' => 'your-secret'
    ],
    'region' => 'your-region',
    'version' => 'latest|version',
]);

$adapter = new AwsS3Adapter($client, 'your-bucket-name');
$filesystem = new Filesystem($adapter);

So simply just new class, after new class etc. To have this injected via yaml - the config looks like -

SilverStripe\Core\Injector\Injector:
  Aws\S3\S3Client:
    constructor:
      configuration:
        region: '`AWS_REGION`'
        version: latest
        credentials:
          key: '`AWS_ACCESS_KEY_ID`'
          secret: '`AWS_SECRET_ACCESS_KEY`'
  SilverStripe\S3\Adapter\PublicAdapter:
    constructor:
      s3Client: '%$Aws\S3\S3Client'
      bucket: '`AWS_BUCKET_NAME`'
      prefix: '`AWS_PUBLIC_BUCKET_PREFIX`'

In the yaml config above you basically create an S3 client that has the config, which is then injected into the ‘PublicAdapter’ config

When using say Rackspace Cloud Files or Google Cloud Storage, there is always an additional step where you have to get an additional object from the actual bucket. Example for google cloud storage -

$storageClient = new StorageClient([
    'projectId' => 'your-project-id',
]);
$bucket = $storageClient->bucket('your-bucket-name'); //This is the main issue

$adapter = new GoogleStorageAdapter($storageClient, $bucket);

$filesystem = new Filesystem($adapter);

In the example above you see that the bucket is pulled from the client created and that is then used to create the new adapter where as with the S3 config - you just pass in the bucket name, not an object that must be gotten and generated.

Does anyone know how to handle this type of injection or how you can reference a function call in yaml? I am guessing I need to create a new class where it’s constructor takes the google ‘StorageClient’ as a param and then just the bucket name but returns then an instance of GoogleStorageAdapter from the constructor?

If any one also has any good docs on how SilverStripe’s yaml injection/traits etc works would be great. I am not finding much in the docs for this type of advanced stuff nor am I sure what to search for on google.

Thanks all!