Extend FileUploader Widget

I want to extend the FileUploader Widget with another FileUploader besides the description and title field. My desired workflow would be:

  1. Upload a image via fileuploader field
  2. Open the fileuploader Widget (where title & description can be set)
  3. Upload a video-file to it
  4. Use the Image as video preview in a video html tag

I’d like to store the relationship in a extra column “video” in the “system_files” table.
I already stumbled over this: October Tricks Add custom form fields/options to a File attachment and some other ressources but I’m stuck on how to proceed…

So far I have a Plugin.php with this that throws Model 'System\Models\File' does not contain a definition for 'video'. when clicking on uploaded images.

use Event;
use System\Classes\PluginBase;
use System\Models\File;

class Plugin extends PluginBase
{
    public function boot()
    {
        Event::listen('backend.form.extendFields', function ($widget) {
            if (!$widget->model instanceof File) return;
            $widget->addFields([
                'video' => [
                    'label' => 'Video',
                    'type' => 'fileupload',
                ]
            ]);
        });
    }
}

See the current plugins github repo. Would be super happy to get some help :slight_smile:

first of all. your model must implement

 // if you wish to attach one file
    public $attachOne = [
        'video' => [\System\Models\File::class, 'delete' => true],
    ];

 // if you wish to attach multiple files
    public $attachMany = [
        'videos' => [\System\Models\File::class, 'delete' => true],
    ];

then extending fields with video will accept file attachment for fileupload

1 Like

Awesome!! Thank you!!

My boot function now:

    public function boot()
    {
        File::extend(function ($model) {
            $model->attachOne['video'] = [
                File::class, 'delete' => true
            ];
        });
        
        Event::listen('backend.form.extendFields', function ($widget) {

            if (!$widget->model instanceof File) return;

            $widget->addFields([
                'video' => [
                    'label' => 'Video',
                    'type' => 'fileupload',
                    'maxFiles'  => 1
                ]
            ]);

        });
    }

It shows the fileuploader inside the fileuploader widget.
But when I upload a file (~1MB) it says Server Error: Server responded with 500 code. and in the Log Allowed memory size of 268435456 bytes exhausted (tried to allocate 65536 bytes) in vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php on line 409.

How is that happening!?

what is “File” model, which you extending? Main System\Models\File ?? if yes, then this is terrible wrong approach. System\Model\File is any filetype you want… you must extend YOUR MODEL, where you wish to use Video or any kind of File attachment to be uploaded.

1 Like

“File” is “System\Models\File” so far…

So by creating a Model I have to store the video files in a new table? I thought I could just use system_files. So I created a model like this now:

models/FileVideo.php

use System\Models\File;

class FileVideo extends File
{

    public $table = 'mg_file_videos';

    public $belongsTo = [
       'file' => File::class
    ];
}

update

// copied from FileBase
Schema::create('mg_file_videos', function (Blueprint $table) {
            $table->increments('id');
            $table->string('disk_name');
            $table->string('file_name');
            $table->integer('file_size');
            $table->string('content_type');
            $table->string('title')->nullable();
            $table->text('description')->nullable();
            $table->string('field')->nullable();
            $table->integer('attachment_id')->nullable();
            $table->string('attachment_type')->nullable();
            $table->boolean('is_public')->default(true);
            $table->integer('sort_order')->nullable();
            $table->timestamps();

            $table->index(['attachment_type', 'attachment_id', 'field'], 'system_files_master_index');
        });

and in boot function

        File::extend(function ($model) {
            $model->attachOne['video'] = [
                FileVideo::class, 'delete' => true
            ];
        });

Have a look to the github repo if this ^^ is to confusing
I guess this must be terribly wrong too… I guess I just don’t get the concept if my previous attempt is wrong :frowning:

Not exactly sure, what you wish to achieve. You wish to extend System\Models\File “form” with what kind of field? Another file upload where you wish to store video file? Probably you will something else, or another point of view.

When we talking about System\Models\File, there can be any type of file, right? Then, when you choose video, it will upload video. Do you wish to upload for that any “preview image” as i got from your first message, right?

Then, probably you wont extend System\Models\File, but create your own Model, like you did, but, wrong way again. You can create a simple model:

class Video extends Model
{

$attachOne = [
    'video' => 'System\Models\File',
    'preview' => 'System\Models\File'
];

then schema will be only

Schema::create('mg_video', function ( Blueprint $table) {
        $table->string('title');
        $table->timestamp('created_at')->nullable();
        $table->timestamp('updated_at')->nullable();
        $table->timestamp('deleted_at')->nullable();
});

then, fields.yaml

fields:
   title:
      type: string
   video:
      type: fileupload
      mode: file
   preview:
      type: fileupload
      mode: image

this will generate a simple model with title for video, 2 upload fileds one for video file one for image

Exactly!
I already have a original october fileupload field to populate a image slider in the frontend. I want to achieve that after uploading a image, I can attach a video-file to that specific image (besides all the other images in the fileuploader) to use the image as video-preview for the video html tag inside the slider in the frontend.

So what I had here was already totaly fine (in the view of the handling in the october backend). And it works with a textfield! Just need to get rid of the memory size exhausting and it would be exactly what I want!

See this screenshot of the current state:

when u facing memory limits then u need to check server limits for file uploads and for max memory limit

I can’t see how 256MB should not be enough for this task. Uploading the video file to the parent fileuploader works without memory limit.

one thing what can cause this may be an internal loop, when you tried to extend System File Model, with another System File Model… but, not sure if this is that case. if you can, try to xdebug cycle of uploading … or. try to use mediafinder instead. this may allow you to upload any file in media library and then pick an uploaded file… then, in this type of “relation” you dont need to extend with attachOne relation, but you need to extend system_file table with new field, for example video_file … and this field then will contain path to media storage.

Yeah if there is no solution for this, that’s going to be the way…
Thank’s for your help so far!

hmmm, probably, other way with fileuploader wont work too, because of extending.
your code

Event::listen('backend.form.extendFields', function ($widget) {

extending only form, not functionality to handle changes, then nothing will be saved… this causes crash to 500 internal server error (timeout or memorylimits) and too, nothing was updated when i tried to change fileupload with mediafinder