10
10
use SilverStripe \Control \Director ;
11
11
use SilverStripe \Control \Controller ;
12
12
use SilverStripe \Forms \FormField ;
13
+ use SilverStripe \Forms \HiddenField ;
13
14
use SilverStripe \Security \SecurityToken ;
14
15
use SilverStripe \Core \Injector \Injector ;
15
16
use SilverStripe \Control \HTTPResponse ;
@@ -36,6 +37,9 @@ class ManyField extends CompositeField
36
37
protected $ canAdd = true ;
37
38
38
39
/**
40
+ * Can records be removed from the list - useful for displaying just an
41
+ * inline edit form.
42
+ *
39
43
* @var boolean
40
44
*/
41
45
protected $ canRemove = true ;
@@ -55,6 +59,16 @@ class ManyField extends CompositeField
55
59
*/
56
60
protected $ addLabel = 'Add ' ;
57
61
62
+ /**
63
+ * Does creating a new row automatically call write to the database?
64
+ *
65
+ * If you use things such as UploadField which requires an ID then it is
66
+ * best to set this to true
67
+ *
68
+ * @var boolean
69
+ */
70
+ protected $ callWriteOnNewRow = false ;
71
+
58
72
/**
59
73
* @var array
60
74
*/
@@ -80,20 +94,27 @@ public function __construct($name, $children = null) {
80
94
}
81
95
82
96
$ this ->children = new FieldList ();
97
+
83
98
$ this ->brokenOnConstruct = false ;
84
99
85
100
FormField::__construct ($ name , null );
86
101
}
87
102
88
103
/**
89
- * A callback to customise a given form field instance. Must take 3
90
- * arguments `$field, $index, $manyField`.
104
+ * A callback to customise a given form field instance. Must take 4
105
+ * arguments `$field, $index, $manyField, $value `.
91
106
*
92
107
* @param string $field
93
108
* @param callable $callback
94
109
*/
95
110
public function addFieldCallback ($ field , $ callback ) {
96
- $ this ->fieldCallbacks [$ field ] = $ callback ;
111
+ if (!isset ($ this ->fieldCallbacks [$ field ])) {
112
+ $ this ->fieldCallbacks [$ field ] = [];
113
+ }
114
+
115
+ $ this ->fieldCallbacks [$ field ][] = $ callback ;
116
+
117
+ return $ this ;
97
118
}
98
119
99
120
/**
@@ -214,6 +235,18 @@ public function hasData()
214
235
return true ;
215
236
}
216
237
238
+ /**
239
+ * @param boolean $bool
240
+ *
241
+ * @return $this
242
+ */
243
+ public function setCallWriteOnNewRow ($ bool )
244
+ {
245
+ $ this ->callWriteOnNewRow = $ bool ;
246
+
247
+ return $ this ;
248
+ }
249
+
217
250
/**
218
251
* Set the field value.
219
252
*
@@ -276,7 +309,7 @@ public function setValue($value, $data = null)
276
309
}
277
310
}
278
311
279
- parent ::setValue ($ value , $ data );
312
+ return parent ::setValue ($ value , $ data );
280
313
}
281
314
282
315
/**
@@ -290,7 +323,6 @@ public function FieldList() {
290
323
$ index = 0 ;
291
324
292
325
if ($ this ->value ) {
293
-
294
326
foreach ($ this ->value as $ record ) {
295
327
$ output ->push ($ this ->generateRow ($ index ++, $ record ));
296
328
}
@@ -315,13 +347,25 @@ public function generateRow($index, $value = null)
315
347
$ row = CompositeField::create ();
316
348
$ row ->addExtraClass ("row manyfield__row " );
317
349
350
+ if (!$ value && $ this ->callWriteOnNewRow ) {
351
+ // create a new value
352
+ $ value = $ this ->createPhysicalRecord ();
353
+ }
354
+
318
355
foreach ($ this ->manyChildren as $ child ) {
319
356
$ field = clone $ child ;
320
357
$ field ->name = $ this ->name . '[ ' .$ child ->name . '][ ' . $ index . '] ' ;
321
- $ field ->setValue (($ value ) ? $ value ->{$ child ->name } : null );
358
+
359
+ if ($ value && $ value ->hasMethod ($ child ->Name )) {
360
+ $ field ->setValue ($ value ->{$ child ->name }());
361
+ } else {
362
+ $ field ->setValue (($ value ) ? $ value ->{$ child ->name } : null );
363
+ }
322
364
323
365
if (isset ($ this ->fieldCallbacks [$ child ->name ])) {
324
- call_user_func ($ this ->fieldCallbacks [$ name ], $ field , $ index , $ this );
366
+ foreach ($ this ->fieldCallbacks [$ child ->name ] as $ cb ) {
367
+ call_user_func ($ cb , $ field , $ index , $ this , $ value );
368
+ }
325
369
}
326
370
327
371
$ row ->push ($ field );
@@ -332,6 +376,16 @@ public function generateRow($index, $value = null)
332
376
return $ row ;
333
377
}
334
378
379
+ public function createPhysicalRecord ()
380
+ {
381
+ $ create = Injector::inst ()->create ($ this ->value ->dataClass ());
382
+ $ create ->write ();
383
+
384
+ $ this ->value ->add ($ create );
385
+
386
+ return $ create ;
387
+ }
388
+
335
389
public function AbsoluteLink ($ action = null )
336
390
{
337
391
return Director::absoluteURL ($ this ->Link ($ action ));
@@ -349,7 +403,7 @@ public function updateRelation(DataObjectInterface $record, $delete = true)
349
403
$ removed = [];
350
404
351
405
// if no value then we should clear everything out
352
- if (!$ this ->value ) {
406
+ if (!$ this ->value && $ this -> canRemove ) {
353
407
if ($ delete ) {
354
408
foreach ($ existing as $ row ) {
355
409
$ row ->delete ();
@@ -366,12 +420,14 @@ public function updateRelation(DataObjectInterface $record, $delete = true)
366
420
throw new Exception ('Missing ID field in ManyMany field list. ' );
367
421
}
368
422
369
- if (!isset ($ this ->value ['ID ' ][$ row ->ID ])) {
370
- // missing so delete or remove.
371
- if ($ delete ) {
372
- $ existing ->find ('ID ' , $ row ->ID )->delete ();
373
- } else {
374
- $ existing ->removeById ($ row ->ID );
423
+ if ($ this ->canRemove ) {
424
+ if (!isset ($ this ->value ['ID ' ][$ row ->ID ])) {
425
+ // missing so delete or remove.
426
+ if ($ delete ) {
427
+ $ existing ->find ('ID ' , $ row ->ID )->delete ();
428
+ } else {
429
+ $ existing ->removeById ($ row ->ID );
430
+ }
375
431
}
376
432
}
377
433
}
0 commit comments