Completed
Push — master ( 5f01c9...dbdbdd )
by Ingo
08:28
created
code/TagField.php 2 patches
Doc Comments   +1 added lines patch added patch discarded remove patch
@@ -235,6 +235,7 @@
 block discarded – undo
235 235
 
236 236
     /**
237 237
      * {@inheritdoc}
238
+     * @param string[] $value
238 239
      */
239 240
     public function setValue($value, $source = null)
240 241
     {
Please login to merge, or discard this patch.
Indentation   +397 added lines, -397 removed lines patch added patch discarded remove patch
@@ -8,401 +8,401 @@
 block discarded – undo
8 8
  */
9 9
 class TagField extends DropdownField
10 10
 {
11
-    /**
12
-     * @var array
13
-     */
14
-    public static $allowed_actions = array(
15
-        'suggest',
16
-    );
17
-
18
-    /**
19
-     * @var bool
20
-     */
21
-    protected $shouldLazyLoad = false;
22
-
23
-    /**
24
-     * @var int
25
-     */
26
-    protected $lazyLoadItemLimit = 10;
27
-
28
-    /**
29
-     * @var bool
30
-     */
31
-    protected $canCreate = true;
32
-
33
-    /**
34
-     * @var string
35
-     */
36
-    protected $titleField = 'Title';
37
-
38
-    /**
39
-     * @var bool
40
-     */
41
-    protected $isMultiple = true;
42
-
43
-    /**
44
-     * @param string $name
45
-     * @param string $title
46
-     * @param null|DataList $source
47
-     * @param null|DataList $value
48
-     */
49
-    public function __construct($name, $title = '', $source = null, $value = null)
50
-    {
51
-        parent::__construct($name, $title, $source, $value);
52
-    }
53
-
54
-    /**
55
-     * @return bool
56
-     */
57
-    public function getShouldLazyLoad()
58
-    {
59
-        return $this->shouldLazyLoad;
60
-    }
61
-
62
-    /**
63
-     * @param bool $shouldLazyLoad
64
-     *
65
-     * @return static
66
-     */
67
-    public function setShouldLazyLoad($shouldLazyLoad)
68
-    {
69
-        $this->shouldLazyLoad = $shouldLazyLoad;
70
-
71
-        return $this;
72
-    }
73
-
74
-    /**
75
-     * @return int
76
-     */
77
-    public function getLazyLoadItemLimit()
78
-    {
79
-        return $this->lazyLoadItemLimit;
80
-    }
81
-
82
-    /**
83
-     * @param int $lazyLoadItemLimit
84
-     *
85
-     * @return static
86
-     */
87
-    public function setLazyLoadItemLimit($lazyLoadItemLimit)
88
-    {
89
-        $this->lazyLoadItemLimit = $lazyLoadItemLimit;
90
-
91
-        return $this;
92
-    }
93
-
94
-    /**
95
-     * @return bool
96
-     */
97
-    public function getIsMultiple()
98
-    {
99
-        return $this->isMultiple;
100
-    }
101
-
102
-    /**
103
-     * @param bool $isMultiple
104
-     *
105
-     * @return static
106
-     */
107
-    public function setIsMultiple($isMultiple)
108
-    {
109
-        $this->isMultiple = $isMultiple;
110
-
111
-        return $this;
112
-    }
113
-
114
-    /**
115
-     * @return bool
116
-     */
117
-    public function getCanCreate()
118
-    {
119
-        return $this->canCreate;
120
-    }
121
-
122
-    /**
123
-     * @param bool $canCreate
124
-     *
125
-     * @return static
126
-     */
127
-    public function setCanCreate($canCreate)
128
-    {
129
-        $this->canCreate = $canCreate;
130
-
131
-        return $this;
132
-    }
133
-
134
-    /**
135
-     * @return string
136
-     */
137
-    public function getTitleField()
138
-    {
139
-        return $this->titleField;
140
-    }
141
-
142
-    /**
143
-     * @param string $titleField
144
-     *
145
-     * @return $this
146
-     */
147
-    public function setTitleField($titleField)
148
-    {
149
-        $this->titleField = $titleField;
150
-
151
-        return $this;
152
-    }
153
-
154
-    /**
155
-     * {@inheritdoc}
156
-     */
157
-    public function Field($properties = array())
158
-    {
159
-        Requirements::css(TAG_FIELD_DIR . '/css/select2.min.css');
160
-        Requirements::css(TAG_FIELD_DIR . '/css/TagField.css');
161
-
162
-        Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
163
-        Requirements::javascript(THIRDPARTY_DIR . '/jquery-entwine/dist/jquery.entwine-dist.js');
164
-        Requirements::javascript(TAG_FIELD_DIR . '/js/select2.js');
165
-        Requirements::javascript(TAG_FIELD_DIR . '/js/TagField.js');
166
-
167
-        $this->addExtraClass('ss-tag-field');
168
-
169
-        if ($this->getIsMultiple()) {
170
-            $this->setAttribute('multiple', 'multiple');
171
-        }
172
-
173
-        if ($this->shouldLazyLoad) {
174
-            $this->setAttribute('data-ss-tag-field-suggest-url', $this->getSuggestURL());
175
-        } else {
176
-            $properties = array_merge($properties, array(
177
-                'Options' => $this->getOptions()
178
-            ));
179
-        }
180
-
181
-        return $this
182
-            ->customise($properties)
183
-            ->renderWith(array("templates/TagField"));
184
-    }
185
-
186
-    /**
187
-     * @return string
188
-     */
189
-    protected function getSuggestURL()
190
-    {
191
-        return Controller::join_links($this->Link(), 'suggest');
192
-    }
193
-
194
-    /**
195
-     * @return ArrayList
196
-     */
197
-    protected function getOptions()
198
-    {
199
-        $options = ArrayList::create();
200
-
201
-        $source = $this->getSource();
202
-
203
-        if (!$source) {
204
-            $source = new ArrayList();
205
-        }
206
-
207
-        $dataClass = $source->dataClass();
208
-
209
-        $values = $this->Value();
210
-
211
-        if (!$values) {
212
-            return $options;
213
-        }
214
-
215
-        if (is_array($values)) {
216
-            $values = DataList::create($dataClass)->filter('ID', $values);
217
-        }
218
-
219
-        $ids = $values->column('ID');
220
-
221
-        $titleField = $this->getTitleField();
222
-
223
-        foreach ($source as $object) {
224
-            $options->push(
225
-                ArrayData::create(array(
226
-                    'Title' => $object->$titleField,
227
-                    'Value' => $object->ID,
228
-                    'Selected' => in_array($object->ID, $ids),
229
-                ))
230
-            );
231
-        }
232
-
233
-        return $options;
234
-    }
235
-
236
-    /**
237
-     * {@inheritdoc}
238
-     */
239
-    public function setValue($value, $source = null)
240
-    {
241
-        if ($source instanceof DataObject) {
242
-            $name = $this->getName();
243
-
244
-            if ($source->hasMethod($name)) {
245
-                $value = $source->$name()->getIDList();
246
-            }
247
-        } elseif ($value instanceof SS_List) {
248
-            $value = $value->column('ID');
249
-        }
250
-
251
-        if (!is_array($value)) {
252
-            return parent::setValue($value);
253
-        }
254
-
255
-        return parent::setValue(array_filter($value));
256
-    }
257
-
258
-    /**
259
-     * {@inheritdoc}
260
-     */
261
-    public function getAttributes()
262
-    {
263
-        return array_merge(
264
-            parent::getAttributes(),
265
-            array('name' => $this->getName() . '[]')
266
-        );
267
-    }
268
-
269
-    /**
270
-     * {@inheritdoc}
271
-     */
272
-    public function saveInto(DataObjectInterface $record)
273
-    {
274
-        parent::saveInto($record);
275
-
276
-        $name = $this->getName();
277
-        $titleField = $this->getTitleField();
278
-
279
-        $source = $this->getSource();
280
-
281
-        $values = $this->Value();
282
-
283
-        if (!$values) {
284
-            $values = array();
285
-        }
286
-
287
-        if (empty($record) || empty($source) || empty($titleField)) {
288
-            return;
289
-        }
290
-
291
-        if (!$record->hasMethod($name)) {
292
-            throw new Exception(
293
-                sprintf("%s does not have a %s method", get_class($record), $name)
294
-            );
295
-        }
296
-
297
-        $relation = $record->$name();
298
-
299
-        foreach ($values as $i => $value) {
300
-            if (!is_numeric($value)) {
301
-                if (!$this->getCanCreate()) {
302
-                    unset($values[$i]);
303
-                    continue;
304
-                }
305
-
306
-                // Get or create record
307
-                $record = $this->getOrCreateTag($value);
308
-                $values[$i] = $record->ID;
309
-            }
310
-        }
311
-
312
-        if ($values instanceof SS_List) {
313
-            $values = iterator_to_array($values);
314
-        }
315
-
316
-        $relation->setByIDList(array_filter($values));
317
-    }
318
-
319
-    /**
320
-     * Get or create tag with the given value
321
-     *
322
-     * @param string $term
323
-     * @return DataObject
324
-     */
325
-    protected function getOrCreateTag($term)
326
-    {
327
-        // Check if existing record can be found
328
-        $source = $this->getSource();
329
-        $titleField = $this->getTitleField();
330
-        $record = $source
331
-            ->filter($titleField, $term)
332
-            ->first();
333
-        if ($record) {
334
-            return $record;
335
-        }
336
-
337
-        // Create new instance if not yet saved
338
-        $dataClass = $source->dataClass();
339
-        $record = Injector::inst()->create($dataClass);
340
-        $record->{$titleField} = $term;
341
-        $record->write();
342
-        return $record;
343
-    }
344
-
345
-    /**
346
-     * Returns a JSON string of tags, for lazy loading.
347
-     *
348
-     * @param SS_HTTPRequest $request
349
-     *
350
-     * @return SS_HTTPResponse
351
-     */
352
-    public function suggest(SS_HTTPRequest $request)
353
-    {
354
-        $tags = $this->getTags($request->getVar('term'));
355
-
356
-        $response = new SS_HTTPResponse();
357
-        $response->addHeader('Content-Type', 'application/json');
358
-        $response->setBody(json_encode(array('items' => $tags)));
359
-
360
-        return $response;
361
-    }
362
-
363
-    /**
364
-     * Returns array of arrays representing tags.
365
-     *
366
-     * @param string $term
367
-     *
368
-     * @return array
369
-     */
370
-    protected function getTags($term)
371
-    {
372
-        /**
373
-         * @var DataList $source
374
-         */
375
-        $source = $this->getSource();
376
-
377
-        $titleField = $this->getTitleField();
378
-
379
-        $query = $source
380
-            ->filter($titleField . ':PartialMatch:nocase', $term)
381
-            ->sort($titleField)
382
-            ->limit($this->getLazyLoadItemLimit());
383
-
384
-        // Map into a distinct list
385
-        $items = array();
386
-        $titleField = $this->getTitleField();
387
-        foreach ($query->map('ID', $titleField) as $id => $title) {
388
-            $items[$title] = array(
389
-                'id' => $id,
390
-                'text' => $title
391
-            );
392
-        }
393
-
394
-        return array_values($items);
395
-    }
396
-
397
-    /**
398
-     * DropdownField assumes value will be a scalar so we must
399
-     * override validate. This only applies to Silverstripe 3.2+
400
-     *
401
-     * @param Validator $validator
402
-     * @return bool
403
-     */
404
-    public function validate($validator)
405
-    {
406
-        return true;
407
-    }
11
+	/**
12
+	 * @var array
13
+	 */
14
+	public static $allowed_actions = array(
15
+		'suggest',
16
+	);
17
+
18
+	/**
19
+	 * @var bool
20
+	 */
21
+	protected $shouldLazyLoad = false;
22
+
23
+	/**
24
+	 * @var int
25
+	 */
26
+	protected $lazyLoadItemLimit = 10;
27
+
28
+	/**
29
+	 * @var bool
30
+	 */
31
+	protected $canCreate = true;
32
+
33
+	/**
34
+	 * @var string
35
+	 */
36
+	protected $titleField = 'Title';
37
+
38
+	/**
39
+	 * @var bool
40
+	 */
41
+	protected $isMultiple = true;
42
+
43
+	/**
44
+	 * @param string $name
45
+	 * @param string $title
46
+	 * @param null|DataList $source
47
+	 * @param null|DataList $value
48
+	 */
49
+	public function __construct($name, $title = '', $source = null, $value = null)
50
+	{
51
+		parent::__construct($name, $title, $source, $value);
52
+	}
53
+
54
+	/**
55
+	 * @return bool
56
+	 */
57
+	public function getShouldLazyLoad()
58
+	{
59
+		return $this->shouldLazyLoad;
60
+	}
61
+
62
+	/**
63
+	 * @param bool $shouldLazyLoad
64
+	 *
65
+	 * @return static
66
+	 */
67
+	public function setShouldLazyLoad($shouldLazyLoad)
68
+	{
69
+		$this->shouldLazyLoad = $shouldLazyLoad;
70
+
71
+		return $this;
72
+	}
73
+
74
+	/**
75
+	 * @return int
76
+	 */
77
+	public function getLazyLoadItemLimit()
78
+	{
79
+		return $this->lazyLoadItemLimit;
80
+	}
81
+
82
+	/**
83
+	 * @param int $lazyLoadItemLimit
84
+	 *
85
+	 * @return static
86
+	 */
87
+	public function setLazyLoadItemLimit($lazyLoadItemLimit)
88
+	{
89
+		$this->lazyLoadItemLimit = $lazyLoadItemLimit;
90
+
91
+		return $this;
92
+	}
93
+
94
+	/**
95
+	 * @return bool
96
+	 */
97
+	public function getIsMultiple()
98
+	{
99
+		return $this->isMultiple;
100
+	}
101
+
102
+	/**
103
+	 * @param bool $isMultiple
104
+	 *
105
+	 * @return static
106
+	 */
107
+	public function setIsMultiple($isMultiple)
108
+	{
109
+		$this->isMultiple = $isMultiple;
110
+
111
+		return $this;
112
+	}
113
+
114
+	/**
115
+	 * @return bool
116
+	 */
117
+	public function getCanCreate()
118
+	{
119
+		return $this->canCreate;
120
+	}
121
+
122
+	/**
123
+	 * @param bool $canCreate
124
+	 *
125
+	 * @return static
126
+	 */
127
+	public function setCanCreate($canCreate)
128
+	{
129
+		$this->canCreate = $canCreate;
130
+
131
+		return $this;
132
+	}
133
+
134
+	/**
135
+	 * @return string
136
+	 */
137
+	public function getTitleField()
138
+	{
139
+		return $this->titleField;
140
+	}
141
+
142
+	/**
143
+	 * @param string $titleField
144
+	 *
145
+	 * @return $this
146
+	 */
147
+	public function setTitleField($titleField)
148
+	{
149
+		$this->titleField = $titleField;
150
+
151
+		return $this;
152
+	}
153
+
154
+	/**
155
+	 * {@inheritdoc}
156
+	 */
157
+	public function Field($properties = array())
158
+	{
159
+		Requirements::css(TAG_FIELD_DIR . '/css/select2.min.css');
160
+		Requirements::css(TAG_FIELD_DIR . '/css/TagField.css');
161
+
162
+		Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
163
+		Requirements::javascript(THIRDPARTY_DIR . '/jquery-entwine/dist/jquery.entwine-dist.js');
164
+		Requirements::javascript(TAG_FIELD_DIR . '/js/select2.js');
165
+		Requirements::javascript(TAG_FIELD_DIR . '/js/TagField.js');
166
+
167
+		$this->addExtraClass('ss-tag-field');
168
+
169
+		if ($this->getIsMultiple()) {
170
+			$this->setAttribute('multiple', 'multiple');
171
+		}
172
+
173
+		if ($this->shouldLazyLoad) {
174
+			$this->setAttribute('data-ss-tag-field-suggest-url', $this->getSuggestURL());
175
+		} else {
176
+			$properties = array_merge($properties, array(
177
+				'Options' => $this->getOptions()
178
+			));
179
+		}
180
+
181
+		return $this
182
+			->customise($properties)
183
+			->renderWith(array("templates/TagField"));
184
+	}
185
+
186
+	/**
187
+	 * @return string
188
+	 */
189
+	protected function getSuggestURL()
190
+	{
191
+		return Controller::join_links($this->Link(), 'suggest');
192
+	}
193
+
194
+	/**
195
+	 * @return ArrayList
196
+	 */
197
+	protected function getOptions()
198
+	{
199
+		$options = ArrayList::create();
200
+
201
+		$source = $this->getSource();
202
+
203
+		if (!$source) {
204
+			$source = new ArrayList();
205
+		}
206
+
207
+		$dataClass = $source->dataClass();
208
+
209
+		$values = $this->Value();
210
+
211
+		if (!$values) {
212
+			return $options;
213
+		}
214
+
215
+		if (is_array($values)) {
216
+			$values = DataList::create($dataClass)->filter('ID', $values);
217
+		}
218
+
219
+		$ids = $values->column('ID');
220
+
221
+		$titleField = $this->getTitleField();
222
+
223
+		foreach ($source as $object) {
224
+			$options->push(
225
+				ArrayData::create(array(
226
+					'Title' => $object->$titleField,
227
+					'Value' => $object->ID,
228
+					'Selected' => in_array($object->ID, $ids),
229
+				))
230
+			);
231
+		}
232
+
233
+		return $options;
234
+	}
235
+
236
+	/**
237
+	 * {@inheritdoc}
238
+	 */
239
+	public function setValue($value, $source = null)
240
+	{
241
+		if ($source instanceof DataObject) {
242
+			$name = $this->getName();
243
+
244
+			if ($source->hasMethod($name)) {
245
+				$value = $source->$name()->getIDList();
246
+			}
247
+		} elseif ($value instanceof SS_List) {
248
+			$value = $value->column('ID');
249
+		}
250
+
251
+		if (!is_array($value)) {
252
+			return parent::setValue($value);
253
+		}
254
+
255
+		return parent::setValue(array_filter($value));
256
+	}
257
+
258
+	/**
259
+	 * {@inheritdoc}
260
+	 */
261
+	public function getAttributes()
262
+	{
263
+		return array_merge(
264
+			parent::getAttributes(),
265
+			array('name' => $this->getName() . '[]')
266
+		);
267
+	}
268
+
269
+	/**
270
+	 * {@inheritdoc}
271
+	 */
272
+	public function saveInto(DataObjectInterface $record)
273
+	{
274
+		parent::saveInto($record);
275
+
276
+		$name = $this->getName();
277
+		$titleField = $this->getTitleField();
278
+
279
+		$source = $this->getSource();
280
+
281
+		$values = $this->Value();
282
+
283
+		if (!$values) {
284
+			$values = array();
285
+		}
286
+
287
+		if (empty($record) || empty($source) || empty($titleField)) {
288
+			return;
289
+		}
290
+
291
+		if (!$record->hasMethod($name)) {
292
+			throw new Exception(
293
+				sprintf("%s does not have a %s method", get_class($record), $name)
294
+			);
295
+		}
296
+
297
+		$relation = $record->$name();
298
+
299
+		foreach ($values as $i => $value) {
300
+			if (!is_numeric($value)) {
301
+				if (!$this->getCanCreate()) {
302
+					unset($values[$i]);
303
+					continue;
304
+				}
305
+
306
+				// Get or create record
307
+				$record = $this->getOrCreateTag($value);
308
+				$values[$i] = $record->ID;
309
+			}
310
+		}
311
+
312
+		if ($values instanceof SS_List) {
313
+			$values = iterator_to_array($values);
314
+		}
315
+
316
+		$relation->setByIDList(array_filter($values));
317
+	}
318
+
319
+	/**
320
+	 * Get or create tag with the given value
321
+	 *
322
+	 * @param string $term
323
+	 * @return DataObject
324
+	 */
325
+	protected function getOrCreateTag($term)
326
+	{
327
+		// Check if existing record can be found
328
+		$source = $this->getSource();
329
+		$titleField = $this->getTitleField();
330
+		$record = $source
331
+			->filter($titleField, $term)
332
+			->first();
333
+		if ($record) {
334
+			return $record;
335
+		}
336
+
337
+		// Create new instance if not yet saved
338
+		$dataClass = $source->dataClass();
339
+		$record = Injector::inst()->create($dataClass);
340
+		$record->{$titleField} = $term;
341
+		$record->write();
342
+		return $record;
343
+	}
344
+
345
+	/**
346
+	 * Returns a JSON string of tags, for lazy loading.
347
+	 *
348
+	 * @param SS_HTTPRequest $request
349
+	 *
350
+	 * @return SS_HTTPResponse
351
+	 */
352
+	public function suggest(SS_HTTPRequest $request)
353
+	{
354
+		$tags = $this->getTags($request->getVar('term'));
355
+
356
+		$response = new SS_HTTPResponse();
357
+		$response->addHeader('Content-Type', 'application/json');
358
+		$response->setBody(json_encode(array('items' => $tags)));
359
+
360
+		return $response;
361
+	}
362
+
363
+	/**
364
+	 * Returns array of arrays representing tags.
365
+	 *
366
+	 * @param string $term
367
+	 *
368
+	 * @return array
369
+	 */
370
+	protected function getTags($term)
371
+	{
372
+		/**
373
+		 * @var DataList $source
374
+		 */
375
+		$source = $this->getSource();
376
+
377
+		$titleField = $this->getTitleField();
378
+
379
+		$query = $source
380
+			->filter($titleField . ':PartialMatch:nocase', $term)
381
+			->sort($titleField)
382
+			->limit($this->getLazyLoadItemLimit());
383
+
384
+		// Map into a distinct list
385
+		$items = array();
386
+		$titleField = $this->getTitleField();
387
+		foreach ($query->map('ID', $titleField) as $id => $title) {
388
+			$items[$title] = array(
389
+				'id' => $id,
390
+				'text' => $title
391
+			);
392
+		}
393
+
394
+		return array_values($items);
395
+	}
396
+
397
+	/**
398
+	 * DropdownField assumes value will be a scalar so we must
399
+	 * override validate. This only applies to Silverstripe 3.2+
400
+	 *
401
+	 * @param Validator $validator
402
+	 * @return bool
403
+	 */
404
+	public function validate($validator)
405
+	{
406
+		return true;
407
+	}
408 408
 }
Please login to merge, or discard this patch.
tests/TagFieldTest.php 2 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -48,7 +48,7 @@
 block discarded – undo
48 48
     }
