Custom form processing in Admin

I would like to do some custom form processing in an Admin form. I am not clear on what events to register or whether I have to enable something if admin (I’ve seen this in several places, not sure when it’s needed!)… The goal is to handle a file upload so that the file gets uploaded to Cloudinary instead of into Grav via their API, and then set the assigned public id as page.header.public_id. This is what I’ve got so far:

blueprint.yaml

title: Cloudinary
'@extends':
    type: default
    context: blueprints://pages

form:
  fields:
    tabs:
      fields:
        cloudinary:
          type: tab
          title: Cloudinary
          fields:
            file_upload:
              name: upload_video
              type: file
              label: Upload file to Cloudinary
              destination: 'self@'
              accept:
                - video/*
              process:
                  - upload: false
                  - uploadFile:

The file gets uploaded into that folder anyway (and I need to set a destination or the form complains). I have defined an onFormProcessed method in my plugin’s class:

    public function onFormProcessed(Event $event)
    {
        \Cloudinary::config(array(
          "cloud_name" => $this->config->get('plugins.cloudinary.cloud_name'),
          "api_key" => $this->config->get('plugins.cloudinary.key'),
          "api_secret" => $this->config->get('plugins.cloudinary.secret')
        ));

        $form = $event['form'];
        $action = $event['action'];
        $params = $event['params'];

        $post = isset($_POST['data']) ? $_POST['data'] : [];

        switch ($action) {
          case 'uploadFile':
            return $result = \Cloudinary\Uploader::upload($post['file_upload']);
        }
    }

Feels to me though as if that method doesn’t get called at all. How can I make this work for an Admin form? Or maybe I can just make a function call in the blueprint like:

process: uploadFileToCloudinary()

I know that can’t be right, but maybe something similar? Or with a different field type? Custom field type??

I have now found that I can do quite a bit in onAdminSave – but no matter what, the file apparently gets uploaded before that event is even fired. Since some video files can be quite large, I’d rather not upload them twice and then delete one afterwards… :sweat_smile:

I came across an old issue for Grav forms on Github, but since onFormProcessed doesn’t seem to get fired I’m not sure how or where I might use $event->stopPropagation(). Does anybody know, or can somebody tell me where or I how I can find out more? Any plugins that do something like this?

Or maybe I’m trying to get at this in the wrong way? What I’m doing is:

public static function getSubscribedEvents()
{
    return [
      'onPluginsInitialized'      => ['onPluginsInitialized', 0]
    ];
}
public function onPluginsInitialized()
{
    if ($this->isAdmin()) {
        $this->enable([
          'onFormProcessed' => ['onFormProcessed', 0],
          'onAdminSave'     => ['onAdminSave', 0]
    ]);
}
public function onFormProcessed(Event $event)
{ // doesn't work at all
    dump($event); exit;
}

I just tried putting the things under $this->enable directly under getSubscribedEvents, and the result seems to be the same: stuff in onAdminSave does what it should, and stuff in onFormProcessed does not. I feel like I still haven’t really understood these bits, and I would be very grateful for some clarification! You can also just throw some links at me ok :grin: