Completed
Push — tests_deprecate_isVersion4 ( 76abb4...1e7e4c )
by André
30:16 queued 10:12
created

testInvalidFieldIdentifierIn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 18
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
5
 * @license For full copyright and license information view LICENSE file distributed with this source code.
6
 */
7
namespace eZ\Publish\API\Repository\Tests;
8
9
use eZ\Publish\API\Repository\Exceptions\NotImplementedException;
10
use EzSystems\EzPlatformSolrSearchEngine\Tests\SetupFactory\LegacySetupFactory as LegacySolrSetupFactory;
11
use eZ\Publish\API\Repository\Tests\SetupFactory\LegacyElasticsearch;
12
use eZ\Publish\API\Repository\Values\Content\Content;
13
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
14
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
15
use eZ\Publish\API\Repository\Values\Content\Query\SortClause;
16
use eZ\Publish\API\Repository\Values\Content\Search\SearchHit;
17
use eZ\Publish\API\Repository\Values\Content\Search\SearchResult;
18
use eZ\Publish\Core\Repository\Values\Content\Location;
19
20
/**
21
 * Test case for Location operations in the SearchService.
22
 *
23
 * @see eZ\Publish\API\Repository\SearchService
24
 * @group integration
25
 * @group search
26
 */
27
class SearchServiceLocationTest extends BaseTest
28
{
29
    const QUERY_CLASS = LocationQuery::class;
30
31
    use Common\FacetedSearchProvider;
32
33
    protected function setUp()
34
    {
35
        $setupFactory = $this->getSetupFactory();
36
        if ($setupFactory instanceof LegacyElasticsearch) {
37
            $this->markTestSkipped('Field Location search is not yet implemented Elasticsearch search engine');
38
        }
39
40
        parent::setUp();
41
    }
42
43
    /**
44
     * Test for the findLocation() method.
45
     *
46
     * @dataProvider getFacetedSearches
47
     *
48
     * @see \eZ\Publish\API\Repository\SearchService::findLoctions()
49
     */
50
    public function testFindFacetedLocation(LocationQuery $query, $fixture)
51
    {
52
        $this->assertQueryFixture($query, $fixture);
53
    }
54
55
    /**
56
     * Create movie Content with subtitle field set to null.
57
     *
58
     * @return \eZ\Publish\API\Repository\Values\Content\Content[]
59
     */
60
    protected function createMovieContent(): array
61
    {
62
        $movies = [];
63
64
        $repository = $this->getRepository();
65
        $contentTypeService = $repository->getContentTypeService();
66
        $contentService = $repository->getContentService();
67
68
        $createStruct = $contentTypeService->newContentTypeCreateStruct('movie');
69
        $createStruct->mainLanguageCode = 'eng-GB';
70
        $createStruct->remoteId = 'movie-123';
71
        $createStruct->names = ['eng-GB' => 'Movie'];
72
        $createStruct->creatorId = 14;
73
        $createStruct->creationDate = new \DateTime();
74
75
        $fieldTitle = $contentTypeService->newFieldDefinitionCreateStruct('title', 'ezstring');
76
        $fieldTitle->names = ['eng-GB' => 'Title'];
77
        $fieldTitle->fieldGroup = 'main';
78
        $fieldTitle->position = 1;
79
        $fieldTitle->isTranslatable = false;
80
        $fieldTitle->isSearchable = true;
81
        $fieldTitle->isRequired = true;
82
        $createStruct->addFieldDefinition($fieldTitle);
83
84
        $fieldSubtitle = $contentTypeService->newFieldDefinitionCreateStruct('subtitle', 'ezstring');
85
        $fieldSubtitle->names = ['eng-GB' => 'Subtitle'];
86
        $fieldSubtitle->fieldGroup = 'main';
87
        $fieldSubtitle->position = 2;
88
        $fieldSubtitle->isTranslatable = false;
89
        $fieldSubtitle->isSearchable = true;
90
        $fieldSubtitle->isRequired = false;
91
        $createStruct->addFieldDefinition($fieldSubtitle);
92
93
        $contentTypeGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
94
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, [$contentTypeGroup]);
95
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
96
        $contentType = $contentTypeService->loadContentType($contentTypeDraft->id);
97
98
        $createStructRambo = $contentService->newContentCreateStruct($contentType, 'eng-GB');
99
        $createStructRambo->remoteId = 'movie-456';
100
        $createStructRambo->alwaysAvailable = false;
101
        $createStructRambo->setField('title', 'Rambo');
102
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
103
104
        $ramboDraft = $contentService->createContent($createStructRambo, [$locationCreateStruct]);
105
        $movies[] = $contentService->publishVersion($ramboDraft->getVersionInfo());
106
        $this->refreshSearch($repository);
107
108
        $createStructRobocop = $contentService->newContentCreateStruct($contentType, 'eng-GB');
109
        $createStructRobocop->remoteId = 'movie-789';
110
        $createStructRobocop->alwaysAvailable = false;
111
        $createStructRobocop->setField('title', 'Robocop');
112
        $createStructRobocop->setField('subtitle', '');
113
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
114
115
        $robocopDraft = $contentService->createContent($createStructRobocop, [$locationCreateStruct]);
116
        $movies[] = $contentService->publishVersion($robocopDraft->getVersionInfo());
117
        $this->refreshSearch($repository);
118
119
        $createStructLastHope = $contentService->newContentCreateStruct($contentType, 'eng-GB');
120
        $createStructLastHope->remoteId = 'movie-101112';
121
        $createStructLastHope->alwaysAvailable = false;
122
        $createStructLastHope->setField('title', 'Star Wars');
123
        $createStructLastHope->setField('subtitle', 'Last Hope');
124
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
125
126
        $lastHopeDraft = $contentService->createContent($createStructLastHope, [$locationCreateStruct]);
127
        $movies[] = $contentService->publishVersion($lastHopeDraft->getVersionInfo());
128
        $this->refreshSearch($repository);
129
130
        return $movies;
131
    }
132
133
    /**
134
     * Create test Content with ezcountry field having multiple countries selected.
135
     *
136
     * @return \eZ\Publish\API\Repository\Values\Content\Content
137
     */