49 49
 
50 50
     /**
51
-     * @param array $expected
51
+     * @param string[] $expected
52 52
      * @param TagFieldTestBlogPost $record
53 53
      */
54 54
     protected function compareExpectedAndActualTags(array $expected, TagFieldTestBlogPost $record)
Please login to merge, or discard this patch.
Indentation   +357 added lines, -357 removed lines patch added patch discarded remove patch
@@ -5,329 +5,329 @@  discard block
 block discarded – undo
5 5
  */
6 6
 class TagFieldTest extends SapphireTest
7 7
 {
8
-    /**
9
-     * @var string
10
-     */
11
-    public static $fixture_file = 'tagfield/tests/TagFieldTest.yml';
12
-
13
-    /**
14
-     * @var array
15
-     */
16
-    protected $extraDataObjects = array(
17
-        'TagFieldTestBlogTag',
18
-        'TagFieldTestBlogPost',
19
-    );
20
-
21
-    public function testItSavesLinksToNewTagsOnNewRecords()
22
-    {
23
-        $record = $this->getNewTagFieldTestBlogPost('BlogPost1');
24
-
25
-        $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
26
-        $field->setValue(array('Tag3', 'Tag4'));
27
-        $field->saveInto($record);
28
-
29
-        $record->write();
30
-
31
-        $this->compareExpectedAndActualTags(
32
-            array('Tag3', 'Tag4'),
33
-            $record
34
-        );
35
-    }
36
-
37
-    /**
38
-     * @param string $name
39
-     *
40
-     * @return TagFieldTestBlogPost
41
-     */
42
-    protected function getNewTagFieldTestBlogPost($name)
43
-    {
44
-        return $this->objFromFixture(
45
-            'TagFieldTestBlogPost',
46
-            $name
47
-        );
48
-    }
49
-
50
-    /**
51
-     * @param array $expected
52
-     * @param TagFieldTestBlogPost $record
53
-     */
54
-    protected function compareExpectedAndActualTags(array $expected, TagFieldTestBlogPost $record)
55
-    {
56
-        $this->compareTagLists($expected, $record->Tags());
57
-    }
58
-
59
-    /**
60
-     * Ensure a source of tags matches the given string tag names
61
-     *
62
-     * @param array $expected
63
-     * @param DataList $actualSource
64
-     */
65
-    protected function compareTagLists(array $expected, DataList $actualSource)
66
-    {
67
-        $actual = array_values($actualSource->map('ID', 'Title')->toArray());
68
-
69
-        sort($expected);
70
-        sort($actual);
71
-
72
-        $this->assertEquals(
73
-            $expected,
74
-            $actual
75
-        );
76
-    }
77
-
78
-    public function testItSavesLinksToNewTagsOnExistingRecords()
79
-    {
80
-        $record = $this->getNewTagFieldTestBlogPost('BlogPost1');
81
-        $record->write();
82
-
83
-        $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
84
-        $field->setValue(array('Tag3', 'Tag4'));
85
-        $field->saveInto($record);
86
-
87
-        $this->compareExpectedAndActualTags(
88
-            array('Tag3', 'Tag4'),
89
-            $record
90
-        );
91
-    }
92
-
93
-    public function testItSavesLinksToExistingTagsOnNewRecords()
94
-    {
95
-        $record = $this->getNewTagFieldTestBlogPost('BlogPost1');
96
-
97
-        $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
98
-        $field->setValue(array('Tag1', 'Tag2'));
99
-        $field->saveInto($record);
100
-
101
-        $record->write();
102
-
103
-        $this->compareExpectedAndActualTags(
104
-            array('Tag1', 'Tag2'),
105
-            $record
106
-        );
107
-    }
108
-
109
-    public function testItSavesLinksToExistingTagsOnExistingRecords()
110
-    {
111
-        $record = $this->getNewTagFieldTestBlogPost('BlogPost1');
112
-        $record->write();
113
-
114
-        $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
115
-        $field->setValue(array('Tag1', 'Tag2'));
116
-        $field->saveInto($record);
117
-
118
-        $this->compareExpectedAndActualTags(
119
-            array('Tag1', 'Tag2'),
120
-            $record
121
-        );
122
-    }
123
-
124
-    /**
125
-     * Ensure that {@see TagField::saveInto} respects existing tags
126
-     */
127
-    public function testSaveDuplicateTags()
128
-    {
129
-        $record = $this->getNewTagFieldTestBlogPost('BlogPost2');
130
-        $record->write();
131
-        $tag2ID = $this->idFromFixture('TagFieldTestBlogTag', 'Tag2');
132
-
133
-        // Check tags before write
134
-        $this->compareExpectedAndActualTags(
135
-            array('Tag1', 'Tag2'),
136
-            $record
137
-        );
138
-        $this->compareTagLists(
139
-            array('Tag1', 'Tag2'),
140
-            TagFieldTestBlogTag::get()
141
-        );
142
-        $this->assertContains($tag2ID, TagFieldTestBlogTag::get()->column('ID'));
143
-
144
-        // Write new tags
145
-        $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
146
-        $field->setValue(array('Tag2', 'Tag3'));
147
-        $field->saveInto($record);
148
-
149
-        // Check only one new tag was added
150
-        $this->compareExpectedAndActualTags(
151
-            array('Tag2', 'Tag3'),
152
-            $record
153
-        );
154
-
155
-        // Ensure that only one new dataobject was added and that tag2s id has not changed
156
-        $this->compareTagLists(
157
-            array('Tag1', 'Tag2', 'Tag3'),
158
-            TagFieldTestBlogTag::get()
159
-        );
160
-        $this->assertContains($tag2ID, TagFieldTestBlogTag::get()->column('ID'));
161
-    }
162
-
163
-    public function testItSuggestsTags()
164
-    {
165
-        $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
166
-
167
-        /**
168
-         * Partial tag title match.
169
-         */
170
-        $request = $this->getNewRequest(array('term' => 'Tag'));
171
-
172
-        $tag1ID = $this->idFromFixture('TagFieldTestBlogTag', 'Tag1');
173
-        $tag2ID = $this->idFromFixture('TagFieldTestBlogTag', 'Tag2');
174
-
175
-        $this->assertEquals(
176
-            sprintf('{"items":[{"id":%d,"text":"Tag1"},{"id":%d,"text":"Tag2"}]}', $tag1ID, $tag2ID),
177
-            $field->suggest($request)->getBody()
178
-        );
179
-
180
-        /**
181
-         * Exact tag title match.
182
-         */
183
-        $request = $this->getNewRequest(array('term' => 'Tag1'));
184
-
185
-        $this->assertEquals(
186
-            sprintf('{"items":[{"id":%d,"text":"Tag1"}]}', $tag1ID),
187
-            $field->suggest($request)->getBody()
188
-        );
189
-
190
-        /**
191
-         * Case-insensitive tag title match.
192
-         */
193
-        $request = $this->getNewRequest(array('term' => 'TAG1'));
194
-
195
-        $this->assertEquals(
196
-            sprintf('{"items":[{"id":%d,"text":"Tag1"}]}', $tag1ID),
197
-            $field->suggest($request)->getBody()
198
-        );
199
-
200
-        /**
201
-         * No tag title match.
202
-         */
203
-        $request = $this->getNewRequest(array('term' => 'unknown'));
204
-
205
-        $this->assertEquals(
206
-            '{"items":[]}',
207
-            $field->suggest($request)->getBody()
208
-        );
209
-    }
210
-
211
-    /**
212
-     * Tests that TagField supports pre-filtered data sources
213
-     */
214
-    public function testRestrictedSuggestions()
215
-    {
216
-        $source = TagFieldTestBlogTag::get()->exclude('Title', 'Tag2');
217
-        $field = new TagField('Tags', '', $source);
218
-        $tag1ID = $this->idFromFixture('TagFieldTestBlogTag', 'Tag1');
219
-
220
-        /**
221
-         * Partial tag title match.
222
-         */
223
-        $request = $this->getNewRequest(array('term' => 'Tag'));
224
-
225
-        $this->assertEquals(
226
-            sprintf('{"items":[{"id":%d,"text":"Tag1"}]}', $tag1ID),
227
-            $field->suggest($request)->getBody()
228
-        );
229
-
230
-        /**
231
-         * Exact tag title match.
232
-         */
233
-        $request = $this->getNewRequest(array('term' => 'Tag1'));
234
-
235
-        $this->assertEquals(
236
-            sprintf('{"items":[{"id":%d,"text":"Tag1"}]}', $tag1ID),
237
-            $field->suggest($request)->getBody()
238
-        );
239
-
240
-        /**
241
-         * Excluded item doesn't appear in matches
242
-         */
243
-        $request = $this->getNewRequest(array('term' => 'Tag2'));
244
-
245
-        $this->assertEquals(
246
-            '{"items":[]}',
247
-            $field->suggest($request)->getBody()
248
-        );
249
-    }
250
-
251
-    /**
252
-     * @param array $parameters
253
-     *
254
-     * @return SS_HTTPRequest
255
-     */
256
-    protected function getNewRequest(array $parameters)
257
-    {
258
-        return new SS_HTTPRequest(
259
-            'get',
260
-            'TagFieldTestController/TagFieldTestForm/fields/Tags/suggest',
261
-            $parameters
262
-        );
263
-    }
264
-
265
-    public function testItDisplaysValuesFromRelations()
266
-    {
267
-        $record = $this->getNewTagFieldTestBlogPost('BlogPost1');
268
-        $record->write();
269
-
270
-        $form = new Form(
271
-            new TagFieldTestController($record),
272
-            'Form',
273
-            new FieldList(
274
-                $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'))
275
-            ),
276
-            new FieldList()
277
-        );
278
-
279
-        $form->loadDataFrom(
280
-            $this->objFromFixture('TagFieldTestBlogPost', 'BlogPost2')
281
-        );
282
-
283
-        $ids = TagFieldTestBlogTag::get()->map('ID', 'ID')->toArray();
284
-
285
-        $this->assertEquals($field->Value(), $ids);
286
-    }
287
-
288
-    public function testItIgnoresNewTagsIfCannotCreate()
289
-    {
290
-        $record = new TagFieldTestBlogPost();
291
-        $record->write();
292
-
293
-        $tag = TagFieldTestBlogTag::get()->filter('Title', 'Tag1')->first();
294
-
295
-        $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'), array($tag->ID, 'Tag3'));
296
-        $field->setCanCreate(false);
297
-        $field->saveInto($record);
298
-
299
-        /**
300
-         * @var TagFieldTestBlogPost $record
301
-         */
302
-        $record = DataObject::get_by_id('TagFieldTestBlogPost', $record->ID);
303
-
304
-        $this->compareExpectedAndActualTags(
305
-            array('Tag1'),
306
-            $record
307
-        );
308
-    }
8
+	/**
9
+	 * @var string
10
+	 */
11
+	public static $fixture_file = 'tagfield/tests/TagFieldTest.yml';
12
+
13
+	/**
14
+	 * @var array
15
+	 */
16
+	protected $extraDataObjects = array(
17
+		'TagFieldTestBlogTag',
18
+		'TagFieldTestBlogPost',
19
+	);
20
+
21
+	public function testItSavesLinksToNewTagsOnNewRecords()
22
+	{
23
+		$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
24
+
25
+		$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
26
+		$field->setValue(array('Tag3', 'Tag4'));
27
+		$field->saveInto($record);
28
+
29
+		$record->write();
30
+
31
+		$this->compareExpectedAndActualTags(
32
+			array('Tag3', 'Tag4'),
33
+			$record
34
+		);
35
+	}
36
+
37
+	/**
38
+	 * @param string $name
39
+	 *
40
+	 * @return TagFieldTestBlogPost
41
+	 */
42
+	protected function getNewTagFieldTestBlogPost($name)
43
+	{
44
+		return $this->objFromFixture(
45
+			'TagFieldTestBlogPost',
46
+			$name
47
+		);
48
+	}
49
+
50
+	/**
51
+	 * @param array $expected
52
+	 * @param TagFieldTestBlogPost $record
53
+	 */
54
+	protected function compareExpectedAndActualTags(array $expected, TagFieldTestBlogPost $record)
55
+	{
56
+		$this->compareTagLists($expected, $record->Tags());
57
+	}
58
+
59
+	/**
60
+	 * Ensure a source of tags matches the given string tag names
61
+	 *
62
+	 * @param array $expected
63
+	 * @param DataList $actualSource
64
+	 */
65
+	protected function compareTagLists(array $expected, DataList $actualSource)
66
+	{
67
+		$actual = array_values($actualSource->map('ID', 'Title')->toArray());
68
+
69
+		sort($expected);
70
+		sort($actual);
71
+
72
+		$this->assertEquals(
73
+			$expected,
74
+			$actual
75
+		);
76
+	}
77
+
78
+	public function testItSavesLinksToNewTagsOnExistingRecords()
79
+	{
80
+		$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
81
+		$record->write();
82
+
83
+		$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
84
+		$field->setValue(array('Tag3', 'Tag4'));
85
+		$field->saveInto($record);
86
+
87
+		$this->compareExpectedAndActualTags(
88
+			array('Tag3', 'Tag4'),
89
+			$record
90
+		);
91
+	}
92
+
93
+	public function testItSavesLinksToExistingTagsOnNewRecords()
94
+	{
95
+		$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
96
+
97
+		$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
98
+		$field->setValue(array('Tag1', 'Tag2'));
99
+		$field->saveInto($record);
100
+
101
+		$record->write();
102
+
103
+		$this->compareExpectedAndActualTags(
104
+			array('Tag1', 'Tag2'),
105
+			$record
106
+		);
107
+	}
108
+
109
+	public function testItSavesLinksToExistingTagsOnExistingRecords()
110
+	{
111
+		$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
112
+		$record->write();
113
+
114
+		$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
115
+		$field->setValue(array('Tag1', 'Tag2'));
116
+		$field->saveInto($record);
117
+
118
+		$this->compareExpectedAndActualTags(
119
+			array('Tag1', 'Tag2'),
120
+			$record
121
+		);
122
+	}
123
+
124
+	/**
125
+	 * Ensure that {@see TagField::saveInto} respects existing tags
126
+	 */
127
+	public function testSaveDuplicateTags()
128
+	{
129
+		$record = $this->getNewTagFieldTestBlogPost('BlogPost2');
130
+		$record->write();
131
+		$tag2ID = $this->idFromFixture('TagFieldTestBlogTag', 'Tag2');
132
+
133
+		// Check tags before write
134
+		$this->compareExpectedAndActualTags(
135
+			array('Tag1', 'Tag2'),
136
+			$record
137
+		);
138
+		$this->compareTagLists(
139
+			array('Tag1', 'Tag2'),
140
+			TagFieldTestBlogTag::get()
141
+		);
142
+		$this->assertContains($tag2ID, TagFieldTestBlogTag::get()->column('ID'));
143
+
144
+		// Write new tags
145
+		$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
146
+		$field->setValue(array('Tag2', 'Tag3'));
147
+		$field->saveInto($record);
148
+
149
+		// Check only one new tag was added
150
+		$this->compareExpectedAndActualTags(
151
+			array('Tag2', 'Tag3'),
152
+			$record
153
+		);
154
+
155
+		// Ensure that only one new dataobject was added and that tag2s id has not changed
156
+		$this->compareTagLists(
157
+			array('Tag1', 'Tag2', 'Tag3'),
158
+			TagFieldTestBlogTag::get()
159
+		);
160
+		$this->assertContains($tag2ID, TagFieldTestBlogTag::get()->column('ID'));
161
+	}
162
+
163
+	public function testItSuggestsTags()
164
+	{
165
+		$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
166
+
167
+		/**
168
+		 * Partial tag title match.
169
+		 */
170
+		$request = $this->getNewRequest(array('term' => 'Tag'));
171
+
172
+		$tag1ID = $this->idFromFixture('TagFieldTestBlogTag', 'Tag1');
173
+		$tag2ID = $this->idFromFixture('TagFieldTestBlogTag', 'Tag2');
174
+
175
+		$this->assertEquals(
176
+			sprintf('{"items":[{"id":%d,"text":"Tag1"},{"id":%d,"text":"Tag2"}]}', $tag1ID, $tag2ID),
177
+			$field->suggest($request)->getBody()
178
+		);
179
+
180
+		/**
181
+		 * Exact tag title match.
182
+		 */
183
+		$request = $this->getNewRequest(array('term' => 'Tag1'));
184
+
185
+		$this->assertEquals(
186
+			sprintf('{"items":[{"id":%d,"text":"Tag1"}]}', $tag1ID),
187
+			$field->suggest($request)->getBody()
188
+		);
189
+
190
+		/**
191
+		 * Case-insensitive tag title match.
192
+		 */
193
+		$request = $this->getNewRequest(array('term' => 'TAG1'));
194
+
195
+		$this->assertEquals(
196
+			sprintf('{"items":[{"id":%d,"text":"Tag1"}]}', $tag1ID),
197
+			$field->suggest($request)->getBody()
198
+		);
199
+
200
+		/**
201
+		 * No tag title match.
202
+		 */
203
+		$request = $this->getNewRequest(array('term' => 'unknown'));
204
+
205
+		$this->assertEquals(
206
+			'{"items":[]}',
207
+			$field->suggest($request)->getBody()
208
+		);
209
+	}
210
+
211
+	/**
212
+	 * Tests that TagField supports pre-filtered data sources
213
+	 */
214
+	public function testRestrictedSuggestions()
215
+	{
216
+		$source = TagFieldTestBlogTag::get()->exclude('Title', 'Tag2');
217
+		$field = new TagField('Tags', '', $source);
218
+		$tag1ID = $this->idFromFixture('TagFieldTestBlogTag', 'Tag1');
219
+
220
+		/**
221
+		 * Partial tag title match.
222
+		 */
223
+		$request = $this->getNewRequest(array('term' => 'Tag'));
224
+
225
+		$this->assertEquals(
226
+			sprintf('{"items":[{"id":%d,"text":"Tag1"}]}', $tag1ID),
227
+			$field->suggest($request)->getBody()
228
+		);
229
+
230
+		/**
231
+		 * Exact tag title match.
232
+		 */
233
+		$request = $this->getNewRequest(array('term' => 'Tag1'));
234
+
235
+		$this->assertEquals(
236
+			sprintf('{"items":[{"id":%d,"text":"Tag1"}]}', $tag1ID),
237
+			$field->suggest($request)->getBody()
238
+		);
239
+
240
+		/**
241
+		 * Excluded item doesn't appear in matches
242
+		 */
243
+		$request = $this->getNewRequest(array('term' => 'Tag2'));
244
+
245
+		$this->assertEquals(
246
+			'{"items":[]}',
247
+			$field->suggest($request)->getBody()
248
+		);
249
+	}
250
+
251
+	/**
252
+	 * @param array $parameters
253
+	 *
254
+	 * @return SS_HTTPRequest
255
+	 */
256
+	protected function getNewRequest(array $parameters)
257
+	{
258
+		return new SS_HTTPRequest(
259
+			'get',
260
+			'TagFieldTestController/TagFieldTestForm/fields/Tags/suggest',
261
+			$parameters
262
+		);
263
+	}
264
+
265
+	public function testItDisplaysValuesFromRelations()
266
+	{
267
+		$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
268
+		$record->write();
269
+
270
+		$form = new Form(
271
+			new TagFieldTestController($record),
272
+			'Form',
273
+			new FieldList(
274
+				$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'))
275
+			),
276
+			new FieldList()
277
+		);
278
+
279
+		$form->loadDataFrom(
280
+			$this->objFromFixture('TagFieldTestBlogPost', 'BlogPost2')
281
+		);
282
+
283
+		$ids = TagFieldTestBlogTag::get()->map('ID', 'ID')->toArray();
284
+
285
+		$this->assertEquals($field->Value(), $ids);
286
+	}
287
+
288
+	public function testItIgnoresNewTagsIfCannotCreate()
289
+	{
290
+		$record = new TagFieldTestBlogPost();
291
+		$record->write();
292
+
293
+		$tag = TagFieldTestBlogTag::get()->filter('Title', 'Tag1')->first();
294
+
295
+		$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'), array($tag->ID, 'Tag3'));
296
+		$field->setCanCreate(false);
297
+		$field->saveInto($record);
298
+
299
+		/**
300
+		 * @var TagFieldTestBlogPost $record
301
+		 */
302
+		$record = DataObject::get_by_id('TagFieldTestBlogPost', $record->ID);
303
+
304
+		$this->compareExpectedAndActualTags(
305
+			array('Tag1'),
306
+			$record
307
+		);
308
+	}
309 309
 }
