Completed
Push — dev2 ( 4094f0...646d6a )
by Gordon
02:58
created

testHasManyExistsSearchableToArray()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 45
Code Lines 29

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 45
rs 8.8571
cc 1
eloc 29
nc 1
nop 0
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 View Code Duplication
	public function testgetFieldValuesAsArrayFromFixtures() {
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
27
		$manyTypes = $this->objFromFixture('ManyTypesPage', 'manytypes0001');
28
		$result = $manyTypes->getFieldValuesAsArray();
29
		$this->generateAssertionsFromArray($result);
30
		$expected = array(
31
			'BooleanField' => '1',
32
			'CurrencyField' => '100.25',
33
			'DateField' => '2014-04-15',
34
			'DecimalField' => '0',
35
			'EnumField' => '',
36
			'HTMLTextField' => '',
37
			'HTMLVarcharField' => 'This is some *HTML*varchar field',
38
			'IntField' => '677',
39
			'PercentageField' => '27',
40
			'SS_DatetimeField' => '2014-10-18 08:24:00',
41
			'TextField' => 'This is a text field',
42
			'TimeField' => '17:48:18',
43
			'Title' => 'Many Types Page',
44
			'Content' => 'Many types of fields',
45
		);
46
		$this->assertEquals($expected, $result);
47
48
	}
49
50
51
52
	public function testBadFormatFields() {
53
		$manyTypes = $this->objFromFixture('ManyTypesPage', 'manytypes0001');
54
		$fields = $manyTypes->getElasticaFields();
55
56
		$expected = array('type' => 'boolean');
57
		$this->assertEquals($expected, $fields['BooleanField']);
58
59
		$expected = array('type' => 'double');
60
		$this->assertEquals($expected, $fields['CurrencyField']);
61
62
		$expected = array('type' => 'date', 'format' => 'y-M-d');
63
		$this->assertEquals($expected, $fields['DateField']);
64
65
		$expected = array('type' => 'double');
66
		$this->assertEquals($expected, $fields['DecimalField']);
67
68
		$stringFormat = array(
69
			'type' => 'string',
70
			'analyzer' => 'stemmed',
71
			'term_vector' => 'yes',
72
			'fields' => array(
73
				'standard' => array(
74
					'type' => 'string',
75
					'analyzer' => 'unstemmed',
76
					'term_vector' => 'yes'
77
				),
78
				'shingles' => array(
79
					'type' => 'string',
80
					'analyzer' => 'shingles',
81
					'term_vector' => 'yes'
82
				)
83
			)
84
		);
85
		$expected = $stringFormat;
86
		$this->assertEquals($expected, $fields['EnumField']);
87
88
		$expected = $stringFormat;
89
		$this->assertEquals($expected, $fields['HTMLTextField']);
90
91
		$expected = $stringFormat;
92
		$this->assertEquals($expected, $fields['HTMLVarcharField']);
93
94
		$expected = array('type' => 'integer');
95
		$this->assertEquals($expected, $fields['IntField']);
96
97
		$expected = array('type' => 'double');
98
		$this->assertEquals($expected, $fields['PercentageField']);
99
100
		$expected = array('type' => 'date', 'format' => 'y-M-d H:m:s');
101
		$this->assertEquals($expected, $fields['SS_DatetimeField']);
102
103
		$expected = $stringFormat;
104
		$this->assertEquals($expected, $fields['TextField']);
105
106
		$expected = array('type' => 'date', 'format' => 'H:m:s');
107
		$this->assertEquals($expected, $fields['TimeField']);
108
	}