138
    protected function createMultipleCountriesContent()
139
    {
140
        $repository = $this->getRepository();
141
        $contentTypeService = $repository->getContentTypeService();
142
        $contentService = $repository->getContentService();
143
144
        $createStruct = $contentTypeService->newContentTypeCreateStruct('countries-multiple');
145
        $createStruct->mainLanguageCode = 'eng-GB';
146
        $createStruct->remoteId = 'countries-multiple-123';
147
        $createStruct->names = ['eng-GB' => 'Multiple countries'];
148
        $createStruct->creatorId = 14;
149
        $createStruct->creationDate = new \DateTime();
150
151
        $fieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('countries', 'ezcountry');
152
        $fieldCreate->names = ['eng-GB' => 'Countries'];
153
        $fieldCreate->fieldGroup = 'main';
154
        $fieldCreate->position = 1;
155
        $fieldCreate->isTranslatable = false;
156
        $fieldCreate->isSearchable = true;
157
        $fieldCreate->fieldSettings = ['isMultiple' => true];
158
159
        $createStruct->addFieldDefinition($fieldCreate);
160
161
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
162
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, [$contentGroup]);
163
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
164
        $contentType = $contentTypeService->loadContentType($contentTypeDraft->id);
165
166
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
167
        $createStruct->remoteId = 'countries-multiple-456';
168
        $createStruct->alwaysAvailable = false;
169
        $createStruct->setField(
170
            'countries',
171
            ['BE', 'DE', 'FR', 'HR', 'NO', 'PT', 'RU']
172
        );
173
174
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
175
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
176
        $content = $contentService->publishVersion($draft->getVersionInfo());
177
178
        $this->refreshSearch($repository);
179
180
        return $content;
181
    }
182
183
    protected function createFolderWithNonPrintableUtf8Characters(): Content
184
    {
185
        $repository = $this->getRepository();
186
        $contentTypeService = $repository->getContentTypeService();
187
        $contentService = $repository->getContentService();
188
189
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
190
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
191
        $createStruct->remoteId = 'non-printable-char-folder-123';
192
        $createStruct->alwaysAvailable = false;
193
        $createStruct->setField(
194
            'name',
195
            utf8_decode("Non\x09Printable\x0EFolder")
196
        );
197
198
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
199
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
200
        $content = $contentService->publishVersion($draft->getVersionInfo());
201
202
        $this->refreshSearch($repository);
203
204
        return $content;
205
    }
206
207
    /**
208
     * Test for the findLocations() method.
209
     *
210
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
211
     */
212
    public function testFieldIsEmptyInLocation()
213
    {
214
        $testContents = $this->createMovieContent();
215
216
        $query = new LocationQuery(
217
            [
218
                'query' => new Criterion\IsFieldEmpty('subtitle'),
219
            ]
220
        );
221
222
        $repository = $this->getRepository();
223
        $searchService = $repository->getSearchService();
224
        $result = $searchService->findLocations($query);
225
226
        $this->assertEquals(2, $result->totalCount);
227
228
        $this->assertEquals(
229
            $testContents[0]->contentInfo->mainLocationId,
230
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
231
        );
232
233
        $this->assertEquals(
234
            $testContents[1]->contentInfo->mainLocationId,
235
            $result->searchHits[1]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
236
        );
237
    }
238
239
    /**
240
     * Test for the findLocations() method.
241
     *
242
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
243
     */
244 View Code Duplication
    public function testFieldIsNotEmptyInLocation()
245
    {
246
        $testContents = $this->createMovieContent();
247
248
        $query = new LocationQuery(
249
            [
250
                'query' => new Criterion\IsFieldEmpty(
251
                    'subtitle',
252
                    false
253
                ),
254
            ]
255
        );
256
257
        $repository = $this->getRepository();
258
        $searchService = $repository->getSearchService();
259
        $result = $searchService->findLocations($query);
260
261
        $this->assertEquals(1, $result->totalCount);
262
263
        $this->assertEquals(
264
            $testContents[2]->contentInfo->mainLocationId,
265
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
266
        );
267
    }
268
269
    /**
270
     * Test for the findLocations() method.
271
     *
272
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
273
     */
274 View Code Duplication
    public function testFieldCollectionContains()
275
    {
276
        $testContent = $this->createMultipleCountriesContent();
277
278
        $query = new LocationQuery(
279
            [
280
                'query' => new Criterion\Field(
281
                    'countries',
282
                    Criterion\Operator::CONTAINS,
283
                    'Belgium'
284
                ),
285
            ]
286
        );
287
288
        $repository = $this->getRepository();
289
        $searchService = $repository->getSearchService();
290
        $result = $searchService->findLocations($query);
291
292
        $this->assertEquals(1, $result->totalCount);
293
        $this->assertEquals(
294
            $testContent->contentInfo->mainLocationId,
295
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
296
        );
297
    }
298
299
    /**
300
     * Test for the findLocations() method.
301
     *
302
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
303
     * @depends eZ\Publish\API\Repository\Tests\SearchServiceTest::testFieldCollectionContains
304
     */
305 View Code Duplication
    public function testFieldCollectionContainsNoMatch()
306
    {
307
        $this->createMultipleCountriesContent();
308
        $query = new LocationQuery(
309
            [
310
                'query' => new Criterion\Field(
311
                    'countries',
312
                    Criterion\Operator::CONTAINS,
313
                    'Netherlands Antilles'
314
                ),
315
            ]
316
        );
317
318
        $repository = $this->getRepository();
319
        $searchService = $repository->getSearchService();
320
        $result = $searchService->findLocations($query);
321
322
        $this->assertEquals(0, $result->totalCount);
323
    }
324
325
    /**
326
     * @covers \eZ\Publish\API\Repository\SearchService::findLocations
327
     */
328 View Code Duplication
    public function testNonPrintableUtf8Characters(): void
