Passed
Push — master ( b4f0a0...3f9085 )
by
unknown
04:22 queued 10s
created
src/StringTagField.php 2 patches
Indentation   +320 added lines, -320 removed lines patch added patch discarded remove patch
@@ -26,324 +26,324 @@
 block discarded – undo
26 26
  */
27 27
 class StringTagField extends DropdownField
28 28
 {
29
-    /**
30
-     * @var array
31
-     */
32
-    private static $allowed_actions = [
33
-        'suggest',
34
-    ];
35
-
36
-    /**
37
-     * @var bool
38
-     */
39
-    protected $shouldLazyLoad = false;
40
-
41
-    /**
42
-     * @var int
43
-     */
44
-    protected $lazyLoadItemLimit = 10;
45
-
46
-    /**
47
-     * @var bool
48
-     */
49
-    protected $canCreate = true;
50
-
51
-    /**
52
-     * @var null|DataObject
53
-     */
54
-    protected $record;
55
-
56
-    /**
57
-     * @var bool
58
-     */
59
-    protected $isMultiple = true;
60
-
61
-    /**
62
-     * @return bool
63
-     */
64
-    public function getShouldLazyLoad()
65
-    {
66
-        return $this->shouldLazyLoad;
67
-    }
68
-
69
-    /**
70
-     * @param bool $shouldLazyLoad
71
-     * @return $this
72
-     */
73
-    public function setShouldLazyLoad($shouldLazyLoad)
74
-    {
75
-        $this->shouldLazyLoad = $shouldLazyLoad;
76
-
77
-        return $this;
78
-    }
79
-
80
-    /**
81
-     * @return int
82
-     */
83
-    public function getLazyLoadItemLimit()
84
-    {
85
-        return $this->lazyLoadItemLimit;
86
-    }
87
-
88
-    /**
89
-     * @param int $lazyLoadItemLimit
90
-     * @return $this
91
-     */
92
-    public function setLazyLoadItemLimit($lazyLoadItemLimit)
93
-    {
94
-        $this->lazyLoadItemLimit = $lazyLoadItemLimit;
95
-
96
-        return $this;
97
-    }
98
-
99
-    /**
100
-     * @return bool
101
-     */
102
-    public function getIsMultiple()
103
-    {
104
-        return $this->isMultiple;
105
-    }
106
-
107
-    /**
108
-     * @param bool $isMultiple
109
-     * @return $this
110
-     */
111
-    public function setIsMultiple($isMultiple)
112
-    {
113
-        $this->isMultiple = $isMultiple;
114
-
115
-        return $this;
116
-    }
117
-
118
-    /**
119
-     * @return null|DataObject
120
-     */
121
-    public function getRecord()
122
-    {
123
-        if ($this->record) {
124
-            return $this->record;
125
-        }
126
-
127
-        if ($form = $this->getForm()) {
128
-            return $form->getRecord();
129
-        }
130
-
131
-        return null;
132
-    }
133
-
134
-    /**
135
-     * @param DataObject $record
136
-     * @return $this
137
-     */
138
-    public function setRecord(DataObject $record)
139
-    {
140
-        $this->record = $record;
141
-
142
-        return $this;
143
-    }
144
-
145
-    public function Field($properties = [])
146
-    {
147
-        $this->addExtraClass('ss-tag-field');
148
-
149
-        return $this
150
-            ->customise($properties)
151
-            ->renderWith(TagField::class);
152
-    }
153
-
154
-    /**
155
-     * Provide TagField data to the JSON schema for the frontend component
156
-     *
157
-     * @return array
158
-     */
159
-    public function getSchemaDataDefaults()
160
-    {
161
-        $schema = array_merge(
162
-            parent::getSchemaDataDefaults(),
163
-            [
164
-                'name' => $this->getName() . '[]',
165
-                'lazyLoad' => $this->getShouldLazyLoad(),
166
-                'creatable' => $this->getCanCreate(),
167
-                'multi' => $this->getIsMultiple(),
168
-                'value' => $this->formatOptions($this->Value()),
169
-                'disabled' => $this->isDisabled() || $this->isReadonly(),
170
-            ]
171
-        );
172
-
173
-        if (!$this->getShouldLazyLoad()) {
174
-            $schema['options'] = $this->getOptions()->toNestedArray();
175
-        } else {
176
-            $schema['optionUrl'] = $this->getSuggestURL();
177
-        }
178
-
179
-        return $schema;
180
-    }
181
-
182
-    protected function formatOptions($fieldValue)
183
-    {
184
-        if (empty($fieldValue)) {
185
-            return [];
186
-        }
187
-
188
-        $formattedValue = [];
189
-        foreach ($fieldValue as $value) {
190
-            $formattedValue[] = [
191
-                'Title' => $value,
192
-                'Value' => $value,
193
-            ];
194
-        }
195
-        return $formattedValue;
196
-    }
197
-
198
-    /**
199
-     * When not used in a React form factory context, this adds the schema data to SilverStripe template
200
-     * rendered attributes lists
201
-     *
202
-     * @return array
203
-     */
204
-    public function getAttributes()
205
-    {
206
-        $attributes = parent::getAttributes();
207
-        $attributes['data-schema'] = json_encode($this->getSchemaData());
208
-        return $attributes;
209
-    }
210
-
211
-    /**
212
-     * @return string
213
-     */
214
-    protected function getSuggestURL()
215
-    {
216
-        return Controller::join_links($this->Link(), 'suggest');
217
-    }
218
-
219
-    /**
220
-     * @return ArrayList
221
-     */
222
-    protected function getOptions()
223
-    {
224
-        $options = ArrayList::create();
225
-
226
-        $source = $this->getSource();
227
-
228
-        if ($source instanceof Iterator) {
229
-            $source = iterator_to_array($source);
230
-        }
231
-
232
-        foreach ($source as $value) {
233
-            $options->push(
234
-                ArrayData::create([
235
-                    'Title' => $value,
236
-                    'Value' => $value,
237
-                ])
238
-            );
239
-        }
240
-
241
-        return $options;
242
-    }
243
-
244
-    public function setValue($value, $source = null)
245
-    {
246
-        if (is_string($value)) {
247
-            $value = explode(',', $value);
248
-        }
249
-
250
-        if ($source instanceof DataObject) {
251
-            $name = $this->getName();
252
-            $value = explode(',', $source->$name);
253
-        }
254
-
255
-        if ($source instanceof SS_List) {
256
-            $value = $source->column('ID');
257
-        }
258
-
259
-        if ($value === null) {
260
-            $value = [];
261
-        }
262
-
263
-        return parent::setValue(array_filter($value));
264
-    }
265
-
266
-    public function saveInto(DataObjectInterface $record)
267
-    {
268
-        parent::saveInto($record);
269
-
270
-        $name = $this->getName();
271
-
272
-        $record->$name = implode(',', $this->Value());
273
-        $record->write();
274
-    }
275
-
276
-    /**
277
-     * Returns a JSON string of tags, for lazy loading.
278
-     *
279
-     * @param  HTTPRequest $request
280
-     * @return HTTPResponse
281
-     */
282
-    public function suggest(HTTPRequest $request)
283
-    {
284
-        $responseBody = json_encode(
285
-            ['items' => $this->getTags($request->getVar('term'))]
286
-        );
287
-
288
-        $response = HTTPResponse::create();
289
-        $response->addHeader('Content-Type', 'application/json');
290
-        $response->setBody($responseBody);
291
-
292
-        return $response;
293
-    }
294
-
295
-    /**
296
-     * Returns array of arrays representing tags that partially match the given search term
297
-     *
298
-     * @param string $term
299
-     * @return array
300
-     */
301
-    protected function getTags($term)
302
-    {
303
-        $items = [];
304
-        foreach ($this->getOptions() as $i => $tag) {
305
-            /** @var ArrayData $tag */
306
-            $tagValue = $tag->Value;
307
-            // Map into a distinct list (prevent duplicates)
308
-            if (stripos($tagValue, $term) !== false && !array_key_exists($tagValue, $items)) {
309
-                $items[$tagValue] = [
310
-                    'id' => $tag->Title,
311
-                    'text' => $tag->Value,
312
-                ];
313
-            }
314
-        }
315
-        // @todo do we actually need lazy loading limits for StringTagField?
316
-        return array_slice(array_values($items), 0, $this->getLazyLoadItemLimit());
317
-    }
318
-
319
-    /**
320
-     * DropdownField assumes value will be a scalar so we must
321
-     * override validate. This only applies to Silverstripe 3.2+
322
-     *
323
-     * @param Validator $validator
324
-     * @return bool
325
-     */
326
-    public function validate($validator)
327
-    {
328
-        return true;
329
-    }
330
-
331
-    /**
332
-     * @return bool
333
-     */
334
-    public function getCanCreate()
335
-    {
336
-        return $this->canCreate;
337
-    }
338
-
339
-    /**
340
-     * @param bool $canCreate
341
-     * @return $this
342
-     */
343
-    public function setCanCreate($canCreate)
344
-    {
345
-        $this->canCreate = $canCreate;
346
-
347
-        return $this;
348
-    }
29
+	/**
30
+	 * @var array
31
+	 */
32
+	private static $allowed_actions = [
33
+		'suggest',
34
+	];
35
+
36
+	/**
37
+	 * @var bool
38
+	 */
39
+	protected $shouldLazyLoad = false;
40
+
41
+	/**
42
+	 * @var int
43
+	 */
44
+	protected $lazyLoadItemLimit = 10;
45
+
46
+	/**
47
+	 * @var bool
48
+	 */
49
+	protected $canCreate = true;
50
+
51
+	/**
52
+	 * @var null|DataObject
53
+	 */
54
+	protected $record;
55
+
56
+	/**
57
+	 * @var bool
58
+	 */
59
+	protected $isMultiple = true;
60
+
61
+	/**
62
+	 * @return bool
63
+	 */
64
+	public function getShouldLazyLoad()
65
+	{
66
+		return $this->shouldLazyLoad;
67
+	}
68
+
69
+	/**
70
+	 * @param bool $shouldLazyLoad
71
+	 * @return $this
72
+	 */
73
+	public function setShouldLazyLoad($shouldLazyLoad)
74
+	{
75
+		$this->shouldLazyLoad = $shouldLazyLoad;
76
+
77
+		return $this;
78
+	}
79
+
80
+	/**
81
+	 * @return int
82
+	 */
83
+	public function getLazyLoadItemLimit()
84
+	{
85
+		return $this->lazyLoadItemLimit;
86
+	}
87
+
88
+	/**
89
+	 * @param int $lazyLoadItemLimit
90
+	 * @return $this
91
+	 */
92
+	public function setLazyLoadItemLimit($lazyLoadItemLimit)
93
+	{
94
+		$this->lazyLoadItemLimit = $lazyLoadItemLimit;
95
+
96
+		return $this;
97
+	}
98
+
99
+	/**
100
+	 * @return bool
101
+	 */
102
+	public function getIsMultiple()
103
+	{
104
+		return $this->isMultiple;
105
+	}
106
+
107
+	/**
108
+	 * @param bool $isMultiple
109
+	 * @return $this
110
+	 */
111
+	public function setIsMultiple($isMultiple)
112
+	{
113
+		$this->isMultiple = $isMultiple;
114
+
115
+		return $this;
116
+	}
117
+
118
+	/**
119
+	 * @return null|DataObject
120
+	 */
121
+	public function getRecord()
122
+	{
123
+		if ($this->record) {
124
+			return $this->record;
125
+		}
126
+
127
+		if ($form = $this->getForm()) {
128
+			return $form->getRecord();
129
+		}
130
+
131
+		return null;
132
+	}
133
+
134
+	/**
135
+	 * @param DataObject $record
136
+	 * @return $this
137
+	 */
138
+	public function setRecord(DataObject $record)
139
+	{
140
+		$this->record = $record;
141
+
142
+		return $this;
143
+	}
144
+
145
+	public function Field($properties = [])
146
+	{
147
+		$this->addExtraClass('ss-tag-field');
148
+
149
+		return $this
150
+			->customise($properties)
151
+			->renderWith(TagField::class);
152
+	}
153
+
154
+	/**
155
+	 * Provide TagField data to the JSON schema for the frontend component
156
+	 *
157
+	 * @return array
158
+	 */
159
+	public function getSchemaDataDefaults()
160
+	{
161
+		$schema = array_merge(
162
+			parent::getSchemaDataDefaults(),
163
+			[
164
+				'name' => $this->getName() . '[]',
165
+				'lazyLoad' => $this->getShouldLazyLoad(),
166
+				'creatable' => $this->getCanCreate(),
167
+				'multi' => $this->getIsMultiple(),
168
+				'value' => $this->formatOptions($this->Value()),
169
+				'disabled' => $this->isDisabled() || $this->isReadonly(),
170
+			]
171
+		);
172
+
173
+		if (!$this->getShouldLazyLoad()) {
174
+			$schema['options'] = $this->getOptions()->toNestedArray();
175
+		} else {
176
+			$schema['optionUrl'] = $this->getSuggestURL();
177
+		}
178
+
179
+		return $schema;
180
+	}
181
+
182
+	protected function formatOptions($fieldValue)
183
+	{
184
+		if (empty($fieldValue)) {
185
+			return [];
186
+		}
187
+
188
+		$formattedValue = [];
189
+		foreach ($fieldValue as $value) {
190
+			$formattedValue[] = [
191
+				'Title' => $value,
192
+				'Value' => $value,
193
+			];
194
+		}
195
+		return $formattedValue;
196
+	}
197
+
198
+	/**
199
+	 * When not used in a React form factory context, this adds the schema data to SilverStripe template
200
+	 * rendered attributes lists
201
+	 *
202
+	 * @return array
203
+	 */
204
+	public function getAttributes()
205
+	{
206
+		$attributes = parent::getAttributes();
207
+		$attributes['data-schema'] = json_encode($this->getSchemaData());
208
+		return $attributes;
209
+	}
210
+
211
+	/**
212
+	 * @return string
213
+	 */
214
+	protected function getSuggestURL()
215
+	{
216
+		return Controller::join_links($this->Link(), 'suggest');
217
+	}
218
+
219
+	/**
220
+	 * @return ArrayList
221
+	 */
222
+	protected function getOptions()
223
+	{
224
+		$options = ArrayList::create();
225
+
226
+		$source = $this->getSource();
227
+
228
+		if ($source instanceof Iterator) {
229
+			$source = iterator_to_array($source);
230
+		}
231
+
232
+		foreach ($source as $value) {
233
+			$options->push(
234
+				ArrayData::create([
235
+					'Title' => $value,
236
+					'Value' => $value,
237
+				])
238
+			);
239
+		}
240
+
241
+		return $options;
242
+	}
243
+
244
+	public function setValue($value, $source = null)
245
+	{
246
+		if (is_string($value)) {
247
+			$value = explode(',', $value);
248
+		}
249
+
250
+		if ($source instanceof DataObject) {
251
+			$name = $this->getName();
252
+			$value = explode(',', $source->$name);
253
+		}
254
+
255
+		if ($source instanceof SS_List) {
256
+			$value = $source->column('ID');
257
+		}
258
+
259
+		if ($value === null) {
260
+			$value = [];
261
+		}
262
+
263
+		return parent::setValue(array_filter($value));
264
+	}
265
+
266
+	public function saveInto(DataObjectInterface $record)
267
+	{
268
+		parent::saveInto($record);
269
+
270
+		$name = $this->getName();
271
+
272
+		$record->$name = implode(',', $this->Value());
273
+		$record->write();
274
+	}
275
+
276
+	/**
277
+	 * Returns a JSON string of tags, for lazy loading.
278
+	 *
279
+	 * @param  HTTPRequest $request
280
+	 * @return HTTPResponse
281
+	 */
282
+	public function suggest(HTTPRequest $request)
283
+	{
284
+		$responseBody = json_encode(
285
+			['items' => $this->getTags($request->getVar('term'))]
286
+		);
287
+
288
+		$response = HTTPResponse::create();
289
+		$response->addHeader('Content-Type', 'application/json');
290
+		$response->setBody($responseBody);
291
+
292
+		return $response;
293
+	}
294
+
295
+	/**
296
+	 * Returns array of arrays representing tags that partially match the given search term
297
+	 *
298
+	 * @param string $term
299
+	 * @return array
300
+	 */
301
+	protected function getTags($term)
302
+	{
303
+		$items = [];
304
+		foreach ($this->getOptions() as $i => $tag) {
305
+			/** @var ArrayData $tag */
306
+			$tagValue = $tag->Value;
307
+			// Map into a distinct list (prevent duplicates)
308
+			if (stripos($tagValue, $term) !== false && !array_key_exists($tagValue, $items)) {
309
+				$items[$tagValue] = [
310
+					'id' => $tag->Title,
311
+					'text' => $tag->Value,
312
+				];
313
+			}
314
+		}
315
+		// @todo do we actually need lazy loading limits for StringTagField?
316
+		return array_slice(array_values($items), 0, $this->getLazyLoadItemLimit());
317
+	}
318
+
319
+	/**
320
+	 * DropdownField assumes value will be a scalar so we must
321
+	 * override validate. This only applies to Silverstripe 3.2+
322
+	 *
323
+	 * @param Validator $validator
324
+	 * @return bool
325
+	 */
326
+	public function validate($validator)
327
+	{
328
+		return true;
329
+	}
330
+
331
+	/**
332
+	 * @return bool
333
+	 */
334
+	public function getCanCreate()
335
+	{
336
+		return $this->canCreate;
337
+	}
338
+
339
+	/**
340
+	 * @param bool $canCreate
341
+	 * @return $this
342
+	 */
343
+	public function setCanCreate($canCreate)
344
+	{
345
+		$this->canCreate = $canCreate;
346
+
347
+		return $this;
348
+	}
349 349
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -161,7 +161,7 @@
 block discarded – undo
161 161
         $schema = array_merge(
162 162
             parent::getSchemaDataDefaults(),
163 163
             [
164
-                'name' => $this->getName() . '[]',
164
+                'name' => $this->getName().'[]',
165 165
                 'lazyLoad' => $this->getShouldLazyLoad(),
166 166
                 'creatable' => $this->getCanCreate(),
167 167
                 'multi' => $this->getIsMultiple(),
Please login to merge, or discard this patch.
src/TagField.php 2 patches
Indentation   +453 added lines, -453 removed lines patch added patch discarded remove patch
@@ -24,457 +24,457 @@
 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 = DataList::create($dataClass)->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
-            return $record;
394
-        }
395
-
396
-        return false;
397
-    }
398
-
399
-    /**
400
-     * Returns a JSON string of tags, for lazy loading.
401
-     *
402
-     * @param  HTTPRequest $request
403
-     * @return HTTPResponse
404
-     */
405
-    public function suggest(HTTPRequest $request)
406
-    {
407
-        $tags = $this->getTags($request->getVar('term'));
408
-
409
-        $response = HTTPResponse::create();
410
-        $response->addHeader('Content-Type', 'application/json');
411
-        $response->setBody(json_encode(['items' => $tags]));
412
-
413
-        return $response;
414
-    }
415
-
416
-    /**
417
-     * Returns array of arrays representing tags.
418
-     *
419
-     * @param  string $term
420
-     * @return array
421
-     */
422
-    protected function getTags($term)
423
-    {
424
-        $source = $this->getSourceList();
425
-
426
-        $titleField = $this->getTitleField();
427
-
428
-        $query = $source
429
-            ->filter($titleField . ':PartialMatch:nocase', $term)
430
-            ->sort($titleField)
431
-            ->limit($this->getLazyLoadItemLimit());
432
-
433
-        // Map into a distinct list
434
-        $items = [];
435
-        $titleField = $this->getTitleField();
436
-        foreach ($query->map('ID', $titleField) as $id => $title) {
437
-            $items[$title] = [
438
-                'id' => $title,
439
-                'text' => $title,
440
-            ];
441
-        }
442
-
443
-        return array_values($items);
444
-    }
445
-
446
-    /**
447
-     * DropdownField assumes value will be a scalar so we must
448
-     * override validate. This only applies to Silverstripe 3.2+
449
-     *
450
-     * @param Validator $validator
451
-     * @return bool
452
-     */
453
-    public function validate($validator)
454
-    {
455
-        return true;
456
-    }
457
-
458
-    /**
459
-     * Converts the field to a readonly variant.
460
-     *
461
-     * @return ReadonlyTagField
462
-     */
463
-    public function performReadonlyTransformation()
464
-    {
465
-        /** @var ReadonlyTagField $copy */
466
-        $copy = $this->castedCopy(ReadonlyTagField::class);
467
-        $copy->setSourceList($this->getSourceList());
468
-        return $copy;
469
-    }
470
-
471
-    /**
472
-     * Prevent the default, which would return "tag"
473
-     *
474
-     * @return string
475
-     */
476
-    public function Type()
477
-    {
478
-        return '';
479
-    }
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 = DataList::create($dataClass)->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
+			return $record;
394
+		}
395
+
396
+		return false;
397
+	}
398
+
399
+	/**
400
+	 * Returns a JSON string of tags, for lazy loading.
401
+	 *
402
+	 * @param  HTTPRequest $request
403
+	 * @return HTTPResponse
404
+	 */
405
+	public function suggest(HTTPRequest $request)
406
+	{
407
+		$tags = $this->getTags($request->getVar('term'));
408
+
409
+		$response = HTTPResponse::create();
410
+		$response->addHeader('Content-Type', 'application/json');
411
+		$response->setBody(json_encode(['items' => $tags]));
412
+
413
+		return $response;
414
+	}
415
+
416
+	/**
417
+	 * Returns array of arrays representing tags.
418
+	 *
419
+	 * @param  string $term
420
+	 * @return array
421
+	 */
422
+	protected function getTags($term)
423
+	{
424
+		$source = $this->getSourceList();
425
+
426
+		$titleField = $this->getTitleField();
427
+
428
+		$query = $source
429
+			->filter($titleField . ':PartialMatch:nocase', $term)
430
+			->sort($titleField)
431
+			->limit($this->getLazyLoadItemLimit());
432
+
433
+		// Map into a distinct list
434
+		$items = [];
435
+		$titleField = $this->getTitleField();
436
+		foreach ($query->map('ID', $titleField) as $id => $title) {
437
+			$items[$title] = [
438
+				'id' => $title,
439
+				'text' => $title,
440
+			];
441
+		}
442
+
443
+		return array_values($items);
444
+	}
445
+
446
+	/**
447
+	 * DropdownField assumes value will be a scalar so we must
448
+	 * override validate. This only applies to Silverstripe 3.2+
449
+	 *
450
+	 * @param Validator $validator
451
+	 * @return bool
452
+	 */
453
+	public function validate($validator)
454
+	{
455
+		return true;
456
+	}
457
+
458
+	/**
459
+	 * Converts the field to a readonly variant.
460
+	 *
461
+	 * @return ReadonlyTagField
462
+	 */
463
+	public function performReadonlyTransformation()
464
+	{
465
+		/** @var ReadonlyTagField $copy */
466
+		$copy = $this->castedCopy(ReadonlyTagField::class);
467
+		$copy->setSourceList($this->getSourceList());
468
+		return $copy;
469
+	}
470
+
471
+	/**
472
+	 * Prevent the default, which would return "tag"
473
+	 *
474
+	 * @return string
475
+	 */
476
+	public function Type()
477
+	{
478
+		return '';
479
+	}
480 480
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -215,7 +215,7 @@  discard block
 block discarded – undo