310 310
 
311 311
 class TagFieldTestBlogTag extends DataObject implements TestOnly
312 312
 {
313
-    /**
314
-     * @var string
315
-     */
316
-    private static $default_sort = '"TagFieldTestBlogTag"."ID" ASC';
317
-
318
-    /**
319
-     * @var array
320
-     */
321
-    private static $db = array(
322
-        'Title' => 'Varchar(200)',
323
-    );
324
-
325
-    /**
326
-     * @var array
327
-     */
328
-    private static $belongs_many_many = array(
329
-        'BlogPosts' => 'TagFieldTestBlogPost',
330
-    );
313
+	/**
314
+	 * @var string
315
+	 */
316
+	private static $default_sort = '"TagFieldTestBlogTag"."ID" ASC';
317
+
318
+	/**
319
+	 * @var array
320
+	 */
321
+	private static $db = array(
322
+		'Title' => 'Varchar(200)',
323
+	);
324
+
325
+	/**
326
+	 * @var array
327
+	 */
328
+	private static $belongs_many_many = array(
329
+		'BlogPosts' => 'TagFieldTestBlogPost',
330
+	);
331 331
 }
332 332
 
333 333
 /**
@@ -335,46 +335,46 @@  discard block
 block discarded – undo
335 335
  */
336 336
 class TagFieldTestBlogPost extends DataObject implements TestOnly