329
    {
330
        $folder = $this->createFolderWithNonPrintableUtf8Characters();
331
        $query = new LocationQuery(
332
            [
333
                'query' => new Criterion\Field(
334
                    'name',
335
                    Criterion\Operator::EQ,
336
                    utf8_decode("Non\x09Printable\x0EFolder")
337
                ),
338
            ]
339
        );
340
341
        $repository = $this->getRepository();
342
        $searchService = $repository->getSearchService();
343
        $result = $searchService->findLocations($query);
344
345
        $this->assertEquals(1, $result->totalCount);
346
        $this->assertEquals(
347
            $folder->contentInfo->mainLocationId,
348
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
349
        );
350
    }
351
352
    /**
353
     * @covers \eZ\Publish\API\Repository\SearchService::findLocations
354
     * @depends \eZ\Publish\API\Repository\Tests\SearchServiceLocationTest::testNonPrintableUtf8Characters
355
     */
356
    public function testEscapedNonPrintableUtf8Characters(): void
357
    {
358
        $setupFactory = $this->getSetupFactory();
359
360
        if (
361
            !$setupFactory instanceof LegacyElasticsearch &&
362
            !$setupFactory instanceof LegacySolrSetupFactory
0 ignored issues
show
Bug introduced by
The class EzSystems\EzPlatformSolr...tory\LegacySetupFactory does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
363
        ) {
364
            $this->markTestIncomplete(
365
                'Field Value mappers are used only with Solr and Elastic search engines'
366
            );
367
        }
368
369
        $query = new LocationQuery(
370
            [
371
                'query' => new Criterion\Field(
372
                    'name',
373
                    Criterion\Operator::EQ,
374
                    'Non PrintableFolder'
375
                ),
376
            ]
377
        );
378
379
        $repository = $this->getRepository();
380
        $searchService = $repository->getSearchService();
381
        $result = $searchService->findLocations($query);
382
383
        $this->assertEquals(1, $result->totalCount);
384
    }
385
386
    /**
387
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
388
     */
389 View Code Duplication
    public function testInvalidFieldIdentifierRange()
390
    {
391
        $repository = $this->getRepository();
392
        $searchService = $repository->getSearchService();
393
394
        $searchService->findLocations(
395
            new LocationQuery(
396
                [
397
                    'filter' => new Criterion\Field(
398
                        'some_hopefully_unknown_field',
399
                        Criterion\Operator::BETWEEN,
400
                        [10, 1000]
401
                    ),
402
                    'sortClauses' => [new SortClause\ContentId()],
403
                ]
404
            )
405
        );
406
    }
407
408
    /**
409
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
410
     */
411
    public function testInvalidFieldIdentifierIn()
412
    {
413
        $repository = $this->getRepository();
414
        $searchService = $repository->getSearchService();
415
416
        $searchService->findLocations(
417
            new LocationQuery(
418
                [
419
                    'filter' => new Criterion\Field(
420
                        'some_hopefully_unknown_field',
421
                        Criterion\Operator::EQ,
422
                        1000
423
                    ),
424
                    'sortClauses' => [new SortClause\ContentId()],
425
                ]
426
            )
427
        );
428
    }
429
430
    /**
431
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
432
     */
433
    public function testFindLocationsWithNonSearchableField()
434
    {
435
        $repository = $this->getRepository();
436
        $searchService = $repository->getSearchService();
437
438
        $searchService->findLocations(
439
            new LocationQuery(
440
                [
441
                    'filter' => new Criterion\Field(
442
                        'tag_cloud_url',
443
                        Criterion\Operator::EQ,
444
                        'http://nimbus.com'
445
                    ),
446
                    'sortClauses' => [new SortClause\ContentId()],
447
                ]
448
            )
449
        );
450
    }
451
452
    /**
453
     * @return array
454
     */
455
    protected function mapResultLocationIds(SearchResult $result)
456
    {
457
        return array_map(
458
            function (SearchHit $searchHit) {
459
                return $searchHit->valueObject->id;
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
460
            },
461
            $result->searchHits
462
        );
463
    }
464
465
    /**
466
     * Test for the findLocations() method.
467
     *
468
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
469
     */
470 View Code Duplication
    public function testQueryCustomField()
471
    {
472
        $query = new LocationQuery(
473
            [
474
                'query' => new Criterion\CustomField(
475
                    'custom_field',
476
                    Criterion\Operator::EQ,
477
                    'AdMiNiStRaToR'
478
                ),
479
                'offset' => 0,
480
                'limit' => 10,
481
                'sortClauses' => [new SortClause\ContentId()],
482
            ]
483
        );
484
        $this->assertQueryFixture(
485
            $query,
486
            $this->getFixtureDir() . '/QueryCustomField.php',
487
            null,
488
            true
489
        );
490
    }
491
492
    /**
493
     * Test for the findLocations() method.
494
     *
495
     * This tests explicitly queries the first_name while user is contained in
496
     * the last_name of admin and anonymous. This is done to show the custom
497
     * copy field working.
498
     *
499
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
500
     */
501 View Code Duplication
    public function testQueryModifiedField()
502
    {
503
        // Check using get_class since the others extend SetupFactory\Legacy
504
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
505
            $this->markTestIncomplete(
506
                'Custom fields not supported by LegacySE ' .
507
                '(@todo: Legacy should fallback to just querying normal field so this should be tested here)'
508
            );
509
        }
510
511
        $query = new LocationQuery(
512
            [
513
                'query' => new Criterion\Field(
514
                    'first_name',
515
                    Criterion\Operator::EQ,
516
                    'User'
517
                ),
518
                'offset' => 0,
519
                'limit' => 10,
520
                'sortClauses' => [new SortClause\ContentId()],
521
            ]
522
        );
523
        $query->query->setCustomField('user', 'first_name', 'custom_field');
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class eZ\Publish\API\Repositor...Content\Query\Criterion as the method setCustomField() does only exist in the following sub-classes of eZ\Publish\API\Repositor...Content\Query\Criterion: eZ\Publish\API\Repositor...t\Query\Criterion\Field, eZ\Publish\API\Repositor...uery\Criterion\FullText, eZ\Publish\API\Repositor...ion\MapLocationDistance. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
524
525
        $this->assertQueryFixture(
526
            $query,
527
            $this->getFixtureDir() . '/QueryModifiedField.php',
528
            null,
529
            true
530
        );
531
    }
