1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
use SilverStripe\Elastica\ElasticSearcher; |
4
|
|
|
|
5
|
|
|
|
6
|
|
|
/** |
7
|
|
|
* Test the functionality of the Searchable extension |
8
|
|
|
* @package elastica |
9
|
|
|
*/ |
10
|
|
|
class SearchableTest extends ElasticsearchBaseTest { |
11
|
|
|
public static $fixture_file = 'elastica/tests/ElasticaTest.yml'; |
12
|
|
|
|
13
|
|
|
public function setUp() { |
14
|
|
|
// this needs to be called in order to create the list of searchable |
15
|
|
|
// classes and fields that are available. Simulates part of a build |
16
|
|
|
$classes = array('SearchableTestPage', 'SiteTree', 'Page', 'FlickrPhotoTO', 'FlickrSetTO', |
17
|
|
|
'FlickrTagTO', 'FlickrAuthorTO', 'FlickrSetTO'); |
18
|
|
|
$this->requireDefaultRecordsFrom = $classes; |
19
|
|
|
|
20
|
|
|
// load fixtures |
21
|
|
|
parent::setUp(); |
22
|
|
|
} |
23
|
|
|
|
24
|
|
|
|
25
|
|
|
/* |
26
|
|
|
FIXME - this method may be problematic, look at when fresh. Different types |
27
|
|
|
returned between mysql and sqlite3 |
28
|
|
|
*/ |
29
|
|
|
public function testgetFieldValuesAsArrayFromFixtures() { |
30
|
|
|
$manyTypes = $this->objFromFixture('ManyTypesPage', 'manytypes0001'); |
31
|
|
|
$result = $manyTypes->getFieldValuesAsArray(); |
32
|
|
|
$this->generateAssertionsFromArray($result); |
33
|
|
|
$expected = array( |
34
|
|
|
'BooleanField' => '1', |
35
|
|
|
'CurrencyField' => '100.25', |
36
|
|
|
'DateField' => '2014-04-15', |
37
|
|
|
'DecimalField' => '0.00', |
38
|
|
|
'HTMLTextField' => '', |
39
|
|
|
'HTMLVarcharField' => 'This is some *HTML*varchar field', |
40
|
|
|
'IntField' => '677', |
41
|
|
|
'PercentageField' => '8.2000', |
42
|
|
|
'SS_DatetimeField' => '2014-10-18 08:24:00', |
43
|
|
|
'TextField' => 'This is a text field', |
44
|
|
|
'TimeField' => '17:48:18', |
45
|
|
|
'Title' => 'Many Types Page', |
46
|
|
|
'Content' => 'Many types of fields' |
47
|
|
|
); |
48
|
|
|
|
49
|
|
|
$this->assertEquals($expected, $result); |
50
|
|
|
|
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
|
54
|
|
|
|
55
|
|
|
public function testBadFormatFields() { |
56
|
|
|
$manyTypes = $this->objFromFixture('ManyTypesPage', 'manytypes0001'); |
57
|
|
|
$fields = $manyTypes->getElasticaFields(); |
58
|
|
|
|
59
|
|
|
$expected = array('type' => 'boolean'); |
60
|
|
|
$this->assertEquals($expected, $fields['BooleanField']); |
61
|
|
|
|
62
|
|
|
$expected = array('type' => 'double'); |
63
|
|
|
$this->assertEquals($expected, $fields['CurrencyField']); |
64
|
|
|
|
65
|
|
|
$expected = array('type' => 'date', 'format' => 'y-M-d'); |
66
|
|
|
$this->assertEquals($expected, $fields['DateField']); |
67
|
|
|
|
68
|
|
|
$expected = array('type' => 'double'); |
69
|
|
|
$this->assertEquals($expected, $fields['DecimalField']); |
70
|
|
|
|
71
|
|
|
$stringFormat = array( |
72
|
|
|
'type' => 'string', |
73
|
|
|
'analyzer' => 'stemmed', |
74
|
|
|
'term_vector' => 'yes', |
75
|
|
|
'fields' => array( |
76
|
|
|
'standard' => array( |
77
|
|
|
'type' => 'string', |
78
|
|
|
'analyzer' => 'unstemmed', |
79
|
|
|
'term_vector' => 'yes' |
80
|
|
|
), |
81
|
|
|
'shingles' => array( |
82
|
|
|
'type' => 'string', |
83
|
|
|
'analyzer' => 'shingles', |
84
|
|
|
'term_vector' => 'yes' |
85
|
|
|
) |
86
|
|
|
) |
87
|
|
|
); |
88
|
|
|
|
89
|
|
|
$expected = $stringFormat; |
90
|
|
|
$this->assertEquals($expected, $fields['HTMLTextField']); |
91
|
|
|
|
92
|
|
|
$expected = $stringFormat; |
93
|
|
|
$this->assertEquals($expected, $fields['HTMLVarcharField']); |
94
|
|
|
|
95
|
|
|
$expected = array('type' => 'integer'); |
96
|
|
|
$this->assertEquals($expected, $fields['IntField']); |
97
|
|
|
|
98
|
|
|
$expected = array('type' => 'double'); |
99
|
|
|
$this->assertEquals($expected, $fields['PercentageField']); |
100
|
|
|
|
101
|
|
|
$expected = array('type' => 'date', 'format' => 'y-M-d H:m:s'); |
102
|
|
|
$this->assertEquals($expected, $fields['SS_DatetimeField']); |
103
|
|
|
|
104
|
|
|
$expected = $stringFormat; |
105
|
|
|
$this->assertEquals($expected, $fields['TextField']); |
106
|
|
|
|
107
|
|
|
$expected = array('type' => 'date', 'format' => 'H:m:s'); |
108
|
|
|
$this->assertEquals($expected, $fields['TimeField']); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
|
112
|
|
|
public function testGetDateFields() { |
113
|
|
|
$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001'); |
114
|
|
|
$fields = $flickrPhoto->getElasticaFields(); |
115
|
|
|
|
116
|
|
|
$expected = array('type' => 'date', 'format' => 'y-M-d H:m:s'); |
117
|
|
|
$this->assertEquals($expected, $fields['TakenAt']); |
118
|
|
|
|
119
|
|
|
$expected = array('type' => 'date', 'format' => 'y-M-d H:m:s'); |
120
|
|
|
$this->assertEquals($expected, $fields['TakenAtDT']); |
121
|
|
|
|
122
|
|
|
$expected = array('type' => 'date', 'format' => 'y-M-d'); |
123
|
|
|
$this->assertEquals($expected, $fields['FirstViewed']); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Test a valid identifier |
129
|
|
|
*/ |
130
|
|
|
public function testMapping() { |
131
|
|
|
$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001'); |
132
|
|
|
$mapping = $flickrPhoto->getElasticaMapping(); |
133
|
|
|
|
134
|
|
|
//array of mapping properties |
135
|
|
|
$properties = $mapping->getProperties(); |
136
|
|
|
|
137
|
|
|
//test FlickrPhotoTO relationships mapping |
138
|
|
|
$expectedRelStringArray = array( |
139
|
|
|
'type' => 'string', |
140
|
|
|
'fields' => array( |
141
|
|
|
'standard' => array( |
142
|
|
|
'type' => 'string', |
143
|
|
|
'analyzer' => 'unstemmed', |
144
|
|
|
'term_vector' => 'yes' |
145
|
|
|
), |
146
|
|
|
'shingles' => array( |
147
|
|
|
'type' => 'string', |
148
|
|
|
'analyzer' => 'shingles', |
149
|
|
|
'term_vector' => 'yes' |
150
|
|
|
) |
151
|
|
|
), |
152
|
|
|
'analyzer' => 'stemmed', |
153
|
|
|
'term_vector' => 'yes' |
154
|
|
|
); |
155
|
|
|
|
156
|
|
|
$this->assertEquals($expectedRelStringArray, |
157
|
|
|
$properties['FlickrAuthorTO']['properties']['DisplayName'] |
158
|
|
|
); |
159
|
|
|
$this->assertEquals($expectedRelStringArray, |
160
|
|
|
$properties['FlickrAuthorTO']['properties']['PathAlias'] |
161
|
|
|
); |
162
|
|
|
$this->assertEquals($expectedRelStringArray, |
163
|
|
|
$properties['FlickrTagTO']['properties']['RawValue'] |
164
|
|
|
); |
165
|
|
|
$this->assertEquals($expectedRelStringArray, |
166
|
|
|
$properties['FlickrSetTO']['properties']['Title'] |
167
|
|
|
); |
168
|
|
|
$this->assertEquals($expectedRelStringArray, |
169
|
|
|
$properties['FlickrSetTO']['properties']['Description'] |
170
|
|
|
); |
171
|
|
|
|
172
|
|
|
// check constructed field, location |
173
|
|
|
$locationProperties = $properties['location']; |
174
|
|
|
$this->assertEquals('geo_point', $locationProperties['type']); |
175
|
|
|
$this->assertEquals('compressed', $locationProperties['fielddata']['format']); |
176
|
|
|
$this->assertEquals('1cm', $locationProperties['fielddata']['precision']); |
177
|
|
|
|
178
|
|
|
|
179
|
|
|
//test the FlickrPhotoTO core model |
180
|
|
|
|
181
|
|
|
|
182
|
|
|
|
183
|
|
|
// check strings |
184
|
|
|
$shouldBeString = array('Title', 'Description'); |
185
|
|
|
$shouldBeInt = array('ISO', 'FlickrID', 'FocalLength35mm'); |
186
|
|
|
$shouldBeBoolean = array('IsInSiteTree'); |
187
|
|
|
$shouldBeDouble = array('Aperture'); |
188
|
|
|
$shouldBeDateTime = array('TakenAt'); |
189
|
|
|
$shouldBeDate = array('FirstViewed'); |
190
|
|
|
|
191
|
|
|
// tokens are strings that have analyzer 'not_analyzed', namely the string is indexed as is |
192
|
|
|
$shouldBeTokens = array('ShutterSpeed', 'Link'); |
193
|
|
|
|
194
|
|
|
|
195
|
|
|
// check strings |
196
|
|
|
$expectedStandardArray = array('type' => 'string', 'analyzer' => 'unstemmed', 'term_vector' => 'yes'); |
197
|
|
|
foreach($shouldBeString as $fieldName) { |
198
|
|
|
$fieldProperties = $properties[$fieldName]; |
199
|
|
|
|
200
|
|
|
$type = $fieldProperties['type']; |
201
|
|
|
$analyzer = $fieldProperties['analyzer']; |
202
|
|
|
$this->assertEquals('string', $type); |
203
|
|
|
|
204
|
|
|
// check for stemmed analysis |
205
|
|
|
$this->assertEquals('stemmed', $analyzer); |
206
|
|
|
|
207
|
|
|
// check for unstemmed analaysis |
208
|
|
|
|
209
|
|
|
$this->assertEquals($expectedStandardArray, $fieldProperties['fields']['standard']); |
210
|
|
|
|
211
|
|
|
// check for only 3 entries |
212
|
|
|
$this->assertEquals(4, sizeof(array_keys($fieldProperties))); |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
// check ints |
216
|
|
|
foreach($shouldBeInt as $fieldName) { |
217
|
|
|
$fieldProperties = $properties[$fieldName]; |
218
|
|
|
$type = $fieldProperties['type']; |
219
|
|
|
$this->assertEquals(1, sizeof(array_keys($fieldProperties))); |
220
|
|
|
$this->assertEquals('integer', $type); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
|
224
|
|
|
// check doubles |
225
|
|
|
foreach($shouldBeDouble as $fieldName) { |
226
|
|
|
$fieldProperties = $properties[$fieldName]; |
227
|
|
|
$type = $fieldProperties['type']; |
228
|
|
|
$this->assertEquals(1, sizeof(array_keys($fieldProperties))); |
229
|
|
|
$this->assertEquals('double', $type); |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
// check boolean |
233
|
|
|
foreach($shouldBeBoolean as $fieldName) { |
234
|
|
|
$fieldProperties = $properties[$fieldName]; |
235
|
|
|
$type = $fieldProperties['type']; |
236
|
|
|
$this->assertEquals(1, sizeof(array_keys($fieldProperties))); |
237
|
|
|
$this->assertEquals('boolean', $type); |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
|
241
|
|
|
foreach($shouldBeDate as $fieldName) { |
|
|
|
|
242
|
|
|
$fieldProperties = $properties[$fieldName]; |
243
|
|
|
$type = $fieldProperties['type']; |
244
|
|
|
$this->assertEquals(2, sizeof(array_keys($fieldProperties))); |
245
|
|
|
$this->assertEquals('date', $type); |
246
|
|
|
$this->assertEquals('y-M-d', $fieldProperties['format']); |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
|
250
|
|
|
|
251
|
|
|
// check date time, stored in Elasticsearch as a date with a different format than above |
252
|
|
|
foreach($shouldBeDateTime as $fieldName) { |
|
|
|
|
253
|
|
|
$fieldProperties = $properties[$fieldName]; |
254
|
|
|
$type = $fieldProperties['type']; |
255
|
|
|
$this->assertEquals(2, sizeof(array_keys($fieldProperties))); |
256
|
|
|
$this->assertEquals('date', $type); |
257
|
|
|
$this->assertEquals('y-M-d H:m:s', $fieldProperties['format']); |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
//check shutter speed is tokenized, ie not analyzed - for aggregation purposes |
261
|
|
|
// |
262
|
|
|
foreach($shouldBeTokens as $fieldName) { |
|
|
|
|
263
|
|
|
$fieldProperties = $properties[$fieldName]; |
264
|
|
|
$type = $fieldProperties['type']; |
265
|
|
|
$this->assertEquals('string', $type); |
266
|
|
|
|
267
|
|
|
// check for no analysis |
268
|
|
|
$analyzer = $fieldProperties['index']; |
269
|
|
|
$this->assertEquals('not_analyzed', $analyzer); |
270
|
|
|
|
271
|
|
|
// check for only 2 entries |
272
|
|
|
$this->assertEquals(2, sizeof(array_keys($fieldProperties))); |
273
|
|
|
} |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
|
277
|
|
|
public function testGetType() { |
278
|
|
|
//A type in Elasticsearch is used to represent each SilverStripe content type, |
279
|
|
|
//the name used being the Silverstripe $fieldName |
280
|
|
|
|
281
|
|
|
$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001'); |
282
|
|
|
$type = $flickrPhoto->getElasticaType(); |
283
|
|
|
$this->assertEquals('FlickrPhotoTO', $type); |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
|
287
|
|
|
/* |
288
|
|
|
Get a record as an Elastic document and check values |
289
|
|
|
*/ |
290
|
|
|
public function testGetElasticaDocument() { |
291
|
|
|
$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001'); |
292
|
|
|
$doc = $flickrPhoto->getElasticaDocument()->getData(); |
293
|
|
|
|
294
|
|
|
$expected = array(); |
295
|
|
|
$expected['Title'] = 'Bangkok'; |
296
|
|
|
$expected['FlickrID'] = '1234567'; |
297
|
|
|
$expected['Description'] = 'Test photograph'; |
298
|
|
|
$expected['TakenAt'] = '2011-07-04 20:36:00'; |
299
|
|
|
$expected['TakenAtDT'] = null; |
300
|
|
|
$expected['FirstViewed'] = '2012-04-28'; |
301
|
|
|
$expected['Aperture'] = 8.0; |
302
|
|
|
|
303
|
|
|
//Shutter speed is altered for aggregations |
304
|
|
|
$expected['ShutterSpeed'] = '0.01|1/100'; |
305
|
|
|
$expected['FocalLength35mm'] = 140; |
306
|
|
|
$expected['ISO'] = 400; |
307
|
|
|
$expected['AspectRatio'] = 1.013; |
308
|
|
|
$expected['Photographer'] = array(); |
309
|
|
|
$expected['FlickrTagTOs'] = array(); |
310
|
|
|
$expected['FlickrSetTOs'] = array(); |
311
|
|
|
$expected['IsInSiteTree'] = false; |
312
|
|
|
$expected['location'] = array('lat' => 13.42, 'lon' => 100); |
313
|
|
|
$expected['TestMethod'] = 'this is a test method'; |
314
|
|
|
$expected['TestMethodHTML'] = 'this is a test method that returns *HTML*'; |
315
|
|
|
$this->assertEquals($expected, $doc); |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
|
319
|
|
|
public function testElasticaResult() { |
320
|
|
|
$resultList = $this->getResultsFor('Bangkok'); |
321
|
|
|
|
322
|
|
|
// there is only one result. Note lack of a 'first' method |
323
|
|
|
foreach($resultList->getIterator() as $fp) { |
324
|
|
|
//This is an Elastica\Result object |
325
|
|
|
$elasticaResult = $fp->getElasticaResult(); |
326
|
|
|
|
327
|
|
|
$fields = $elasticaResult->getSource(); |
328
|
|
|
|
329
|
|
|
$this->assertEquals($fp->Title, $fields['Title']); |
330
|
|
|
$this->assertEquals($fp->FlickrID, $fields['FlickrID']); |
331
|
|
|
$this->assertEquals($fp->Description, $fields['Description']); |
332
|
|
|
$this->assertEquals($fp->TakenAt, $fields['TakenAt']); |
333
|
|
|
$this->assertEquals($fp->FirstViewed, $fields['FirstViewed']); |
334
|
|
|
$this->assertEquals($fp->Aperture, $fields['Aperture']); |
335
|
|
|
|
336
|
|
|
//ShutterSpeed is a special case, mangled field |
337
|
|
|
$this->assertEquals('0.01|1/100', $fields['ShutterSpeed']); |
338
|
|
|
$this->assertEquals($fp->FocalLength35mm, $fields['FocalLength35mm']); |
339
|
|
|
$this->assertEquals($fp->ISO, $fields['ISO']); |
340
|
|
|
$this->assertEquals($fp->AspectRatio, $fields['AspectRatio']); |
341
|
|
|
|
342
|
|
|
//Empty arrays for null values |
343
|
|
|
$this->assertEquals(array(), $fields['Photographer']); |
344
|
|
|
$this->assertEquals(array(), $fields['FlickrTagTOs']); |
345
|
|
|
$this->assertEquals(array(), $fields['FlickrSetTOs']); |
346
|
|
|
$this->assertEquals(false, $fields['IsInSiteTree']); |
347
|
|
|
} |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
|
351
|
|
|
public function testDeleteNonExistentDoc() { |
352
|
|
|
$fp = new FlickrPhotoTO(); |
353
|
|
|
$fp->Title = 'Test Deletion'; |
354
|
|
|
$fp->IndexingOff = true; // do no index this |
355
|
|
|
$fp->write(); |
356
|
|
|
$fp->IndexingOff = false; |
357
|
|
|
|
358
|
|
|
try { |
359
|
|
|
$fp->delete(); |
360
|
|
|
$this->fail('Exception should have been thrown when deleting non existent item'); |
361
|
|
|
} catch (Exception $e) { |
362
|
|
|
//This error comes out of Elastica itself |
363
|
|
|
$this->assertEquals('Deleted document FlickrPhotoTO (2) not found in search index.', |
364
|
|
|
$e->getMessage()); |
365
|
|
|
} |
366
|
|
|
} |
367
|
|
|
|
368
|
|
|
|
369
|
|
|
|
370
|
|
|
|
371
|
|
|
public function testUnpublishPublish() { |
372
|
|
|
$nDocsAtStart = $this->getNumberOfIndexedDocuments(); |
373
|
|
|
$this->checkNumberOfIndexedDocuments($nDocsAtStart); |
374
|
|
|
|
375
|
|
|
$page = $this->objFromFixture('SiteTree', 'sitetree001'); |
376
|
|
|
$page->doUnpublish(); |
377
|
|
|
|
378
|
|
|
$this->checkNumberOfIndexedDocuments($nDocsAtStart - 1); |
379
|
|
|
|
380
|
|
|
$page->doPublish(); |
381
|
|
|
$this->checkNumberOfIndexedDocuments($nDocsAtStart); |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* For a page that is already published, set the ShowInSearch flag to false, |
387
|
|
|
* write to stage, and then rePublish |
388
|
|
|
*/ |
389
|
|
|
public function testUnpublishAlreadyPublisedhHideFromSearch() { |
390
|
|
|
$page = $this->objFromFixture('SiteTree', 'sitetree001'); |
391
|
|
|
|
392
|
|
|
// By default the page is not indexed (for speed reasons) |
393
|
|
|
// Change the title, turn on indexing and save it |
394
|
|
|
// This will invoke a database write |
395
|
|
|
$page->Title = "I will be indexed"; |
396
|
|
|
$page->IndexingOff = true; |
397
|
|
|
$page->write(); |
398
|
|
|
|
399
|
|
|
$nDocsAtStart = $this->getNumberOfIndexedDocuments(); |
400
|
|
|
$this->checkNumberOfIndexedDocuments($nDocsAtStart); |
401
|
|
|
|
402
|
|
|
// assert keys of term vectors, this will indicate page |
403
|
|
|
// is stored in the index or not |
404
|
|
|
$termVectors = $page->getTermVectors(); |
405
|
|
|
$expected = array( |
406
|
|
|
'0' => 'Content', |
407
|
|
|
'1' => 'Content.shingles', |
408
|
|
|
'2' => 'Content.standard', |
409
|
|
|
'3' => 'Link', |
410
|
|
|
'4' => 'Title', |
411
|
|
|
'5' => 'Title.autocomplete', |
412
|
|
|
'6' => 'Title.shingles', |
413
|
|
|
'7' => 'Title.standard', |
414
|
|
|
); |
415
|
|
|
|
416
|
|
|
$keys = array_keys($termVectors); |
417
|
|
|
sort($keys); |
418
|
|
|
|
419
|
|
|
$this->assertEquals($expected, $keys); |
420
|
|
|
|
421
|
|
|
|
422
|
|
|
//CURRENT |
423
|
|
|
$page->ShowInSearch = false; |
424
|
|
|
$page->write(); |
425
|
|
|
|
426
|
|
|
$this->checkNumberOfIndexedDocuments($nDocsAtStart); |
427
|
|
|
|
428
|
|
|
$page->doPublish(); |
429
|
|
|
$this->checkNumberOfIndexedDocuments($nDocsAtStart); |
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
|
433
|
|
|
|
434
|
|
|
/** |
435
|
|
|
* For a page that is not published, set the ShowInSearch flag to false, |
436
|
|
|
* write to stage, and then rePublish. Same as previous test except |
437
|
|
|
* no need to delete from the index as it already does not exist |
438
|
|
|
*/ |
439
|
|
|
public function testUnpublishPublishHideFromSearch() { |
440
|
|
|
$page = $this->objFromFixture('SiteTree', 'sitetree001'); |
441
|
|
|
$page->doUnpublish(); |
442
|
|
|
|
443
|
|
|
// By default the page is not indexed (for speed reasons) |
444
|
|
|
// Change the title, turn on indexing and save it |
445
|
|
|
// This will invoke a database write |
446
|
|
|
$page->Title = "I will be indexed"; |
447
|
|
|
$page->IndexingOff = true; |
448
|
|
|
$page->write(); |
449
|
|
|
|
450
|
|
|
$nDocsAtStart = $this->getNumberOfIndexedDocuments(); |
451
|
|
|
$this->checkNumberOfIndexedDocuments($nDocsAtStart); |
452
|
|
|
$page->ShowInSearch = false; |
453
|
|
|
$page->write(); |
454
|
|
|
|
455
|
|
|
$this->checkNumberOfIndexedDocuments($nDocsAtStart); |
456
|
|
|
|
457
|
|
|
$page->doPublish(); |
458
|
|
|
$this->checkNumberOfIndexedDocuments($nDocsAtStart); |
459
|
|
|
} |
460
|
|
|
|
461
|
|
|
|
462
|
|
|
|
463
|
|
|
|
464
|
|
|
public function testGetCMSFields() { |
465
|
|
|
$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001'); |
466
|
|
|
$fields = $flickrPhoto->getCMSFields(); |
467
|
|
|
|
468
|
|
|
$this->checkTabExists($fields, 'ElasticaTermsset'); |
469
|
|
|
} |
470
|
|
|
|
471
|
|
|
|
472
|
|
|
public function testNoSearchableFieldsConfigured() { |
473
|
|
|
$config = Config::inst(); |
474
|
|
|
$sf = $config->get('FlickrPhotoTO', 'searchable_fields'); |
475
|
|
|
$config->remove('FlickrPhotoTO', 'searchable_fields'); |
476
|
|
|
$fp = Injector::inst()->create('FlickrPhotoTO'); |
477
|
|
|
try { |
478
|
|
|
$fp->getAllSearchableFields(); |
479
|
|
|
$this->fail("getAllSearchableFields should have failed as static var searchable_fields not configured"); |
480
|
|
|
} catch (Exception $e) { |
481
|
|
|
$this->assertEquals('The field $searchable_fields must be set for the class FlickrPhotoTO', $e->getMessage()); |
482
|
|
|
} |
483
|
|
|
|
484
|
|
|
$config->update('FlickrPhotoTO', 'searchable_fields', $sf); |
485
|
|
|
} |
486
|
|
|
|
487
|
|
|
|
488
|
|
|
public function testNoSearchableFieldsConfiguredForHasManyRelation() { |
489
|
|
|
$config = Config::inst(); |
490
|
|
|
$sf = $config->get('FlickrTagTO', 'searchable_fields'); |
491
|
|
|
$config->remove('FlickrTagTO', 'searchable_fields'); |
492
|
|
|
$fp = Injector::inst()->create('FlickrPhotoTO'); |
493
|
|
|
try { |
494
|
|
|
$fp->getAllSearchableFields(); |
495
|
|
|
$this->fail("getAllSearchableFields should have failed as static var searchable_fields not configured"); |
496
|
|
|
} catch (Exception $e) { |
497
|
|
|
$this->assertEquals('The field $searchable_fields must be set for the class FlickrTagTO', $e->getMessage()); |
498
|
|
|
} |
499
|
|
|
|
500
|
|
|
$config->update('FlickrTagTO', 'searchable_fields', $sf); |
501
|
|
|
|
502
|
|
|
} |
503
|
|
|
|
504
|
|
|
|
505
|
|
|
public function testNoSearchableFieldsConfiguredForHasOneRelation() { |
506
|
|
|
$config = Config::inst(); |
507
|
|
|
$sf = $config->get('FlickrAuthorTO', 'searchable_fields'); |
508
|
|
|
$config->remove('FlickrAuthorTO', 'searchable_fields'); |
509
|
|
|
$fp = Injector::inst()->create('FlickrPhotoTO'); |
510
|
|
|
try { |
511
|
|
|
$fp->getAllSearchableFields(); |
512
|
|
|
$this->fail("getAllSearchableFields should have failed as static var searchable_fields not configured"); |
513
|
|
|
} catch (Exception $e) { |
514
|
|
|
$this->assertEquals('The field $searchable_fields must be set for the class FlickrAuthorTO', $e->getMessage()); |
515
|
|
|
} |
516
|
|
|
|
517
|
|
|
$config->update('FlickrAuthorTO', 'searchable_fields', $sf); |
518
|
|
|
|
519
|
|
|
} |
520
|
|
|
|
521
|
|
|
|
522
|
|
|
public function testSearchableMethodNotExist() { |
523
|
|
|
$config = Config::inst(); |
524
|
|
|
$sr = $config->get('FlickrPhotoTO', 'searchable_relationships'); |
525
|
|
|
$config->remove('FlickrPhotoTO', 'searchable_relationships'); |
526
|
|
|
$config->update('FlickrPhotoTO', 'searchable_relationships', array('thisMethodDoesNotExist')); |
527
|
|
|
$fp = Injector::inst()->create('FlickrPhotoTO'); |
528
|
|
|
try { |
529
|
|
|
$fp->getAllSearchableFields(); |
530
|
|
|
$this->fail("getAllSearchableFields should have failed searchable relationship does not exist"); |
531
|
|
|
} catch (Exception $e) { |
532
|
|
|
$this->assertEquals('The method thisMethodDoesNotExist not found in class FlickrPhotoTO, please check configuration', |
533
|
|
|
$e->getMessage()); |
534
|
|
|
} |
535
|
|
|
|
536
|
|
|
// MUST REMOVE FIRST. Otherwise append and the erroroneus value above still exists |
537
|
|
|
$config->remove('FlickrPhotoTO', 'searchable_relationships'); |
538
|
|
|
$config->update('FlickrPhotoTO', 'searchable_relationships', $sr); |
539
|
|
|
} |
540
|
|
|
|
541
|
|
|
|
542
|
|
|
public function testFieldsToElasticaConfig() { |
543
|
|
|
$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001'); |
544
|
|
|
$fields = $flickrPhoto->getAllSearchableFields(); |
545
|
|
|
|
546
|
|
|
$expected = array( |
547
|
|
|
'Title' => array( |
548
|
|
|
'title' => 'Title', |
549
|
|
|
'filter' => 'PartialMatchFilter' |
550
|
|
|
), |
551
|
|
|
'FlickrID' => array( |
552
|
|
|
'title' => 'Flickr ID', |
553
|
|
|
'filter' => 'PartialMatchFilter' |
554
|
|
|
), |
555
|
|
|
'Description' => array( |
556
|
|
|
'title' => 'Description', |
557
|
|
|
'filter' => 'PartialMatchFilter' |
558
|
|
|
), |
559
|
|
|
'TakenAt' => array( |
560
|
|
|
'title' => 'Taken At', |
561
|
|
|
'filter' => 'PartialMatchFilter' |
562
|
|
|
), |
563
|
|
|
'TakenAtDT' => array( |
564
|
|
|
'title' => 'Taken At DT', |
565
|
|
|
'filter' => 'PartialMatchFilter' |
566
|
|
|
), |
567
|
|
|
'FirstViewed' => array( |
568
|
|
|
'title' => 'First Viewed', |
569
|
|
|
'filter' => 'PartialMatchFilter' |
570
|
|
|
), |
571
|
|
|
'Aperture' => array( |
572
|
|
|
'title' => 'Aperture', |
573
|
|
|
'filter' => 'PartialMatchFilter' |
574
|
|
|
), |
575
|
|
|
'ShutterSpeed' => array( |
576
|
|
|
'title' => 'Shutter Speed', |
577
|
|
|
'filter' => 'PartialMatchFilter' |
578
|
|
|
), |
579
|
|
|
'FocalLength35mm' => array( |
580
|
|
|
'title' => 'Focal Length35mm', |
581
|
|
|
'filter' => 'PartialMatchFilter' |
582
|
|
|
), |
583
|
|
|
'ISO' => array( |
584
|
|
|
'title' => 'ISO', |
585
|
|
|
'filter' => 'PartialMatchFilter' |
586
|
|
|
), |
587
|
|
|
'AspectRatio' => array( |
588
|
|
|
'title' => 'Aspect Ratio', |
589
|
|
|
'filter' => 'PartialMatchFilter' |
590
|
|
|
), |
591
|
|
|
'TestMethod' => array( |
592
|
|
|
'title' => 'Test Method', |
593
|
|
|
'filter' => 'PartialMatchFilter' |
594
|
|
|
), |
595
|
|
|
'TestMethodHTML' => array( |
596
|
|
|
'title' => 'Test Method HTML', |
597
|
|
|
'filter' => 'PartialMatchFilter' |
598
|
|
|
), |
599
|
|
|
'Photographer()' => array( |
600
|
|
|
'PathAlias' => array( |
601
|
|
|
'title' => 'Path Alias', |
602
|
|
|
'filter' => 'PartialMatchFilter' |
603
|
|
|
), |
604
|
|
|
'DisplayName' => array( |
605
|
|
|
'title' => 'Display Name', |
606
|
|
|
'filter' => 'PartialMatchFilter' |
607
|
|
|
) |
608
|
|
|
), |
609
|
|
|
'FlickrTagTOs()' => array( |
610
|
|
|
'RawValue' => array( |
611
|
|
|
'title' => 'Raw Value', |
612
|
|
|
'filter' => 'PartialMatchFilter' |
613
|
|
|
) |
614
|
|
|
), |
615
|
|
|
'FlickrSetTOs()' => array( |
616
|
|
|
'Title' => array( |
617
|
|
|
'title' => 'Title', |
618
|
|
|
'filter' => 'PartialMatchFilter' |
619
|
|
|
), |
620
|
|
|
'FlickrID' => array( |
621
|
|
|
'title' => 'Flickr ID', |
622
|
|
|
'filter' => 'PartialMatchFilter' |
623
|
|
|
), |
624
|
|
|
'Description' => array( |
625
|
|
|
'title' => 'Description', |
626
|
|
|
'filter' => 'PartialMatchFilter' |
627
|
|
|
) |
628
|
|
|
) |
629
|
|
|
); |
630
|
|
|
|
631
|
|
|
$this->assertEquals($expected, $fields); |
632
|
|
|
} |
633
|
|
|
|
634
|
|
|
|
635
|
|
|
public function testHasOneExistsSearchableToArray() { |
636
|
|
|
$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001'); |
637
|
|
|
$flickrPhoto->IndexingOff = false; |
638
|
|
|
$flickrPhoto->Title = 'Test title edited'; |
639
|
|
|
$photographer = new FlickrAuthorTO(); |
640
|
|
|
$photographer->DisplayName = 'Fred Bloggs'; |
641
|
|
|
$photographer->PathAlias = '/fredbloggs'; |
642
|
|
|
|
643
|
|
|
$photographer->write(); |
644
|
|
|
|
645
|
|
|
$flickrPhoto->PhotographerID = $photographer->ID; ; |
646
|
|
|
$flickrPhoto->write(); |
647
|
|
|
$fieldValuesArray = $flickrPhoto->getFieldValuesAsArray(); |
648
|
|
|
|
649
|
|
|
$actual = $fieldValuesArray['Photographer']; |
650
|
|
|
$this->generateAssertionsFromArray($actual); |
651
|
|
|
$expected = array( |
652
|
|
|
'PathAlias' => '/fredbloggs', |
653
|
|
|
'DisplayName' => 'Fred Bloggs', |
654
|
|
|
'FlickrPhotoTO' => '', |
655
|
|
|
); |
656
|
|
|
|
657
|
|
|
$this->assertEquals($expected, $actual); |
658
|
|
|
} |
659
|
|
|
|
660
|
|
|
|
661
|
|
|
|
662
|
|
|
public function testHasManyExistsSearchableToArray() { |
663
|
|
|
$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001'); |
664
|
|
|
$flickrPhoto->IndexingOff = false; |
665
|
|
|
$flickrPhoto->Title = 'Test title edited'; |
666
|
|
|
$tag1 = new FlickrTagTO(); |
667
|
|
|
$tag1->FlickrID = '1000001'; |
668
|
|
|
$tag1->Value = 'auckland'; |
669
|
|
|
$tag1->RawValue = 'Auckland'; |
670
|
|
|
$tag1->write(); |
671
|
|
|
|
672
|
|
|
|
673
|
|
|
$tag2 = new FlickrTagTO(); |
674
|
|
|
$tag2->FlickrID = '1000002'; |
675
|
|
|
$tag2->Value = 'wellington'; |
676
|
|
|
$tag2->RawValue = 'Wellington'; |
677
|
|
|
$tag2->write(); |
678
|
|
|
|
679
|
|
|
$flickrPhoto->FlickrTagTOs()->add($tag1); |
680
|
|
|
$flickrPhoto->FlickrTagTOs()->add($tag2); |
681
|
|
|
$flickrPhoto->write(); |
682
|
|
|
$fieldValuesArray = $flickrPhoto->getFieldValuesAsArray(); |
683
|
|
|
$actual = $fieldValuesArray['Photographer']; |
684
|
|
|
$this->assertEquals(array(), $actual); |
685
|
|
|
|
686
|
|
|
$actual = $fieldValuesArray['FlickrTagTOs']; |
687
|
|
|
$this->generateAssertionsFromArrayRecurse($actual); |
688
|
|
|
|
689
|
|
|
$expected = array( |
690
|
|
|
'0' => array( |
691
|
|
|
'RawValue' => 'Auckland' |
692
|
|
|
), |
693
|
|
|
'1' => array( |
694
|
|
|
'RawValue' => 'Wellington' |
695
|
|
|
) |
696
|
|
|
); |
697
|
|
|
|
698
|
|
|
|
699
|
|
|
$this->assertEquals($expected, $actual); |
700
|
|
|
} |
701
|
|
|
|
702
|
|
|
|
703
|
|
|
public function testUpdateCMSFieldsDatabject() { |
704
|
|
|
$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001'); |
705
|
|
|
$flickrPhoto->IndexingOff = false; |
706
|
|
|
$flickrPhoto->Title = 'Test title edited'; |
707
|
|
|
$flickrPhoto->write(); |
708
|
|
|
$fields = $flickrPhoto->getCMSFields(); |
709
|
|
|
|
710
|
|
|
$tabset = $fields->findOrMakeTab('Root.ElasticaTerms'); |
711
|
|
|
$tabNames = array(); |
712
|
|
View Code Duplication |
foreach($tabset->Tabs() as $tab) { |
|
|
|
|
713
|
|
|
$tabFields = array(); |
714
|
|
|
foreach($tab->FieldList() as $field) { |
715
|
|
|
array_push($tabFields, $field->getName()); |
716
|
|
|
} |
717
|
|
|
$expectedName = 'TermsFor' . $tab->getName(); |
|
|
|
|
718
|
|
|
//$expected = array($expectedName); |
|
|
|
|
719
|
|
|
//$this->assertEquals($expected, $tabFields); |
|
|
|
|
720
|
|
|
array_push($tabNames, $tab->getName()); |
721
|
|
|
} |
722
|
|
|
$expected = array('Description_stemmed', 'Description_shingles', 'Description_unstemmed', |
723
|
|
|
'ShutterSpeed_stemmed', 'TestMethod_stemmed', 'TestMethod_shingles', 'TestMethod_unstemmed', |
724
|
|
|
'TestMethodHTML_stemmed', 'TestMethodHTML_shingles', 'TestMethodHTML_unstemmed', |
725
|
|
|
'Title_stemmed', 'Title_autocomplete', 'Title_shingles', 'Title_unstemmed'); |
726
|
|
|
|
727
|
|
|
$this->assertEquals($expected, $tabNames); |
728
|
|
|
} |
729
|
|
|
|
730
|
|
|
|
731
|
|
|
public function testUpdateCMSFieldsSiteTreeLive() { |
732
|
|
|
$page = $this->objFromFixture('SearchableTestPage', 'first'); |
733
|
|
|
$page->IndexingOff = false; |
734
|
|
|
$page->Title = 'Test title edited'; |
735
|
|
|
$page->write(); |
736
|
|
|
$page->doPublish(); |
737
|
|
|
$fields = $page->getCMSFields(); |
738
|
|
|
|
739
|
|
|
$tabset = $fields->findOrMakeTab('Root.ElasticaTerms'); |
740
|
|
|
$tabNames = array(); |
741
|
|
View Code Duplication |
foreach($tabset->Tabs() as $tab) { |
742
|
|
|
$tabFields = array(); |
743
|
|
|
foreach($tab->FieldList() as $field) { |
744
|
|
|
array_push($tabFields, $field->getName()); |
745
|
|
|
} |
746
|
|
|
array_push($tabNames, $tab->getName()); |
747
|
|
|
} |
748
|
|
|
$expected = array( |
749
|
|
|
'Content_stemmed', 'Content_unstemmed', 'Link_stemmed', |
750
|
|
|
'Title_stemmed', 'Title_autocomplete', 'Title_shingles', |
751
|
|
|
'Title_unstemmed'); |
752
|
|
|
$this->generateAssertionsFromArray1D($tabNames); |
753
|
|
|
$this->assertEquals($expected, $tabNames); |
754
|
|
|
|
755
|
|
|
} |
756
|
|
|
|
757
|
|
|
|
758
|
|
View Code Duplication |
private function getResultsFor($query, $pageLength = 10) { |
759
|
|
|
$es = new ElasticSearcher(); |
760
|
|
|
$es->setStart(0); |
761
|
|
|
$es->setPageLength($pageLength); |
762
|
|
|
$es->setClasses('FlickrPhotoTO'); |
763
|
|
|
$fields = array('Title' => 1, 'Description' => 1); |
764
|
|
|
$resultList = $es->search($query, $fields)->getList(); |
765
|
|
|
$this->assertEquals('SilverStripe\Elastica\ResultList', get_class($resultList)); |
766
|
|
|
return $resultList; |
767
|
|
|
} |
768
|
|
|
|
769
|
|
|
} |
770
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.