diff --git a/README.md b/README.md index d797743..6cbf42c 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,10 @@ [![Version](http://img.shields.io/packagist/v/fullscreeninteractive/silverstripe-manyfield.svg)](https://packagist.org/packages/fullscreeninteractive/silverstripe-manyfield) [![License](http://img.shields.io/packagist/l/fullscreeninteractive/silverstripe-manyfield.svg)](license.md) -A reusable approach to a form field which allows you to create and delete rows -in Forms. +A reusable approach to a form field which allows you to create and delete rows +in either custom built forms or in Userforms. -This is designed to work on the front-end with limited javascript (i.e it does +This is designed to work on the front-end with limited javascript (i.e it does not require `GridField` or entwine). Each row can relate to a DataObject subclass or simply to be used to capture the @@ -35,7 +35,7 @@ $fields = new FieldList( ); ``` -Data will either be saved as `setSwabList($data)`, `SwabList` database field or +Data will either be saved as `setSwabList($data)`, `SwabList` database field or in the `SwabList` relation. If you are saving into a relation such as `HasMany` or `ManyMany` list then make sure you include a hidden field in your field list. @@ -69,13 +69,23 @@ Include a Hidden field `Sort` and make sure sorting is enabled. ## Javascript Events -If you have UI handlers that need to run when fields are added or removed +If you have UI handlers that need to run when fields are added or removed (such as Date Pickers) create a handler on your `` element and listen for either: * `manyFieldAdded` * `manyFieldRemoved` +## FAQ + +### When I use this with File fields I don't get files uploaded? + +Make sure your form encoding is set to the correct MIME type. + +``` +$form->setEncType(Form::ENC_TYPE_MULTIPART); +``` + ## Licence -BSD 3-Clause License \ No newline at end of file +BSD 3-Clause License diff --git a/src/EditableManyField.php b/src/EditableManyField.php index 7c8ecf3..3ebddc7 100644 --- a/src/EditableManyField.php +++ b/src/EditableManyField.php @@ -3,9 +3,12 @@ namespace FullscreenInteractive\ManyField; use Dotenv\Exception\ValidationException; +use Exception; use SilverStripe\Forms\GridField\GridField; use FullscreenInteractive\ManyField\ManyField; +use Psr\Log\LoggerInterface; use SilverStripe\Assets\Upload; +use SilverStripe\Core\Injector\Injector; use SilverStripe\Forms\FieldList; use SilverStripe\Forms\GridField\GridFieldButtonRow; use SilverStripe\Forms\GridField\GridFieldConfig; @@ -156,9 +159,18 @@ public function getValueFromData($data) foreach ($this->Children() as $field) { - foreach ($incoming[$field->Name] as $i => $value) { - if ($value && !empty($value)) { - $rowHasValue[$i] = true; + if (isset($incoming[$field->Name])) { + foreach ($incoming[$field->Name] as $i => $value) { + if ($value && !empty($value)) { + $rowHasValue[$i] = true; + } + } + } elseif (isset($incoming['name']) && isset($incoming['name'][$field->Name])) { + // handle multi-part + foreach ($incoming['name'][$field->Name] as $i => $value) { + if ($value && !empty($value)) { + $rowHasValue[$i] = true; + } } } } @@ -167,21 +179,37 @@ public function getValueFromData($data) foreach ($this->Children() as $field) { - foreach ($incoming[$field->Name] as $i => $value) { - if (!isset($rowHasValue[$i])) { - // empty row; - continue; - } + if (isset($incoming[$field->Name])) { + foreach ($incoming[$field->Name] as $i => $value) { + if (!isset($rowHasValue[$i])) { + // empty row; + continue; + } + + if (!isset($rows[$i])) { + $rows[$i] = []; + } - if (!isset($rows[$i])) { - $rows[$i] = []; + $submittedField = $this->createNestedSubmittedFormField($field, [ + $field->Name => $value + ]); + + $rows[$i][$field->Name] = $submittedField->ID; } + } elseif (isset($incoming['name']) && isset($incoming['name'][$field->Name])) { + // handle multi-part + foreach ($incoming['name'][$field->Name] as $i => $value) { + if (!isset($rowHasValue[$i])) { + // empty row; + continue; + } - $submittedField = $this->createNestedSubmittedFormField($field, [ - $field->Name => $value - ]); + $submittedField = $this->createNestedSubmittedFormField($field, [ + $field->Name => $value + ]); - $rows[$i][$field->Name] = $submittedField->ID; + $rows[$i][$field->Name] = $submittedField->ID; + } } } @@ -204,26 +232,42 @@ public function createNestedSubmittedFormField(EditableFormField $field, $data) } } - if (!empty($data[$field->Name])) { - if (in_array(EditableFileField::class, $field->getClassAncestry())) { - if (!empty($_FILES[$field->Name]['name'])) { - $foldername = $field->getFormField()->getFolderName(); - $upload = Upload::create(); + $file = null; + if (!empty($_FILES[$field->Name]['name'])) { + $file = $_FILES[$field->Name]; + } else if (!empty($_FILES[$this->Name]['name'])) { + if (!empty($_FILES[$this->Name]['name'][$field->Name])) { + $file = [ + 'tmp_name' => $_FILES[$this->Name]['tmp_name'][$field->Name][0], + 'type' => $_FILES[$this->Name]['type'][$field->Name][0], + 'name' => $_FILES[$this->Name]['name'][$field->Name][0], + 'error' => $_FILES[$this->Name]['error'][$field->Name][0], + 'size' => $_FILES[$this->Name]['size'][$field->Name][0] + ]; + } + } - try { - $upload->loadIntoFile($_FILES[$field->Name], null, $foldername); + if ($file) { + $foldername = $field->getFormField()->getFolderName(); + $upload = Upload::create(); - /** @var AssetContainer|File $file */ - $file = $upload->getFile(); - $file->ShowInSearch = 0; - $file->UserFormUpload = UserFormFileExtension::USER_FORM_UPLOAD_TRUE; - $file->write(); + try { + $result = $upload->loadIntoFile($file, null, $foldername); - $submittedField->UploadedFileID = $file->ID; - } catch (ValidationException $e) { + /** @var AssetContainer|File $fileObj */ + $fileObj = $upload->getFile(); - } + if ($result && $fileObj) { + $fileObj->ShowInSearch = 0; + $fileObj->UserFormUpload = UserFormFileExtension::USER_FORM_UPLOAD_TRUE; + $fileObj->write(); + + $submittedField->UploadedFileID = $fileObj->ID; + } else { + throw new Exception('Could not upload files: %s', implode($upload->getErrors())); } + } catch (ValidationException $e) { + Injector::inst()->get(LoggerInterface::class)->error($e); } }