532
533
    /**
534
     * @return \eZ\Publish\API\Repository\Values\ContentType\ContentType
535
     */
536 View Code Duplication
    protected function createTestPlaceContentType()
537
    {
538
        $repository = $this->getRepository();
539
        $contentTypeService = $repository->getContentTypeService();
540
541
        $createStruct = $contentTypeService->newContentTypeCreateStruct('testtype');
542
        $createStruct->mainLanguageCode = 'eng-GB';
543
        $createStruct->names = ['eng-GB' => 'Test type'];
544
        $createStruct->creatorId = 14;
545
        $createStruct->creationDate = new \DateTime();
546
547
        $translatableFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('maplocation', 'ezgmaplocation');
548
        $translatableFieldCreate->names = ['eng-GB' => 'Map location field'];
549
        $translatableFieldCreate->fieldGroup = 'main';
550
        $translatableFieldCreate->position = 1;
551
        $translatableFieldCreate->isTranslatable = false;
552
        $translatableFieldCreate->isSearchable = true;
553
554
        $createStruct->addFieldDefinition($translatableFieldCreate);
555
556
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
557
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, [$contentGroup]);
558
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
559
        $contentType = $contentTypeService->loadContentType($contentTypeDraft->id);
560
561
        return $contentType;
562
    }
563
564
    /**
565
     * Test for the findLocations() method.
566
     *
567
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
568
     * @group maplocation
569
     */
570 View Code Duplication
    public function testMapLocationDistanceLessThanOrEqual()
571
    {
572
        $contentType = $this->createTestPlaceContentType();
573
574
        // Create a draft to account for behaviour with ContentType in different states
575
        $repository = $this->getRepository();
576
        $contentTypeService = $repository->getContentTypeService();
577
        $contentService = $repository->getContentService();
578
        $contentTypeService->createContentTypeDraft($contentType);
579
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
580
581
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
582
        $createStruct->alwaysAvailable = false;
583
        $createStruct->mainLanguageCode = 'eng-GB';
584
        $createStruct->setField(
585
            'maplocation',
586
            [
587
                'latitude' => 45.894877,
588
                'longitude' => 15.972699,
589
                'address' => 'Here be wild boars',
590
            ],
591
            'eng-GB'
592
        );
593
594
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
595
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
596
597
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
598
        $createStruct->alwaysAvailable = false;
599
        $createStruct->mainLanguageCode = 'eng-GB';
600
        $createStruct->setField(
601
            'maplocation',
602
            [
603
                'latitude' => 45.927334,
604
                'longitude' => 15.934847,
605
                'address' => 'A lone tree',
606
            ],
607
            'eng-GB'
608
        );
609
610
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
611
        $tree = $contentService->publishVersion($draft->getVersionInfo());
0 ignored issues
show
Unused Code introduced by
$tree 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...
612
613
        $this->refreshSearch($repository);
614
615
        $query = new LocationQuery(
616
            [
617
                'filter' => new Criterion\LogicalAnd(
618
                    [
619
                        new Criterion\ContentTypeId($contentType->id),
620
                        new Criterion\MapLocationDistance(
621
                            'maplocation',
622
                            Criterion\Operator::LTE,
623
                            240,
624
                            43.756825,
625
                            15.775074
626
                        ),
627
                    ]
628
                ),
629
                'offset' => 0,
630
                'limit' => 10,
631
                'sortClauses' => [],
632
            ]
633
        );
634
635
        $searchService = $repository->getSearchService();
636
        $result = $searchService->findLocations($query);
637
638
        $this->assertEquals(1, $result->totalCount);
639
        $this->assertEquals(
640
            $wildBoars->contentInfo->mainLocationId,
641
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
642
        );
643
    }
644
645
    /**
646
     * Test for the findLocations() method.
647
     *
648
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
649
     * @group maplocation
650
     */
651 View Code Duplication
    public function testMapLocationDistanceGreaterThanOrEqual()
652
    {
653
        $contentType = $this->createTestPlaceContentType();
654
655
        // Create a draft to account for behaviour with ContentType in different states
656
        $repository = $this->getRepository();
657
        $contentTypeService = $repository->getContentTypeService();
658
        $contentService = $repository->getContentService();
659
        $contentTypeService->createContentTypeDraft($contentType);
660
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
661
662
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
663
        $createStruct->alwaysAvailable = false;
664
        $createStruct->mainLanguageCode = 'eng-GB';
665
        $createStruct->setField(
666
            'maplocation',
667
            [
668
                'latitude' => 45.894877,
669
                'longitude' => 15.972699,
670
                'address' => 'Here be wild boars',
671
            ],
672
            'eng-GB'
673
        );
674
675
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
676
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
0 ignored issues
show
Unused Code introduced by
$wildBoars 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...
677
678
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
679
        $createStruct->alwaysAvailable = false;
680
        $createStruct->mainLanguageCode = 'eng-GB';
681
        $createStruct->setField(
682
            'maplocation',
683
            [
684
                'latitude' => 45.927334,
685
                'longitude' => 15.934847,
686
                'address' => 'A lone tree',
687
            ],
688
            'eng-GB'
689
        );
690
691
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
692
        $tree = $contentService->publishVersion($draft->getVersionInfo());
693
694
        $this->refreshSearch($repository);
695
696
        $query = new LocationQuery(
697
            [
698
                'filter' => new Criterion\LogicalAnd(
699
                    [
700
                        new Criterion\ContentTypeId($contentType->id),
701
                        new Criterion\MapLocationDistance(
702
                            'maplocation',
703
                            Criterion\Operator::GTE,
704
                            240,
705
                            43.756825,
706
                            15.775074
707
                        ),
708
                    ]
709
                ),
710
                'offset' => 0,
711
                'limit' => 10,
712
                'sortClauses' => [],
713
            ]
714
        );
715
716
        $searchService = $repository->getSearchService();
717
        $result = $searchService->findLocations($query);
718
719
        $this->assertEquals(1, $result->totalCount);
720
        $this->assertEquals(
721
            $tree->contentInfo->mainLocationId,
722
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
723
        );
724
    }
725
726
    /**
727
     * Test for the findLocations() method.
728
     *
729
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
730
     * @group maplocation
731
     */
