Marc,
Feel free to ask for me to go in more detail, but here’s the broad picture (with comments where I’ve omitted details specific to your use case):
1. Enable file uploads on the booking form
The booking form by default only supports $_POST
data. To support file uploads you’ll need to add the attribute enctype="multipart/form-data"
to the <form>
tag in templates/eo-booking-form.php
template:
<form enctype="multipart/form-data ...>
...
</form>
Copy that file to the root directory of your theme and edit there so it survives updates to the plug-in.
2. Declare the Element class
This is similar to your class but I’ve extended the EO_Booking_Form_Element_Input
class – this is for convenience as I no longer have to declare a view. Views are registered as you have shown, but if my element doesn’t have a view it will proceed through the class’ ancestors until it finds a View. In this case, the parent is EO_Booking_Form_Element_Input
which does have a view class: EO_Booking_Form_Element_Input_View
– and this just so happens to be exactly what I need: an <input>
with a configurable type (which I set below in get_field_type()
)
Of course if you wish you can register your own View class if you wish.
class EO_Booking_Form_Element_File extends EO_Booking_Form_Element_Input{
static function get_type_name(){
return 'Fichier';
}
function get_field_type(){
return 'file';
}
function get_defaults(){
return array(
'label' => 'Fichier',
);
}
function get_data(){
return $this->get( 'data' );
}
function validate( $input ) {
//@see http://php.net/manual/en/reserved.variables.files.php for details
$file = array(
'tmp_name' => $_FILES['eventorganiser']['tmp_name']['booking']['file'],
'name' => $_FILES['eventorganiser']['name']['booking']['file'],
'size' => $_FILES['eventorganiser']['size']['booking']['file'],
'error' => $_FILES['eventorganiser']['error']['booking']['file'],
'type' => $_FILES['eventorganiser']['type']['booking']['file'],
);
//Validate file, e.g. check type, check for errors, and check for size
//PLease note that $file['type'] can be spoofed - its best to analyzie the contents of the file
//if there is any error: $this->add_error( 'my-error-code', 'Error message' );
//Otherwise set value
$this->set_value( $file );
}
function save( $booking_id ) {
$file = $this->get_value(); //returns the array set above in validate().
//You can now upload the file
//@see https://codex.wordpress.org/Function_Reference/wp_handle_upload
$_file = wp_handle_upload( $file, array( 'test_form' => false ), time() );
//Once the file is uploaded you could either
//Store a reference to the file location in as booking meta,
//Or use wp_insert_attachment and store a reference to the attacment ID in booking meta
//In either case, to add booking meta
//update_post_meta( $booking_id, 'my_meta_key', 'my_value' );
}
}
I’ve simply added two methods to the class. First is validate()
– this is where you should perform any checks on the file. You might want to consider:
- Analysing the type and content of the file to prevent any uploads of malicious files
- Imposing a size limit on the file
- Checking the error number: it should be 0 if all is well
The function also sets the value of the element so that we can retrieve this later (i.e. in save()
). (This really could/should be set earlier but this will suffice). To prevent the booking from proceeding and return the user to the booking page with an error message, simply add an error the element as shown.
The second method is save( $booking_id )
. This is triggered after the booking is made (not necessarily confirmed) and this where you should upload the file to the server. (wp_handle_upload()
is good for that).
You should then store a means of linking a file and a booking. You could do that by simply storing the file location as post meta. Or create an attachment for the uploaded file and store the attachment ID as a booking meta data. (Bookings are posts so you can use the usual post meta functions).
3. Add to the form
Please note that this is part of the API may change – you can alternatively programatically add the element the form.
To do add the element to the form customiserL:
EO_Booking_Form_Controller::register(
'file', //element type ID
'Fichier', //Label for the form customiser
'http://yoursite.com/url/to/backbone-model.js', //url to customiser 'model'
'http://yoursite.com/url/to/customiser-view.tmpl',//url to customiser view
'advanced' //which metabox to add the button to: standard, advanced
);
The model ‘is’ your file element type in the customiser. It essentially stores the default values of an instance of that type.
eo.bfc.Model.EOFormElementFile = eo.bfc.Model.EOFormElementInput.extend({
defaults:{
label: eo.gettext("Fichier"),
name: eo.gettext("Fichier"),
description: "",
required: false,
field_type: 'text',
parent: 0,
},
});
you could specify the settings, but we’ll just inherit the settings for input.
The template is used to generate a preview of the element in the customiser. E.g. put the following in the .tmpl
file:
<label>{{label}}</label><# if( required ){ #><span class="required">*</span><#}#><br>
<input type="file" disabled="disabled" />
<# if( description ){ #><p class="description">{{description}}</p><#}#>
Side remarks: Backbone is used for the Model and Views in the customiser and Underscore is used for template rendering.