1 | <?php |
||
2 | |||
3 | namespace SilverStripe\FullTextSearch\Tests; |
||
4 | |||
5 | use Apache_Solr_Document; |
||
6 | use Page; |
||
7 | use SilverStripe\Assets\File; |
||
8 | use SilverStripe\Assets\Image; |
||
9 | use SilverStripe\CMS\Model\SiteTree; |
||
10 | use SilverStripe\Core\Config\Config; |
||
11 | use SilverStripe\Core\Injector\Injector; |
||
12 | use SilverStripe\Dev\SapphireTest; |
||
13 | use SilverStripe\FullTextSearch\Search\FullTextSearch; |
||
14 | use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateImmediateProcessor; |
||
15 | use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateProcessor; |
||
16 | use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater; |
||
17 | use SilverStripe\FullTextSearch\Search\Variants\SearchVariantSubsites; |
||
18 | use SilverStripe\FullTextSearch\Solr\Services\Solr4Service; |
||
19 | use SilverStripe\FullTextSearch\Tests\SolrIndexSubsitesTest\SolrIndexSubsitesTest_Index; |
||
20 | use SilverStripe\FullTextSearch\Tests\SolrIndexVersionedTest\SolrDocumentMatcher; |
||
21 | use SilverStripe\ORM\DataObject; |
||
22 | use SilverStripe\Subsites\Model\Subsite; |
||
23 | use SilverStripe\Versioned\Versioned; |
||
24 | |||
25 | /** |
||
26 | * Subsite specific solr testing |
||
27 | */ |
||
28 | class SolrIndexSubsitesTest extends SapphireTest |
||
29 | { |
||
30 | protected static $fixture_file = 'SolrIndexSubsitesTest/SolrIndexSubsitesTest.yml'; |
||
31 | |||
32 | /** |
||
33 | * @var SolrIndexSubsitesTest_Index |
||
34 | */ |
||
35 | private static $index = null; |
||
36 | |||
37 | protected $server = null; |
||
38 | |||
39 | protected function setUp() |
||
40 | { |
||
41 | // Prevent parent::setUp() crashing on db build |
||
42 | if (!class_exists(Subsite::class)) { |
||
43 | static::$fixture_file = null; |
||
44 | } |
||
45 | |||
46 | parent::setUp(); |
||
47 | |||
48 | if (!class_exists(Subsite::class)) { |
||
49 | $this->markTestSkipped("These tests need the Subsite module installed to run"); |
||
50 | } |
||
51 | |||
52 | $this->server = $_SERVER; |
||
53 | |||
54 | if (self::$index === null) { |
||
55 | self::$index = singleton(SolrIndexSubsitesTest_Index::class); |
||
56 | } |
||
57 | |||
58 | Config::modify()->set(Injector::class, SearchUpdateProcessor::class, [ |
||
59 | 'class' => SearchUpdateImmediateProcessor::class, |
||
60 | ]); |
||
61 | |||
62 | FullTextSearch::force_index_list(self::$index); |
||
63 | SearchUpdater::clear_dirty_indexes(); |
||
64 | } |
||
65 | |||
66 | protected function tearDown() |
||
67 | { |
||
68 | if ($this->server) { |
||
69 | $_SERVER = $this->server; |
||
70 | $this->server = null; |
||
71 | } |
||
72 | parent::tearDown(); |
||
73 | } |
||
74 | |||
75 | protected function getServiceMock() |
||
76 | { |
||
77 | return $this->getMockBuilder(Solr4Service::class) |
||
78 | ->setMethods(['addDocument', 'commit']) |
||
79 | ->getMock(); |
||
80 | } |
||
81 | |||
82 | /** |
||
83 | * @param DataObject $object Item being added |
||
84 | * @param int $subsiteID |
||
85 | * @param string $stage |
||
86 | * @return string |
||
87 | */ |
||
88 | protected function getExpectedDocumentId($object, $subsiteID, $stage = null) |
||
89 | { |
||
90 | $id = $object->ID; |
||
91 | $class = DataObject::getSchema()->baseDataClass($object); |
||
92 | $variants = array(); |
||
93 | |||
94 | // Check subsite |
||
95 | if (class_exists(Subsite::class) |
||
96 | && DataObject::getSchema()->hasOneComponent($object->getClassName(), 'Subsite') |
||
97 | ) { |
||
98 | $variants[] = '"SearchVariantSubsites":"' . $subsiteID . '"'; |
||
99 | } |
||
100 | |||
101 | // Check versioned |
||
102 | if ($stage) { |
||
103 | $variants[] = '"SearchVariantVersioned":"' . $stage . '"'; |
||
104 | } |
||
105 | return $id . '-' . $class . '-{' . implode(',', $variants) . '}'; |
||
106 | } |
||
107 | |||
108 | public function testPublishing() |
||
109 | { |
||
110 | // Setup mocks |
||
111 | $serviceMock = $this->getServiceMock(); |
||
112 | self::$index->setService($serviceMock); |
||
113 | |||
114 | $subsite1 = $this->objFromFixture(Subsite::class, 'subsite1'); |
||
115 | |||
116 | // Add records to first subsite |
||
117 | Versioned::set_stage(Versioned::DRAFT); |
||
118 | $_SERVER['HTTP_HOST'] = 'www.subsite1.com'; |
||
119 | |||
120 | $file = new File(); |
||
121 | $file->Title = 'My File'; |
||
122 | $file->SubsiteID = $subsite1->ID; |
||
123 | $file->write(); |
||
124 | |||
125 | $page = new Page(); |
||
126 | $page->Title = 'My Page'; |
||
127 | $page->SubsiteID = $subsite1->ID; |
||
128 | $page->write(); |
||
129 | |||
130 | $doc1 = new Apache_Solr_Document([ |
||
0 ignored issues
–
show
|
|||
131 | '_documentid' => $this->getExpectedDocumentId($page, $subsite1->ID, 'Stage'), |
||
132 | 'ClassName' => 'Page', |
||
133 | 'SiteTree_Title' => 'My Page', |
||
134 | '_versionedstage' => 'Stage', |
||
135 | '_subsite' => $subsite1->ID, |
||
136 | ]); |
||
137 | |||
138 | $doc2 = new Apache_Solr_Document([ |
||
139 | '_documentid' => $this->getExpectedDocumentId($file, $subsite1->ID), |
||
140 | 'ClassName' => File::class, |
||
141 | 'File_Title' => 'My File', |
||
142 | '_subsite' => $subsite1->ID, |
||
143 | ]); |
||
144 | |||
145 | $serviceMock |
||
146 | ->expects($this->exactly(2)) |
||
147 | ->method('addDocument') |
||
148 | ->withConsecutive($doc1, $doc2); |
||
149 | |||
150 | SearchUpdater::flush_dirty_indexes(); |
||
151 | } |
||
152 | |||
153 | public function testCorrectSubsiteIDOnPageWrite() |
||
154 | { |
||
155 | $mockWrites = [ |
||
156 | '3367:SiteTree:a:1:{s:22:"SearchVariantVersioned";s:4:"Live";}' => [ |
||
157 | 'base' => 'SilverStripe\\CMS\\Model\\SiteTree', |
||
158 | 'class' => 'Page', |
||
159 | 'id' => 3367, |
||
160 | 'statefulids' => [ |
||
161 | [ |
||
162 | 'id' => 3367, |
||
163 | 'state' => [ |
||
164 | 'SearchVariantVersioned' => 'Live', |
||
165 | ], |
||
166 | ], |
||
167 | ], |
||
168 | 'fields' => [ |
||
169 | 'SilverStripe\\CMS\\Model\\SiteTree:ClassName' => 'Page', |
||
170 | 'SilverStripe\\CMS\\Model\\SiteTree:LastEdited' => '2016-12-08 23:55:30', |
||
171 | 'SilverStripe\\CMS\\Model\\SiteTree:Created' => '2016-11-30 05:23:58', |
||
172 | 'SilverStripe\\CMS\\Model\\SiteTree:URLSegment' => 'test', |
||
173 | 'SilverStripe\\CMS\\Model\\SiteTree:Title' => 'Test Title', |
||
174 | 'SilverStripe\\CMS\\Model\\SiteTree:Content' => '<p>test content</p>', |
||
175 | 'SilverStripe\\CMS\\Model\\SiteTree:MetaDescription' => 'a solr test', |
||
176 | 'SilverStripe\\CMS\\Model\\SiteTree:ShowInMenus' => 1, |
||
177 | 'SilverStripe\\CMS\\Model\\SiteTree:ShowInSearch' => 1, |
||
178 | 'SilverStripe\\CMS\\Model\\SiteTree:Sort' => 77, |
||
179 | 'SilverStripe\\CMS\\Model\\SiteTree:HasBrokenFile' => 0, |
||
180 | 'SilverStripe\\CMS\\Model\\SiteTree:HasBrokenLink' => 0, |
||
181 | 'SilverStripe\\CMS\\Model\\SiteTree:CanViewType' => 'Inherit', |
||
182 | 'SilverStripe\\CMS\\Model\\SiteTree:CanEditType' => 'Inherit', |
||
183 | 'SilverStripe\\CMS\\Model\\SiteTree:Locale' => 'en_NZ', |
||
184 | 'SilverStripe\\CMS\\Model\\SiteTree:SubsiteID' => 0, |
||
185 | 'Page:ID' => 3367, |
||
186 | 'Page:MetaKeywords' => null, |
||
187 | ], |
||
188 | ], |
||
189 | ]; |
||
190 | $variant = new SearchVariantSubsites(); |
||
191 | $tmpMockWrites = $mockWrites; |
||
192 | $variant->extractManipulationWriteState($tmpMockWrites); |
||
193 | |||
194 | foreach ($tmpMockWrites as $mockWrite) { |
||
195 | $this->assertCount(1, $mockWrite['statefulids']); |
||
196 | $statefulIDs = array_shift($mockWrite['statefulids']); |
||
197 | |||
198 | $this->assertArrayHasKey(SearchVariantSubsites::class, $statefulIDs['state']); |
||
199 | $this->assertEquals(0, $statefulIDs['state'][SearchVariantSubsites::class]); |
||
200 | } |
||
201 | |||
202 | $subsite = $this->objFromFixture(Subsite::class, 'subsite1'); |
||
203 | $tmpMockWrites = $mockWrites; |
||
204 | $tmpMockWrites['3367:SiteTree:a:1:{s:22:"SearchVariantVersioned";s:4:"Live";}']['fields'][SiteTree::class . ':SubsiteID'] = $subsite->ID; |
||
205 | |||
206 | $variant->extractManipulationWriteState($tmpMockWrites); |
||
207 | foreach ($tmpMockWrites as $mockWrite) { |
||
208 | $this->assertCount(1, $mockWrite['statefulids']); |
||
209 | $statefulIDs = array_shift($mockWrite['statefulids']); |
||
210 | |||
211 | $this->assertArrayHasKey(SearchVariantSubsites::class, $statefulIDs['state']); |
||
212 | $this->assertEquals($subsite->ID, $statefulIDs['state'][SearchVariantSubsites::class]); |
||
213 | } |
||
214 | } |
||
215 | |||
216 | public function testCorrectSubsiteIDOnFileWrite() |
||
217 | { |
||
218 | $subsiteIDs = ['0'] + $this->allFixtureIDs(Subsite::class); |
||
219 | $mockWrites = [ |
||
220 | '35910:File:a:0:{}' => [ |
||
221 | 'base' => File::class, |
||
222 | 'class' => File::class, |
||
223 | 'id' => 35910, |
||
224 | 'statefulids' => [ |
||
225 | [ |
||
226 | 'id' => 35910, |
||
227 | 'state' => [], |
||
228 | ], |
||
229 | ], |
||
230 | 'fields' => [ |
||
231 | File::class . ':ClassName' => Image::class, |
||
232 | File::class . ':ShowInSearch' => 1, |
||
233 | File::class . ':ParentID' => 26470, |
||
234 | File::class . ':Filename' => 'assets/Uploads/pic.jpg', |
||
235 | File::class . ':Name' => 'pic.jpg', |
||
236 | File::class . ':Title' => 'pic', |
||
237 | File::class . ':SubsiteID' => 0, |
||
238 | File::class . ':OwnerID' => 661, |
||
239 | File::class . ':CurrentVersionID' => 22038, |
||
240 | File::class . ':LastEdited' => '2016-12-09 00:35:13', |
||
241 | ], |
||
242 | ], |
||
243 | ]; |
||
244 | $variant = new SearchVariantSubsites(); |
||
245 | $tmpMockWrites = $mockWrites; |
||
246 | $variant->extractManipulationWriteState($tmpMockWrites); |
||
247 | foreach ($tmpMockWrites as $mockWrite) { |
||
248 | $this->assertCount(count($subsiteIDs), $mockWrite['statefulids']); |
||
249 | foreach ($mockWrite['statefulids'] as $statefulIDs) { |
||
250 | $this->assertContains( |
||
251 | $statefulIDs['state'][SearchVariantSubsites::class], |
||
252 | $subsiteIDs, |
||
253 | sprintf( |
||
254 | 'Failed to assert that %s is in list of valid subsites: %s', |
||
255 | $statefulIDs['state'][SearchVariantSubsites::class], |
||
256 | implode(', ', $subsiteIDs) |
||
257 | ) |
||
258 | ); |
||
259 | } |
||
260 | } |
||
261 | |||
262 | $subsite = $this->objFromFixture(Subsite::class, 'subsite1'); |
||
263 | $tmpMockWrites = $mockWrites; |
||
264 | $tmpMockWrites['35910:File:a:0:{}']['fields'][File::class . ':SubsiteID'] = $subsite->ID; |
||
265 | |||
266 | $variant->extractManipulationWriteState($tmpMockWrites); |
||
267 | foreach ($tmpMockWrites as $mockWrite) { |
||
268 | $this->assertCount(1, $mockWrite['statefulids']); |
||
269 | $statefulIDs = array_shift($mockWrite['statefulids']); |
||
270 | $this->assertEquals($subsite->ID, $statefulIDs['state'][SearchVariantSubsites::class]); |
||
271 | } |
||
272 | } |
||
273 | } |
||
274 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.