1

I'm trying to set the asset volume dynamically for new assets, using a module. I would like the volume to be based on the asset's file kind – in my case, automatically putting MP4s into a 'Videos' asset volume.

I would like this to work when the asset is uploaded via an assets field, or directly via the Assets CP screen.

The Craft docs for this stuff are a bit of a mystery to me as they lack examples and explanations... here's what I've tried so far in my site module. It works when uploading assets on the Assets CP screen, but it does nothing when uploading via an Assets field on an entry:

use yii\base\Event;
use craft\elements\Asset;
use craft\events\ModelEvent;

// Automatically put MP4 uploads into the 'Videos' asset volume (volume ID 2, folder ID 2).
// This function is called in the module's constructor.
private function registerDynamicAssetVolumeSettings()
{
    Event::on(
        Asset::class,
        Asset::EVENT_BEFORE_SAVE,
        function (ModelEvent $event) {

            // only act on new assets matching my `mp4` custom file kind
            if ($event->isNew && $event->sender->kind == 'mp4') {

                // only act on mp4s which are not already being put into the mp4 volume
                if ($event->sender->getVolumeId() !== 2) {
                    $event->sender->setVolumeId(2);
                    $event->sender->newLocation = '{folder:2}' . $event->sender->getFilename();
                }
            }
        }
    );
}

Thanks in advance for any thoughts 🌞

1 Answer 1

1

Craft's developer support helped me out with this.

The key was to use Asset::EVENT_AFTER_SAVE and the Craft asset service's moveAsset function.

use yii\base\Event;
use craft\elements\Asset;
use craft\events\ModelEvent

class SiteModule extends \yii\base\Module
{

    public function init()
    {
        // ...

        $this->registerAssetEvents();
    }

    private function registerAssetEvents()
    {
        // Automatically assign asset volumes on upload, based on file kind.
        Event::on(
            Asset::class,
            Asset::EVENT_AFTER_SAVE,
            function (ModelEvent $event) {
                $asset = $event->sender;

                // mp4s which are not being put into the videos volume (id 2)
                // will be moved to the videos volume
                // NB this requires a GeneralConfig::$extraFileKinds definition for mp4s.
                if ($asset->kind == 'mp4' && $asset->getVolumeId() !== 2) {
                    $targetFolder = Craft::$app->assets->getRootFolderByVolumeId(2);
                    Craft::$app->assets->moveAsset($asset, $targetFolder);
                }
            }
        );
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.