Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

General Questions

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Extended FileObject - Upload to correct ObjectType in Frontend


Reply

7 Posts   262 Views

Avatar
Andre

12 February 2014 at 6:04am Community Member, 126 Posts

Hi there, I have extended class "File" to class "VideoFile" (which does some automatic screenshots after the upload etc).

Now I have also recognized how to use the Uploadfield (the Ajax Stuff) on the Frontend.

Here is now my Problem:
I create an Object Movie, which has a relation to one Video of class VideoFile

class Movie extends DataObject{
static private $db = array("Title" => "Varchar(255)");
static private $has_one = array("Video" => "VideoFile");
}

Adding Movies to the collection by using ModelAdmin in the Backend, when creating a new Movie, the relation is set correctly and the File gets saved as type VideoFile on upload (even if I did not saved the Movie Object previously).

When creating a Form in the Frontend, I can also use UploadField for the File, but how do I tell it, that the Uploaded File should be of Type VideoFile.
Normaly, when the Form is created, the relation to the Object that it will create (Movie) will be set, when the form was submitted and the method saveInto is run on a Movie Object.

Would be nice, if smeone can help me, finding the right parts in the code, that I have to write an extension for.

kind regards

Avatar
Devlin

13 February 2014 at 12:44am Community Member, 215 Posts

mysite/_config/config.yml

File:
class_for_file_extension:
'mp4': 'VideoFile'
'm4v': 'VideoFile'

Avatar
Andre

13 February 2014 at 1:44am Community Member, 126 Posts

Thats one possible way, but with the downside, that I always have to use the VideoFile Object, when uploading files.

I was more thinking of a way, o be more flexible here. When the Object has the relation with VideoFile, than the Uploaded File should be of this class, otherwise the uploaded File should be of File class.

When Setting up a ModelAdmin, the File class is taken from the relationship, even if I do not set it i "class_for_file_extensions" separately.

class MovieAdmin extends ModelAdmin {

private static $managed_models = array('Movie');
private static $url_segment = 'testmovie';
private static $menu_title = 'Movie Test';

}

I tried to reverse engeneer the ModelAdmin and have examined, that ModelAdmin::getEditForm seems to be the Method, where regarding to the relation on the Parent Object (in my case "Movie"), the File is saved with the correct class (VideoFile).

Now my frontendform looks the following:
class MovieForm extends Form {
public function __construct($controller, $name) {
$fields = new FieldList(
$Title = new TextField('Title', 'Title'),
$File = new UploadField('Video', 'Video File')
);

$actions = new FieldList(new FormAction('save', 'Save video'));
$validator = new RequiredFields(array("Title"));

parent::__construct($controller, $name, $fields, $actions, $validator);
}
public function save(array $data, Form $form) {
$Movie = new Movie();
$form->saveInto($Movie)
...
}
}

I'm sure, I can set some kind of validator, to set the correct class for the File, but I do not know how to do it. So if anyone can help me, to examine how the ModelAdmin is selecting the right class by the Parent Models Relationships, that would be really cool.

Avatar
Devlin

13 February 2014 at 2:23am (Last edited: 13 February 2014 3:18am), Community Member, 215 Posts

how the ModelAdmin is selecting the right class

ModelAdmin doesn't do this.

The UploadField determines the file class by comparing the name of the UploadField with the names of the relations you've defined in the current DataObject.

- UploadField->getRelationAutosetClass()
- DataObject->getRelationClass()

You could overload UploadField->getRelationAutosetClass() to return "VideoFile".

You could try to set the record for the form. e.g.

$form = new Form();
$form->loadDataFrom($myRecord);
// or
$form->setDataModel(singleton('myObject'));

Edit 2: According to the documentation, this should be sufficient.
$movie = new Movie();
$form->saveInto($movie);
$movie->write();

http://doc.silverstripe.org/framework/en/reference/uploadfield#using-the-uploadfield-in-a-frontend-form

Avatar
Andre

13 February 2014 at 4:08am Community Member, 126 Posts

Thanks Devlin, you've safed my day defnetly.

Avatar
Devlin

13 February 2014 at 4:31am Community Member, 215 Posts

Hint: If you're using the UploadField in the frondend, you really need to set permissions to your File DataObject or bad things will happen.

Avatar
Andre

13 February 2014 at 4:43am Community Member, 126 Posts

Wll, thanks.

One more thing to add:

$form->setDataModel(singleton('myObject'));
setting the DataModel didn't helped in my case, but without allready having an object, where I can load the Form from, the singleton method had helped at this place.

class MovieForm extends Form {
public function __construct($controller, $name) {
$fields = new FieldList(
$Title = new TextField('Title', 'Title'),
$File = new UploadField('Video', 'Video File')
);

$actions = new FieldList(new FormAction('save', 'Save video'));
$validator = new RequiredFields(array("Title"));

parent::__construct($controller, $name, $fields, $actions, $validator);
$form->loadDataFrom(singleton('Movie'));
}
public function save(array $data, Form $form) {
$Movie = new Movie();
$form->saveInto($Movie)
...
}
}

So thanks again