732
    public function testMapLocationDistanceBetween()
733
    {
734
        $contentType = $this->createTestPlaceContentType();
735
736
        // Create a draft to account for behaviour with ContentType in different states
737
        $repository = $this->getRepository();
738
        $contentTypeService = $repository->getContentTypeService();
739
        $contentService = $repository->getContentService();
740
        $contentTypeService->createContentTypeDraft($contentType);
741
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
742
743
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
744
        $createStruct->alwaysAvailable = false;
745
        $createStruct->mainLanguageCode = 'eng-GB';
746
        $createStruct->setField(
747
            'maplocation',
748
            [
749
                'latitude' => 45.894877,
750
                'longitude' => 15.972699,
751
                'address' => 'Here be wild boars',
752
            ],
753
            'eng-GB'
754
        );
755
756
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
757
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
0 ignored issues
show
Unused Code introduced by
$wildBoars 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...
758
759
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
760
        $createStruct->alwaysAvailable = false;
761
        $createStruct->mainLanguageCode = 'eng-GB';
762
        $createStruct->setField(
763
            'maplocation',
764
            [
765
                'latitude' => 45.927334,
766
                'longitude' => 15.934847,
767
                'address' => 'A lone tree',
768
            ],
769
            'eng-GB'
770
        );
771
772
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
773
        $tree = $contentService->publishVersion($draft->getVersionInfo());
0 ignored issues
show
Unused Code introduced by
$tree 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...
774
775
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
776
        $createStruct->alwaysAvailable = false;
777
        $createStruct->mainLanguageCode = 'eng-GB';
778
        $createStruct->setField(
779
            'maplocation',
780
            [
781
                'latitude' => 45.903777,
782
                'longitude' => 15.958788,
783
                'address' => 'Meadow with mushrooms',
784
            ],
785
            'eng-GB'
786
        );
787
788
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
789
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
790
791
        $this->refreshSearch($repository);
792
793
        $query = new LocationQuery(
794
            [
795
                'filter' => new Criterion\LogicalAnd(
796
                    [
797
                        new Criterion\ContentTypeId($contentType->id),
798
                        new Criterion\MapLocationDistance(
799
                            'maplocation',
800
                            Criterion\Operator::BETWEEN,
801
                            [239, 241],
802
                            43.756825,
803
                            15.775074
804
                        ),
805
                    ]
806
                ),
807
                'offset' => 0,
808
                'limit' => 10,
809
                'sortClauses' => [],
810
            ]
811
        );
812
813
        $searchService = $repository->getSearchService();
814
        $result = $searchService->findLocations($query);
815
816
        $this->assertEquals(1, $result->totalCount);
817
        $this->assertEquals(
818
            $mushrooms->contentInfo->mainLocationId,
819
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
820
        );
821
    }
822
823
    /**
824
     * Test for the findLocations() method.
825
     *
826
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
827
     * @group maplocation
828
     */
829 View Code Duplication
    public function testMapLocationDistanceSortAscending()
830
    {
831
        $contentType = $this->createTestPlaceContentType();
832
833
        // Create a draft to account for behaviour with ContentType in different states
834
        $repository = $this->getRepository();
835
        $contentTypeService = $repository->getContentTypeService();
836
        $contentService = $repository->getContentService();
837
        $contentTypeService->createContentTypeDraft($contentType);
838
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
839
840
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
841
        $createStruct->alwaysAvailable = false;
842
        $createStruct->mainLanguageCode = 'eng-GB';
843
        $createStruct->setField(
844
            'maplocation',
845
            [
846
                'latitude' => 45.894877,
847
                'longitude' => 15.972699,
848
                'address' => 'Here be wild boars',
849
            ],
850
            'eng-GB'
851
        );
852
853
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
854
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
855
856
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
857
        $createStruct->alwaysAvailable = false;
858
        $createStruct->mainLanguageCode = 'eng-GB';
859
        $createStruct->setField(
860
            'maplocation',
861
            [
862
                'latitude' => 45.927334,
863
                'longitude' => 15.934847,
864
                'address' => 'A lone tree',
865
            ],
866
            'eng-GB'
867
        );
868
869
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
870
        $tree = $contentService->publishVersion($draft->getVersionInfo());
871
872
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
873
        $createStruct->alwaysAvailable = false;
874
        $createStruct->mainLanguageCode = 'eng-GB';
875
        $createStruct->setField(
876
            'maplocation',
877
            [
878
                'latitude' => 45.903777,
879
                'longitude' => 15.958788,
880
                'address' => 'Meadow with mushrooms',
881
            ],
882
            'eng-GB'
883
        );
884
885
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
886
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
887
888
        $this->refreshSearch($repository);
889
890
        $wellInVodice = [
891
            'latitude' => 43.756825,
892
            'longitude' => 15.775074,
893
        ];
894
895
        $query = new LocationQuery(
896
            [
897
                'filter' => new Criterion\LogicalAnd(
898
                    [
899
                        new Criterion\ContentTypeId($contentType->id),
900
                        new Criterion\MapLocationDistance(
901
                            'maplocation',
902
                            Criterion\Operator::GTE,
903
                            235,
904
                            $wellInVodice['latitude'],
905
                            $wellInVodice['longitude']
906
                        ),
907
                    ]
908
                ),
909
                'offset' => 0,
910
                'limit' => 10,
911
                'sortClauses' => [
912
                    new SortClause\MapLocationDistance(
913
                        'testtype',
914
                        'maplocation',
915
                        $wellInVodice['latitude'],
916
                        $wellInVodice['longitude'],
917
                        LocationQuery::SORT_ASC
918
                    ),
919
                ],
920
            ]
921
        );
922
923
        $searchService = $repository->getSearchService();
924
        $result = $searchService->findLocations($query);
925
926
        $this->assertEquals(3, $result->totalCount);
927
        $this->assertEquals(
928
            $wildBoars->contentInfo->mainLocationId,
929
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
930
        );
931
        $this->assertEquals(
932
            $mushrooms->contentInfo->mainLocationId,
933
            $result->searchHits[1]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
934
        );
935
        $this->assertEquals(
936
            $tree->contentInfo->mainLocationId,
937
            $result->searchHits[2]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
938
        );
939
    }