215 215
         $schema = array_merge(
216 216
             parent::getSchemaDataDefaults(),
217 217
             [
218
-                'name' => $this->getName() . '[]',
218
+                'name' => $this->getName().'[]',
219 219
                 'lazyLoad' => $this->getShouldLazyLoad(),
220 220
                 'creatable' => $this->getCanCreate(),
221 221
                 'multi' => $this->getIsMultiple(),
@@ -426,7 +426,7 @@  discard block
 block discarded – undo
426 426
         $titleField = $this->getTitleField();
427 427
 
428 428
         $query = $source
429
-            ->filter($titleField . ':PartialMatch:nocase', $term)
429
+            ->filter($titleField.':PartialMatch:nocase', $term)
430 430
             ->sort($titleField)
431 431
             ->limit($this->getLazyLoadItemLimit());
432 432
 
Please login to merge, or discard this patch.
tests/StringTagFieldTest.php 1 patch
Indentation   +140 added lines, -140 removed lines patch added patch discarded remove patch
@@ -15,144 +15,144 @@
 block discarded – undo
15 15
  */
16 16
 class StringTagFieldTest extends SapphireTest
17 17
 {
18
-    /**
19
-     * @var string
20
-     */
21
-    protected static $fixture_file = 'StringTagFieldTest.yml';
22
-
23
-    /**
24
-     * @var array
25
-     */
26
-    protected static $extra_dataobjects = [
27
-        StringTagFieldTestBlogPost::class,
28
-    ];
29
-
30
-    public function testItSavesTagsOnNewRecords()
31
-    {
32
-        $record = $this->getNewStringTagFieldTestBlogPost('BlogPost1');
33
-
34
-        $field = new StringTagField('Tags');
35
-        $field->setValue(['Tag1', 'Tag2']);
36
-        $field->saveInto($record);
37
-
38
-        $record->write();
39
-
40
-        $this->assertEquals('Tag1,Tag2', $record->Tags);
41
-    }
42
-
43
-    /**
44
-     * @param string $name
45
-     *
46
-     * @return StringTagFieldTestBlogPost
47
-     */
48
-    protected function getNewStringTagFieldTestBlogPost($name)
49
-    {
50
-        return $this->objFromFixture(
51
-            StringTagFieldTestBlogPost::class,
52
-            $name
53
-        );
54
-    }
55
-
56
-    public function testItSavesTagsOnExistingRecords()
57
-    {
58
-        $record = $this->getNewStringTagFieldTestBlogPost('BlogPost1');
59
-        $record->write();
60
-
61
-        $field = new StringTagField('Tags');
62
-        $field->setValue(['Tag1', 'Tag2']);
63
-        $field->saveInto($record);
64
-
65
-        $this->assertEquals('Tag1,Tag2', $record->Tags);
66
-    }
67
-
68
-    public function testItSuggestsTags()
69
-    {
70
-        $field = new StringTagField('SomeField', 'Some field', ['Tag1', 'Tag2'], []);
71
-
72
-        /**
73
-         * Partial tag title match.
74
-         */
75
-        $request = $this->getNewRequest(['term' => 'Tag']);
76
-
77
-        $this->assertEquals(
78
-            '{"items":[{"id":"Tag1","text":"Tag1"},{"id":"Tag2","text":"Tag2"}]}',
79
-            $field->suggest($request)->getBody()
80
-        );
81
-
82
-        /**
83
-         * Exact tag title match.
84
-         */
85
-        $request = $this->getNewRequest(['term' => 'Tag1']);
86
-
87
-        $this->assertEquals($field->suggest($request)->getBody(), '{"items":[{"id":"Tag1","text":"Tag1"}]}');
88
-
89
-        /**
90
-         * Case-insensitive tag title match.
91
-         */
92
-        $request = $this->getNewRequest(['term' => 'TAG1']);
93
-
94
-        $this->assertEquals(
95
-            '{"items":[{"id":"Tag1","text":"Tag1"}]}',
96
-            $field->suggest($request)->getBody()
97
-        );
98
-
99
-        /**
100
-         * No tag title match.
101
-         */
102
-        $request = $this->getNewRequest(['term' => 'unknown']);
103
-
104
-        $this->assertEquals(
105
-            '{"items":[]}',
106
-            $field->suggest($request)->getBody()
107
-        );
108
-    }
109
-
110
-    public function testGetSchemaDataDefaults()
111
-    {
112
-        $form = new Form(null, 'Form', new FieldList(), new FieldList());
113
-        $field = new StringTagField('TestField', 'Test Field', ['one', 'two']);
114
-        $field->setForm($form);
115
-
116
-        $field
117
-            ->setShouldLazyLoad(false)
118
-            ->setCanCreate(false);
119
-
120
-        $schema = $field->getSchemaDataDefaults();
121
-        $this->assertSame('TestField[]', $schema['name']);
122
-        $this->assertFalse($schema['lazyLoad']);
123
-        $this->assertFalse($schema['creatable']);
124
-        $this->assertEquals([
125
-            ['Title' => 'one', 'Value' => 'one'],
126
-            ['Title' => 'two', 'Value' => 'two'],
127
-        ], $schema['options']);
128
-
129
-        $field
130
-            ->setShouldLazyLoad(true)
131
-            ->setCanCreate(true);
132
-
133
-        $schema = $field->getSchemaDataDefaults();
134
-        $this->assertTrue($schema['lazyLoad']);
135
-        $this->assertTrue($schema['creatable']);
136
-        $this->assertContains('suggest', $schema['optionUrl']);
137
-    }
138
-
139
-    public function testSchemaIsAddedToAttributes()
140
-    {
141
-        $field = new StringTagField('TestField');
142
-        $attributes = $field->getAttributes();
143
-        $this->assertNotEmpty($attributes['data-schema']);
144
-    }
145
-
146
-    /**
147
-     * @param array $parameters
148
-     * @return HTTPRequest
149
-     */
150
-    protected function getNewRequest(array $parameters)
151
-    {
152
-        return new HTTPRequest(
153
-            'get',
154
-            'StringTagFieldTestController/StringTagFieldTestForm/fields/Tags/suggest',
155
-            $parameters
156
-        );
157
-    }
18
+	/**
19
+	 * @var string
20
+	 */
21
+	protected static $fixture_file = 'StringTagFieldTest.yml';
22
+
23
+	/**
24
+	 * @var array
25
+	 */
26
+	protected static $extra_dataobjects = [
27
+		StringTagFieldTestBlogPost::class,
28
+	];
29
+
30
+	public function testItSavesTagsOnNewRecords()
31
+	{
32
+		$record = $this->getNewStringTagFieldTestBlogPost('BlogPost1');
33
+
34
+		$field = new StringTagField('Tags');
35
+		$field->setValue(['Tag1', 'Tag2']);
36
+		$field->saveInto($record);
37
+
38
+		$record->write();
39
+
40
+		$this->assertEquals('Tag1,Tag2', $record->Tags);
41
+	}
42
+
43
+	/**
44
+	 * @param string $name
45
+	 *
46
+	 * @return StringTagFieldTestBlogPost
47
+	 */
48
+	protected function getNewStringTagFieldTestBlogPost($name)
49
+	{
50
+		return $this->objFromFixture(
51
+			StringTagFieldTestBlogPost::class,
52
+			$name
53
+		);
54
+	}
55
+
56
+	public function testItSavesTagsOnExistingRecords()
57
+	{
58
+		$record = $this->getNewStringTagFieldTestBlogPost('BlogPost1');
59
+		$record->write();
60
+
61
+		$field = new StringTagField('Tags');
62
+		$field->setValue(['Tag1', 'Tag2']);
63
+		$field->saveInto($record);
64
+
65
+		$this->assertEquals('Tag1,Tag2', $record->Tags);
66
+	}
67
+
68
+	public function testItSuggestsTags()
69
+	{
70
+		$field = new StringTagField('SomeField', 'Some field', ['Tag1', 'Tag2'], []);
71
+
72
+		/**
73
+		 * Partial tag title match.
74
+		 */
75
+		$request = $this->getNewRequest(['term' => 'Tag']);
76
+
77
+		$this->assertEquals(
78
+			'{"items":[{"id":"Tag1","text":"Tag1"},{"id":"Tag2","text":"Tag2"}]}',
79
+			$field->suggest($request)->getBody()
80
+		);
81
+
82
+		/**
83
+		 * Exact tag title match.
84
+		 */
85
+		$request = $this->getNewRequest(['term' => 'Tag1']);
86
+
87
+		$this->assertEquals($field->suggest($request)->getBody(), '{"items":[{"id":"Tag1","text":"Tag1"}]}');
88
+
89
+		/**
90
+		 * Case-insensitive tag title match.
91
+		 */
92
+		$request = $this->getNewRequest(['term' => 'TAG1']);
93
+
94
+		$this->assertEquals(
95
+			'{"items":[{"id":"Tag1","text":"Tag1"}]}',
96
+			$field->suggest($request)->getBody()
97
+		);
98
+
99
+		/**
100
+		 * No tag title match.
101
+		 */
102
+		$request = $this->getNewRequest(['term' => 'unknown']);
103
+
104
+		$this->assertEquals(
105
+			'{"items":[]}',
106
+			$field->suggest($request)->getBody()
107
+		);
108
+	}
109
+
110
+	public function testGetSchemaDataDefaults()
111
+	{
112
+		$form = new Form(null, 'Form', new FieldList(), new FieldList());
113
+		$field = new StringTagField('TestField', 'Test Field', ['one', 'two']);
114
+		$field->setForm($form);
115
+
116
+		$field
117
+			->setShouldLazyLoad(false)
118
+			->setCanCreate(false);
119
+
120
+		$schema = $field->getSchemaDataDefaults();
121
+		$this->assertSame('TestField[]', $schema['name']);
122
+		$this->assertFalse($schema['lazyLoad']);
123
+		$this->assertFalse($schema['creatable']);
124
+		$this->assertEquals([
125
+			['Title' => 'one', 'Value' => 'one'],
126
+			['Title' => 'two', 'Value' => 'two'],
127
+		], $schema['options']);
128
+
129
+		$field
130
+			->setShouldLazyLoad(true)
131
+			->setCanCreate(true);
132
+
133
+		$schema = $field->getSchemaDataDefaults();
134
+		$this->assertTrue($schema['lazyLoad']);
135
+		$this->assertTrue($schema['creatable']);
136
+		$this->assertContains('suggest', $schema['optionUrl']);
137
+	}
138
+
139
+	public function testSchemaIsAddedToAttributes()
140
+	{
141
+		$field = new StringTagField('TestField');
142
+		$attributes = $field->getAttributes();
143
+		$this->assertNotEmpty($attributes['data-schema']);
144
+	}
145
+
146
+	/**
147
+	 * @param array $parameters
148
+	 * @return HTTPRequest
149
+	 */
150
+	protected function getNewRequest(array $parameters)
151
+	{
152
+		return new HTTPRequest(
153
+			'get',
154
+			'StringTagFieldTestController/StringTagFieldTestForm/fields/Tags/suggest',
155
+			$parameters
156
+		);
157
+	}
158 158
 }
Please login to merge, or discard this patch.
tests/TagFieldTest.php 1 patch
Indentation   +369 added lines, -369 removed lines patch added patch discarded remove patch
@@ -20,373 +20,373 @@
 block discarded – undo
20 20
  */
21 21
 class TagFieldTest extends SapphireTest
22 22
 {
23
-    /**
24
-     * @var string
25
-     */
26
-    protected static $fixture_file = 'TagFieldTest.yml';
27
-
28
-    /**
29
-     * @var array
30
-     */
31
-    protected static $extra_dataobjects = [
32
-        TagFieldTestBlogTag::class,
33
-        TagFieldTestBlogPost::class,
34
-    ];
35
-
36
-    public function testItSavesLinksToNewTagsOnNewRecords()
37
-    {
38
-        $record = $this->getNewTagFieldTestBlogPost('BlogPost1');
39
-        $field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
40
-        $field->setValue(['Tag3', 'Tag4']);
41
-        $field->saveInto($record);
42
-        $record->write();
43
-        $this->compareExpectedAndActualTags(
44
-            ['Tag3', 'Tag4'],
45
-            $record
46
-        );
47
-    }
48
-
49
-    /**
50
-     * @param string $name
51
-     *
52
-     * @return TagFieldTestBlogPost
53
-     */
54
-    protected function getNewTagFieldTestBlogPost($name)
55
-    {
56
-        return $this->objFromFixture(
57
-            TagFieldTestBlogPost::class,
58
-            $name
59
-        );
60
-    }
61
-
62
-    /**
63
-     * @param array $expected
64
-     * @param TagFieldTestBlogPost $record
65
-     */
66
-    protected function compareExpectedAndActualTags(array $expected, TagFieldTestBlogPost $record)
67
-    {
68
-        $this->compareTagLists($expected, $record->Tags());
69
-    }
70
-
71
-    /**
72
-     * Ensure a source of tags matches the given string tag names
73
-     *
74
-     * @param array $expected
75
-     * @param DataList $actualSource
76
-     */
77
-    protected function compareTagLists(array $expected, DataList $actualSource)
78
-    {
79
-        $actual = array_values($actualSource->map('ID', 'Title')->toArray());
80
-        sort($expected);
81
-        sort($actual);
82
-
83
-        $this->assertEquals(
84
-            $expected,
85
-            $actual
86
-        );
87
-    }
88
-
89
-    public function testItSavesLinksToNewTagsOnExistingRecords()
90
-    {
91
-        $record = $this->getNewTagFieldTestBlogPost('BlogPost1');
92
-        $record->write();
93
-
94
-        $field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
95
-        $field->setValue(['Tag3', 'Tag4']);
96
-        $field->saveInto($record);
97
-
98
-        $this->compareExpectedAndActualTags(
99
-            array('Tag3', 'Tag4'),
100
-            $record
101
-        );
102
-    }
103
-
104
-    public function testItSavesLinksToExistingTagsOnNewRecords()
105
-    {
106
-        $record = $this->getNewTagFieldTestBlogPost('BlogPost1');
107
-
108
-        $field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
109
-        $field->setValue(['Tag1', 'Tag2']);
110
-        $field->saveInto($record);
111
-
112
-        $record->write();
113
-
114
-        $this->compareExpectedAndActualTags(
115
-            ['Tag1', 'Tag2'],
116
-            $record
117
-        );
118
-    }
119
-
120
-    public function testItSavesLinksToExistingTagsOnExistingRecords()
121
-    {
122
-        $record = $this->getNewTagFieldTestBlogPost('BlogPost1');
123
-        $record->write();
124
-
125
-        $field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
126
-        $field->setValue(['Tag1', 'Tag2']);
127
-        $field->saveInto($record);
128
-
129
-        $this->compareExpectedAndActualTags(
130
-            ['Tag1', 'Tag2'],
131
-            $record
132
-        );
133
-    }
134
-
135
-    /**
136
-     * Ensure that {@see TagField::saveInto} respects existing tags
137
-     */
138
-    public function testSaveDuplicateTags()
139
-    {
140
-        $record = $this->getNewTagFieldTestBlogPost('BlogPost2');
141
-        $record->write();
142
-        $tag2ID = $this->idFromFixture(TagFieldTestBlogTag::class, 'Tag2');
143
-
144
-        // Check tags before write
145
-        $this->compareExpectedAndActualTags(
146
-            ['Tag1', '222'],
147
-            $record
148
-        );
149
-        $this->compareTagLists(
150
-            ['Tag1', '222'],
151
-            TagFieldTestBlogTag::get()
152
-        );
153
-        $this->assertContains($tag2ID, TagFieldTestBlogTag::get()->column('ID'));
154
-
155
-        // Write new tags
156
-        $field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
157
-        $field->setValue(['222', 'Tag3']);
158
-        $field->saveInto($record);
159
-
160
-        // Check only one new tag was added
161
-        $this->compareExpectedAndActualTags(
162
-            ['222', 'Tag3'],
163
-            $record
164
-        );
165
-
166
-        // Ensure that only one new dataobject was added and that tag2s id has not changed
167
-        $this->compareTagLists(
168
-            ['Tag1', '222', 'Tag3'],
169
-            TagFieldTestBlogTag::get()
170
-        );
171
-        $this->assertContains($tag2ID, TagFieldTestBlogTag::get()->column('ID'));
172
-    }
173
-
174
-    public function testItSuggestsTags()
175
-    {
176
-        $field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
177
-
178
-        /**
179
-         * Partial tag title match.
180
-         */
181
-        $request = $this->getNewRequest(['term' => 'Tag']);
182
-
183
-        $this->assertEquals(
184
-            '{"items":[{"id":"Tag1","text":"Tag1"}]}',
185
-            $field->suggest($request)->getBody()
186
-        );
187
-
188
-        /**
189
-         * Exact tag title match.
190
-         */
191
-        $request = $this->getNewRequest(['term' => '222']);
192
-
193
-        $this->assertEquals(
194
-            '{"items":[{"id":"222","text":"222"}]}',
195
-            $field->suggest($request)->getBody()
196
-        );
197
-
198
-        /**
199
-         * Case-insensitive tag title match.
200
-         */
201
-        $request = $this->getNewRequest(['term' => 'TAG1']);
202
-
203
-        $this->assertEquals(
204
-            '{"items":[{"id":"Tag1","text":"Tag1"}]}',
205
-            $field->suggest($request)->getBody()
206
-        );
207
-
208
-        /**
209
-         * No tag title match.
210
-         */
211
-        $request = $this->getNewRequest(['term' => 'unknown']);
212
-
213
-        $this->assertEquals(
214
-            '{"items":[]}',
215
-            $field->suggest($request)->getBody()
216
-        );
217
-    }
218
-
219
-    /**
220
-     * Tests that TagField supports pre-filtered data sources
221
-     */
222
-    public function testRestrictedSuggestions()
223
-    {
224
-        $source = TagFieldTestBlogTag::get()->exclude('Title', 'Tag2');
225
-        $field = new TagField('Tags', '', $source);
226
-
227
-        /**
228
-         * Partial tag title match.
229
-         */
230
-        $request = $this->getNewRequest(['term' => 'Tag']);
231
-
232
-        $this->assertEquals(
233
-            '{"items":[{"id":"Tag1","text":"Tag1"}]}',
234
-            $field->suggest($request)->getBody()
235
-        );
236
-
237
-        /**
238
-         * Exact tag title match.
239
-         */
240
-        $request = $this->getNewRequest(['term' => 'Tag1']);
241
-
242
-        $this->assertEquals(
243
-            '{"items":[{"id":"Tag1","text":"Tag1"}]}',
244
-            $field->suggest($request)->getBody()
245
-        );
246
-
247
-        /**
248
-         * Excluded item doesn't appear in matches
249
-         */
250
-        $request = $this->getNewRequest(['term' => 'Tag2']);
251
-
252
-        $this->assertEquals(
253
-            '{"items":[]}',
254
-            $field->suggest($request)->getBody()
255
-        );
256
-    }
257
-
258
-    /**
259
-     * @param array $parameters
260
-     *
261
-     * @return HTTPRequest
262
-     */
263
-    protected function getNewRequest(array $parameters)
264
-    {
265
-        return new HTTPRequest(
266
-            'get',
267
-            'TagFieldTestController/TagFieldTestForm/fields/Tags/suggest',
268
-            $parameters
269
-        );
270
-    }
271
-
272
-    public function testItDisplaysValuesFromRelations()
273
-    {
274
-        $record = $this->getNewTagFieldTestBlogPost('BlogPost1');
275
-        $record->write();
276
-
277
-        $form = new Form(
278
-            new TagFieldTestController(),
279
-            'Form',
280
-            new FieldList(
281
-                $field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class))
282
-            ),
283
-            new FieldList()
284
-        );
285
-
286
-        $form->loadDataFrom(
287
-            $this->objFromFixture(TagFieldTestBlogPost::class, 'BlogPost2')
288
-        );
289
-
290
-        $ids = TagFieldTestBlogTag::get()->column('Title');
291
-
292
-        $this->assertEquals($field->Value(), $ids);
293
-    }
294
-
295
-    public function testItIgnoresNewTagsIfCannotCreate()
296
-    {
297
-        $this->markTestSkipped(
298
-            'This test has not been updated yet.'
299
-        );
300
-
301
-        $record = new TagFieldTestBlogPost();
302
-        $record->write();
303
-
304
-        $tag = TagFieldTestBlogTag::get()->filter('Title', 'Tag1')->first();
305
-
306
-        $field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class), [$tag->Title, 'Tag3']);
307
-        $field->setCanCreate(false);
308
-        $field->saveInto($record);
309
-
310
-        /**
311
-         * @var TagFieldTestBlogPost $record
312
-         */
313
-        $record = DataObject::get_by_id(TagFieldTestBlogPost::class, $record->ID);
314
-
315
-        $this->compareExpectedAndActualTags(
316
-            ['Tag1'],
317
-            $record
318
-        );
319
-    }
320
-
321
-    /**
322
-     * Test you can save without a source set
323
-     */
324
-    public function testSaveEmptySource()
325
-    {
326
-        $record = new TagFieldTestBlogPost();
327
-        $record->write();
328
-
329
-        // Clear database of tags
330
-        TagFieldTestBlogTag::get()->removeAll();
331
-
332
-        $field = new TagField('Tags', '', TagFieldTestBlogTag::get());
333
-        $field->setValue(['New Tag']);
334
-        $field->setCanCreate(true);
335
-        $field->saveInto($record);
336
-
337
-        $tag = TagFieldTestBlogTag::get()->first();
338
-        $this->assertNotEmpty($tag);
339
-        $this->assertEquals('New Tag', $tag->Title);
340
-        $record = TagFieldTestBlogPost::get()->byID($record->ID);
341
-        $this->assertEquals(
342
-            $tag->ID,
343
-            $record->Tags()->first()->ID
344
-        );
345
-    }
346
-
347
-    /**
348
-     * Test read only fields are returned
349
-     */
350
-    public function testReadonlyTransformation()
351
-    {
352
-        $field = new TagField('Tags', '', TagFieldTestBlogTag::get());
353
-        $readOnlyField = $field->performReadonlyTransformation();
354
-        $this->assertInstanceOf(ReadonlyTagField::class, $readOnlyField);
355
-    }
356
-
357
-    public function testGetSchemaDataDefaults()
358
-    {
359
-        $form = new Form(null, 'Form', new FieldList(), new FieldList());
360
-        $field = new TagField('TestField', 'Test Field', TagFieldTestBlogTag::get());
361
-        $field->setForm($form);
362
-
363
-        $field
364
-            ->setShouldLazyLoad(false)
365
-            ->setCanCreate(false);
366
-
367
-        $schema = $field->getSchemaDataDefaults();
368
-        $this->assertSame('TestField[]', $schema['name']);
369
-        $this->assertFalse($schema['lazyLoad']);
370
-        $this->assertFalse($schema['creatable']);
371
-        $this->assertEquals([
372
-            ['Title' => 'Tag1', 'Value' => 'Tag1'],
373
-            ['Title' => '222', 'Value' => '222'],
374
-        ], $schema['options']);
375
-
376
-        $field
377
-            ->setShouldLazyLoad(true)
378
-            ->setCanCreate(true);
379
-
380
-        $schema = $field->getSchemaDataDefaults();
381
-        $this->assertTrue($schema['lazyLoad']);
382
-        $this->assertTrue($schema['creatable']);
383
-        $this->assertContains('suggest', $schema['optionUrl']);
384
-    }
385
-
386
-    public function testSchemaIsAddedToAttributes()
387
-    {
388
-        $field = new TagField('TestField');
389
-        $attributes = $field->getAttributes();
390
-        $this->assertNotEmpty($attributes['data-schema']);
391
-    }
23
+	/**
24
+	 * @var string
25
+	 */
26
+	protected static $fixture_file = 'TagFieldTest.yml';
27
+
28
+	/**
29
+	 * @var array
30
+	 */
31
+	protected static $extra_dataobjects = [
32
+		TagFieldTestBlogTag::class,
33
+		TagFieldTestBlogPost::class,
34
+	];
35
+
36
+	public function testItSavesLinksToNewTagsOnNewRecords()
37
+	{
38
+		$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
39
+		$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
40
+		$field->setValue(['Tag3', 'Tag4']);
41
+		$field->saveInto($record);
42
+		$record->write();
43
+		$this->compareExpectedAndActualTags(
44
+			['Tag3', 'Tag4'],
45
+			$record
46
+		);
47
+	}
48
+
49
+	/**
50
+	 * @param string $name
51
+	 *
52
+	 * @return TagFieldTestBlogPost
53
+	 */
54
+	protected function getNewTagFieldTestBlogPost($name)
55
+	{
56
+		return $this->objFromFixture(
57
+			TagFieldTestBlogPost::class,
58
+			$name
59
+		);
60
+	}
61
+
62
+	/**
63
+	 * @param array $expected
64
+	 * @param TagFieldTestBlogPost $record
65
+	 */
66
+	protected function compareExpectedAndActualTags(array $expected, TagFieldTestBlogPost $record)
67
+	{
68
+		$this->compareTagLists($expected, $record->Tags());
69
+	}
70
+
71
+	/**
72
+	 * Ensure a source of tags matches the given string tag names
73
+	 *
74
+	 * @param array $expected
75
+	 * @param DataList $actualSource
76
+	 */
77
+	protected function compareTagLists(array $expected, DataList $actualSource)
78
+	{
79
+		$actual = array_values($actualSource->map('ID', 'Title')->toArray());
80
+		sort($expected);
81
+		sort($actual);
82
+
83
+		$this->assertEquals(
84
+			$expected,
85
+			$actual
86
+		);
87
+	}
88
+
89
+	public function testItSavesLinksToNewTagsOnExistingRecords()
90
+	{
91
+		$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
92
+		$record->write();
93
+
94
+		$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
95
+		$field->setValue(['Tag3', 'Tag4']);
96
+		$field->saveInto($record);
97
+
98
+		$this->compareExpectedAndActualTags(
99
+			array('Tag3', 'Tag4'),
100
+			$record
101
+		);
102
+	}
103
+
104
+	public function testItSavesLinksToExistingTagsOnNewRecords()
105
+	{
106
+		$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
107
+
108
+		$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
109
+		$field->setValue(['Tag1', 'Tag2']);
110
+		$field->saveInto($record);
111
+
112
+		$record->write();
113
+
114
+		$this->compareExpectedAndActualTags(
115
+			['Tag1', 'Tag2'],
116
+			$record
117
+		);
118
+	}
119
+
120
+	public function testItSavesLinksToExistingTagsOnExistingRecords()
121
+	{
122
+		$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
123
+		$record->write();
124
+
125
+		$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
126
+		$field->setValue(['Tag1', 'Tag2']);
127
+		$field->saveInto($record);
128
+
129
+		$this->compareExpectedAndActualTags(
130
+			['Tag1', 'Tag2'],
131
+			$record
132
+		);
133
+	}
134
+
135
+	/**
136
+	 * Ensure that {@see TagField::saveInto} respects existing tags
137
+	 */
138
+	public function testSaveDuplicateTags()
139
+	{
140
+		$record = $this->getNewTagFieldTestBlogPost('BlogPost2');
141
+		$record->write();
142
+		$tag2ID = $this->idFromFixture(TagFieldTestBlogTag::class, 'Tag2');
143
+
144
+		// Check tags before write
145
+		$this->compareExpectedAndActualTags(
146
+			['Tag1', '222'],
147
+			$record
148
+		);
149
+		$this->compareTagLists(
150
+			['Tag1', '222'],
151
+			TagFieldTestBlogTag::get()
152
+		);
153
+		$this->assertContains($tag2ID, TagFieldTestBlogTag::get()->column('ID'));
154
+
155
+		// Write new tags
156
+		$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
157
+		$field->setValue(['222', 'Tag3']);
158
+		$field->saveInto($record);
159
+
160
+		// Check only one new tag was added
161
+		$this->compareExpectedAndActualTags(
162
+			['222', 'Tag3'],
163
+			$record
164
+		);
165
+
166
+		// Ensure that only one new dataobject was added and that tag2s id has not changed
167
+		$this->compareTagLists(
168
+			['Tag1', '222', 'Tag3'],
169
+			TagFieldTestBlogTag::get()
170
+		);
171
+		$this->assertContains($tag2ID, TagFieldTestBlogTag::get()->column('ID'));
172
+	}
173
+
174
+	public function testItSuggestsTags()
175
+	{
176
+		$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
177
+
178
+		/**
179
+		 * Partial tag title match.
180
+		 */
181
+		$request = $this->getNewRequest(['term' => 'Tag']);
182
+
183
+		$this->assertEquals(
184
+			'{"items":[{"id":"Tag1","text":"Tag1"}]}',
185
+			$field->suggest($request)->getBody()
186
+		);
187
+
188
+		/**
189
+		 * Exact tag title match.
190
+		 */
191
+		$request = $this->getNewRequest(['term' => '222']);
192
+
193
+		$this->assertEquals(
194
+			'{"items":[{"id":"222","text":"222"}]}',
195
+			$field->suggest($request)->getBody()
196
+		);
197
+
198
+		/**
199
+		 * Case-insensitive tag title match.
200
+		 */
201
+		$request = $this->getNewRequest(['term' => 'TAG1']);
202
+
203
+		$this->assertEquals(
204
+			'{"items":[{"id":"Tag1","text":"Tag1"}]}',
205
+			$field->suggest($request)->getBody()
206
+		);
207
+
208
+		/**
209
+		 * No tag title match.
210
+		 */
211
+		$request = $this->getNewRequest(['term' => 'unknown']);
212
+
213
+		$this->assertEquals(
214
+			'{"items":[]}',
215
+			$field->suggest($request)->getBody()
216
+		);
217
+	}
218
+
219
+	/**
220
+	 * Tests that TagField supports pre-filtered data sources
221
+	 */
222
+	public function testRestrictedSuggestions()
223
+	{
224
+		$source = TagFieldTestBlogTag::get()->exclude('Title', 'Tag2');
225
+		$field = new TagField('Tags', '', $source);
226
+
227
+		/**
228
+		 * Partial tag title match.
229
+		 */
230
+		$request = $this->getNewRequest(['term' => 'Tag']);
231
+
232
+		$this->assertEquals(
233
+			'{"items":[{"id":"Tag1","text":"Tag1"}]}',
234
+			$field->suggest($request)->getBody()
235
+		);
236
+
237
+		/**
238
+		 * Exact tag title match.
239
+		 */
240
+		$request = $this->getNewRequest(['term' => 'Tag1']);
241
+
242
+		$this->assertEquals(
243
+			'{"items":[{"id":"Tag1","text":"Tag1"}]}',
244
+			$field->suggest($request)->getBody()
245
+		);
246
+
247
+		/**
248
+		 * Excluded item doesn't appear in matches
249
+		 */
250
+		$request = $this->getNewRequest(['term' => 'Tag2']);
251
+
252
+		$this->assertEquals(
253
+			'{"items":[]}',
254
+			$field->suggest($request)->getBody()
255
+		);
256
+	}
257
+
258
+	/**
259
+	 * @param array $parameters
260
+	 *
261
+	 * @return HTTPRequest
262
+	 */
263
+	protected function getNewRequest(array $parameters)
264
+	{
265
+		return new HTTPRequest(
266
+			'get',
267
+			'TagFieldTestController/TagFieldTestForm/fields/Tags/suggest',
268
+			$parameters
269
+		);
270
+	}
271
+
272
+	public function testItDisplaysValuesFromRelations()
273
+	{
274
+		$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
275
+		$record->write();
276
+
277
+		$form = new Form(
278
+			new TagFieldTestController(),
279
+			'Form',
280
+			new FieldList(
281
+				$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class))
282
+			),
283
+			new FieldList()
284
+		);
285
+
286
+		$form->loadDataFrom(
287
+			$this->objFromFixture(TagFieldTestBlogPost::class, 'BlogPost2')
288
+		);
289
+
290
+		$ids = TagFieldTestBlogTag::get()->column('Title');
291
+
292
+		$this->assertEquals($field->Value(), $ids);
293
+	}
294
+
295
+	public function testItIgnoresNewTagsIfCannotCreate()
296
+	{
297
+		$this->markTestSkipped(
298
+			'This test has not been updated yet.'
299
+		);
300
+
301
+		$record = new TagFieldTestBlogPost();
302
+		$record->write();
303
+
304
+		$tag = TagFieldTestBlogTag::get()->filter('Title', 'Tag1')->first();
305
+
306
+		$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class), [$tag->Title, 'Tag3']);
307
+		$field->setCanCreate(false);
308
+		$field->saveInto($record);
309
+
310
+		/**
311
+		 * @var TagFieldTestBlogPost $record
312
+		 */
313
+		$record = DataObject::get_by_id(TagFieldTestBlogPost::class, $record->ID);
314
+
315
+		$this->compareExpectedAndActualTags(
316
+			['Tag1'],
317
+			$record
318
+		);
319
+	}
320
+
321
+	/**
322
+	 * Test you can save without a source set
323
+	 */
324
+	public function testSaveEmptySource()
325
+	{
326
+		$record = new TagFieldTestBlogPost();
327
+		$record->write();
328
+
329
+		// Clear database of tags
330
+		TagFieldTestBlogTag::get()->removeAll();
331
+
332
+		$field = new TagField('Tags', '', TagFieldTestBlogTag::get());
333
+		$field->setValue(['New Tag']);
334
+		$field->setCanCreate(true);
335
+		$field->saveInto($record);
336
+
337
+		$tag = TagFieldTestBlogTag::get()->first();
338
+		$this->assertNotEmpty($tag);
339
+		$this->assertEquals('New Tag', $tag->Title);
340
+		$record = TagFieldTestBlogPost::get()->byID($record->ID);
341
+		$this->assertEquals(
342
+			$tag->ID,
343
+			$record->Tags()->first()->ID
344
+		);
345
+	}
346
+
347
+	/**
348
+	 * Test read only fields are returned
349
+	 */
350
+	public function testReadonlyTransformation()
351
+	{
352
+		$field = new TagField('Tags', '', TagFieldTestBlogTag::get());
353
+		$readOnlyField = $field->performReadonlyTransformation();
354
+		$this->assertInstanceOf(ReadonlyTagField::class, $readOnlyField);
355
+	}
356
+
357
+	public function testGetSchemaDataDefaults()
358
+	{
359
+		$form = new Form(null, 'Form', new FieldList(), new FieldList());
360
+		$field = new TagField('TestField', 'Test Field', TagFieldTestBlogTag::get());
361
+		$field->setForm($form);
362
+
363
+		$field
364
+			->setShouldLazyLoad(false)
365
+			->setCanCreate(false);
366
+
367
+		$schema = $field->getSchemaDataDefaults();
368
+		$this->assertSame('TestField[]', $schema['name']);
369
+		$this->assertFalse($schema['lazyLoad']);
370
+		$this->assertFalse($schema['creatable']);
371
+		$this->assertEquals([
372
+			['Title' => 'Tag1', 'Value' => 'Tag1'],
373
+			['Title' => '222', 'Value' => '222'],
374
+		], $schema['options']);
375
+
376
+		$field
377
+			->setShouldLazyLoad(true)
378
+			->setCanCreate(true);
379
+
380
+		$schema = $field->getSchemaDataDefaults();
381
+		$this->assertTrue($schema['lazyLoad']);
382
+		$this->assertTrue($schema['creatable']);
383
+		$this->assertContains('suggest', $schema['optionUrl']);
384
+	}
385
+
386
+	public function testSchemaIsAddedToAttributes()
387
+	{
388
+		$field = new TagField('TestField');
389
+		$attributes = $field->getAttributes();
390
+		$this->assertNotEmpty($attributes['data-schema']);
391
+	}
392 392
 }
Please login to merge, or discard this patch.