This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * @package comments |
||
5 | */ |
||
6 | class ElasticSearchPageTest extends ElasticsearchBaseTest { |
||
7 | |||
8 | public static $fixture_file = 'elastica/tests/ElasticaTest.yml'; |
||
9 | |||
10 | |||
11 | public function testCMSFields() { |
||
12 | $searchPage = $this->objFromFixture('ElasticSearchPage', 'search'); |
||
13 | |||
14 | $fields = $searchPage->getCMSFields(); |
||
15 | |||
16 | $mainTab = $this->checkTabExists($fields,'Main'); |
||
17 | $this->checkFieldExists($mainTab, 'Identifier'); |
||
18 | $this->checkFieldExists($mainTab, 'ContentForEmptySearch'); |
||
19 | |||
20 | $searchTab = $this->checkTabExists($fields,'Search.SearchFor'); |
||
21 | $fieldsTab = $this->checkTabExists($fields,'Search.Fields'); |
||
22 | $autoCompleteTab = $this->checkTabExists($fields,'Search.AutoComplete'); |
||
0 ignored issues
–
show
|
|||
23 | $aggTab = $this->checkTabExists($fields,'Search.Aggregations'); |
||
24 | $simTab = $this->checkTabExists($fields,'Search.Similarity'); |
||
25 | |||
26 | $this->checkFieldExists($searchTab, 'InfoField'); |
||
27 | $this->checkFieldExists($searchTab, 'SiteTreeOnly'); |
||
28 | $this->checkFieldExists($searchTab, 'ClassesToSearch'); |
||
29 | $this->checkFieldExists($searchTab, 'InfoField'); |
||
30 | $this->checkFieldExists($searchTab, 'SiteTreeOnly'); |
||
31 | $this->checkFieldExists($searchTab, 'ResultsPerPage'); |
||
32 | |||
33 | $this->checkFieldExists($aggTab, 'SearchHelper'); |
||
34 | |||
35 | $this->checkFieldExists($fieldsTab, 'SearchInfo'); |
||
36 | $this->checkFieldExists($fieldsTab, 'ElasticaSearchableFields'); |
||
37 | |||
38 | $this->checkFieldExists($simTab, 'SimilarityNotes'); |
||
39 | $this->checkFieldExists($simTab, 'MinTermFreq'); |
||
40 | $this->checkFieldExists($simTab, 'MaxTermFreq'); |
||
41 | $this->checkFieldExists($simTab, 'MinDocFreq'); |
||
42 | $this->checkFieldExists($simTab, 'MaxDocFreq'); |
||
43 | $this->checkFieldExists($simTab, 'MinWordLength'); |
||
44 | $this->checkFieldExists($simTab, 'MaxWordLength'); |
||
45 | $this->checkFieldExists($simTab, 'MinShouldMatch'); |
||
46 | |||
47 | $form = new Form($this, 'Form', $fields, new FieldList()); |
||
0 ignored issues
–
show
$this is of type this<ElasticSearchPageTest> , but the function expects a object<Controller> .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() $form is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
48 | |||
49 | $tab = $fields->findOrMakeTab("Root.Search.Fields"); |
||
50 | $fieldsTab = $tab->Fields(); |
||
51 | |||
52 | $pickerField = $fieldsTab->fieldByName('ElasticaSearchableFields'); |
||
53 | $pickerConfig = $pickerField->getConfig(); |
||
54 | $gridDetailForm = $pickerConfig->getComponentByType('GridFieldDetailForm'); |
||
55 | |||
56 | $searchableField = $searchPage->ElasticaSearchableFields()->filter( |
||
0 ignored issues
–
show
The method
ElasticaSearchableFields() does not exist on DataObject . Did you maybe mean searchableFields() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
57 | array('ClazzName' => 'SiteTree', 'Name' => 'Title') |
||
58 | )->first(); |
||
59 | |||
60 | $request = new GridFieldDetailForm_ItemRequest( |
||
61 | GridField::create('ElasticaSearchableFields', 'ElasticaSearchableFields'), |
||
62 | $gridDetailForm, |
||
63 | $searchableField, |
||
64 | new Controller(), |
||
65 | 'Form' |
||
66 | ); |
||
67 | $form = $request->ItemEditForm(); |
||
68 | $field = $form->Fields()->fieldByName('ClazzName'); |
||
69 | $this->assertEquals('ClazzName', $field->getName()); |
||
70 | $this->assertEquals('SiteTree', $field->Value()); |
||
71 | |||
72 | $field = $form->Fields()->fieldByName('Autocomplete'); |
||
73 | $this->assertEquals('Autocomplete', $field->getName()); |
||
74 | $this->assertEquals(1, $field->Value()); |
||
75 | |||
76 | $field = $form->Fields()->fieldByName('ManyMany[Searchable]'); |
||
77 | $this->assertEquals('ManyMany[Searchable]', $field->getName()); |
||
78 | $this->assertEquals(0, $field->Value()); |
||
79 | |||
80 | $field = $form->Fields()->fieldByName('ManyMany[SimilarSearchable]'); |
||
81 | $this->assertEquals('ManyMany[SimilarSearchable]', $field->getName()); |
||
82 | $this->assertEquals(0, $field->Value()); |
||
83 | |||
84 | $field = $form->Fields()->fieldByName('ManyMany[Weight]'); |
||
85 | $this->assertEquals('ManyMany[Weight]', $field->getName()); |
||
86 | $this->assertEquals('', $field->Value()); |
||
87 | |||
88 | $field = $form->Fields()->fieldByName('ShowHighlights'); |
||
89 | $this->assertEquals('ShowHighlights', $field->getName()); |
||
90 | $this->assertEquals(0, $field->Value()); |
||
91 | |||
92 | $this->assertNotNull($form->Fields()->fieldByName('SecurityID')); |
||
93 | } |
||
94 | |||
95 | |||
96 | public function testCannotWriteBlankIdentifier() { |
||
97 | $esp = new ElasticSearchPage(); |
||
98 | $esp->Title = 'test'; |
||
99 | try { |
||
100 | $esp->write(); |
||
101 | } catch (ValidationException $e) { |
||
102 | $this->assertEquals('The identifier cannot be blank', $e->getMessage()); |
||
103 | } |
||
104 | } |
||
105 | |||
106 | |||
107 | public function testCannotWriteDuplicateIdentifierDraft() { |
||
108 | $esp = new ElasticSearchPage(); |
||
109 | $esp->Title = 'test'; |
||
110 | $otherIdentifier = ElasticSearchPage::get()->first()->Identifier; |
||
111 | $esp->Identifier = $otherIdentifier; |
||
112 | try { |
||
113 | $esp->write(); |
||
114 | } catch (ValidationException $e) { |
||
115 | $this->assertEquals('The identifier testsearchpage already exists', $e->getMessage()); |
||
116 | } |
||
117 | } |
||
118 | |||
119 | |||
120 | public function testCannotWriteDuplicateIdentifierLive() { |
||
121 | $esp = new ElasticSearchPage(); |
||
122 | $esp->Title = 'unique-id'; |
||
123 | $otherIdentifier = ElasticSearchPage::get()->first()->Identifier; |
||
124 | $esp->Identifier = $otherIdentifier; |
||
125 | try { |
||
126 | $esp->write(); |
||
127 | $esp->doPublish(); |
||
128 | $esp->Identifier = $otherIdentifier; |
||
129 | $esp->write(); |
||
130 | } catch (ValidationException $e) { |
||
131 | $this->assertEquals('The identifier testsearchpage already exists', $e->getMessage()); |
||
132 | } |
||
133 | } |
||
134 | |||
135 | |||
136 | |||
137 | |||
138 | /* |
||
139 | Test the button override function |
||
140 | */ |
||
141 | public function testModelSearchFormAutocompleteAttributes() { |
||
142 | $searchPageObj = $this->objFromFixture('ElasticSearchPage', 'search'); |
||
143 | |||
144 | $searchPageObj->ClassesToSearch = 'FlickrPhotoTO'; |
||
145 | $filter = array('ClazzName' => 'FlickrPhotoTO', 'Name' => 'Title'); |
||
146 | $sfid = SearchableField::get()->filter($filter)->first()->ID; |
||
147 | $searchPageObj->AutoCompleteFieldID = $sfid; |
||
148 | $pageLength = 10; // the default |
||
149 | $searchPageObj->ResultsPerPage = $pageLength; |
||
150 | $searchPageObj->write(); |
||
151 | $searchPageObj->publish('Stage','Live'); |
||
152 | |||
153 | $form = $searchPageObj->SearchForm(); |
||
154 | $fields = $form->Fields(); |
||
155 | $q = $fields->fieldByName('q'); |
||
0 ignored issues
–
show
|
|||
156 | $attributes = $q->getAttributes(); |
||
157 | $expected = array( |
||
0 ignored issues
–
show
$expected is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
158 | 'type' => 'text', |
||
159 | 'name' => 'q', |
||
160 | 'value' => '', |
||
161 | 'class' => 'text autocomplete nolabel', |
||
162 | 'id' => 'ElasticSearchForm_SearchForm_q', |
||
163 | 'disabled' => '', |
||
164 | 'readonly' => '', |
||
165 | 'data-autocomplete' => 'true', |
||
166 | 'data-autocomplete-field' => 'Title', |
||
167 | 'data-autocomplete-classes' => 'FlickrPhotoTO', |
||
168 | 'data-autocomplete-sitetree' => '1', |
||
169 | 'data-autocomplete-source' => '/search/', |
||
170 | 'data-autocomplete-function' => '', |
||
171 | ); |
||
172 | $this->assertEquals($attributes, $attributes); |
||
173 | |||
174 | } |
||
175 | |||
176 | |||
177 | |||
178 | /* |
||
179 | Test the button override function |
||
180 | */ |
||
181 | public function testModelSearchFormButtonOverride() { |
||
182 | $override = 'My Button Override Text'; |
||
183 | $searchPageObj = $this->objFromFixture('ElasticSearchPage', 'search'); |
||
184 | $form = $searchPageObj->SearchForm($override); |
||
185 | $actions = $form->Actions(); |
||
186 | $button = $actions->fieldByName('action_submit'); |
||
187 | $this->assertEquals($override, $button->Title()); |
||
188 | |||
189 | // no override, use default |
||
190 | $form = $searchPageObj->SearchForm(); |
||
191 | $actions = $form->Actions(); |
||
192 | $button = $actions->fieldByName('action_submit'); |
||
193 | $this->assertEquals('', $button->Value()); |
||
194 | } |
||
195 | |||
196 | |||
197 | |||
198 | View Code Duplication | public function testCannotWriteInvalidClassname() { |
|
199 | $searchPage = $this->objFromFixture('ElasticSearchPage', 'search'); |
||
200 | $searchPage->ClassesToSearch = 'ThisClassDoesNotExist'; |
||
201 | $searchPage->SiteTreeOnly = false; |
||
202 | |||
203 | try { |
||
204 | $searchPage->write(); |
||
205 | $this->fail('Page should not be writeable'); |
||
206 | } catch (ValidationException $e) { |
||
207 | $this->assertEquals('The class ThisClassDoesNotExist does not exist', $e->getMessage()); |
||
208 | } |
||
209 | } |
||
210 | |||
211 | View Code Duplication | public function testCannotWriteNoSiteTreeOnlyNoClassNames() { |
|
212 | $searchPage = $this->objFromFixture('ElasticSearchPage', 'search'); |
||
213 | $searchPage->ClassesToSearch = ''; |
||
214 | $searchPage->SiteTreeOnly = false; |
||
215 | |||
216 | try { |
||
217 | $searchPage->write(); |
||
218 | $this->fail('Page should not be writeable'); |
||
219 | } catch (ValidationException $e) { |
||
220 | $this->assertEquals('At least one searchable class must be available, or SiteTreeOnly flag set', $e->getMessage()); |
||
221 | } |
||
222 | } |
||
223 | |||
224 | |||
225 | View Code Duplication | public function testEmptySearchableClass() { |
|
226 | $searchPage = $this->objFromFixture('ElasticSearchPage', 'search'); |
||
227 | |||
228 | // This does not implement searchable |
||
229 | $searchPage->ClassesToSearch = ''; |
||
230 | $searchPage->SiteTreeOnly = false; |
||
231 | |||
232 | try { |
||
233 | $searchPage->write(); |
||
234 | $this->fail('Page should not be writeable'); |
||
235 | } catch (ValidationException $e) { |
||
236 | $this->assertEquals( |
||
237 | 'At least one searchable class must be available, or SiteTreeOnly flag set', |
||
238 | $e->getMessage() |
||
239 | ); |
||
240 | } |
||
241 | } |
||
242 | |||
243 | |||
244 | public function testNonSearchableClass() { |
||
245 | $searchPage = $this->objFromFixture('ElasticSearchPage', 'search'); |
||
246 | $searchPage->SiteTreeOnly = false; |
||
247 | |||
248 | // This does not implement searchable |
||
249 | $searchPage->ClassesToSearch = 'Member'; |
||
250 | |||
251 | try { |
||
252 | $searchPage->write(); |
||
253 | $this->fail('Page should not be writeable'); |
||
254 | } catch (ValidationException $e) { |
||
255 | $this->assertEquals('The class Member must have the Searchable extension', $e->getMessage()); |
||
256 | } |
||
257 | |||
258 | $this->assertEquals(8, $searchPage->ElasticaSearchableFields()->count()); |
||
0 ignored issues
–
show
The method
ElasticaSearchableFields() does not exist on DataObject . Did you maybe mean searchableFields() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
259 | |||
260 | //Because the write should fail, this will still be the original value of 8 |
||
261 | $this->assertEquals(8, $searchPage->ElasticaSearchableFields()->filter('Active', true)->count()); |
||
0 ignored issues
–
show
The method
ElasticaSearchableFields() does not exist on DataObject . Did you maybe mean searchableFields() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
262 | |||
263 | } |
||
264 | |||
265 | |||
266 | /* |
||
267 | Test setting up a search page for data objects as if editing the CMS directly |
||
268 | */ |
||
269 | public function testSearchPageForDataObjects() { |
||
270 | $searchPage = $this->objFromFixture('ElasticSearchPage', 'search'); |
||
271 | |||
272 | $searchPage->ClassesToSearch = 'FlickrPhotoTO'; |
||
273 | $searchPage->SiteTreeOnly = 0; |
||
274 | $searchPage->Title = '**** Flickr Photo Search ****'; |
||
275 | $searchPage->write(); |
||
276 | //$searchPage->publish('Stage', 'Live'); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
80% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
277 | |||
278 | $filter = array('ClazzName' => 'FlickrPhotoTO', 'Name' => 'Title'); |
||
0 ignored issues
–
show
$filter is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
279 | |||
280 | //Check fieldnames as expected |
||
281 | $searchableFields = $searchPage->ElasticaSearchableFields()->filter('Active',1); |
||
0 ignored issues
–
show
The method
ElasticaSearchableFields() does not exist on DataObject . Did you maybe mean searchableFields() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
282 | $sfs = $searchableFields->map('Name')->toArray(); |
||
283 | sort($sfs); |
||
284 | $expected = array('Aperture','AspectRatio','Description','FirstViewed','FlickrID', |
||
285 | 'FlickrSetTOs','FlickrTagTOs','FocalLength35mm','ISO','Photographer','ShutterSpeed', |
||
286 | 'TakenAt', 'TakenAtDT', 'TestMethod', 'TestMethodHTML', 'Title'); |
||
287 | $this->assertEquals($expected, $sfs); |
||
288 | |||
289 | |||
290 | $searchPage->ClassesToSearch = ''; |
||
291 | $searchPage->SiteTreeOnly = 1; |
||
292 | $searchPage->Title = '**** SiteTree Search ****'; |
||
293 | $searchPage->write(); |
||
294 | |||
295 | $searchableFields = $searchPage->ElasticaSearchableFields()->filter('Active',1); |
||
296 | $sfs = $searchableFields->map('Name')->toArray(); |
||
297 | sort($sfs); |
||
298 | $expected = array('Content', 'Country', 'PageDate', 'Title'); |
||
299 | $this->assertEquals($expected, $sfs); |
||
300 | } |
||
301 | |||
302 | |||
303 | /* |
||
304 | Test that during the build process, requireDefaultRecords creates records for |
||
305 | each unique field name declared in searchable_fields |
||
306 | */ |
||
307 | public function testSearchableFieldsCreatedAtBuildTime() { |
||
308 | $searchableTestPage = $this->objFromFixture('SearchableTestPage', 'first'); |
||
0 ignored issues
–
show
$searchableTestPage is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
309 | $searchPage = $this->objFromFixture('ElasticSearchPage', 'search'); |
||
310 | |||
311 | // expected mapping of searchable classes to searchable fields that will be |
||
312 | // stored in the database as SearchableClass and SearchableField |
||
313 | $expected = array( |
||
314 | 'Page' => array('Title','Content'), |
||
315 | 'SiteTree' => array('Title','Content'), |
||
316 | 'SearchableTestPage' => array('Title','Content','Country','PageDate'), |
||
317 | 'FlickrTagTO' => array('RawValue'), |
||
318 | 'FlickrAuthorTO' => array('PathAlias','DisplayName','FlickrPhotoTOs'), |
||
319 | 'FlickrPhotoTO' => array('Title','FlickrID','Description','TakenAt', 'TakenAtDT', 'Aperture', |
||
320 | 'ShutterSpeed','FocalLength35mm','ISO','Photographer','FlickrTagTOs','FlickrSetTOs', |
||
321 | 'FirstViewed','AspectRatio', 'TestMethod', 'TestMethodHTML'), |
||
322 | 'FlickrSetTO' => array('Title','FlickrID','Description') |
||
323 | ); |
||
324 | |||
325 | // check the expected classes |
||
326 | $expectedClasses = array_keys($expected); |
||
327 | $nSearchableClasses = SearchableClass::get()->count(); |
||
328 | $this->assertEquals(sizeof($expectedClasses), $nSearchableClasses); |
||
329 | |||
330 | |||
331 | $searchPage->SiteTreeOnly = true; |
||
332 | $searchPage->Content = 'some random string'; |
||
333 | $searchPage->write(); |
||
334 | $scs = SearchableClass::get(); |
||
0 ignored issues
–
show
$scs is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
335 | |||
336 | $sfs = $searchPage->SearchableFields(); |
||
0 ignored issues
–
show
$sfs is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
337 | |||
338 | // check the names expected to appear |
||
339 | $fieldCtr = 0; |
||
340 | foreach ($expectedClasses as $expectedClass) { |
||
341 | $expectedFields = array(); |
||
342 | $sc = SearchableClass::get()->filter('Name', $expectedClass)->first(); |
||
343 | $this->assertEquals($expectedClass,$sc->Name); |
||
344 | |||
345 | $inSiteTree = 1; |
||
346 | $start = substr($expectedClass, 0,6); |
||
347 | if ($start == 'Flickr') { |
||
348 | $inSiteTree = 0; |
||
349 | }; |
||
350 | $this->assertEquals($inSiteTree,$sc->InSiteTree); |
||
351 | |||
352 | $expectedNames = $expected[$expectedClass]; |
||
353 | foreach ($expectedNames as $expectedName) { |
||
354 | $filter = array('Name' => $expectedName, 'SearchableClassID' => $sc->ID ); |
||
355 | $sf = SearchableField::get()->filter($filter)->first(); |
||
356 | $this->assertEquals($expectedName, $sf->Name); |
||
357 | $fieldCtr++; |
||
358 | array_push($expectedFields, $expectedName); |
||
359 | } |
||
360 | } |
||
361 | $nSearchableFields = SearchableField::get()->count(); |
||
362 | |||
363 | $this->assertEquals($fieldCtr, $nSearchableFields); |
||
364 | } |
||
365 | |||
366 | |||
367 | public function testGetCMSValidator() { |
||
368 | $searchPage = $this->objFromFixture('ElasticSearchPage', 'search'); |
||
369 | $validator = $searchPage->getCMSValidator(); |
||
370 | $this->assertEquals('ElasticSearchPage_Validator', get_class($validator)); |
||
371 | } |
||
372 | |||
373 | |||
374 | View Code Duplication | public function testValidateClassesToSearchNonExistent() { |
|
375 | $searchPage = $this->objFromFixture('ElasticSearchPage', 'search'); |
||
376 | $searchPage->ClassesToSearch = 'WibbleWobble'; // does not exist |
||
377 | $searchPage->SiteTreeOnly = false; |
||
378 | try { |
||
379 | $searchPage->write(); |
||
380 | $this->fail('Test should have failed as WibbleWobble is not a valid class'); |
||
381 | } catch (ValidationException $e) { |
||
382 | $this->assertEquals('The class WibbleWobble does not exist', $e->getMessage()); |
||
383 | } |
||
384 | } |
||
385 | |||
386 | |||
387 | View Code Duplication | public function testValidateClassesToSearchNotSearchable() { |
|
388 | $searchPage = $this->objFromFixture('ElasticSearchPage', 'search'); |
||
389 | $searchPage->ClassesToSearch = 'member'; // does not implement Searchable |
||
390 | $searchPage->SiteTreeOnly = false; |
||
391 | try { |
||
392 | $searchPage->write(); |
||
393 | $this->fail('Test should have failed as WibbleWobble is not a valid class'); |
||
394 | } catch (ValidationException $e) { |
||
395 | $this->assertEquals('The class member must have the Searchable extension', $e->getMessage()); |
||
396 | } |
||
397 | } |
||
398 | } |
||
399 |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.