940
941
    /**
942
     * Test for the findLocations() method.
943
     *
944
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
945
     * @group maplocation
946
     */
947 View Code Duplication
    public function testMapLocationDistanceSortDescending()
948
    {
949
        $contentType = $this->createTestPlaceContentType();
950
951
        // Create a draft to account for behaviour with ContentType in different states
952
        $repository = $this->getRepository();
953
        $contentTypeService = $repository->getContentTypeService();
954
        $contentService = $repository->getContentService();
955
        $contentTypeService->createContentTypeDraft($contentType);
956
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
957
958
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
959
        $createStruct->alwaysAvailable = false;
960
        $createStruct->mainLanguageCode = 'eng-GB';
961
        $createStruct->setField(
962
            'maplocation',
963
            [
964
                'latitude' => 45.894877,
965
                'longitude' => 15.972699,
966
                'address' => 'Here be wild boars',
967
            ],
968
            'eng-GB'
969
        );
970
971
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
972
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
973
974
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
975
        $createStruct->alwaysAvailable = false;
976
        $createStruct->mainLanguageCode = 'eng-GB';
977
        $createStruct->setField(
978
            'maplocation',
979
            [
980
                'latitude' => 45.927334,
981
                'longitude' => 15.934847,
982
                'address' => 'A lone tree',
983
            ],
984
            'eng-GB'
985
        );
986
987
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
988
        $tree = $contentService->publishVersion($draft->getVersionInfo());
989
990
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
991
        $createStruct->alwaysAvailable = false;
992
        $createStruct->mainLanguageCode = 'eng-GB';
993
        $createStruct->setField(
994
            'maplocation',
995
            [
996
                'latitude' => 45.903777,
997
                'longitude' => 15.958788,
998
                'address' => 'Meadow with mushrooms',
999
            ],
1000
            'eng-GB'
1001
        );
1002
1003
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
1004
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
1005
1006
        $this->refreshSearch($repository);
1007
1008
        $well = [
1009
            'latitude' => 43.756825,
1010
            'longitude' => 15.775074,
1011
        ];
1012
1013
        $query = new LocationQuery(
1014
            [
1015
                'filter' => new Criterion\LogicalAnd(
1016
                    [
1017
                        new Criterion\ContentTypeId($contentType->id),
1018
                        new Criterion\MapLocationDistance(
1019
                            'maplocation',
1020
                            Criterion\Operator::GTE,
1021
                            235,
1022
                            $well['latitude'],
1023
                            $well['longitude']
1024
                        ),
1025
                    ]
1026
                ),
1027
                'offset' => 0,
1028
                'limit' => 10,
1029
                'sortClauses' => [
1030
                    new SortClause\MapLocationDistance(
1031
                        'testtype',
1032
                        'maplocation',
1033
                        $well['latitude'],
1034
                        $well['longitude'],
1035
                        LocationQuery::SORT_DESC
1036
                    ),
1037
                ],
1038
            ]
1039
        );
1040
1041
        $searchService = $repository->getSearchService();
1042
        $result = $searchService->findLocations($query);
1043
1044
        $this->assertEquals(3, $result->totalCount);
1045
        $this->assertEquals(
1046
            $wildBoars->contentInfo->mainLocationId,
1047
            $result->searchHits[2]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
1048
        );
1049
        $this->assertEquals(
1050
            $mushrooms->contentInfo->mainLocationId,
1051
            $result->searchHits[1]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
1052
        );
1053
        $this->assertEquals(
1054
            $tree->contentInfo->mainLocationId,
1055
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
1056
        );
1057
    }
1058
1059
    /**
1060
     * Test for the findLocations() method.
1061
     *
1062
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
1063
     * @group maplocation
1064
     */
1065
    public function testMapLocationDistanceWithCustomField()
1066
    {
1067
        $contentType = $this->createTestPlaceContentType();
1068
1069
        // Create a draft to account for behaviour with ContentType in different states
1070
        $repository = $this->getRepository();
1071
        $contentTypeService = $repository->getContentTypeService();
1072
        $contentService = $repository->getContentService();
1073
        $contentTypeService->createContentTypeDraft($contentType);
1074
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
1075
1076
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
1077
        $createStruct->alwaysAvailable = false;
1078
        $createStruct->mainLanguageCode = 'eng-GB';
1079
        $createStruct->setField(
1080
            'maplocation',
1081
            [
1082
                'latitude' => 45.894877,
1083
                'longitude' => 15.972699,
1084
                'address' => 'Here be wild boars',
1085
            ],
1086
            'eng-GB'
1087
        );
1088
1089
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
1090
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
1091
1092
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
1093
        $createStruct->alwaysAvailable = false;
1094
        $createStruct->mainLanguageCode = 'eng-GB';
1095
        $createStruct->setField(
1096
            'maplocation',
1097
            [
1098
                'latitude' => 45.927334,
1099
                'longitude' => 15.934847,
1100
                'address' => 'A lone tree',
1101
            ],
1102
            'eng-GB'
1103
        );
1104
1105
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
1106
        $tree = $contentService->publishVersion($draft->getVersionInfo());
0 ignored issues
show
Unused Code introduced by
$tree 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...
1107
1108
        $this->refreshSearch($repository);
1109
1110
        $distanceCriterion = new Criterion\MapLocationDistance(
1111
            'maplocation',
1112
            Criterion\Operator::LTE,
1113
            240,
1114
            43.756825,
1115
            15.775074
1116
        );
1117
        $distanceCriterion->setCustomField('testtype', 'maplocation', 'custom_geolocation_field');
1118
1119
        $query = new LocationQuery(
1120
            [
1121
                'filter' => new Criterion\LogicalAnd(
1122
                    [
1123
                        new Criterion\ContentTypeId($contentType->id),
1124
                        $distanceCriterion,
1125
                    ]
1126
                ),
1127
                'offset' => 0,
1128
                'limit' => 10,
1129
                'sortClauses' => [],
1130
            ]
1131
        );
1132
1133
        $searchService = $repository->getSearchService();
1134
        $result = $searchService->findLocations($query);
1135
1136
        $this->assertEquals(1, $result->totalCount);
1137
        $this->assertEquals(
1138
            $wildBoars->contentInfo->mainLocationId,
1139
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
1140
        );
1141
    }