109
110
111
	public function testGetDateFields() {
112
		$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001');
113
		$fields = $flickrPhoto->getElasticaFields();
114
115
		print_r($fields);
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 View Code Duplication
		foreach ($shouldBeDate as $fieldName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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 View Code Duplication
		foreach ($shouldBeDateTime as $fieldName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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 View Code Duplication
		foreach ($shouldBeTokens as $fieldName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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
316
317
		print_r($doc);
318
319
		$this->assertEquals($expected, $doc);
320
	}
321
322
323
	public function testElasticaResult() {
324
		$resultList = $this->getResultsFor('Bangkok');
325
326
		// there is only one result.  Note lack of a 'first' method
327
		foreach ($resultList->getIterator() as $fp) {
328
			//This is an Elastica\Result object
329
			$elasticaResult = $fp->getElasticaResult();
330
331
			$fields = $elasticaResult->getSource();
332
333
			$this->assertEquals($fp->Title, $fields['Title']);
334
			$this->assertEquals($fp->FlickrID, $fields['FlickrID']);
335
			$this->assertEquals($fp->Description, $fields['Description']);
336
			$this->assertEquals($fp->TakenAt, $fields['TakenAt']);
337
			$this->assertEquals($fp->FirstViewed, $fields['FirstViewed']);
338
			$this->assertEquals($fp->Aperture, $fields['Aperture']);
339
340
			//ShutterSpeed is a special case, mangled field
341
			$this->assertEquals('0.01|1/100', $fields['ShutterSpeed']);
342
			$this->assertEquals($fp->FocalLength35mm, $fields['FocalLength35mm']);
343
			$this->assertEquals($fp->ISO, $fields['ISO']);
344
			$this->assertEquals($fp->AspectRatio, $fields['AspectRatio']);
345
346
			//Empty arrays for null values
347
			$this->assertEquals(array(), $fields['Photographer']);
348
			$this->assertEquals(array(), $fields['FlickrTagTOs']);
349
			$this->assertEquals(array(), $fields['FlickrSetTOs']);
350
			$this->assertEquals(false, $fields['IsInSiteTree']);
351
		}
352
	}
353
354
355
	public function testDeleteNonExistentDoc() {
356
		$fp = new FlickrPhotoTO();
357
		$fp->Title = 'Test Deletion';
1 ignored issue
show
Documentation introduced by
The property Title does not exist on object<FlickrPhotoTO>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
358
		$fp->IndexingOff = true; // do no index this
1 ignored issue
show
Documentation introduced by
The property IndexingOff does not exist on object<FlickrPhotoTO>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
359
		$fp->write();
360
		$fp->IndexingOff = false;
1 ignored issue
show
Documentation introduced by
The property IndexingOff does not exist on object<FlickrPhotoTO>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
361
362
		try {
363
			$fp->delete();
364
			$this->fail('Exception should have been thrown when deleting non existent item');
365
		} catch (Exception $e) {
366
			//This error comes out of Elastica itself
367
			$this->assertEquals('Deleted document FlickrPhotoTO (2) not found in search index.',
368
				$e->getMessage());
369
		}
370
	}
371
372
373
374
375
	public function testUnpublishPublish() {
376
		$nDocsAtStart = $this->getNumberOfIndexedDocuments();
377
		$this->checkNumberOfIndexedDocuments($nDocsAtStart);
378
379
		$page = $this->objFromFixture('SiteTree', 'sitetree001');
380
		$page->doUnpublish();
381
382
		$this->checkNumberOfIndexedDocuments($nDocsAtStart-1);
383
384
		$page->doPublish();
385
		$this->checkNumberOfIndexedDocuments($nDocsAtStart);
386
	}
387
388
389
	/**
390
	 * For a page that is already published, set the ShowInSearch flag to false,
391
	 * write to stage, and then rePublish
392
	 */
393
	public function testUnpublishAlreadyPublisedhHideFromSearch() {
394
		$page = $this->objFromFixture('SiteTree', 'sitetree001');
395
396
		// By default the page is not indexed (for speed reasons)
397
		// Change the title, turn on indexing and save it
398
		// This will invoke a database write
399
		$page->Title = "I will be indexed";
400
		$page->IndexingOff = true;
401
		$page->write();
402
403
		$nDocsAtStart = $this->getNumberOfIndexedDocuments();
404
		$this->checkNumberOfIndexedDocuments($nDocsAtStart);
405
406
		// assert keys of term vectors, this will indicate page
407
		// is stored in the index or not
408
		$termVectors = $page->getTermVectors();
409
		$expected = array(
410
		'0' => 'Content',
411
		'1' => 'Content.shingles',
412
		'2' => 'Content.standard',
413
		'3' => 'Link',
414
				'4' => 'Title',
415
		'5' => 'Title.autocomplete',
416
		'6' => 'Title.shingles',
417
		'7' => 'Title.standard',
418
		);
419
420
		$keys = array_keys($termVectors);
421
		sort($keys);
422
423
		$this->assertEquals($expected, $keys);
424
425
426
//CURRENT
427
		$page->ShowInSearch = false;
428
		$page->write();
429
430
		$this->checkNumberOfIndexedDocuments($nDocsAtStart);
431
432
		$page->doPublish();
433
		$this->checkNumberOfIndexedDocuments($nDocsAtStart);
434
	}
435
436
437
438
	/**
439
	 * For a page that is not published, set the ShowInSearch flag to false,
440
	 * write to stage, and then rePublish.  Same as previous test except
441
	 * no need to delete from the index as it already does not exist
442
	 * @return [type] [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
443
	 */
444
	public function testUnpublishPublishHideFromSearch() {
445
		$page = $this->objFromFixture('SiteTree', 'sitetree001');
446
		$page->doUnpublish();
447
448
		// By default the page is not indexed (for speed reasons)
449
		// Change the title, turn on indexing and save it
450
		// This will invoke a database write
451
		$page->Title = "I will be indexed";
452
		$page->IndexingOff = true;
453
		$page->write();
454
455
		$nDocsAtStart = $this->getNumberOfIndexedDocuments();
456
		$this->checkNumberOfIndexedDocuments($nDocsAtStart);
457
		$page->ShowInSearch = false;
458
		$page->write();
459
460
		$this->checkNumberOfIndexedDocuments($nDocsAtStart);
461
462
		$page->doPublish();
463
		$this->checkNumberOfIndexedDocuments($nDocsAtStart);
464
	}
465
466
467
468
469
	public function testGetCMSFields() {
470
		$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001');
471
		$fields = $flickrPhoto->getCMSFields();
472
473
		$this->checkTabExists($fields,'ElasticaTermsset');
474
	}
475
476
477 View Code Duplication
	public function testNoSearchableFieldsConfigured() {
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
478
		$config = Config::inst();
479
		$sf = $config->get('FlickrPhotoTO', 'searchable_fields');
480
		$config->remove('FlickrPhotoTO', 'searchable_fields');
481
		$fp = Injector::inst()->create('FlickrPhotoTO');
482
		try {
483
			$fp->getAllSearchableFields();
484
			$this->fail("getAllSearchableFields should have failed as static var searchable_fields not configured");
485
		} catch (Exception $e) {
486
			$this->assertEquals('The field $searchable_fields must be set for the class FlickrPhotoTO', $e->getMessage());
487
		}
488
489
		$config->update('FlickrPhotoTO' ,'searchable_fields', $sf);
490
	}
491
492
493 View Code Duplication
	public function testNoSearchableFieldsConfiguredForHasManyRelation() {
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
494
		$config = Config::inst();
495
		$sf = $config->get('FlickrTagTO', 'searchable_fields');
496
		$config->remove('FlickrTagTO', 'searchable_fields');
497
		$fp = Injector::inst()->create('FlickrPhotoTO');
498
		try {
499
			$fp->getAllSearchableFields();
500
			$this->fail("getAllSearchableFields should have failed as static var searchable_fields not configured");
501
		} catch (Exception $e) {
502
			$this->assertEquals('The field $searchable_fields must be set for the class FlickrTagTO', $e->getMessage());
503
		}
504
505
		$config->update('FlickrTagTO' ,'searchable_fields', $sf);
506
507
	}
508
509
510 View Code Duplication
	public function testNoSearchableFieldsConfiguredForHasOneRelation() {
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
511
		$config = Config::inst();
512
		$sf = $config->get('FlickrAuthorTO', 'searchable_fields');
513
		$config->remove('FlickrAuthorTO', 'searchable_fields');
514
		$fp = Injector::inst()->create('FlickrPhotoTO');
515
		try {
516
			$fp->getAllSearchableFields();
517
			$this->fail("getAllSearchableFields should have failed as static var searchable_fields not configured");
518
		} catch (Exception $e) {
519
			$this->assertEquals('The field $searchable_fields must be set for the class FlickrAuthorTO', $e->getMessage());
520
		}
521
522
		$config->update('FlickrAuthorTO' ,'searchable_fields', $sf);
523
524
	}
525
526
527
	public function testSearchableMethodNotExist() {
528
		$config = Config::inst();
529
		$sr = $config->get('FlickrPhotoTO', 'searchable_relationships');
530
		$config->remove('FlickrPhotoTO', 'searchable_relationships');
531
		$config->update('FlickrPhotoTO', 'searchable_relationships',array('thisMethodDoesNotExist'));
532
		$fp = Injector::inst()->create('FlickrPhotoTO');
533
		try {
534
			$fp->getAllSearchableFields();
535
			$this->fail("getAllSearchableFields should have failed searchable relationship does not exist");
536
		} catch (Exception $e) {
537
			$this->assertEquals('The method thisMethodDoesNotExist not found in class FlickrPhotoTO, please check configuration',
538
				 $e->getMessage());
539
		}
540
541
    	// MUST REMOVE FIRST.  Otherwise append and the erroroneus value above still exists
542
    	$config->remove('FlickrPhotoTO', 'searchable_relationships');
543
		$config->update('FlickrPhotoTO' ,'searchable_relationships', $sr);
544
	}
545
546
547
	public function testFieldsToElasticaConfig() {
548
		$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001');
549
		$fields = $flickrPhoto->getAllSearchableFields();
1 ignored issue
show
Bug introduced by
The method getAllSearchableFields() 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.

Loading history...
550
551
		$expected = array(
552
			'Title' => array(
553
				'title' => 'Title',
554
				'filter' => 'PartialMatchFilter'
555
			),
556
			'FlickrID' => array(
557
				'title' => 'Flickr ID',
558
				'filter' => 'PartialMatchFilter'
559
			),
560
			'Description' => array(
561
				'title' => 'Description',
562
				'filter' => 'PartialMatchFilter'
563
			),
564
			'TakenAt' => array(
565
				'title' => 'Taken At',
566
				'filter' => 'PartialMatchFilter'
567
			),
568
			'TakenAtDT' => array(
569
				'title' => 'Taken At DT',
570
				'filter' => 'PartialMatchFilter'
571
			),
572
			'FirstViewed' => array(
573
				'title' => 'First Viewed',
574
				'filter' => 'PartialMatchFilter'
575
			),
576
			'Aperture' => array(
577
				'title' => 'Aperture',
578
				'filter' => 'PartialMatchFilter'
579
			),
580
			'ShutterSpeed' => array(
581
				'title' => 'Shutter Speed',
582
				'filter' => 'PartialMatchFilter'
583
			),
584
			'FocalLength35mm' => array(
585
				'title' => 'Focal Length35mm',
586
				'filter' => 'PartialMatchFilter'
587
			),
588
			'ISO' => array(
589
				'title' => 'ISO',
590
				'filter' => 'PartialMatchFilter'
591
			),
592
			'AspectRatio' => array(
593
				'title' => 'Aspect Ratio',
594
				'filter' => 'PartialMatchFilter'
595
			),
596
			'TestMethod' => array(
597
				'title' => 'Test Method',
598
				'filter' => 'PartialMatchFilter'
599
			),
600
			'TestMethodHTML' => array(
601
				'title' => 'Test Method HTML',
602
				'filter' => 'PartialMatchFilter'
603
			),
604
			'Photographer()' => array(
605
				'PathAlias' => array(
606
					'title' => 'Path Alias',
607
					'filter' => 'PartialMatchFilter'
608
				),
609
				'DisplayName' => array(
610
					'title' => 'Display Name',
611
					'filter' => 'PartialMatchFilter'
612
				)
613
			),
614
			'FlickrTagTOs()' => array(
615
				'RawValue' => array(
616
					'title' => 'Raw Value',
617
					'filter' => 'PartialMatchFilter'
618
				)
619
			),
620
			'FlickrSetTOs()' => array(
621
				'Title' => array(
622
					'title' => 'Title',
623
					'filter' => 'PartialMatchFilter'
624
				),
625
				'FlickrID' => array(
626
					'title' => 'Flickr ID',
627
					'filter' => 'PartialMatchFilter'
628
				),
629
				'Description' => array(
630
					'title' => 'Description',
631
					'filter' => 'PartialMatchFilter'
632
				)
633
			)
634
		);
635
636
		$this->assertEquals($expected, $fields);
637
	}
638
639
640
	public function testHasOneExistsSearchableToArray() {
641
		$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001');
642
		$flickrPhoto->IndexingOff = false;
643
		$flickrPhoto->Title = 'Test title edited';
644
		$photographer = new FlickrAuthorTO();
645
		$photographer->DisplayName = 'Fred Bloggs';
1 ignored issue
show
Documentation introduced by
The property DisplayName does not exist on object<FlickrAuthorTO>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
646
		$photographer->PathAlias = '/fredbloggs';
1 ignored issue
show
Documentation introduced by
The property PathAlias does not exist on object<FlickrAuthorTO>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
647
648
		$photographer->write();
649
650
		$flickrPhoto->PhotographerID = $photographer->ID;;
651
		$flickrPhoto->write();
652
		echo 'ID='.$flickrPhoto->PhotographerID;
653
		$fieldValuesArray = $flickrPhoto->getFieldValuesAsArray();
654
655
		$actual = $fieldValuesArray['Photographer'];
656
		$this->generateAssertionsFromArray($actual);
657
		$expected = array(
658
			'PathAlias' => '/fredbloggs',
659
			'DisplayName' => 'Fred Bloggs',
660
			'FlickrPhotoTO' => '',
661
		);
662
663
		$this->assertEquals($expected, $actual);
664
	}
665
666
667
668
	public function testHasManyExistsSearchableToArray() {
669
		$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001');
670
		$flickrPhoto->IndexingOff = false;
671
		$flickrPhoto->Title = 'Test title edited';
672
		$tag1 = new FlickrTagTO();
673
		$tag1->FlickrID = '1000001';
1 ignored issue
show
Documentation introduced by
The property FlickrID does not exist on object<FlickrTagTO>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
674
		$tag1->Value = 'auckland';
1 ignored issue
show
Documentation introduced by
The property Value does not exist on object<FlickrTagTO>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
675
		$tag1->RawValue = 'Auckland';
1 ignored issue
show
Documentation introduced by
The property RawValue does not exist on object<FlickrTagTO>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
676
		$tag1->write();
677
678
679
		$tag2 = new FlickrTagTO();
680
		$tag2->FlickrID = '1000002';
1 ignored issue
show
Documentation introduced by
The property FlickrID does not exist on object<FlickrTagTO>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
681
		$tag2->Value = 'wellington';
1 ignored issue
show
Documentation introduced by
The property Value does not exist on object<FlickrTagTO>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
682
		$tag2->RawValue = 'Wellington';
1 ignored issue
show
Documentation introduced by
The property RawValue does not exist on object<FlickrTagTO>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
683
		$tag2->write();
684
685
		$flickrPhoto->FlickrTagTOs()->add($tag1);
686
		$flickrPhoto->FlickrTagTOs()->add($tag2);
687
688
689
690
691
		$flickrPhoto->write();
692
		echo 'ID='.$flickrPhoto->PhotographerID;
693
		$fieldValuesArray = $flickrPhoto->getFieldValuesAsArray();
694
		$actual = $fieldValuesArray['Photographer'];
695
		$this->assertEquals(array(), $actual);
696
697
698
		$actual = $fieldValuesArray['FlickrTagTOs'];
699
		$this->generateAssertionsFromArrayRecurse($actual);
700
701
		$expected = array(
702
			'0' => array(
703
				'RawValue' => 'Auckland'
704
			),
705
			'1' => array(
706
				'RawValue' => 'Wellington'
707
			)
708
		);
709
710
711
		$this->assertEquals($expected, $actual);
712
	}
713
714
715
	public function testUpdateCMSFieldsDatabject() {
716
		$flickrPhoto = $this->objFromFixture('FlickrPhotoTO', 'photo0001');
717
		$flickrPhoto->IndexingOff = false;
718
		$flickrPhoto->Title = 'Test title edited';
719
		$flickrPhoto->write();
720
		$fields = new FieldList();
0 ignored issues
show
Unused Code introduced by
$fields 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 $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.

Loading history...
721
		$fields = $flickrPhoto->getCMSFields();
722
723
		$tabset = $fields->findOrMakeTab('Root.ElasticaTerms');
724
		$tabNames = array();
725 View Code Duplication
		foreach ($tabset->Tabs() as $tab) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
726
			$tabFields = array();
727
			foreach ($tab->FieldList() as $field) {
728
				array_push($tabFields, $field->getName());
729
			}
730
			$expectedName = 'TermsFor'.$tab->getName();;
731
			$expected = array($expectedName);
732
			$this->assertEquals($expected, $tabFields);
733
			array_push($tabNames, $tab->getName());
734
		}
735
		$expected = array('Description','Description_shingles','Description_standard',
736
			'ShutterSpeed',  'TestMethod', 'TestMethod_shingles', 'TestMethod_standard',
737
			'TestMethodHTML', 'TestMethodHTML_shingles', 'TestMethodHTML_standard',
738
			'Title','Title_autocomplete','Title_shingles','Title_standard');
739
740
		$this->assertEquals($expected, $tabNames);
741
	}
742
743
744
	public function testUpdateCMSFieldsSiteTreeLive() {
745
		echo "+++++++++++++++++ testUpdateCMSFieldsSiteTreeLive +++++++++++++\n";
746
		$page = $this->objFromFixture('SearchableTestPage', 'first');
747
		$page->IndexingOff = false;
748
		$page->Title = 'Test title edited';
749
		$page->write();
750
		$page->doPublish();
751
		$fields = new FieldList();
0 ignored issues
show
Unused Code introduced by
$fields 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 $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.

Loading history...
752
753
		$fields = $page->getCMSFields();
754
755
		$tabset = $fields->findOrMakeTab('Root.ElasticaTerms');
756
		$tabNames = array();
757 View Code Duplication
		foreach ($tabset->Tabs() as $tab) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
758
			$tabFields = array();
759
			foreach ($tab->FieldList() as $field) {
760
				array_push($tabFields, $field->getName());
761
			}
762
			$expectedName = 'TermsFor'.$tab->getName();;
763
			$expected = array($expectedName);
764
			$this->assertEquals($expected, $tabFields);
765
			array_push($tabNames, $tab->getName());
766
		}
767
		$expected = array(
768
			'Content','Content_standard','Link','Title','Title_autocomplete','Title_shingles',
769
			'Title_standard');
770
		$this->generateAssertionsFromArray1D($tabNames);
771
		$this->assertEquals($expected, $tabNames);
772
773
	}
774
775
776 View Code Duplication
	private function getResultsFor($query, $pageLength = 10) {
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
777
		$es = new ElasticSearcher();
778
		$es->setStart(0);
779
		$es->setPageLength($pageLength);
780
		//$es->addFilter('IsInSiteTree', false);
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.

Loading history...
781
		$es->setClasses('FlickrPhotoTO');
782
		$fields = array('Title' => 1, 'Description' => 1);
783
		$resultList = $es->search($query, $fields)->getList();
784
		$this->assertEquals('SilverStripe\Elastica\ResultList', get_class($resultList));
785
		return $resultList;
786
	}
787
788
}
789