Search code examples
silverstripesilverstripe-4

How to override the existing method of an existing class, FlysystemAssetStore that is part of the framework in SilverStripe


I am working on a SilverStripe project, in my project, I need to change the behavior of a class that is part of the SilverStripe framework. The class I need to modify is SilverStripe\Assets\Flysystem\FlysystemAssetStore. For example, I am now trying to modify the exists method of the class. I tried using two options Injector and Extension. Both did not work.

The first option I tried is using the Injector. This is what I did.

First, I created a class called, CustomFlysystemAssetStore.

Then I added the following code to the mysite.yml

SilverStripe\Assets\Flysystem\FlysystemAssetStore:
    class: CustomFlysystemAssetStore

I declared the public function called exists in the CustomFlysystemAssetStore class to override the existing behavior. But it did not work. The new method within the new class was not executed at all.

The second option I tried is using the Extension. This is what I did.

First, I created a class called CustomFlysystemAssetStore that is extending the DataExtension class.

Then, I added the following code snippet into the mysite.yml.

SilverStripe\Assets\Flysystem\FlysystemAssetStore:
  extensions:
    - CustomFlysystemAssetStore

Then I declared a public method in the new class called exists to see if the new method is called.

Unfortunately, the second approach did not work either. How can I override the methods of the SilverStripe\Assets\Flysystem\FlysystemAssetStore class that is part of the framework?

This is my assets.yml file

---
Name: silverstripes3-flysystem
Only:
  envvarset: AWS_BUCKET_NAME
After:
  - '#assetsflysystem'
---
SilverStripe\Core\Injector\Injector:
  Aws\S3\S3Client:
    constructor:
      configuration:
        region: '`AWS_REGION`'
        version: latest
  League\Flysystem\Adapter\Local:
    class: League\Flysystem\Adapter\Local
    constructor:
      root: '`TEMP_PATH`'

  SilverStripe\S3\Adapter\PublicAdapter:
    constructor:
      s3Client: '%$Aws\S3\S3Client'
      bucket: '`AWS_BUCKET_NAME`'
      prefix: '`AWS_PUBLIC_BUCKET_PREFIX`'
  League\Flysystem\Cached\Storage\Memory.public:
    class: League\Flysystem\Cached\Storage\Memory
  League\Flysystem\Cached\Storage\Adapter.public:
    class: League\Flysystem\Cached\Storage\Adapter
    constructor:
      adapter: '%$League\Flysystem\Adapter\Local'
      file: 's3metadata/public'
      expire: 259200
  SilverStripe\Assets\Flysystem\PublicAdapter:
    class: SilverStripe\S3\Adapter\PublicCachedAdapter
    constructor:
      adapter: '%$SilverStripe\S3\Adapter\PublicAdapter'
      cache: '%$League\Flysystem\Cached\Storage\Adapter.public'

  SilverStripe\S3\Adapter\ProtectedAdapter:
    constructor:
      s3Client: '%$Aws\S3\S3Client'
      bucket: '`AWS_BUCKET_NAME`'
      prefix: '`AWS_PROTECTED_BUCKET_PREFIX`'
  League\Flysystem\Cached\Storage\Adapter.protected:
    class: League\Flysystem\Cached\Storage\Adapter
    constructor:
      adapter: '%$League\Flysystem\Adapter\Local'
      file: 's3metadata/protected'
      expire: 259200
  SilverStripe\Assets\Flysystem\ProtectedAdapter:
    class: SilverStripe\S3\Adapter\ProtectedCachedAdapter
    constructor:
      adapter: '%$SilverStripe\S3\Adapter\ProtectedAdapter'
      cache: '%$League\Flysystem\Cached\Storage\Adapter.protected'
#---
Name: silverstripes3-assetscore
Only:
  envvarset: AWS_BUCKET_NAME
After:
  - '#assetscore'
---
SilverStripe\Core\Injector\Injector:
  SilverStripe\Assets\Storage\AssetStore:
    class: CustomFlysystemAssetStore

Solution

  • In Silverstripe 4.5 we can extend FlysystemAssetStore and define our own exists method.

    First we create a CustomFlysystemAssetStore.php file in our project:

    app/src/CustomFlysystemAssetStore.php

    use SilverStripe\Assets\Flysystem\FlysystemAssetStore;
    
    class CustomFlysystemAssetStore extends FlysystemAssetStore {
    
        public function exists($filename, $hash, $variant = null)
        {
            // Custom logic goes here
            // ...
    
            // Fallback to the parent exists function
            return parent::exists($filename, $hash, $variant);
        }
    }
    

    We then set this as the AssetStore we want the system to use through a yml config file. We create an assets.yml file:

    app/_config/assets.yml

    ---
    Name: app-assetscore
    After:
      - '#assetscore'
    ---
    
    SilverStripe\Core\Injector\Injector:
      SilverStripe\Assets\Storage\AssetStore:
        class: CustomFlysystemAssetStore