337 337
 {
338
-    /**
339
-     * @var array
340
-     */
341
-    private static $db = array(
342
-        'Title' => 'Text',
343
-        'Content' => 'Text',
344
-    );
345
-
346
-    /**
347
-     * @var array
348
-     */
349
-    private static $many_many = array(
350
-        'Tags' => 'TagFieldTestBlogTag',
351
-    );
338
+	/**
339
+	 * @var array
340
+	 */
341
+	private static $db = array(
342
+		'Title' => 'Text',
343
+		'Content' => 'Text',
344
+	);
345
+
346
+	/**
347
+	 * @var array
348
+	 */
349
+	private static $many_many = array(
350
+		'Tags' => 'TagFieldTestBlogTag',
351
+	);
352 352
 }
353 353
 
354 354
 class TagFieldTestController extends Controller implements TestOnly
355 355
 {
356
-    /**
357
-     * @return Form
358
-     */
359
-    public function TagFieldTestForm()
360
-    {
361
-        $fields = new FieldList(
362
-            $tagField = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'))
363
-        );
364
-
365
-        $actions = new FieldList(
366
-            new FormAction('TagFieldTestFormSubmit')
367
-        );
368
-
369
-        return new Form($this, 'TagFieldTestForm', $fields, $actions);
370
-    }
371
-
372
-    /**
373
-     * @param DataObject $dataObject
374
-     * @param Form $form
375
-     */
376
-    public function TagFieldTestFormSubmit(DataObject $dataObject, Form $form)
377
-    {
378
-        $form->saveInto($dataObject);
379
-    }
356
+	/**
357
+	 * @return Form
358
+	 */
359
+	public function TagFieldTestForm()
360
+	{
361
+		$fields = new FieldList(
362
+			$tagField = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'))
363
+		);
364
+
365
+		$actions = new FieldList(
366
+			new FormAction('TagFieldTestFormSubmit')
367
+		);
368
+
369
+		return new Form($this, 'TagFieldTestForm', $fields, $actions);
370
+	}
371
+
372
+	/**
373
+	 * @param DataObject $dataObject
374
+	 * @param Form $form
375
+	 */
376
+	public function TagFieldTestFormSubmit(DataObject $dataObject, Form $form)
377
+	{
378
+		$form->saveInto($dataObject);
379
+	}
380 380
 }
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
@@ -5,114 +5,114 @@  discard block
 block discarded – undo