1142
1143
    /**
1144
     * Test for the findLocations() method.
1145
     *
1146
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
1147
     * @group maplocation
1148
     */
1149
    public function testMapLocationDistanceWithCustomFieldSort()
1150
    {
1151
        $contentType = $this->createTestPlaceContentType();
1152
1153
        // Create a draft to account for behaviour with ContentType in different states
1154
        $repository = $this->getRepository();
1155
        $contentTypeService = $repository->getContentTypeService();
1156
        $contentService = $repository->getContentService();
1157
        $contentTypeService->createContentTypeDraft($contentType);
1158
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
1159
1160
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
1161
        $createStruct->alwaysAvailable = false;
1162
        $createStruct->mainLanguageCode = 'eng-GB';
1163
        $createStruct->setField(
1164
            'maplocation',
1165
            [
1166
                'latitude' => 45.894877,
1167
                'longitude' => 15.972699,
1168
                'address' => 'Here be wild boars',
1169
            ],
1170
            'eng-GB'
1171
        );
1172
1173
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
1174
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
1175
1176
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
1177
        $createStruct->alwaysAvailable = false;
1178
        $createStruct->mainLanguageCode = 'eng-GB';
1179
        $createStruct->setField(
1180
            'maplocation',
1181
            [
1182
                'latitude' => 45.927334,
1183
                'longitude' => 15.934847,
1184
                'address' => 'A lone tree',
1185
            ],
1186
            'eng-GB'
1187
        );
1188
1189
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
1190
        $tree = $contentService->publishVersion($draft->getVersionInfo());
1191
1192
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
1193
        $createStruct->alwaysAvailable = false;
1194
        $createStruct->mainLanguageCode = 'eng-GB';
1195
        $createStruct->setField(
1196
            'maplocation',
1197
            [
1198
                'latitude' => 45.903777,
1199
                'longitude' => 15.958788,
1200
                'address' => 'Meadow with mushrooms',
1201
            ],
1202
            'eng-GB'
1203
        );
1204
1205
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
1206
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
1207
1208
        $this->refreshSearch($repository);
1209
1210
        $well = [
1211
            'latitude' => 43.756825,
1212
            'longitude' => 15.775074,
1213
        ];
1214
1215
        $sortClause = new SortClause\MapLocationDistance(
1216
            'testtype',
1217
            'maplocation',
1218
            $well['latitude'],
1219
            $well['longitude'],
1220
            LocationQuery::SORT_DESC
1221
        );
1222
        $sortClause->setCustomField('testtype', 'maplocation', 'custom_geolocation_field');
1223
1224
        $query = new LocationQuery(
1225
            [
1226
                'filter' => new Criterion\LogicalAnd(
1227
                    [
1228
                        new Criterion\ContentTypeId($contentType->id),
1229
                        new Criterion\MapLocationDistance(
1230
                            'maplocation',
1231
                            Criterion\Operator::GTE,
1232
                            235,
1233
                            $well['latitude'],
1234
                            $well['longitude']
1235
                        ),
1236
                    ]
1237
                ),
1238
                'offset' => 0,
1239
                'limit' => 10,
1240
                'sortClauses' => [
1241
                    $sortClause,
1242
                ],
1243
            ]
1244
        );
1245
1246
        $searchService = $repository->getSearchService();
1247
        $result = $searchService->findLocations($query);
1248
1249
        $this->assertEquals(3, $result->totalCount);
1250
        $this->assertEquals(
1251
            $wildBoars->contentInfo->mainLocationId,
1252
            $result->searchHits[2]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
1253
        );
1254
        $this->assertEquals(
1255
            $mushrooms->contentInfo->mainLocationId,
1256
            $result->searchHits[1]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
1257
        );
1258
        $this->assertEquals(
1259
            $tree->contentInfo->mainLocationId,
1260
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
1261
        );
1262
    }
1263
1264
    /**
1265
     * Test for the findLocations() method.
1266
     *
1267
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
1268
     */
1269
    public function testVisibilityCriterionWithHiddenContent()
1270
    {
1271
        $repository = $this->getRepository();
1272
        $contentTypeService = $repository->getContentTypeService();
1273
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
1274
1275
        $contentService = $repository->getContentService();
1276
        $locationService = $repository->getLocationService();
1277
        $searchService = $repository->getSearchService();
1278
1279
        $testRootContentCreate = $contentService->newContentCreateStruct($contentType, 'eng-US');
1280
        $testRootContentCreate->setField('name', 'Root for test');
1281
1282
        $rootContent = $contentService->createContent(
1283
            $testRootContentCreate,
1284
            [
1285
                $locationService->newLocationCreateStruct(
1286
                    $this->generateId('location', 2)
1287
                ),
1288
            ]
1289
        );
1290
1291
        $publishedRootContent = $contentService->publishVersion($rootContent->versionInfo);
1292
1293
        $contentCreate = $contentService->newContentCreateStruct($contentType, 'eng-US');
1294
        $contentCreate->setField('name', 'To Hide');
1295
1296
        $content = $contentService->createContent(
1297
            $contentCreate,
1298
            [
1299
                $locationService->newLocationCreateStruct(
1300
                    $publishedRootContent->contentInfo->mainLocationId
1301
                ),
1302
            ]
1303
        );
1304
        $publishedContent = $contentService->publishVersion($content->versionInfo);
1305
1306
        $childContentCreate = $contentService->newContentCreateStruct($contentType, 'eng-US');
1307
        $childContentCreate->setField('name', 'Invisible Child');
1308
1309
        $childContent = $contentService->createContent(
1310
            $childContentCreate,
1311
            [
1312
                $locationService->newLocationCreateStruct(
1313
                    $publishedContent->contentInfo->mainLocationId
1314
                ),
1315
            ]
1316
        );
1317
        $rootLocation = $locationService->loadLocation($publishedRootContent->contentInfo->mainLocationId);
1318
1319
        $contentService->publishVersion($childContent->versionInfo);
1320
        $this->refreshSearch($repository);
1321
1322
        $query = new LocationQuery([
1323
            'query' => new Criterion\LogicalAnd([
1324
                new Criterion\Visibility(
1325
                    Criterion\Visibility::VISIBLE
1326
                ),
1327
                new Criterion\Subtree(
1328
                    $rootLocation->pathString
1329
                ),
1330
            ]),
1331
        ]);
1332
1333
        //Sanity check for visible locations
1334
        $result = $searchService->findLocations($query);
1335
        $this->assertEquals(3, $result->totalCount);
1336
1337
        //Hide main content
1338
        $contentService->hideContent($publishedContent->contentInfo);
1339
        $this->refreshSearch($repository);
1340
1341
        $result = $searchService->findLocations($query);
1342
        $this->assertEquals(1, $result->totalCount);
1343
1344
        //Query for invisible content
1345
        $hiddenQuery = new LocationQuery([
1346
            'query' => new Criterion\LogicalAnd([
1347
                new Criterion\Visibility(
1348
                    Criterion\Visibility::HIDDEN
1349
                ),
1350
                new Criterion\Subtree(
1351
                    $rootLocation->pathString
1352
                ),
1353
            ]),
1354
        ]);
1355
1356
        $result = $searchService->findLocations($hiddenQuery);
1357
        $this->assertEquals(2, $result->totalCount);
1358
    }
