Skip to content

Commit

Permalink
feat: add support for uploading multiple files to the file upload field
Browse files Browse the repository at this point in the history
  • Loading branch information
rasstislav committed Feb 6, 2025
1 parent 184dad7 commit c2b94b6
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 103 deletions.
121 changes: 74 additions & 47 deletions code/Control/UserDefinedFormController.php
Original file line number Diff line number Diff line change
Expand Up @@ -313,49 +313,74 @@ public function process($data, $form)
$field->createProtectedFolder();
}

$file = Versioned::withVersionedMode(function () use ($field, $form) {
$stage = Injector::inst()->get(UserDefinedFormController::class)->config()->get('file_upload_stage');
Versioned::set_stage($stage);

$foldername = $field->getFormField()->getFolderName();
// create the file from post data
$upload = Upload::create();
try {
$upload->loadIntoFile($_FILES[$field->Name], null, $foldername);
} catch (ValidationException $e) {
$validationResult = $e->getResult();
foreach ($validationResult->getMessages() as $message) {
$form->sessionMessage($message['message'], ValidationResult::TYPE_ERROR);
$processFile = function ($fileData) use ($field, $form, &$attachments) {
$file = Versioned::withVersionedMode(function () use ($fileData, $field, $form, &$attachments) {
$stage = Injector::inst()->get(UserDefinedFormController::class)->config()->get('file_upload_stage');
Versioned::set_stage($stage);

$foldername = $field->getFormField()->getFolderName();
// create the file from post data
$upload = Upload::create();
try {
$upload->loadIntoFile($fileData, null, $foldername);
} catch (ValidationException $e) {
$validationResult = $e->getResult();
foreach ($validationResult->getMessages() as $message) {
$form->sessionMessage($message['message'], ValidationResult::TYPE_ERROR);
}
Controller::curr()->redirectBack();
return null;
}
Controller::curr()->redirectBack();
/** @var AssetContainer|File $file */
$file = $upload->getFile();
$file->ShowInSearch = 0;
$file->UserFormUpload = UserFormFileExtension::USER_FORM_UPLOAD_TRUE;
$file->write();

return $file;
});

if (is_null($file)) {
return null;
}
/** @var AssetContainer|File $file */
$file = $upload->getFile();
$file->ShowInSearch = 0;
$file->UserFormUpload = UserFormFileExtension::USER_FORM_UPLOAD_TRUE;
$file->write();

// generate image thumbnail to show in asset-admin
// you can run userforms without asset-admin, so need to ensure asset-admin is installed
if (class_exists(AssetAdmin::class)) {
AssetAdmin::singleton()->generateThumbnails($file);
}

// attach a file to recipient email only if lower than configured size
if ($file->getAbsoluteSize() <= $this->getMaximumAllowedEmailAttachmentSize()) {
$attachments[$field->Name][] = $file;
}

return $file;
});
};

if (is_null($file)) {
return;
}
$files = $_FILES[$field->Name];

// generate image thumbnail to show in asset-admin
// you can run userforms without asset-admin, so need to ensure asset-admin is installed
if (class_exists(AssetAdmin::class)) {
AssetAdmin::singleton()->generateThumbnails($file);
}
if (is_array($files['name'])) {
foreach (array_keys((array) $files['name']) as $key) {
$fileData = [];
foreach ($files as $column => $data) {
$fileData[$column] = $data[$key];
}

// write file to form field
$submittedField->UploadedFileID = $file->ID;
if (!$file = $processFile($fileData)) {
return;
}

// write file to form field
$submittedField->UploadedFiles()->add($file);
}
} else {
if (!$file = $processFile($files)) {
return;
}

// attach a file to recipient email only if lower than configured size
if ($file->getAbsoluteSize() <= $this->getMaximumAllowedEmailAttachmentSize()) {
// using the field name as array index is fine as file upload field only allows one file
$attachments[$field->Name] = $file;
// write file to form field
$submittedField->UploadedFileID = $file->ID;
}
}
}
Expand Down Expand Up @@ -393,21 +418,23 @@ public function process($data, $form)
$mergeFields = $this->getMergeFieldsMap($emailData['Fields']);

if ($attachments && (bool) $recipient->HideFormData === false) {
foreach ($attachments as $uploadFieldName => $file) {
/** @var File $file */
if ((int) $file->ID === 0) {
continue;
}
foreach ($attachments as $uploadFieldName => $files) {
foreach ($files as $file) {
/** @var File $file */
if ((int) $file->ID === 0) {
continue;
}

$canAttachFileForRecipient = true;
$this->extend('updateCanAttachFileForRecipient', $canAttachFileForRecipient, $recipient, $uploadFieldName, $file);
$canAttachFileForRecipient = true;
$this->extend('updateCanAttachFileForRecipient', $canAttachFileForRecipient, $recipient, $uploadFieldName, $file);

if ($canAttachFileForRecipient) {
$email->addAttachmentFromData(
$file->getString(),
$file->getFilename(),
$file->getMimeType()
);
if ($canAttachFileForRecipient) {
$email->addAttachmentFromData(
$file->getString(),
$file->getFilename(),
$file->getMimeType()
);
}
}
}
}
Expand Down
20 changes: 19 additions & 1 deletion code/Model/EditableFormField/EditableFileField.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use SilverStripe\Core\Convert;
use SilverStripe\Forms\FieldList;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Forms\CheckboxField;
use SilverStripe\Forms\FileField;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\NumericField;
Expand All @@ -18,6 +19,7 @@
use SilverStripe\Security\InheritedPermissions;
use SilverStripe\UserForms\Control\UserDefinedFormAdmin;
use SilverStripe\UserForms\Control\UserDefinedFormController;
use SilverStripe\UserForms\Model\EditableCustomRule;
use SilverStripe\UserForms\Model\EditableFormField;
use SilverStripe\UserForms\Model\Submission\SubmittedFileField;

Expand All @@ -40,6 +42,7 @@ class EditableFileField extends EditableFormField
private static $db = [
'MaxFileSizeMB' => 'Float',
'FolderConfirmed' => 'Boolean',
'Multiple' => 'Boolean',
];

private static $has_one = [
Expand Down Expand Up @@ -173,6 +176,12 @@ public function getCMSFields()
->setDescription("Note: Maximum php allowed size is {$this->getPHPMaxFileSizeMB()} MB")
);

$fields->addFieldToTab(
'Root.Main',
CheckboxField::create('Multiple')
->setTitle('Allow multiple files')
);

$fields->removeByName('Default');
});

Expand Down Expand Up @@ -209,7 +218,7 @@ public function createProtectedFolder(): void

public function getFormField()
{
$field = FileField::create($this->Name, $this->Title ?: false)
$field = FileField::create($this->Name . ($this->Multiple ? '[]' : ''), $this->Title ?: false)
->setFieldHolderTemplate(EditableFormField::class . '_holder')
->setTemplate(__CLASS__)
->setValidator(Injector::inst()->get(Upload_Validator::class . '.userforms', false));
Expand All @@ -231,6 +240,10 @@ public function getFormField()
$field->getValidator()->setAllowedMaxFileSize(static::get_php_max_file_size());
}

if ($this->Multiple) {
$field->setAttribute('multiple', 'multiple');
}

$folder = $this->Folder();
if ($folder && $folder->exists()) {
$field->setFolderName(
Expand Down Expand Up @@ -300,4 +313,9 @@ public function onBeforeWrite()
$this->FolderConfirmed = true;
}
}

public function getSelectorFieldOnly()
{
return $this->Multiple ? "[name='{$this->Name}[]']" : parent::getSelectorFieldOnly();
}
}
Loading

0 comments on commit c2b94b6

Please sign in to comment.