5 5
  */
6 6
 class StringTagFieldTest extends SapphireTest
7 7
 {
8
-    /**
9
-     * @var string
10
-     */
11
-    public static $fixture_file = 'tagfield/tests/StringTagFieldTest.yml';
12
-
13
-    /**
14
-     * @var array
15
-     */
16
-    protected $extraDataObjects = array(
17
-        'StringTagFieldTestBlogPost',
18
-    );
19
-
20
-    public function testItSavesTagsOnNewRecords()
21
-    {
22
-        $record = $this->getNewStringTagFieldTestBlogPost('BlogPost1');
23
-
24
-        $field = new StringTagField('Tags');
25
-        $field->setValue(array('Tag1', 'Tag2'));
26
-        $field->saveInto($record);
27
-
28
-        $record->write();
29
-
30
-        $this->assertEquals('Tag1,Tag2', $record->Tags);
31
-    }
32
-
33
-    /**
34
-     * @param string $name
35
-     *
36
-     * @return StringTagFieldTestBlogPost
37
-     */
38
-    protected function getNewStringTagFieldTestBlogPost($name)
39
-    {
40
-        return $this->objFromFixture(
41
-            'StringTagFieldTestBlogPost',
42
-            $name
43
-        );
44
-    }
45
-
46
-    public function testItSavesTagsOnExistingRecords()
47
-    {
48
-        $record = $this->getNewStringTagFieldTestBlogPost('BlogPost1');
49
-        $record->write();
50
-
51
-        $field = new StringTagField('Tags');
52
-        $field->setValue(array('Tag1', 'Tag2'));
53
-        $field->saveInto($record);
54
-
55
-        $this->assertEquals('Tag1,Tag2', $record->Tags);
56
-    }
57
-
58
-    public function testItSuggestsTags()
59
-    {
60
-        $record = $this->getNewStringTagFieldTestBlogPost('BlogPost2');
61
-
62
-        $field = new StringTagField('Tags');
63
-        $field->setRecord($record);
64
-
65
-        /**
66
-         * Partial tag title match.
67
-         */
68
-        $request = $this->getNewRequest(array('term' => 'Tag'));
69
-
70
-        $this->assertEquals(
71
-            '{"items":[{"id":"Tag1","text":"Tag1"},{"id":"Tag2","text":"Tag2"}]}',
72
-            $field->suggest($request)->getBody()
73
-        );
74
-
75
-        /**
76
-         * Exact tag title match.
77
-         */
78
-        $request = $this->getNewRequest(array('term' => 'Tag1'));
79
-
80
-        $this->assertEquals($field->suggest($request)->getBody(), '{"items":[{"id":"Tag1","text":"Tag1"}]}');
81
-
82
-        /**
83
-         * Case-insensitive tag title match.
84
-         */
85
-        $request = $this->getNewRequest(array('term' => 'TAG1'));
86
-
87
-        $this->assertEquals(
88
-            '{"items":[{"id":"Tag1","text":"Tag1"}]}',
89
-            $field->suggest($request)->getBody()
90
-        );
91
-
92
-        /**
93
-         * No tag title match.
94
-         */
95
-        $request = $this->getNewRequest(array('term' => 'unknown'));
96
-
97
-        $this->assertEquals(
98
-            '{"items":[]}',
99
-            $field->suggest($request)->getBody()
100
-        );
101
-    }
102
-
103
-    /**
104
-     * @param array $parameters
105
-     *
106
-     * @return SS_HTTPRequest
107
-     */
108
-    protected function getNewRequest(array $parameters)
109
-    {
110
-        return new SS_HTTPRequest(
111
-            'get',
112
-            'StringTagFieldTestController/StringTagFieldTestForm/fields/Tags/suggest',
113
-            $parameters
114
-        );
115
-    }
8
+	/**
9
+	 * @var string
10
+	 */
11
+	public static $fixture_file = 'tagfield/tests/StringTagFieldTest.yml';
12
+
13
+	/**
14
+	 * @var array
15
+	 */
16
+	protected $extraDataObjects = array(
17
+		'StringTagFieldTestBlogPost',
18
+	);
19
+
20
+	public function testItSavesTagsOnNewRecords()
21
+	{
22
+		$record = $this->getNewStringTagFieldTestBlogPost('BlogPost1');
23
+
24
+		$field = new StringTagField('Tags');
25
+		$field->setValue(array('Tag1', 'Tag2'));
26
+		$field->saveInto($record);
27
+
28
+		$record->write();
29
+
30
+		$this->assertEquals('Tag1,Tag2', $record->Tags);
31
+	}
32
+
33
+	/**
34
+	 * @param string $name
35
+	 *
36
+	 * @return StringTagFieldTestBlogPost
37
+	 */
38
+	protected function getNewStringTagFieldTestBlogPost($name)
39
+	{
40
+		return $this->objFromFixture(
41
+			'StringTagFieldTestBlogPost',
42
+			$name
43
+		);
44
+	}
45
+
46
+	public function testItSavesTagsOnExistingRecords()
47
+	{
48
+		$record = $this->getNewStringTagFieldTestBlogPost('BlogPost1');
49
+		$record->write();
50
+
51
+		$field = new StringTagField('Tags');
52
+		$field->setValue(array('Tag1', 'Tag2'));
53
+		$field->saveInto($record);
54
+
55
+		$this->assertEquals('Tag1,Tag2', $record->Tags);
56
+	}
57
+
58
+	public function testItSuggestsTags()
59
+	{
60
+		$record = $this->getNewStringTagFieldTestBlogPost('BlogPost2');
61
+
62
+		$field = new StringTagField('Tags');
63
+		$field->setRecord($record);
64
+
65
+		/**
66
+		 * Partial tag title match.
67
+		 */
68
+		$request = $this->getNewRequest(array('term' => 'Tag'));
69
+
70
+		$this->assertEquals(
71
+			'{"items":[{"id":"Tag1","text":"Tag1"},{"id":"Tag2","text":"Tag2"}]}',
72
+			$field->suggest($request)->getBody()
73
+		);
74
+
75
+		/**
76
+		 * Exact tag title match.
77
+		 */
78
+		$request = $this->getNewRequest(array('term' => 'Tag1'));
79
+
80
+		$this->assertEquals($field->suggest($request)->getBody(), '{"items":[{"id":"Tag1","text":"Tag1"}]}');
81
+
82
+		/**
83
+		 * Case-insensitive tag title match.
84
+		 */
85
+		$request = $this->getNewRequest(array('term' => 'TAG1'));
86
+
87
+		$this->assertEquals(
88
+			'{"items":[{"id":"Tag1","text":"Tag1"}]}',
89
+			$field->suggest($request)->getBody()
90
+		);
91
+
92
+		/**
93
+		 * No tag title match.
94
+		 */
95
+		$request = $this->getNewRequest(array('term' => 'unknown'));
96
+
97
+		$this->assertEquals(
98
+			'{"items":[]}',
99
+			$field->suggest($request)->getBody()
100
+		);
101
+	}
102
+
103
+	/**
104
+	 * @param array $parameters
105
+	 *
106
+	 * @return SS_HTTPRequest
107
+	 */
108
+	protected function getNewRequest(array $parameters)
109
+	{
110
+		return new SS_HTTPRequest(
111
+			'get',
112
+			'StringTagFieldTestController/StringTagFieldTestForm/fields/Tags/suggest',
113
+			$parameters
114
+		);
115
+	}
116 116
 }