1359
1360
    /**
1361
     * Assert that query result matches the given fixture.
1362
     *
1363
     * @param string $fixture
1364
     * @param callable|null $closure
1365
     */
1366
    protected function assertQueryFixture(LocationQuery $query, $fixture, $closure = null, $ignoreScore = true)
1367
    {
1368
        $repository = $this->getRepository();
1369
        $searchService = $repository->getSearchService();
1370
1371
        try {
1372
            $result = $searchService->findLocations($query);
1373
            $this->simplifySearchResult($result);
1374
        } catch (NotImplementedException $e) {
1375
            $this->markTestSkipped(
1376
                'This feature is not supported by the current search backend: ' . $e->getMessage()
1377
            );
1378
        }
1379
1380 View Code Duplication
        if (!is_file($fixture)) {
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...
1381
            if (isset($_ENV['ez_tests_record'])) {
1382
                file_put_contents(
1383
                    $record = $fixture . '.recording',
1384
                    "<?php\n\nreturn " . var_export($result, true) . ";\n\n"
1385
                );
1386
                $this->markTestIncomplete("No fixture available. Result recorded at $record. Result: \n" . $this->printResult($result));
1387
            } else {
1388
                $this->markTestIncomplete("No fixture available. Set \$_ENV['ez_tests_record'] to generate:\n " . $fixture);
1389
            }
1390
        }
1391
1392
        $fixture = include $fixture;
1393
1394
        if ($closure !== null) {
1395
            $closure($result);
1396
        }
1397
1398 View Code Duplication
        if ($ignoreScore) {
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...
1399
            foreach ([$fixture, $result] as $result) {
1400
                $property = new \ReflectionProperty(get_class($result), 'maxScore');
1401
                $property->setAccessible(true);
1402
                $property->setValue($result, 0.0);
1403
1404
                foreach ($result->searchHits as $hit) {
1405
                    $property = new \ReflectionProperty(get_class($hit), 'score');
1406
                    $property->setAccessible(true);
1407
                    $property->setValue($hit, 0.0);
1408
                }
1409
            }
1410
        }
1411
1412
        foreach ([$fixture, $result] as $set) {
1413
            foreach ($set->searchHits as $hit) {
1414
                $property = new \ReflectionProperty(get_class($hit), 'index');
1415
                $property->setAccessible(true);
1416
                $property->setValue($hit, null);
1417
1418
                $property = new \ReflectionProperty(get_class($hit), 'matchedTranslation');
1419
                $property->setAccessible(true);
1420
                $property->setValue($hit, null);
1421
            }
1422
        }
1423
1424
        $this->assertEquals(
1425
            $fixture,
1426
            $result,
1427
            'Search results do not match.',
1428
            .2 // Be quite generous regarding delay -- most important for scores
1429
        );
1430
    }
1431
1432
    /**
1433
     * Show a simplified view of the search result for manual introspection.
1434
     *
1435
     * @return string
1436
     */
1437 View Code Duplication
    protected function printResult(SearchResult $result)
1438
    {
1439
        $printed = '';
1440
        foreach ($result->searchHits as $hit) {
1441
            $printed .= sprintf(" - %s (%s)\n", $hit->valueObject['title'], $hit->valueObject['id']);
1442
        }
1443
1444
        return $printed;
1445
    }
1446
1447
    /**
1448
     * Simplify search result.
1449
     *
1450
     * This leads to saner comparisons of results, since we do not get the full
1451
     * content objects every time.
1452
     */
1453
    protected function simplifySearchResult(SearchResult $result)
1454
    {
1455
        $result->time = 1;
1456
1457
        foreach ($result->searchHits as $hit) {
1458
            switch (true) {
1459 View Code Duplication
                case $hit->valueObject instanceof Location:
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...
1460
                    $hit->valueObject = [
0 ignored issues
show
Documentation Bug introduced by
It seems like array('id' => $hit->valu...ect->contentInfo->name) of type array<string,*,{"id":"*","title":"string"}> is incompatible with the declared type object<eZ\Publish\API\Re...ory\Values\ValueObject> of property $valueObject.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1461
                        'id' => $hit->valueObject->contentInfo->id,
1462
                        'title' => $hit->valueObject->contentInfo->name,
1463
                    ];
1464
                    break;
1465
1466
                default:
1467
                    throw new \RuntimeException('Unknown search result hit type: ' . get_class($hit->valueObject));
1468
            }
1469
        }
1470
    }
1471
1472
    /**
1473
     * Get fixture directory.
1474
     *
1475
     * @return string
1476
     */
1477
    protected function getFixtureDir()
1478
    {
1479
        return __DIR__ . '/_fixtures/' . getenv('fixtureDir') . '/';
1480
    }
1481
}
1482