Skip to content

Commit 4ffc651

Browse files
committed
feat: add UserDefinedForm field for integration
1 parent 454f8b1 commit 4ffc651

File tree

4 files changed

+404
-2
lines changed

4 files changed

+404
-2
lines changed

src/EditableManyField.php

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
<?php
2+
3+
namespace FullscreenInteractive\ManyField;
4+
5+
use Dotenv\Exception\ValidationException;
6+
use SilverStripe\Forms\GridField\GridField;
7+
use FullscreenInteractive\ManyField\ManyField;
8+
use SilverStripe\Assets\Upload;
9+
use SilverStripe\Forms\FieldList;
10+
use SilverStripe\Forms\GridField\GridFieldButtonRow;
11+
use SilverStripe\Forms\GridField\GridFieldConfig;
12+
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
13+
use SilverStripe\Forms\GridField\GridFieldDetailForm;
14+
use SilverStripe\Forms\GridField\GridFieldEditButton;
15+
use SilverStripe\Forms\GridField\GridFieldPaginator;
16+
use SilverStripe\Forms\GridField\GridFieldToolbarHeader;
17+
use SilverStripe\UserForms\Extension\UserFormFileExtension;
18+
use SilverStripe\UserForms\Form\GridFieldAddClassesButton;
19+
use SilverStripe\UserForms\Model\EditableFormField;
20+
use SilverStripe\UserForms\Model\EditableFormField\EditableFileField;
21+
use SilverStripe\UserForms\Model\EditableFormField\EditableTextField;
22+
use Symbiote\GridFieldExtensions\GridFieldEditableColumns;
23+
use Symbiote\GridFieldExtensions\GridFieldOrderableRows;
24+
25+
if (class_exists(EditableFormField::class)) {
26+
return;
27+
}
28+
29+
class EditableManyField extends EditableFormField
30+
{
31+
private static $singular_name = 'Repeater Field';
32+
33+
private static $plural_name = 'Repeater Fields';
34+
35+
private static $db = [];
36+
37+
private static $table_name = 'EditableManyField';
38+
39+
private static $many_many = [
40+
'Children' => EditableFormField::class
41+
];
42+
43+
private static $owns = [
44+
'Children'
45+
];
46+
47+
private static $cascade_deletes = [
48+
'Children'
49+
];
50+
51+
private static $cascade_duplicates = [
52+
'Children'
53+
];
54+
55+
/**
56+
* @return FieldList
57+
*/
58+
public function getCMSFields()
59+
{
60+
$this->beforeUpdateCMSFields(function (FieldList $fields) {
61+
$editableColumns = new GridFieldEditableColumns();
62+
$fieldClasses = singleton(EditableFormField::class)->getEditableFieldClasses();
63+
$editableColumns->setDisplayFields([
64+
'ClassName' => function ($record, $column, $grid) use ($fieldClasses) {
65+
if ($record instanceof EditableFormField) {
66+
$field = $record->getInlineClassnameField($column, $fieldClasses);
67+
if ($record instanceof EditableFileField) {
68+
$field->setAttribute('data-folderconfirmed', $record->FolderConfirmed ? 1 : 0);
69+
}
70+
return $field;
71+
}
72+
},
73+
'Title' => function ($record, $column, $grid) {
74+
if ($record instanceof EditableFormField) {
75+
return $record->getInlineTitleField($column);
76+
}
77+
}
78+
]);
79+
80+
$config = GridFieldConfig::create()
81+
->addComponents(
82+
$editableColumns,
83+
new GridFieldButtonRow(),
84+
(new GridFieldAddClassesButton(EditableTextField::class))
85+
->setButtonName(_t(__CLASS__ . '.ADD_FIELD', 'Add Field'))
86+
->setButtonClass('btn-primary'),
87+
(new GridFieldAddClassesButton(EditableFormStep::class))
88+
->setButtonName(_t(__CLASS__ . '.ADD_PAGE_BREAK', 'Add Page Break'))
89+
->setButtonClass('btn-secondary'),
90+
(new GridFieldAddClassesButton([EditableFieldGroup::class, EditableFieldGroupEnd::class]))
91+
->setButtonName(_t(__CLASS__ . '.ADD_FIELD_GROUP', 'Add Field Group'))
92+
->setButtonClass('btn-secondary'),
93+
$editButton = new GridFieldEditButton(),
94+
new GridFieldDeleteAction(),
95+
new GridFieldToolbarHeader(),
96+
new GridFieldOrderableRows('Sort'),
97+
new GridFieldDetailForm(),
98+
// Betterbuttons prev and next is enabled by adding a GridFieldPaginator component
99+
new GridFieldPaginator(999)
100+
);
101+
102+
$fields->addFieldsToTab('Root.Main', [
103+
GridField::create(
104+
'Children',
105+
'Children',
106+
$this->Children(),
107+
$config
108+
)
109+
]);
110+
});
111+
112+
return parent::getCMSFields();
113+
}
114+
115+
/**
116+
* Return the form field
117+
*
118+
*/
119+
public function getFormField()
120+
{
121+
$children = [];
122+
foreach ($this->Children() as $editableFormField) {
123+
$children[] = $editableFormField->getFormField();
124+
}
125+
126+
$field = ManyField::create($this->Name, FieldList::create($children))
127+
->setCanSort(false)
128+
->setMinRecords(1);
129+
130+
$this->doUpdateFormField($field);
131+
132+
return $field;
133+
}
134+
135+
136+
public function getSubmittedFormField(): SubmittedManyFormField
137+
{
138+
return SubmittedManyFormField::create();
139+
}
140+
141+
142+
/**
143+
* When saving this data from the front end, extract the array and
144+
* create the children records
145+
*/
146+
public function getValueFromData($data)
147+
{
148+
$incoming = isset($data[$this->Name]) ? $data[$this->Name] : false;
149+
150+
if (!$incoming) {
151+
return json_encode([]);
152+
}
153+
154+
// unset any rows which don't have any values at all
155+
$rowHasValue = [];
156+
157+
foreach ($this->Children() as $field)
158+
{
159+
foreach ($incoming[$field->Name] as $i => $value) {
160+
if ($value && !empty($value)) {
161+
$rowHasValue[$i] = true;
162+
}
163+
}
164+
}
165+
166+
$rows = [];
167+
168+
foreach ($this->Children() as $field)
169+
{
170+
foreach ($incoming[$field->Name] as $i => $value) {
171+
if (!isset($rowHasValue[$i])) {
172+
// empty row;
173+
continue;
174+
}
175+
176+
if (!isset($rows[$i])) {
177+
$rows[$i] = [];
178+
}
179+
180+
$submittedField = $this->createNestedSubmittedFormField($field, [
181+
$field->Name => $value
182+
]);
183+
184+
$rows[$i][$field->Name] = $submittedField->ID;
185+
}
186+
}
187+
188+
return json_encode($rows);
189+
}
190+
191+
192+
public function createNestedSubmittedFormField(EditableFormField $field, $data)
193+
{
194+
$submittedField = $field->getSubmittedFormField();
195+
$submittedField->Name = $field->Name;
196+
$submittedField->Title = $field->getField('Title');
197+
198+
// save the value from the data
199+
if ($field->hasMethod('getValueFromData')) {
200+
$submittedField->Value = $field->getValueFromData($data);
201+
} else {
202+
if (isset($data[$field->Name])) {
203+
$submittedField->Value = $data[$field->Name];
204+
}
205+
}
206+
207+
if (!empty($data[$field->Name])) {
208+
if (in_array(EditableFileField::class, $field->getClassAncestry())) {
209+
if (!empty($_FILES[$field->Name]['name'])) {
210+
$foldername = $field->getFormField()->getFolderName();
211+
$upload = Upload::create();
212+
213+
try {
214+
$upload->loadIntoFile($_FILES[$field->Name], null, $foldername);
215+
216+
/** @var AssetContainer|File $file */
217+
$file = $upload->getFile();
218+
$file->ShowInSearch = 0;
219+
$file->UserFormUpload = UserFormFileExtension::USER_FORM_UPLOAD_TRUE;
220+
$file->write();
221+
222+
$submittedField->UploadedFileID = $file->ID;
223+
} catch (ValidationException $e) {
224+
225+
}
226+
}
227+
}
228+
}
229+
230+
$submittedField->extend('onPopulationFromField', $field);
231+
$submittedField->write();
232+
233+
return $submittedField;
234+
}
235+
}

src/ManyField.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ protected function updateManyNestedField($field, $index, $value, $prefixName) {
610610
}
611611
}
612612
} else {
613-
if ($value && $value->hasMethod($name)) {
613+
if ($value && is_object($value) && $value->hasMethod($name)) {
614614
$field->setValue($value->{$name}(), $value);
615615
} else if (is_object($value)) {
616616
$field->setValue($value->{$name}, $value);
@@ -660,7 +660,7 @@ public function generateRow($index, $value = null, $prefixName = true)
660660
$field = $field->setReadonly($this->readonly);
661661
$field = $field->setDisabled($this->readonly);
662662

663-
if ($value && $value->hasMethod('modifyManyRecordField')) {
663+
if ($value && is_object($value) && $value->hasMethod('modifyManyRecordField')) {
664664
$field = $value->modifyManyRecordField($field);
665665
}
666666

0 commit comments

Comments
 (0)