Completed
Push — master ( 5bf4b2...b5ca87 )
by Robbie
28s queued 25s
created
src/TagField.php 1 patch
Indentation   +456 added lines, -456 removed lines patch added patch discarded remove patch
@@ -24,460 +24,460 @@
 block discarded – undo
24 24
  */
25 25
 class TagField extends DropdownField
26 26
 {
27
-    /**
28
-     * @var array
29
-     */
30
-    private static $allowed_actions = [
31
-        'suggest',
32
-    ];
33
-
34
-    /**
35
-     * @var bool
36
-     */
37
-    protected $shouldLazyLoad = false;
38
-
39
-    /**
40
-     * @var int
41
-     */
42
-    protected $lazyLoadItemLimit = 10;
43
-
44
-    /**
45
-     * @var bool
46
-     */
47
-    protected $canCreate = true;
48
-
49
-    /**
50
-     * @var string
51
-     */
52
-    protected $titleField = 'Title';
53
-
54
-    /**
55
-     * @var DataList
56
-     */
57
-    protected $sourceList;
58
-
59
-    /**
60
-     * @var bool
61
-     */
62
-    protected $isMultiple = true;
63
-
64
-    /**
65
-     * @param string $name
66
-     * @param string $title
67
-     * @param null|DataList $source
68
-     * @param null|DataList $value
69
-     * @param string $titleField
70
-     */
71
-    public function __construct($name, $title = '', $source = [], $value = null, $titleField = 'Title')
72
-    {
73
-        $this->setSourceList($source);
74
-        $this->setTitleField($titleField);
75
-        parent::__construct($name, $title, $source, $value);
76
-    }
77
-
78
-    /**
79
-     * @return bool
80
-     */
81
-    public function getShouldLazyLoad()
82
-    {
83
-        return $this->shouldLazyLoad;
84
-    }
85
-
86
-    /**
87
-     * @param bool $shouldLazyLoad
88
-     *
89
-     * @return static
90
-     */
91
-    public function setShouldLazyLoad($shouldLazyLoad)
92
-    {
93
-        $this->shouldLazyLoad = $shouldLazyLoad;
94
-
95
-        return $this;
96
-    }
97
-
98
-    /**
99
-     * @return int
100
-     */
101
-    public function getLazyLoadItemLimit()
102
-    {
103
-        return $this->lazyLoadItemLimit;
104
-    }
105
-
106
-    /**
107
-     * @param int $lazyLoadItemLimit
108
-     *
109
-     * @return static
110
-     */
111
-    public function setLazyLoadItemLimit($lazyLoadItemLimit)
112
-    {
113
-        $this->lazyLoadItemLimit = $lazyLoadItemLimit;
114
-
115
-        return $this;
116
-    }
117
-
118
-    /**
119
-     * @return bool
120
-     */
121
-    public function getIsMultiple()
122
-    {
123
-        return $this->isMultiple;
124
-    }
125
-
126
-    /**
127
-     * @param bool $isMultiple
128
-     *
129
-     * @return static
130
-     */
131
-    public function setIsMultiple($isMultiple)
132
-    {
133
-        $this->isMultiple = $isMultiple;
134
-
135
-        return $this;
136
-    }
137
-
138
-    /**
139
-     * @return bool
140
-     */
141
-    public function getCanCreate()
142
-    {
143
-        return $this->canCreate;
144
-    }
145
-
146
-    /**
147
-     * @param bool $canCreate
148
-     *
149
-     * @return static
150
-     */
151
-    public function setCanCreate($canCreate)
152
-    {
153
-        $this->canCreate = $canCreate;
154
-
155
-        return $this;
156
-    }
157
-
158
-    /**
159
-     * @return string
160
-     */
161
-    public function getTitleField()
162
-    {
163
-        return $this->titleField;
164
-    }
165
-
166
-    /**
167
-     * @param string $titleField
168
-     *
169
-     * @return $this
170
-     */
171
-    public function setTitleField($titleField)
172
-    {
173
-        $this->titleField = $titleField;
174
-
175
-        return $this;
176
-    }
177
-
178
-    /**
179
-     * Get the DataList source. The 4.x upgrade for SelectField::setSource starts to convert this to an array
180
-     * @return DataList
181
-     */
182
-    public function getSourceList()
183
-    {
184
-        return $this->sourceList;
185
-    }
186
-
187
-    /**
188
-     * Set the model class name for tags
189
-     * @param  DataList $className
190
-     * @return self
191
-     */
192
-    public function setSourceList($sourceList)
193
-    {
194
-        $this->sourceList = $sourceList;
195
-        return $this;
196
-    }
197
-
198
-    /**
199
-     * {@inheritdoc}
200
-     */
201
-    public function Field($properties = [])
202
-    {
203
-        $this->addExtraClass('ss-tag-field');
204
-
205
-        return $this->customise($properties)->renderWith(self::class);
206
-    }
207
-
208
-    /**
209
-     * Provide TagField data to the JSON schema for the frontend component
210
-     *
211
-     * @return array
212
-     */
213
-    public function getSchemaDataDefaults()
214
-    {
215
-        $schema = array_merge(
216
-            parent::getSchemaDataDefaults(),
217
-            [
218
-                'name' => $this->getName() . '[]',
219
-                'lazyLoad' => $this->getShouldLazyLoad(),
220
-                'creatable' => $this->getCanCreate(),
221
-                'multi' => $this->getIsMultiple(),
222
-                'value' => $this->Value(),
223
-                'disabled' => $this->isDisabled() || $this->isReadonly(),
224
-            ]
225
-        );
226
-
227
-        if (!$this->getShouldLazyLoad()) {
228
-            $schema['options'] = array_values($this->getOptions()->toNestedArray());
229
-        } else {
230
-            if ($this->Value()) {
231
-                $schema['value'] = $this->getOptions(true)->toNestedArray();
232
-            }
233
-            $schema['optionUrl'] = $this->getSuggestURL();
234
-        }
235
-
236
-        return $schema;
237
-    }
238
-
239
-    /**
240
-     * When not used in a React form factory context, this adds the schema data to SilverStripe template
241
-     * rendered attributes lists
242
-     *
243
-     * @return array
244
-     */
245
-    public function getAttributes()
246
-    {
247
-        $attributes = parent::getAttributes();
248
-        $attributes['data-schema'] = json_encode($this->getSchemaData());
249
-        return $attributes;
250
-    }
251
-
252
-    /**
253
-     * @return string
254
-     */
255
-    protected function getSuggestURL()
256
-    {
257
-        return Controller::join_links($this->Link(), 'suggest');
258
-    }
259
-
260
-    /**
261
-     * @param bool $onlySelected Only return options that are selected
262
-     * @return ArrayList
263
-     */
264
-    protected function getOptions($onlySelected = false)
265
-    {
266
-        $source = $this->getSourceList();
267
-
268
-        if (!$source) {
269
-            $source = ArrayList::create();
270
-        }
271
-
272
-        $dataClass = $source->dataClass();
273
-        $titleField = $this->getTitleField();
274
-        $values = $this->Value();
275
-
276
-        if ($values) {
277
-            if (is_array($values)) {
278
-                $values = $source->filter($titleField, $values);
279
-            }
280
-        }
281
-        if ($onlySelected) {
282
-            $source = $values;
283
-        }
284
-
285
-        return $source instanceof DataList ? $this->formatOptions($source) : ArrayList::create();
286
-    }
287
-
288
-    /**
289
-     * @param DataList $source
290
-     * @return ArrayList
291
-     */
292
-    protected function formatOptions(DataList $source)
293
-    {
294
-        $options = ArrayList::create();
295
-        $titleField = $this->getTitleField();
296
-
297
-        foreach ($source as $object) {
298
-            $options->push(
299
-                ArrayData::create([
300
-                    'Title' => $object->$titleField,
301
-                    'Value' => $object->Title,
302
-                ])
303
-            );
304
-        }
305
-
306
-        return $options;
307
-    }
308
-
309
-    /**
310
-     * {@inheritdoc}
311
-     */
312
-    public function setValue($value, $source = null)
313
-    {
314
-        if ($source instanceof DataObject) {
315
-            $name = $this->getName();
316
-
317
-            if ($source->hasMethod($name)) {
318
-                $value = $source->$name()->column($this->getTitleField());
319
-            }
320
-        } elseif ($value instanceof SS_List) {
321
-            $value = $value->column($this->getTitleField());
322
-        }
323
-
324
-        if (!is_array($value)) {
325
-            return parent::setValue($value);
326
-        }
327
-
328
-        return parent::setValue(array_filter($value));
329
-    }
330
-
331
-    /**
332
-     * {@inheritdoc}
333
-     */
334
-    public function saveInto(DataObjectInterface $record)
335
-    {
336
-        parent::saveInto($record);
337
-
338
-        $name = $this->getName();
339
-        $titleField = $this->getTitleField();
340
-        $values = $this->Value();
341
-        $relation = $record->$name();
342
-        $ids = [];
343
-
344
-        if (!$values) {
345
-            $values = [];
346
-        }
347
-        if (empty($record) || empty($titleField)) {
348
-            return;
349
-        }
350
-
351
-        if (!$record->hasMethod($name)) {
352
-            throw new Exception(
353
-                sprintf("%s does not have a %s method", get_class($record), $name)
354
-            );
355
-        }
356
-
357
-        foreach ($values as $key => $value) {
358
-            // Get or create record
359
-            $record = $this->getOrCreateTag($value);
360
-            if ($record) {
361
-                $ids[] = $record->ID;
362
-                $values[$key] = $record->Title;
363
-            }
364
-        }
365
-
366
-        $relation->setByIDList(array_filter($ids));
367
-    }
368
-
369
-    /**
370
-     * Get or create tag with the given value
371
-     *
372
-     * @param  string $term
373
-     * @return DataObject|bool
374
-     */
375
-    protected function getOrCreateTag($term)
376
-    {
377
-        // Check if existing record can be found
378
-        $source = $this->getSourceList();
379
-        $titleField = $this->getTitleField();
380
-        $record = $source
381
-            ->filter($titleField, $term)
382
-            ->first();
383
-        if ($record) {
384
-            return $record;
385
-        }
386
-
387
-        // Create new instance if not yet saved
388
-        if ($this->getCanCreate()) {
389
-            $dataClass = $source->dataClass();
390
-            $record = Injector::inst()->create($dataClass);
391
-            $record->{$titleField} = $term;
392
-            $record->write();
393
-            if ($source instanceof SS_List) {
394
-                $source->add($record);
395
-            }
396
-            return $record;
397
-        }
398
-
399
-        return false;
400
-    }
401
-
402
-    /**
403
-     * Returns a JSON string of tags, for lazy loading.
404
-     *
405
-     * @param  HTTPRequest $request
406
-     * @return HTTPResponse
407
-     */
408
-    public function suggest(HTTPRequest $request)
409
-    {
410
-        $tags = $this->getTags($request->getVar('term'));
411
-
412
-        $response = HTTPResponse::create();
413
-        $response->addHeader('Content-Type', 'application/json');
414
-        $response->setBody(json_encode(['items' => $tags]));
415
-
416
-        return $response;
417
-    }
418
-
419
-    /**
420
-     * Returns array of arrays representing tags.
421
-     *
422
-     * @param  string $term
423
-     * @return array
424
-     */
425
-    protected function getTags($term)
426
-    {
427
-        $source = $this->getSourceList();
428
-
429
-        $titleField = $this->getTitleField();
430
-
431
-        $query = $source
432
-            ->filter($titleField . ':PartialMatch:nocase', $term)
433
-            ->sort($titleField)
434
-            ->limit($this->getLazyLoadItemLimit());
435
-
436
-        // Map into a distinct list
437
-        $items = [];
438
-        $titleField = $this->getTitleField();
439
-        foreach ($query->map('ID', $titleField) as $id => $title) {
440
-            $items[$title] = [
441
-                'id' => $title,
442
-                'text' => $title,
443
-            ];
444
-        }
445
-
446
-        return array_values($items);
447
-    }
448
-
449
-    /**
450
-     * DropdownField assumes value will be a scalar so we must
451
-     * override validate. This only applies to Silverstripe 3.2+
452
-     *
453
-     * @param Validator $validator
454
-     * @return bool
455
-     */
456
-    public function validate($validator)
457
-    {
458
-        return true;
459
-    }
460
-
461
-    /**
462
-     * Converts the field to a readonly variant.
463
-     *
464
-     * @return ReadonlyTagField
465
-     */
466
-    public function performReadonlyTransformation()
467
-    {
468
-        /** @var ReadonlyTagField $copy */
469
-        $copy = $this->castedCopy(ReadonlyTagField::class);
470
-        $copy->setSourceList($this->getSourceList());
471
-        return $copy;
472
-    }
473
-
474
-    /**
475
-     * Prevent the default, which would return "tag"
476
-     *
477
-     * @return string
478
-     */
479
-    public function Type()
480
-    {
481
-        return '';
482
-    }
27
+	/**
28
+	 * @var array
29
+	 */
30
+	private static $allowed_actions = [
31
+		'suggest',
32
+	];
33
+
34
+	/**
35
+	 * @var bool
36
+	 */
37
+	protected $shouldLazyLoad = false;
38
+
39
+	/**
40
+	 * @var int
41
+	 */
42
+	protected $lazyLoadItemLimit = 10;
43
+
44
+	/**
45
+	 * @var bool
46
+	 */
47
+	protected $canCreate = true;
48
+
49
+	/**
50
+	 * @var string
51
+	 */
52
+	protected $titleField = 'Title';
53
+
54
+	/**
55
+	 * @var DataList
56
+	 */
57
+	protected $sourceList;
58
+
59
+	/**
60
+	 * @var bool
61
+	 */
62
+	protected $isMultiple = true;
63
+
64
+	/**
65
+	 * @param string $name
66
+	 * @param string $title
67
+	 * @param null|DataList $source
68
+	 * @param null|DataList $value
69
+	 * @param string $titleField
70
+	 */
71
+	public function __construct($name, $title = '', $source = [], $value = null, $titleField = 'Title')
72
+	{
73
+		$this->setSourceList($source);
74
+		$this->setTitleField($titleField);
75
+		parent::__construct($name, $title, $source, $value);
76
+	}
77
+
78
+	/**
79
+	 * @return bool
80
+	 */
81
+	public function getShouldLazyLoad()
82
+	{
83
+		return $this->shouldLazyLoad;
84
+	}
85
+
86
+	/**
87
+	 * @param bool $shouldLazyLoad
88
+	 *
89
+	 * @return static
90
+	 */
91
+	public function setShouldLazyLoad($shouldLazyLoad)
92
+	{
93
+		$this->shouldLazyLoad = $shouldLazyLoad;
94
+
95
+		return $this;
96
+	}
97
+
98
+	/**
99
+	 * @return int
100
+	 */
101
+	public function getLazyLoadItemLimit()
102
+	{
103
+		return $this->lazyLoadItemLimit;
104
+	}
105
+
106
+	/**
107
+	 * @param int $lazyLoadItemLimit
108
+	 *
109
+	 * @return static
110
+	 */
111
+	public function setLazyLoadItemLimit($lazyLoadItemLimit)
112
+	{
113
+		$this->lazyLoadItemLimit = $lazyLoadItemLimit;
114
+
115
+		return $this;
116
+	}
117
+
118
+	/**
119
+	 * @return bool
120
+	 */
121
+	public function getIsMultiple()
122
+	{
123
+		return $this->isMultiple;
124
+	}
125
+
126
+	/**
127
+	 * @param bool $isMultiple
128
+	 *
129
+	 * @return static
130
+	 */
131
+	public function setIsMultiple($isMultiple)
132
+	{
133
+		$this->isMultiple = $isMultiple;
134
+
135
+		return $this;
136
+	}
137
+
138
+	/**
139
+	 * @return bool
140
+	 */
141
+	public function getCanCreate()
142
+	{
143
+		return $this->canCreate;
144
+	}
145
+
146
+	/**
147
+	 * @param bool $canCreate
148
+	 *
149
+	 * @return static
150
+	 */
151
+	public function setCanCreate($canCreate)
152
+	{
153
+		$this->canCreate = $canCreate;
154
+
155
+		return $this;
156
+	}
157
+
158
+	/**
159
+	 * @return string
160
+	 */
161
+	public function getTitleField()
162
+	{
163
+		return $this->titleField;
164
+	}
165
+
166
+	/**
167
+	 * @param string $titleField
168
+	 *
169
+	 * @return $this
170
+	 */
171
+	public function setTitleField($titleField)
172
+	{
173
+		$this->titleField = $titleField;
174
+
175
+		return $this;
176
+	}
177
+
178
+	/**
179
+	 * Get the DataList source. The 4.x upgrade for SelectField::setSource starts to convert this to an array
180
+	 * @return DataList
181
+	 */
182
+	public function getSourceList()
183
+	{
184
+		return $this->sourceList;
185
+	}
186
+
187
+	/**
188
+	 * Set the model class name for tags
189
+	 * @param  DataList $className
190
+	 * @return self
191
+	 */
192
+	public function setSourceList($sourceList)
193
+	{
194
+		$this->sourceList = $sourceList;
195
+		return $this;
196
+	}
197
+
198
+	/**
199
+	 * {@inheritdoc}
200
+	 */
201
+	public function Field($properties = [])
202
+	{
203
+		$this->addExtraClass('ss-tag-field');
204
+
205
+		return $this->customise($properties)->renderWith(self::class);
206
+	}
207
+
208
+	/**
209
+	 * Provide TagField data to the JSON schema for the frontend component
210
+	 *
211
+	 * @return array
212
+	 */
213
+	public function getSchemaDataDefaults()
214
+	{
215
+		$schema = array_merge(
216
+			parent::getSchemaDataDefaults(),
217
+			[
218
+				'name' => $this->getName() . '[]',
219
+				'lazyLoad' => $this->getShouldLazyLoad(),
220
+				'creatable' => $this->getCanCreate(),
221
+				'multi' => $this->getIsMultiple(),
222
+				'value' => $this->Value(),
223
+				'disabled' => $this->isDisabled() || $this->isReadonly(),
224
+			]
225
+		);
226
+
227
+		if (!$this->getShouldLazyLoad()) {
228
+			$schema['options'] = array_values($this->getOptions()->toNestedArray());
229
+		} else {
230
+			if ($this->Value()) {
231
+				$schema['value'] = $this->getOptions(true)->toNestedArray();
232
+			}
233
+			$schema['optionUrl'] = $this->getSuggestURL();
234
+		}
235
+
236
+		return $schema;
237
+	}
238
+
239
+	/**
240
+	 * When not used in a React form factory context, this adds the schema data to SilverStripe template
241
+	 * rendered attributes lists
242
+	 *
243
+	 * @return array
244
+	 */
245
+	public function getAttributes()
246
+	{
247
+		$attributes = parent::getAttributes();
248
+		$attributes['data-schema'] = json_encode($this->getSchemaData());
249
+		return $attributes;
250
+	}
251
+
252
+	/**
253
+	 * @return string
254
+	 */
255
+	protected function getSuggestURL()
256
+	{
257
+		return Controller::join_links($this->Link(), 'suggest');
258
+	}
259
+
260
+	/**
261
+	 * @param bool $onlySelected Only return options that are selected
262
+	 * @return ArrayList
263
+	 */
264
+	protected function getOptions($onlySelected = false)
265
+	{
266
+		$source = $this->getSourceList();
267
+
268
+		if (!$source) {
269
+			$source = ArrayList::create();
270
+		}
271
+
272
+		$dataClass = $source->dataClass();
273
+		$titleField = $this->getTitleField();
274
+		$values = $this->Value();
275
+
276
+		if ($values) {
277
+			if (is_array($values)) {
278
+				$values = $source->filter($titleField, $values);
279
+			}
280
+		}
281
+		if ($onlySelected) {
282
+			$source = $values;
283
+		}
284
+
285
+		return $source instanceof DataList ? $this->formatOptions($source) : ArrayList::create();
286
+	}
287
+
288
+	/**
289
+	 * @param DataList $source
290
+	 * @return ArrayList
291
+	 */
292
+	protected function formatOptions(DataList $source)
293
+	{
294
+		$options = ArrayList::create();
295
+		$titleField = $this->getTitleField();
296
+
297
+		foreach ($source as $object) {
298
+			$options->push(
299
+				ArrayData::create([
300
+					'Title' => $object->$titleField,
301
+					'Value' => $object->Title,
302
+				])
303
+			);
304
+		}
305
+
306
+		return $options;
307
+	}
308
+
309
+	/**
310
+	 * {@inheritdoc}
311
+	 */
312
+	public function setValue($value, $source = null)
313
+	{
314
+		if ($source instanceof DataObject) {
315
+			$name = $this->getName();
316
+
317
+			if ($source->hasMethod($name)) {
318
+				$value = $source->$name()->column($this->getTitleField());
319
+			}
320
+		} elseif ($value instanceof SS_List) {
321
+			$value = $value->column($this->getTitleField());
322
+		}
323
+
324
+		if (!is_array($value)) {
325
+			return parent::setValue($value);
326
+		}
327
+
328
+		return parent::setValue(array_filter($value));
329
+	}
330
+
331
+	/**
332
+	 * {@inheritdoc}
333
+	 */
334
+	public function saveInto(DataObjectInterface $record)
335
+	{
336
+		parent::saveInto($record);
337
+
338
+		$name = $this->getName();
339
+		$titleField = $this->getTitleField();
340
+		$values = $this->Value();
341
+		$relation = $record->$name();
342
+		$ids = [];
343
+
344
+		if (!$values) {
345
+			$values = [];
346
+		}
347
+		if (empty($record) || empty($titleField)) {
348
+			return;
349
+		}
350
+
351
+		if (!$record->hasMethod($name)) {
352
+			throw new Exception(
353
+				sprintf("%s does not have a %s method", get_class($record), $name)
354
+			);
355
+		}
356
+
357
+		foreach ($values as $key => $value) {
358
+			// Get or create record
359
+			$record = $this->getOrCreateTag($value);
360
+			if ($record) {
361
+				$ids[] = $record->ID;
362
+				$values[$key] = $record->Title;
363
+			}
364
+		}
365
+
366
+		$relation->setByIDList(array_filter($ids));
367
+	}
368
+
369
+	/**
370
+	 * Get or create tag with the given value
371
+	 *
372
+	 * @param  string $term
373
+	 * @return DataObject|bool
374
+	 */
375
+	protected function getOrCreateTag($term)
376
+	{
377
+		// Check if existing record can be found
378
+		$source = $this->getSourceList();
379
+		$titleField = $this->getTitleField();
380
+		$record = $source
381
+			->filter($titleField, $term)
382
+			->first();
383
+		if ($record) {
384
+			return $record;
385
+		}
386
+
387
+		// Create new instance if not yet saved
388
+		if ($this->getCanCreate()) {
389
+			$dataClass = $source->dataClass();
390
+			$record = Injector::inst()->create($dataClass);
391
+			$record->{$titleField} = $term;
392
+			$record->write();
393
+			if ($source instanceof SS_List) {
394
+				$source->add($record);
395
+			}
396
+			return $record;
397
+		}
398
+
399
+		return false;
400
+	}
401
+
402
+	/**
403
+	 * Returns a JSON string of tags, for lazy loading.
404
+	 *
405
+	 * @param  HTTPRequest $request
406
+	 * @return HTTPResponse
407
+	 */
408
+	public function suggest(HTTPRequest $request)
409
+	{
410
+		$tags = $this->getTags($request->getVar('term'));
411
+
412
+		$response = HTTPResponse::create();
413
+		$response->addHeader('Content-Type', 'application/json');
414
+		$response->setBody(json_encode(['items' => $tags]));
415
+
416
+		return $response;
417
+	}
418
+
419
+	/**
420
+	 * Returns array of arrays representing tags.
421
+	 *
422
+	 * @param  string $term
423
+	 * @return array
424
+	 */
425
+	protected function getTags($term)
426
+	{
427
+		$source = $this->getSourceList();
428
+
429
+		$titleField = $this->getTitleField();
430
+
431
+		$query = $source
432
+			->filter($titleField . ':PartialMatch:nocase', $term)
433
+			->sort($titleField)
434
+			->limit($this->getLazyLoadItemLimit());
435
+
436
+		// Map into a distinct list
437
+		$items = [];
438
+		$titleField = $this->getTitleField();
439
+		foreach ($query->map('ID', $titleField) as $id => $title) {
440
+			$items[$title] = [
441
+				'id' => $title,
442
+				'text' => $title,
443
+			];
444
+		}
445
+
446
+		return array_values($items);
447
+	}
448
+
449
+	/**
450
+	 * DropdownField assumes value will be a scalar so we must
451
+	 * override validate. This only applies to Silverstripe 3.2+
452
+	 *
453
+	 * @param Validator $validator
454
+	 * @return bool
455
+	 */
456
+	public function validate($validator)
457
+	{
458
+		return true;
459
+	}
460
+
461
+	/**
462
+	 * Converts the field to a readonly variant.
463
+	 *
464
+	 * @return ReadonlyTagField
465
+	 */
466
+	public function performReadonlyTransformation()
467
+	{
468
+		/** @var ReadonlyTagField $copy */
469
+		$copy = $this->castedCopy(ReadonlyTagField::class);
470
+		$copy->setSourceList($this->getSourceList());
471
+		return $copy;
472
+	}
473
+
474
+	/**
475
+	 * Prevent the default, which would return "tag"
476
+	 *
477
+	 * @return string
478
+	 */
479
+	public function Type()
480
+	{
481
+		return '';
482
+	}
483 483
 }
Please login to merge, or discard this patch.