1 | <?php |
||||
2 | |||||
3 | namespace SilverStripe\FullTextSearch\Tests; |
||||
4 | |||||
5 | use Apache_Solr_Document; |
||||
6 | use Page; |
||||
7 | use SebastianBergmann\Version; |
||||
8 | use SilverStripe\Assets\File; |
||||
9 | use SilverStripe\CMS\Model\SiteTree; |
||||
10 | use SilverStripe\Core\Config\Config; |
||||
11 | use SilverStripe\Core\Environment; |
||||
12 | use SilverStripe\Core\Injector\Injector; |
||||
13 | use SilverStripe\Core\Kernel; |
||||
14 | use SilverStripe\Dev\SapphireTest; |
||||
15 | use SilverStripe\FullTextSearch\Search\FullTextSearch; |
||||
16 | use SilverStripe\FullTextSearch\Search\Queries\SearchQuery; |
||||
17 | use SilverStripe\FullTextSearch\Search\Services\IndexableService; |
||||
18 | use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater; |
||||
19 | use SilverStripe\FullTextSearch\Search\Variants\SearchVariantSubsites; |
||||
20 | use SilverStripe\FullTextSearch\Solr\SolrIndex; |
||||
21 | use SilverStripe\FullTextSearch\Solr\Services\Solr3Service; |
||||
22 | use SilverStripe\FullTextSearch\Solr\Services\Solr4Service; |
||||
23 | use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_Container; |
||||
24 | use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_HasOne; |
||||
25 | use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_HasMany; |
||||
26 | use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_ManyMany; |
||||
27 | use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_OtherContainer; |
||||
28 | use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_AmbiguousRelationIndex; |
||||
29 | use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_AmbiguousRelationInheritedIndex; |
||||
30 | use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_BoostedIndex; |
||||
31 | use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_FakeIndex; |
||||
32 | use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_FakeIndex2; |
||||
33 | use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_ShowInSearchIndex; |
||||
34 | use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_MyPage; |
||||
35 | use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_MyDataObjectOne; |
||||
36 | use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_MyDataObjectTwo; |
||||
37 | use SilverStripe\ORM\DataObject; |
||||
38 | use SilverStripe\Subsites\Model\Subsite; |
||||
39 | use SilverStripe\Versioned\Versioned; |
||||
40 | |||||
41 | class SolrIndexTest extends SapphireTest |
||||
42 | { |
||||
43 | |||||
44 | protected $usesDatabase = true; |
||||
45 | |||||
46 | protected static $extra_dataobjects = [ |
||||
47 | SolrIndexTest_MyPage::class, |
||||
48 | SolrIndexTest_MyDataObjectOne::class, |
||||
49 | SolrIndexTest_MyDataObjectTwo::class, |
||||
50 | ]; |
||||
51 | |||||
52 | public function testFieldDataHasOne() |
||||
53 | { |
||||
54 | $index = new SolrIndexTest_FakeIndex(); |
||||
55 | $data = $index->fieldData('HasOneObject.Field1'); |
||||
56 | |||||
57 | $data = $data[SearchUpdaterTest_Container::class . '_HasOneObject_Field1']; |
||||
58 | |||||
59 | $this->assertEquals(SearchUpdaterTest_Container::class, $data['origin']); |
||||
60 | $this->assertEquals(SearchUpdaterTest_Container::class, $data['base']); |
||||
61 | $this->assertEquals(SearchUpdaterTest_HasOne::class, $data['class']); |
||||
62 | } |
||||
63 | |||||
64 | public function testFieldDataHasMany() |
||||
65 | { |
||||
66 | $index = new SolrIndexTest_FakeIndex(); |
||||
67 | $data = $index->fieldData('HasManyObjects.Field1'); |
||||
68 | $data = $data[SearchUpdaterTest_Container::class . '_HasManyObjects_Field1']; |
||||
69 | |||||
70 | $this->assertEquals(SearchUpdaterTest_Container::class, $data['origin']); |
||||
71 | $this->assertEquals(SearchUpdaterTest_Container::class, $data['base']); |
||||
72 | $this->assertEquals(SearchUpdaterTest_HasMany::class, $data['class']); |
||||
73 | } |
||||
74 | |||||
75 | public function testFieldDataManyMany() |
||||
76 | { |
||||
77 | $index = new SolrIndexTest_FakeIndex(); |
||||
78 | $data = $index->fieldData('ManyManyObjects.Field1'); |
||||
79 | $data = $data[SearchUpdaterTest_Container::class . '_ManyManyObjects_Field1']; |
||||
80 | |||||
81 | $this->assertEquals(SearchUpdaterTest_Container::class, $data['origin']); |
||||
82 | $this->assertEquals(SearchUpdaterTest_Container::class, $data['base']); |
||||
83 | $this->assertEquals(SearchUpdaterTest_ManyMany::class, $data['class']); |
||||
84 | } |
||||
85 | |||||
86 | public function testFieldDataAmbiguousHasMany() |
||||
87 | { |
||||
88 | $index = new SolrIndexTest_AmbiguousRelationIndex(); |
||||
89 | $data = $index->fieldData('HasManyObjects.Field1'); |
||||
90 | |||||
91 | $this->assertArrayHasKey(SearchUpdaterTest_Container::class . '_HasManyObjects_Field1', $data); |
||||
92 | $this->assertArrayHasKey(SearchUpdaterTest_OtherContainer::class . '_HasManyObjects_Field1', $data); |
||||
93 | |||||
94 | $dataContainer = $data[SearchUpdaterTest_Container::class . '_HasManyObjects_Field1']; |
||||
95 | $this->assertEquals(SearchUpdaterTest_Container::class, $dataContainer['origin']); |
||||
96 | $this->assertEquals(SearchUpdaterTest_Container::class, $dataContainer['base']); |
||||
97 | $this->assertEquals(SearchUpdaterTest_HasMany::class, $dataContainer['class']); |
||||
98 | |||||
99 | $dataOtherContainer = $data[SearchUpdaterTest_OtherContainer::class . '_HasManyObjects_Field1']; |
||||
100 | $this->assertEquals(SearchUpdaterTest_OtherContainer::class, $dataOtherContainer['origin']); |
||||
101 | $this->assertEquals(SearchUpdaterTest_OtherContainer::class, $dataOtherContainer['base']); |
||||
102 | $this->assertEquals(SearchUpdaterTest_HasMany::class, $dataOtherContainer['class']); |
||||
103 | } |
||||
104 | |||||
105 | public function testFieldDataAmbiguousManyMany() |
||||
106 | { |
||||
107 | $index = new SolrIndexTest_AmbiguousRelationIndex(); |
||||
108 | $data = $index->fieldData('ManyManyObjects.Field1'); |
||||
109 | |||||
110 | $this->assertArrayHasKey(SearchUpdaterTest_Container::class . '_ManyManyObjects_Field1', $data); |
||||
111 | $this->assertArrayHasKey(SearchUpdaterTest_OtherContainer::class . '_ManyManyObjects_Field1', $data); |
||||
112 | |||||
113 | $dataContainer = $data[SearchUpdaterTest_Container::class . '_ManyManyObjects_Field1']; |
||||
114 | $this->assertEquals(SearchUpdaterTest_Container::class, $dataContainer['origin']); |
||||
115 | $this->assertEquals(SearchUpdaterTest_Container::class, $dataContainer['base']); |
||||
116 | $this->assertEquals(SearchUpdaterTest_ManyMany::class, $dataContainer['class']); |
||||
117 | |||||
118 | $dataOtherContainer = $data[SearchUpdaterTest_OtherContainer::class . '_ManyManyObjects_Field1']; |
||||
119 | $this->assertEquals(SearchUpdaterTest_OtherContainer::class, $dataOtherContainer['origin']); |
||||
120 | $this->assertEquals(SearchUpdaterTest_OtherContainer::class, $dataOtherContainer['base']); |
||||
121 | $this->assertEquals(SearchUpdaterTest_ManyMany::class, $dataOtherContainer['class']); |
||||
122 | } |
||||
123 | |||||
124 | public function testFieldDataAmbiguousManyManyInherited() |
||||
125 | { |
||||
126 | $index = new SolrIndexTest_AmbiguousRelationInheritedIndex(); |
||||
127 | $data = $index->fieldData('ManyManyObjects.Field1'); |
||||
128 | |||||
129 | $this->assertArrayHasKey(SearchUpdaterTest_Container::class . '_ManyManyObjects_Field1', $data); |
||||
130 | $this->assertArrayHasKey(SearchUpdaterTest_OtherContainer::class . '_ManyManyObjects_Field1', $data); |
||||
131 | $this->assertArrayNotHasKey(SearchUpdaterTest_ExtendedContainer::class . '_ManyManyObjects_Field1', $data); |
||||
132 | |||||
133 | $dataContainer = $data[SearchUpdaterTest_Container::class . '_ManyManyObjects_Field1']; |
||||
134 | $this->assertEquals(SearchUpdaterTest_Container::class, $dataContainer['origin']); |
||||
135 | $this->assertEquals(SearchUpdaterTest_Container::class, $dataContainer['base']); |
||||
136 | $this->assertEquals(SearchUpdaterTest_ManyMany::class, $dataContainer['class']); |
||||
137 | |||||
138 | $dataOtherContainer = $data[SearchUpdaterTest_OtherContainer::class . '_ManyManyObjects_Field1']; |
||||
139 | $this->assertEquals(SearchUpdaterTest_OtherContainer::class, $dataOtherContainer['origin']); |
||||
140 | $this->assertEquals(SearchUpdaterTest_OtherContainer::class, $dataOtherContainer['base']); |
||||
141 | $this->assertEquals(SearchUpdaterTest_ManyMany::class, $dataOtherContainer['class']); |
||||
142 | } |
||||
143 | |||||
144 | /** |
||||
145 | * Test boosting on SearchQuery |
||||
146 | */ |
||||
147 | public function testBoostedQuery() |
||||
148 | { |
||||
149 | /** @var Solr3Service|PHPUnit_Framework_MockObject_MockObject $serviceMock */ |
||||
150 | $serviceMock = $this->getMockBuilder(Solr3Service::class) |
||||
151 | ->setMethods(['search']) |
||||
152 | ->getMock(); |
||||
153 | |||||
154 | $serviceMock->expects($this->once()) |
||||
155 | ->method('search') |
||||
156 | ->with( |
||||
157 | $this->equalTo('+(Field1:term^1.5 OR HasOneObject_Field1:term^3)'), |
||||
158 | $this->anything(), |
||||
159 | $this->anything(), |
||||
160 | $this->anything(), |
||||
161 | $this->anything() |
||||
162 | )->willReturn($this->getFakeRawSolrResponse()); |
||||
163 | |||||
164 | $index = new SolrIndexTest_FakeIndex(); |
||||
165 | $index->setService($serviceMock); |
||||
166 | |||||
167 | $query = new SearchQuery(); |
||||
168 | $query->addSearchTerm( |
||||
169 | 'term', |
||||
170 | null, |
||||
171 | array('Field1' => 1.5, 'HasOneObject_Field1' => 3) |
||||
172 | ); |
||||
173 | $index->search($query); |
||||
174 | } |
||||
175 | |||||
176 | /** |
||||
177 | * Test boosting on field schema (via queried fields parameter) |
||||
178 | */ |
||||
179 | public function testBoostedField() |
||||
180 | { |
||||
181 | if (class_exists(Subsite::class)) { |
||||
182 | Config::modify()->set(SearchVariantSubsites::class, 'enabled', false); |
||||
183 | } |
||||
184 | |||||
185 | /** @var Solr3Service|PHPUnit_Framework_MockObject_MockObject $serviceMock */ |
||||
186 | $serviceMock = $this->getMockBuilder(Solr3Service::class) |
||||
187 | ->setMethods(['search']) |
||||
188 | ->getMock(); |
||||
189 | |||||
190 | $serviceMock->expects($this->once()) |
||||
191 | ->method('search') |
||||
192 | ->with( |
||||
193 | $this->equalTo('+term'), |
||||
194 | $this->anything(), |
||||
195 | $this->anything(), |
||||
196 | $this->equalTo([ |
||||
197 | 'qf' => SearchUpdaterTest_Container::class . '_Field1^1.5 ' |
||||
198 | . SearchUpdaterTest_Container::class . '_Field2^2.1 _text', |
||||
199 | 'fq' => '', |
||||
200 | ]), |
||||
201 | $this->anything() |
||||
202 | )->willReturn($this->getFakeRawSolrResponse()); |
||||
203 | |||||
204 | $index = new SolrIndexTest_BoostedIndex(); |
||||
205 | $index->setService($serviceMock); |
||||
206 | |||||
207 | $query = new SearchQuery(); |
||||
208 | $query->addSearchTerm('term'); |
||||
209 | $index->search($query); |
||||
210 | } |
||||
211 | |||||
212 | public function testHighlightQueryOnBoost() |
||||
213 | { |
||||
214 | /** @var SilverStripe\FullTextSearch\Solr\Services\Solr3Service|ObjectProphecy $serviceMock */ |
||||
215 | $serviceMock = $this->getMockBuilder(Solr3Service::class) |
||||
216 | ->setMethods(['search']) |
||||
217 | ->getMock(); |
||||
218 | |||||
219 | $serviceMock->expects($this->exactly(2)) |
||||
220 | ->method('search') |
||||
221 | ->withConsecutive( |
||||
222 | [ |
||||
223 | $this->equalTo('+(Field1:term^1.5 OR HasOneObject_Field1:term^3)'), |
||||
224 | $this->anything(), |
||||
225 | $this->anything(), |
||||
226 | $this->logicalNot( |
||||
227 | $this->arrayHasKey('hl.q') |
||||
228 | ), |
||||
229 | $this->anything() |
||||
230 | ], |
||||
231 | [ |
||||
232 | $this->equalTo('+(Field1:term^1.5 OR HasOneObject_Field1:term^3)'), |
||||
233 | $this->anything(), |
||||
234 | $this->anything(), |
||||
235 | $this->arrayHasKey('hl.q'), |
||||
236 | $this->anything() |
||||
237 | ] |
||||
238 | )->willReturn($this->getFakeRawSolrResponse()); |
||||
239 | |||||
240 | $index = new SolrIndexTest_FakeIndex(); |
||||
241 | $index->setService($serviceMock); |
||||
242 | |||||
243 | // Search without highlighting |
||||
244 | $query = new SearchQuery(); |
||||
245 | $query->addSearchTerm( |
||||
246 | 'term', |
||||
247 | null, |
||||
248 | array('Field1' => 1.5, 'HasOneObject_Field1' => 3) |
||||
249 | ); |
||||
250 | $index->search($query); |
||||
251 | |||||
252 | // Search with highlighting |
||||
253 | $query = new SearchQuery(); |
||||
254 | $query->addSearchTerm( |
||||
255 | 'term', |
||||
256 | null, |
||||
257 | array('Field1' => 1.5, 'HasOneObject_Field1' => 3) |
||||
258 | ); |
||||
259 | $index->search($query, -1, -1, array('hl' => true)); |
||||
260 | } |
||||
261 | |||||
262 | public function testIndexExcludesNullValues() |
||||
263 | { |
||||
264 | /** @var Solr3Service|ObjectProphecy $serviceMock */ |
||||
265 | $serviceMock = $this->createMock(Solr3Service::class); |
||||
266 | $index = new SolrIndexTest_FakeIndex(); |
||||
267 | $index->setService($serviceMock); |
||||
268 | $obj = new SearchUpdaterTest_Container(); |
||||
269 | |||||
270 | $obj->Field1 = 'Field1 val'; |
||||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||||
271 | $obj->Field2 = null; |
||||
0 ignored issues
–
show
The property
Field2 does not exist on SilverStripe\FullTextSea...chUpdaterTest_Container . Since you implemented __set , consider adding a @property annotation.
![]() |
|||||
272 | $obj->MyDate = null; |
||||
0 ignored issues
–
show
The property
MyDate does not exist on SilverStripe\FullTextSea...chUpdaterTest_Container . Since you implemented __set , consider adding a @property annotation.
![]() |
|||||
273 | $docs = $index->add($obj); |
||||
274 | $value = $docs[0]->getField(SearchUpdaterTest_Container::class . '_Field1'); |
||||
275 | $this->assertEquals('Field1 val', $value['value'], 'Writes non-NULL string fields'); |
||||
276 | $value = $docs[0]->getField(SearchUpdaterTest_Container::class . '_Field2'); |
||||
277 | $this->assertFalse($value, 'Ignores string fields if they are NULL'); |
||||
278 | $value = $docs[0]->getField(SearchUpdaterTest_Container::class . '_MyDate'); |
||||
279 | $this->assertFalse($value, 'Ignores date fields if they are NULL'); |
||||
280 | |||||
281 | $obj->MyDate = '2010-12-30'; |
||||
282 | $docs = $index->add($obj); |
||||
283 | $value = $docs[0]->getField(SearchUpdaterTest_Container::class . '_MyDate'); |
||||
284 | $this->assertEquals('2010-12-30T00:00:00Z', $value['value'], 'Writes non-NULL dates'); |
||||
285 | } |
||||
286 | |||||
287 | public function testAddFieldExtraOptions() |
||||
288 | { |
||||
289 | Injector::inst()->get(Kernel::class)->setEnvironment('live'); |
||||
290 | |||||
291 | $index = new SolrIndexTest_FakeIndex(); |
||||
292 | |||||
293 | $defs = simplexml_load_string('<fields>' . $index->getFieldDefinitions() . '</fields>'); |
||||
294 | $defField1 = $defs->xpath('field[@name="' . SearchUpdaterTest_Container::class . '_Field1"]'); |
||||
295 | $this->assertEquals((string)$defField1[0]['stored'], 'false'); |
||||
296 | |||||
297 | $index->addFilterField('Field1', null, array('stored' => 'true')); |
||||
0 ignored issues
–
show
array('stored' => 'true') of type array<string,string> is incompatible with the type string expected by parameter $extraOptions of SilverStripe\FullTextSea...Index::addFilterField() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
298 | $defs = simplexml_load_string('<fields>' . $index->getFieldDefinitions() . '</fields>'); |
||||
299 | $defField1 = $defs->xpath('field[@name="' . SearchUpdaterTest_Container::class . '_Field1"]'); |
||||
300 | $this->assertEquals((string)$defField1[0]['stored'], 'true'); |
||||
301 | } |
||||
302 | |||||
303 | public function testAddAnalyzer() |
||||
304 | { |
||||
305 | $index = new SolrIndexTest_FakeIndex(); |
||||
306 | |||||
307 | $defs = simplexml_load_string('<fields>' . $index->getFieldDefinitions() . '</fields>'); |
||||
308 | $defField1 = $defs->xpath('field[@name="' . SearchUpdaterTest_Container::class . '_Field1"]'); |
||||
309 | $analyzers = $defField1[0]->analyzer; |
||||
310 | $this->assertFalse((bool)$analyzers); |
||||
311 | |||||
312 | $index->addAnalyzer('Field1', 'charFilter', array('class' => 'solr.HTMLStripCharFilterFactory')); |
||||
313 | $defs = simplexml_load_string('<fields>' . $index->getFieldDefinitions() . '</fields>'); |
||||
314 | $defField1 = $defs->xpath('field[@name="' . SearchUpdaterTest_Container::class . '_Field1"]'); |
||||
315 | $analyzers = $defField1[0]->analyzer; |
||||
316 | $this->assertTrue((bool)$analyzers); |
||||
317 | $this->assertEquals('solr.HTMLStripCharFilterFactory', $analyzers[0]->charFilter[0]['class']); |
||||
318 | } |
||||
319 | |||||
320 | public function testAddCopyField() |
||||
321 | { |
||||
322 | $index = new SolrIndexTest_FakeIndex(); |
||||
323 | $index->addCopyField('sourceField', 'destField'); |
||||
324 | |||||
325 | $defs = simplexml_load_string('<fields>' . $index->getCopyFieldDefinitions() . '</fields>'); |
||||
326 | $copyField = $defs->xpath('copyField'); |
||||
327 | |||||
328 | $this->assertEquals('sourceField', $copyField[0]['source']); |
||||
329 | $this->assertEquals('destField', $copyField[0]['dest']); |
||||
330 | } |
||||
331 | |||||
332 | /** |
||||
333 | * Tests the setting of the 'stored' flag |
||||
334 | */ |
||||
335 | public function testStoredFields() |
||||
336 | { |
||||
337 | // Test two fields |
||||
338 | $index = new SolrIndexTest_FakeIndex2(); |
||||
339 | $index->addStoredField('Field1'); |
||||
340 | $index->addFulltextField('Field2'); |
||||
341 | $schema = $index->getFieldDefinitions(); |
||||
342 | $this->assertContains( |
||||
343 | "<field name='" . SearchUpdaterTest_Container::class . "_Field1' type='text' indexed='true' stored='true'", |
||||
344 | $schema |
||||
345 | ); |
||||
346 | $this->assertContains( |
||||
347 | "<field name='" . SearchUpdaterTest_Container::class . "_Field2' type='text' indexed='true' stored='false'", |
||||
348 | $schema |
||||
349 | ); |
||||
350 | |||||
351 | // Test with addAllFulltextFields |
||||
352 | $index2 = new SolrIndexTest_FakeIndex2(); |
||||
353 | $index2->addAllFulltextFields(); |
||||
354 | $index2->addStoredField('Field2'); |
||||
355 | $schema2 = $index2->getFieldDefinitions(); |
||||
356 | $this->assertContains( |
||||
357 | "<field name='" . SearchUpdaterTest_Container::class . "_Field1' type='text' indexed='true' stored='false'", |
||||
358 | $schema2 |
||||
359 | ); |
||||
360 | $this->assertContains( |
||||
361 | "<field name='" . SearchUpdaterTest_Container::class . "_Field2' type='text' indexed='true' stored='true'", |
||||
362 | $schema2 |
||||
363 | ); |
||||
364 | } |
||||
365 | |||||
366 | public function testSanitiseClassName() |
||||
367 | { |
||||
368 | $index = new SolrIndexTest_FakeIndex2; |
||||
369 | |||||
370 | $this->assertSame( |
||||
371 | 'SilverStripe\\\\FullTextSearch\\\\Tests\\\\SolrIndexTest', |
||||
372 | $index->sanitiseClassName(static::class) |
||||
373 | ); |
||||
374 | |||||
375 | $this->assertSame( |
||||
376 | 'SilverStripe-FullTextSearch-Tests-SolrIndexTest', |
||||
377 | $index->sanitiseClassName(static::class, '-') |
||||
378 | ); |
||||
379 | } |
||||
380 | |||||
381 | public function testGetIndexName() |
||||
382 | { |
||||
383 | $index = new SolrIndexTest_FakeIndex2; |
||||
384 | $this->assertSame( |
||||
385 | 'SilverStripe-FullTextSearch-Tests-SolrIndexTest-SolrIndexTest_FakeIndex2', |
||||
386 | $index->getIndexName() |
||||
387 | ); |
||||
388 | } |
||||
389 | |||||
390 | public function testGetIndexNameWithPrefixAndSuffixFromEnvironment() |
||||
391 | { |
||||
392 | $index = new SolrIndexTest_FakeIndex2; |
||||
393 | |||||
394 | Environment::putEnv('SS_SOLR_INDEX_PREFIX="foo_"'); |
||||
395 | Environment::putEnv('SS_SOLR_INDEX_SUFFIX="_bar"'); |
||||
396 | |||||
397 | $this->assertSame( |
||||
398 | 'foo_SilverStripe-FullTextSearch-Tests-SolrIndexTest-SolrIndexTest_FakeIndex2_bar', |
||||
399 | $index->getIndexName() |
||||
400 | ); |
||||
401 | } |
||||
402 | |||||
403 | /** |
||||
404 | * Test that ShowInSearch and getShowInSearch() exclude DataObjects from being added to the index |
||||
405 | * |
||||
406 | * Note: this code path that really being tested here is SearchUpdateProcessor->prepareIndexes() |
||||
407 | * This code path is used for 'inlet' filtering on CMS->save() |
||||
408 | * The results of this will show-up in SolrIndex->_addAs() |
||||
409 | */ |
||||
410 | public function testShowInSearch() |
||||
411 | { |
||||
412 | $defaultMode = Versioned::get_reading_mode(); |
||||
413 | Versioned::set_reading_mode('Stage.' . Versioned::DRAFT); |
||||
414 | |||||
415 | $serviceMock = $this->getMockBuilder(Solr4Service::class) |
||||
416 | ->setMethods(['addDocument', 'deleteById']) |
||||
417 | ->getMock(); |
||||
418 | |||||
419 | $index = new SolrIndexTest_ShowInSearchIndex(); |
||||
420 | $index->setService($serviceMock); |
||||
421 | FullTextSearch::force_index_list($index); |
||||
422 | |||||
423 | // will get added |
||||
424 | $pageA = new Page(); |
||||
425 | $pageA->Title = 'Test Page true'; |
||||
426 | $pageA->ShowInSearch = true; |
||||
427 | $pageA->write(); |
||||
428 | |||||
429 | // will get filtered out |
||||
430 | $page = new Page(); |
||||
431 | $page->Title = 'Test Page false'; |
||||
432 | $page->ShowInSearch = false; |
||||
433 | $page->write(); |
||||
434 | |||||
435 | // will get added |
||||
436 | $fileA = new File(); |
||||
437 | $fileA->Title = 'Test File true'; |
||||
438 | $fileA->ShowInSearch = true; |
||||
439 | $fileA->write(); |
||||
440 | |||||
441 | // will get filtered out |
||||
442 | $file = new File(); |
||||
443 | $file->Title = 'Test File false'; |
||||
444 | $file->ShowInSearch = false; |
||||
445 | $file->write(); |
||||
446 | |||||
447 | // will get added |
||||
448 | $objOneA = new SolrIndexTest_MyDataObjectOne(); |
||||
449 | $objOneA->Title = 'Test MyDataObjectOne true'; |
||||
450 | $objOneA->ShowInSearch = true; |
||||
451 | $objOneA->write(); |
||||
452 | |||||
453 | // will get filtered out |
||||
454 | $objOne = new SolrIndexTest_MyDataObjectOne(); |
||||
455 | $objOne->Title = 'Test MyDataObjectOne false'; |
||||
456 | $objOne->ShowInSearch = false; |
||||
457 | $objOne->write(); |
||||
458 | |||||
459 | // will get added |
||||
460 | // this class has a getShowInSearch() == true, which will override $mypage->ShowInSearch = false |
||||
461 | $objTwoA = new SolrIndexTest_MyDataObjectTwo(); |
||||
462 | $objTwoA->Title = 'Test MyDataObjectTwo false'; |
||||
463 | $objTwoA->ShowInSearch = false; |
||||
464 | $objTwoA->write(); |
||||
465 | |||||
466 | // will get added |
||||
467 | // this class has a getShowInSearch() == true, which will override $mypage->ShowInSearch = false |
||||
468 | $myPageA = new SolrIndexTest_MyPage(); |
||||
469 | $myPageA->Title = 'Test MyPage false'; |
||||
470 | $myPageA->ShowInSearch = false; |
||||
471 | $myPageA->write(); |
||||
472 | |||||
473 | $callback = function (Apache_Solr_Document $doc) use ($pageA, $myPageA, $fileA, $objOneA, $objTwoA): bool { |
||||
474 | $validKeys = [ |
||||
475 | Page::class . $pageA->ID, |
||||
476 | SolrIndexTest_MyPage::class . $myPageA->ID, |
||||
477 | File::class . $fileA->ID, |
||||
478 | SolrIndexTest_MyDataObjectOne::class . $objOneA->ID, |
||||
479 | SolrIndexTest_MyDataObjectTwo::class . $objTwoA->ID |
||||
480 | ]; |
||||
481 | return in_array($this->createSolrDocKey($doc), $validKeys); |
||||
482 | }; |
||||
483 | |||||
484 | $serviceMock |
||||
485 | ->expects($this->exactly(5)) |
||||
486 | ->method('addDocument') |
||||
487 | ->withConsecutive( |
||||
488 | [$this->callback($callback)], |
||||
489 | [$this->callback($callback)], |
||||
490 | [$this->callback($callback)], |
||||
491 | [$this->callback($callback)], |
||||
492 | [$this->callback($callback)] |
||||
493 | ); |
||||
494 | |||||
495 | // This is what actually triggers all the solr stuff |
||||
496 | SearchUpdater::flush_dirty_indexes(); |
||||
497 | |||||
498 | // delete a solr doc by setting ShowInSearch to false |
||||
499 | $pageA->ShowInSearch = false; |
||||
500 | $pageA->write(); |
||||
501 | |||||
502 | $serviceMock |
||||
503 | ->expects($this->exactly(1)) |
||||
504 | ->method('deleteById') |
||||
505 | ->withConsecutive( |
||||
506 | [$this->callback(function (string $docID) use ($pageA): bool { |
||||
507 | return strpos($docID, $pageA->ID . '-' . SiteTree::class) !== false; |
||||
508 | })] |
||||
509 | ); |
||||
510 | |||||
511 | IndexableService::singleton()->clearCache(); |
||||
512 | SearchUpdater::flush_dirty_indexes(); |
||||
513 | |||||
514 | Versioned::set_reading_mode($defaultMode); |
||||
515 | } |
||||
516 | |||||
517 | protected function createSolrDocKey(Apache_Solr_Document $doc) |
||||
518 | { |
||||
519 | return $doc->getField('ClassName')['value'] . $doc->getField('ID')['value']; |
||||
520 | } |
||||
521 | |||||
522 | protected function getFakeRawSolrResponse() |
||||
523 | { |
||||
524 | return new \Apache_Solr_Response( |
||||
525 | new \Apache_Solr_HttpTransport_Response( |
||||
526 | null, |
||||
527 | null, |
||||
528 | '{}' |
||||
529 | ) |
||||
530 | ); |
||||
531 | } |
||||
532 | } |
||||
533 |