This pull request doesn't alter current forms submission behavior (in essence it ensures that the "forms.submit.before" event is always triggered for each form submission).
empty $_POST data is passed to Forms\Controller\RestApi::submit causing an early exit from that function and without being so able to parse $_FILES data inside the "forms.submit.before" hook
// Forms::submit
$this->app->trigger('forms.submit.before', [$form, &$data, $frm, &$options]); // <-- parse here form $data request
if (empty($data)) {
return false;
}
Example of usage:
Dynamically check and populate forms $data['files'] entry:
// config/bootstrap.php
$app->on('forms.submit.before', function($form, &$data, $frm, &$options) use ($app) {
// see "Helper Functions" for more info about it
$files = get_uploaded_files()
if (!empty($files)) {
$files = $app->module('cockpit')->uploadAssets('files', ['folder' => get_forms_uploads_folder()]);
$data['files'] = $files['uploaded']; // <-- save entries as filename
}
});
Contact Form
Simple contact form template with **single input `files[]`**:
![contact](https://user-images.githubusercontent.com/9614886/106008118-494d0c80-60b7-11eb-91ae-adb0af7f77e0.png)
**Lexy template:**
```blade
@form( 'contact', [ 'id' => 'contact-form', 'class'=>'contact-form' ] )
@endform
```
Upload Form
Simple contact form template with **multiple input `files[]`** :
![upload](https://user-images.githubusercontent.com/9614886/106009161-56b6c680-60b8-11eb-8a4e-4436864a7014.png)
**Lexy template:**
```blade
@form( 'upload', [ 'id' => 'upload-form', 'class'=>'upload-form' ] )
@lang('Thank You! I\'ll get back to you real soon...')
@endform
```
Helper Functions
config/bootstrap.php
```php
/**
* Check and retrieve forms uploaded files
*
* @return array $data
*/
function get_uploaded_files() {
$app = cockpit();
$files = $app->param('files', [], $_FILES);
$data = [];
if (isset($files['name']) && is_array($files['name'])) {
for ($i = 0; $i < count($files['name']); $i++) {
if (is_uploaded_file($files['tmp_name'][$i]) && !$files['error'][$i]) {
foreach($files as $k => $v) {
$data['files'][$k] = $data['files'][$k] ?? [];
$data['files'][$k][] = $files[$k][$i];
}
}
}
}
return $data;
}
/**
* Check and retrieve forms upload folder
*
* @return array $folder
*/
function get_forms_uploads_folder() {
$app = cockpit();
$name = 'forms_uploads';
$parent = '';
$folder = $app->storage->findOne('cockpit/assets_folders', ['name'=>$name, '_p'=>$parent]);
if (empty($folder)) {
$user = $app->storage->findOne('cockpit/accounts', ['group'=>'admin'], ['_id' => 1]);
$meta = [
'name' => $name,
'_p' => $parent,
'_by' => $user['_id'] ?? '',
];
$folder = $app->storage->save('cockpit/assets_folders', $meta);
}
return $folder;
}
/**
* Check and populate forms $data['files'] entry
*/
$app->on('forms.submit.before', function($form, &$data, $frm, &$options) use ($app) {
$files = get_uploaded_files();
if (!empty($files)) {
$files = $app->module('cockpit')->uploadAssets('files', ['folder' => get_forms_uploads_folder()]);
$data['files'] = [];
$ASSETS_URL = rtrim($app->filestorage->getUrl('assets://'), '/');
// save entries as filename
// $data['files'] = $files['uploaded'];
// save entries as absolute urls
foreach($files['assets'] as $file) {
$data['files'][] = $ASSETS_URL.$file['path'];
}
}
});
```
End notes
The Contact Form example reported above does not suffer from this problem because the variable $_POST is still populated by other input fields.
The Upload Form (with just input $_FILES) is purely demonstrative. It can be solved somehow by hooking the assets api, however, it would be nice to be able to do it with the same hook (regardless of the number of parameters and without having to define custom rest api endpoints...)
Preamble
This pull request doesn't alter current forms submission behavior (in essence it ensures that the
"forms.submit.before"
event is always triggered for each form submission).A borderline example is shown below.
Issue description:
When using a form call like the following:
empty
$_POST
data is passed toForms\Controller\RestApi::submit
causing an early exit from that function and without being so able to parse$_FILES
data inside the"forms.submit.before"
hookhttps://github.com/agentejo/cockpit/blob/efb8944051d7f347a4114cd21d8f01ecab373a00/modules/Forms/Controller/RestApi.php#L23-L34
Proposed solution:
Set fallback param
$data
to empty array and delegate empty check validation toForms::submit
function.Example of usage:
Dynamically check and populate forms
$data['files']
entry:Contact Form
Simple contact form template with **single input `files[]`**: ![contact](https://user-images.githubusercontent.com/9614886/106008118-494d0c80-60b7-11eb-91ae-adb0af7f77e0.png) **Lexy template:** ```blade @form( 'contact', [ 'id' => 'contact-form', 'class'=>'contact-form' ] ) @endform ```
Upload Form
Simple contact form template with **multiple input `files[]`** : ![upload](https://user-images.githubusercontent.com/9614886/106009161-56b6c680-60b8-11eb-8a4e-4436864a7014.png) **Lexy template:** ```blade @form( 'upload', [ 'id' => 'upload-form', 'class'=>'upload-form' ] )