silverstripe /
silverstripe-fulltextsearch
| 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
Loading history...
|
|||||
| 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.
Loading history...
|
|||||
| 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.
Loading history...
|
|||||
| 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
Loading history...
|
|||||
| 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 |