117 117
 
118 118
 /**
@@ -120,40 +120,40 @@  discard block
 block discarded – undo
120 120
  */
121 121
 class StringTagFieldTestBlogPost extends DataObject implements TestOnly
122 122
 {
123
-    /**
124
-     * @var array
125
-     */
126
-    private static $db = array(
127
-        'Title' => 'Text',
128
-        'Content' => 'Text',
129
-        'Tags' => 'Text',
130
-    );
123
+	/**
124
+	 * @var array
125
+	 */
126
+	private static $db = array(
127
+		'Title' => 'Text',
128
+		'Content' => 'Text',
129
+		'Tags' => 'Text',
130
+	);
131 131
 }
132 132
 
133 133
 class StringTagFieldTestController extends Controller implements TestOnly
134 134
 {
135
-    /**
136
-     * @return Form
137
-     */
138
-    public function StringTagFieldTestForm()
139
-    {
140
-        $fields = new FieldList(
141
-            $tagField = new StringTagField('Tags')
142
-        );
143
-
144
-        $actions = new FieldList(
145
-            new FormAction('StringTagFieldTestFormSubmit')
146
-        );
147
-
148
-        return new Form($this, 'StringTagFieldTestForm', $fields, $actions);
149
-    }
150
-
151
-    /**
152
-     * @param DataObject $dataObject
153
-     * @param Form $form
154
-     */
155
-    public function StringTagFieldTestFormSubmit(DataObject $dataObject, Form $form)
156
-    {
157
-        $form->saveInto($dataObject);
158
-    }
135
+	/**
136
+	 * @return Form
137
+	 */
138
+	public function StringTagFieldTestForm()
139
+	{
140
+		$fields = new FieldList(
141
+			$tagField = new StringTagField('Tags')
142
+		);
143
+
144
+		$actions = new FieldList(
145
+			new FormAction('StringTagFieldTestFormSubmit')
146
+		);
147
+
148
+		return new Form($this, 'StringTagFieldTestForm', $fields, $actions);
149
+	}
150
+
151
+	/**
152
+	 * @param DataObject $dataObject
153
+	 * @param Form $form
154
+	 */
155
+	public function StringTagFieldTestFormSubmit(DataObject $dataObject, Form $form)
156
+	{
157
+		$form->saveInto($dataObject);
158
+	}
159 159
 }
Please login to merge, or discard this patch.
code/StringTagField.php 2 patches
Doc Comments   +1 added lines patch added patch discarded remove patch
@@ -235,6 +235,7 @@
 block discarded – undo
235 235
 
236 236
     /**
237 237
      * {@inheritdoc}
238
+     * @param string[] $value
238 239
      */
239 240
     public function setValue($value, $source = null)
240 241
     {
Please login to merge, or discard this patch.
Indentation   +330 added lines, -330 removed lines patch added patch discarded remove patch
@@ -11,334 +11,334 @@
 block discarded – undo
11 11
  */
12 12
 class StringTagField extends DropdownField
13 13
 {
14
-    /**
15
-     * @var array
16
-     */
17
-    public static $allowed_actions = array(
18
-        'suggest',
19
-    );
20
-
21
-    /**
22
-     * @var bool
23
-     */
24
-    protected $shouldLazyLoad = false;
25
-
26
-    /**
27
-     * @var int
28
-     */
29
-    protected $lazyLoadItemLimit = 10;
30
-
31
-    /**
32
-     * @var null|DataObject
33
-     */
34
-    protected $record;
35
-
36
-    /**
37
-     * @var bool
38
-     */
39
-    protected $isMultiple = true;
40
-
41
-    /**
42
-     * @param string $name
43
-     * @param string $title
44
-     * @param array|SS_List $source
45
-     * @param array|SS_List $value
46
-     */
47
-    public function __construct($name, $title = '', $source = array(), $value = array())
48
-    {
49
-        parent::__construct($name, $title, $source, $value);
50
-    }
51
-
52
-    /**
53
-     * @return bool
54
-     */
55
-    public function getShouldLazyLoad()
56
-    {
57
-        return $this->shouldLazyLoad;
58
-    }
59
-
60
-    /**
61
-     * @param bool $shouldLazyLoad
62
-     *
63
-     * @return static
64
-     */
65
-    public function setShouldLazyLoad($shouldLazyLoad)
66
-    {
67
-        $this->shouldLazyLoad = $shouldLazyLoad;
68
-
69
-        return $this;
70
-    }
71
-
72
-    /**
73
-     * @return int
74
-     */
75
-    public function getLazyLoadItemLimit()
76
-    {
77
-        return $this->lazyLoadItemLimit;
78
-    }
79
-
80
-    /**
81
-     * @param int $lazyLoadItemLimit
82
-     *
83
-     * @return static
84
-     */
85
-    public function setLazyLoadItemLimit($lazyLoadItemLimit)
86
-    {
87
-        $this->lazyLoadItemLimit = $lazyLoadItemLimit;
88
-
89
-        return $this;
90
-    }
91
-
92
-    /**
93
-     * @return bool
94
-     */
95
-    public function getIsMultiple()
96
-    {
97
-        return $this->isMultiple;
98
-    }
99
-
100
-    /**
101
-     * @param bool $isMultiple
102
-     *
103
-     * @return static
104
-     */
105
-    public function setIsMultiple($isMultiple)
106
-    {
107
-        $this->isMultiple = $isMultiple;
108
-
109
-        return $this;
110
-    }
111
-
112
-    /**
113
-     * @return null|DataObject
114
-     */
115
-    public function getRecord()
116
-    {
117
-        if ($this->record) {
118
-            return $this->record;
119
-        }
120
-
121
-        if ($form = $this->getForm()) {
122
-            return $form->getRecord();
123
-        }
124
-
125
-        return null;
126
-    }
127
-
128
-    /**
129
-     * @param DataObject $record
130
-     *
131
-     * @return $this
132
-     */
133
-    public function setRecord(DataObject $record)
134
-    {
135
-        $this->record = $record;
136
-
137
-        return $this;
138
-    }
139
-
140
-    /**
141
-     * {@inheritdoc}
142
-     */
143
-    public function Field($properties = array())
144
-    {
145
-        Requirements::css(TAG_FIELD_DIR . '/css/select2.min.css');
146
-        Requirements::css(TAG_FIELD_DIR . '/css/TagField.css');
147
-
148
-        Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
149
-        Requirements::javascript(THIRDPARTY_DIR . '/jquery-entwine/dist/jquery.entwine-dist.js');
150
-        Requirements::javascript(TAG_FIELD_DIR . '/js/select2.js');
151
-        Requirements::javascript(TAG_FIELD_DIR . '/js/TagField.js');
152
-
153
-        $this->addExtraClass('ss-tag-field');
154
-
155
-        if ($this->getIsMultiple()) {
156
-            $this->setAttribute('multiple', 'multiple');
157
-        }
158
-
159
-        if ($this->getShouldLazyLoad()) {
160
-            $this->setAttribute('data-ss-tag-field-suggest-url', $this->getSuggestURL());
161
-        } else {
162
-            $properties = array_merge($properties, array(
163
-                'Options' => $this->getOptions()
164
-            ));
165
-        }
166
-
167
-        return $this
168
-            ->customise($properties)
169
-            ->renderWith(array("templates/TagField"));
170
-    }
171
-
172
-    /**
173
-     * @return string
174
-     */
175
-    protected function getSuggestURL()
176
-    {
177
-        return Controller::join_links($this->Link(), 'suggest');
178
-    }
179
-
180
-    /**
181
-     * @return ArrayList
182
-     */
183
-    protected function getOptions()
184
-    {
185
-        $options = ArrayList::create();
186
-
187
-        $source = $this->getSource();
188
-
189
-        if ($source instanceof Iterator) {
190
-            $source = iterator_to_array($source);
191
-        }
192
-
193
-        $values = $this->Value();
194
-
195
-        foreach ($source as $value) {
196
-            $options->push(
197
-                ArrayData::create(array(
198
-                    'Title' => $value,
199
-                    'Value' => $value,
200
-                    'Selected' => in_array($value, $values),
201
-                ))
202
-            );
203
-        }
204
-
205
-        return $options;
206
-    }
207
-
208
-    /**
209
-     * {@inheritdoc}
210
-     */
211
-    public function setValue($value, $source = null)
212
-    {
213
-        if (is_string($value)) {
214
-            $value = explode(',', $value);
215
-        }
216
-
217
-        if ($source instanceof DataObject) {
218
-            $name = $this->getName();
219
-            $value = explode(',', $source->$name);
220
-        }
221
-
222
-        if ($source instanceof SS_List) {
223
-            $value = $source->column('ID');
224
-        }
225
-
226
-        if (is_null($value)) {
227
-            $value = array();
228
-        }
229
-
230
-        return parent::setValue(array_filter($value));
231
-    }
232
-
233
-    /**
234
-     * {@inheritdoc}
235
-     */
236
-    public function getAttributes()
237
-    {
238
-        return array_merge(
239
-            parent::getAttributes(),
240
-            array('name' => $this->getName() . '[]')
241
-        );
242
-    }
243
-
244
-    /**
245
-     * {@inheritdoc}
246
-     */
247
-    public function saveInto(DataObjectInterface $record)
248
-    {
249
-        parent::saveInto($record);
250
-
251
-        $name = $this->getName();
252
-
253
-        $record->$name = join(',', $this->Value());
254
-        $record->write();
255
-    }
256
-
257
-    /**
258
-     * Returns a JSON string of tags, for lazy loading.
259
-     *
260
-     * @param SS_HTTPRequest $request
261
-     *
262
-     * @return SS_HTTPResponse
263
-     */
264
-    public function suggest(SS_HTTPRequest $request)
265
-    {
266
-        $responseBody = Convert::raw2json(
267
-            array('items' => array())
268
-        );
269
-
270
-        $response = new SS_HTTPResponse();
271
-        $response->addHeader('Content-Type', 'application/json');
272
-
273
-        if ($record = $this->getRecord()) {
274
-            $tags = array();
275
-            $term = $request->getVar('term');
276
-
277
-            if ($record->hasField($this->getName())) {
278
-                $tags = $this->getTags($term);
279
-            }
280
-
281
-            $responseBody = Convert::raw2json(
282
-                array('items' => $tags)
283
-            );
284
-        }
285
-
286
-        $response->setBody($responseBody);
287
-
288
-        return $response;
289
-    }
290
-
291
-    /**
292
-     * Returns array of arrays representing tags.
293
-     *
294
-     * @param string $term
295
-     *
296
-     * @return array
297
-     */
298
-    protected function getTags($term)
299
-    {
300
-        $record = $this->getRecord();
301
-
302
-        if (!$record) {
303
-            return array();
304
-        }
305
-
306
-        $fieldName = $this->getName();
307
-        $className = $record->getClassName();
308
-
309
-        $term = Convert::raw2sql($term);
310
-
311
-        $query = $className::get()
312
-            ->filter($fieldName . ':PartialMatch:nocase', $term)
313
-            ->limit($this->getLazyLoadItemLimit());
314
-
315
-        $items = array();
316
-
317
-        foreach ($query->column($fieldName) as $tags) {
318
-            $tags = explode(',', $tags);
319
-
320
-            foreach ($tags as $i => $tag) {
321
-                if (stripos($tag, $term) !== false && !in_array($tag, $items)) {
322
-                    $items[] = array(
323
-                        'id' => $tag,
324
-                        'text' => $tag
325
-                    );
326
-                }
327
-            }
328
-        }
329
-
330
-        return $items;
331
-    }
332
-
333
-    /**
334
-     * DropdownField assumes value will be a scalar so we must
335
-     * override validate. This only applies to Silverstripe 3.2+
336
-     *
337
-     * @param Validator $validator
338
-     * @return bool
339
-     */
340
-    public function validate($validator)
341
-    {
342
-        return true;
343
-    }
14
+	/**
15
+	 * @var array
16
+	 */
17
+	public static $allowed_actions = array(
18
+		'suggest',
19
+	);
20
+
21
+	/**
22
+	 * @var bool
23
+	 */
24
+	protected $shouldLazyLoad = false;
25
+
26
+	/**
27
+	 * @var int
28
+	 */
29
+	protected $lazyLoadItemLimit = 10;
30
+
31
+	/**
32
+	 * @var null|DataObject
33
+	 */
34
+	protected $record;
35
+
36
+	/**
37
+	 * @var bool
38
+	 */
39
+	protected $isMultiple = true;
40
+
41
+	/**
42
+	 * @param string $name
43
+	 * @param string $title
44
+	 * @param array|SS_List $source
45
+	 * @param array|SS_List $value
46
+	 */
47
+	public function __construct($name, $title = '', $source = array(), $value = array())
48
+	{
49
+		parent::__construct($name, $title, $source, $value);
50
+	}
51
+
52
+	/**
53
+	 * @return bool
54
+	 */
55
+	public function getShouldLazyLoad()
56
+	{
57
+		return $this->shouldLazyLoad;
58
+	}
59
+
60
+	/**
61
+	 * @param bool $shouldLazyLoad
62
+	 *
63
+	 * @return static
64
+	 */
65
+	public function setShouldLazyLoad($shouldLazyLoad)
66
+	{
67
+		$this->shouldLazyLoad = $shouldLazyLoad;
68
+
69
+		return $this;
70
+	}
71
+
72
+	/**
73
+	 * @return int
74
+	 */
75
+	public function getLazyLoadItemLimit()
76
+	{
77
+		return $this->lazyLoadItemLimit;
78
+	}
79
+
80
+	/**
81
+	 * @param int $lazyLoadItemLimit
82
+	 *
83
+	 * @return static
84
+	 */
85
+	public function setLazyLoadItemLimit($lazyLoadItemLimit)
86
+	{
87
+		$this->lazyLoadItemLimit = $lazyLoadItemLimit;
88
+
89
+		return $this;
90
+	}
91
+
92
+	/**
93
+	 * @return bool
94
+	 */
95
+	public function getIsMultiple()
96
+	{
97
+		return $this->isMultiple;
98
+	}
99
+
100
+	/**
101
+	 * @param bool $isMultiple
102
+	 *
103
+	 * @return static
104
+	 */
105
+	public function setIsMultiple($isMultiple)
106
+	{
107
+		$this->isMultiple = $isMultiple;
108
+
109
+		return $this;
110
+	}
111
+
112
+	/**
113
+	 * @return null|DataObject
114
+	 */
115
+	public function getRecord()
116
+	{
117
+		if ($this->record) {
118
+			return $this->record;
119
+		}
120
+
121
+		if ($form = $this->getForm()) {
122
+			return $form->getRecord();
123
+		}
124
+
125
+		return null;
126
+	}
127
+
128
+	/**
129
+	 * @param DataObject $record
130
+	 *
131
+	 * @return $this
132
+	 */
133
+	public function setRecord(DataObject $record)
134
+	{
135
+		$this->record = $record;
136
+
137
+		return $this;
138
+	}
139
+
140
+	/**
141
+	 * {@inheritdoc}
142
+	 */
143
+	public function Field($properties = array())
144
+	{
145
+		Requirements::css(TAG_FIELD_DIR . '/css/select2.min.css');
146
+		Requirements::css(TAG_FIELD_DIR . '/css/TagField.css');
147
+
148
+		Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
149
+		Requirements::javascript(THIRDPARTY_DIR . '/jquery-entwine/dist/jquery.entwine-dist.js');
150
+		Requirements::javascript(TAG_FIELD_DIR . '/js/select2.js');
151
+		Requirements::javascript(TAG_FIELD_DIR . '/js/TagField.js');
152
+
153
+		$this->addExtraClass('ss-tag-field');
154
+
155
+		if ($this->getIsMultiple()) {
156
+			$this->setAttribute('multiple', 'multiple');
157
+		}
158
+
159
+		if ($this->getShouldLazyLoad()) {
160
+			$this->setAttribute('data-ss-tag-field-suggest-url', $this->getSuggestURL());
161
+		} else {
162
+			$properties = array_merge($properties, array(
163
+				'Options' => $this->getOptions()
164
+			));
165
+		}
166
+
167
+		return $this
168
+			->customise($properties)
169
+			->renderWith(array("templates/TagField"));
170
+	}
171
+
172
+	/**
173
+	 * @return string
174
+	 */
175
+	protected function getSuggestURL()
176
+	{
177
+		return Controller::join_links($this->Link(), 'suggest');
178
+	}
179
+
180
+	/**
181
+	 * @return ArrayList
182
+	 */
183
+	protected function getOptions()
184
+	{
185
+		$options = ArrayList::create();
186
+
187
+		$source = $this->getSource();
188
+
189
+		if ($source instanceof Iterator) {
190
+			$source = iterator_to_array($source);
191
+		}
192
+
193
+		$values = $this->Value();
194
+
195
+		foreach ($source as $value) {
196
+			$options->push(
197
+				ArrayData::create(array(
198
+					'Title' => $value,
199
+					'Value' => $value,
200
+					'Selected' => in_array($value, $values),
201
+				))
202
+			);
203
+		}
204
+
205
+		return $options;
206
+	}
207
+
208
+	/**
209
+	 * {@inheritdoc}
210
+	 */
211
+	public function setValue($value, $source = null)
212
+	{
213
+		if (is_string($value)) {
214
+			$value = explode(',', $value);
215
+		}
216
+
217
+		if ($source instanceof DataObject) {
218
+			$name = $this->getName();
219
+			$value = explode(',', $source->$name);
220
+		}
221
+
222
+		if ($source instanceof SS_List) {
223
+			$value = $source->column('ID');
224
+		}
225
+
226
+		if (is_null($value)) {
227
+			$value = array();
228
+		}
229
+
230
+		return parent::setValue(array_filter($value));
231
+	}
232
+
233
+	/**
234
+	 * {@inheritdoc}
235
+	 */
236
+	public function getAttributes()
237
+	{
238
+		return array_merge(
239
+			parent::getAttributes(),
240
+			array('name' => $this->getName() . '[]')
241
+		);
242
+	}
243
+
244
+	/**
245
+	 * {@inheritdoc}
246
+	 */
247
+	public function saveInto(DataObjectInterface $record)
248
+	{
249
+		parent::saveInto($record);
250
+
251
+		$name = $this->getName();
252
+
253
+		$record->$name = join(',', $this->Value());
254
+		$record->write();
255
+	}
256
+
257
+	/**
258
+	 * Returns a JSON string of tags, for lazy loading.
259
+	 *
260
+	 * @param SS_HTTPRequest $request
261
+	 *
262
+	 * @return SS_HTTPResponse
263
+	 */
264
+	public function suggest(SS_HTTPRequest $request)
265
+	{
266
+		$responseBody = Convert::raw2json(
267
+			array('items' => array())
268
+		);
269
+
270
+		$response = new SS_HTTPResponse();
271
+		$response->addHeader('Content-Type', 'application/json');
272
+
273
+		if ($record = $this->getRecord()) {
274
+			$tags = array();
275
+			$term = $request->getVar('term');
276
+
277
+			if ($record->hasField($this->getName())) {
278
+				$tags = $this->getTags($term);
279
+			}
280
+
281
+			$responseBody = Convert::raw2json(
282
+				array('items' => $tags)
283
+			);
284
+		}
285
+
286
+		$response->setBody($responseBody);
287
+
288
+		return $response;
289
+	}
290
+
291
+	/**
292
+	 * Returns array of arrays representing tags.
293
+	 *
294
+	 * @param string $term
295
+	 *
296
+	 * @return array
297
+	 */
298
+	protected function getTags($term)
299
+	{
300
+		$record = $this->getRecord();
301
+
302
+		if (!$record) {
303
+			return array();
304
+		}
305
+
306
+		$fieldName = $this->getName();
307
+		$className = $record->getClassName();
308
+
309
+		$term = Convert::raw2sql($term);
310
+
311
+		$query = $className::get()
312
+			->filter($fieldName . ':PartialMatch:nocase', $term)
313
+			->limit($this->getLazyLoadItemLimit());
314
+
315
+		$items = array();
316
+
317
+		foreach ($query->column($fieldName) as $tags) {
318
+			$tags = explode(',', $tags);
319
+
320
+			foreach ($tags as $i => $tag) {
321
+				if (stripos($tag, $term) !== false && !in_array($tag, $items)) {
322
+					$items[] = array(
323
+						'id' => $tag,
324
+						'text' => $tag
325
+					);
326
+				}
327
+			}
328
+		}
329
+
330
+		return $items;
331
+	}
332
+
333
+	/**
334
+	 * DropdownField assumes value will be a scalar so we must
335
+	 * override validate. This only applies to Silverstripe 3.2+
336
+	 *
337
+	 * @param Validator $validator
338
+	 * @return bool
339
+	 */
340
+	public function validate($validator)
341
+	{
342
+		return true;
343
+	}
344 344
 }
Please login to merge, or discard this patch.