Completed
Push — fix_ezp29385 ( 36b56f...415bc3 )
by
unknown
56:19 queued 22:25
created

SearchServiceLocationTest::setUp()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the SearchServiceLocationTest class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\API\Repository\Tests;
10
11
use eZ\Publish\API\Repository\Tests\SetupFactory\LegacyElasticsearch;
12
use eZ\Publish\Core\Repository\Values\Content\Location;
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\SearchResult;
17
use eZ\Publish\API\Repository\Values\Content\Search\SearchHit;
18
use eZ\Publish\API\Repository\Exceptions\NotImplementedException;
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
    protected function setUp()
30
    {
31
        $setupFactory = $this->getSetupFactory();
32
        if ($setupFactory instanceof LegacyElasticsearch) {
33
            $this->markTestSkipped('Field Location search is not yet implemented Elasticsearch search engine');
34
        }
35
36
        parent::setUp();
37
    }
38
39
    /**
40
     * Create test Content with ezcountry field having multiple countries selected.
41
     *
42
     * @return \eZ\Publish\API\Repository\Values\Content\Content
43
     */
44
    protected function createMultipleCountriesContent()
45
    {
46
        $repository = $this->getRepository();
47
        $contentTypeService = $repository->getContentTypeService();
48
        $contentService = $repository->getContentService();
49
50
        $createStruct = $contentTypeService->newContentTypeCreateStruct('countries-multiple');
51
        $createStruct->mainLanguageCode = 'eng-GB';
52
        $createStruct->remoteId = 'countries-multiple-123';
53
        $createStruct->names = array('eng-GB' => 'Multiple countries');
54
        $createStruct->creatorId = 14;
55
        $createStruct->creationDate = new \DateTime();
56
57
        $fieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('countries', 'ezcountry');
58
        $fieldCreate->names = array('eng-GB' => 'Countries');
59
        $fieldCreate->fieldGroup = 'main';
60
        $fieldCreate->position = 1;
61
        $fieldCreate->isTranslatable = false;
62
        $fieldCreate->isSearchable = true;
63
        $fieldCreate->fieldSettings = array('isMultiple' => true);
64
65
        $createStruct->addFieldDefinition($fieldCreate);
66
67
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
68
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, array($contentGroup));
69
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
70
        $contentType = $contentTypeService->loadContentType($contentTypeDraft->id);
71
72
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
73
        $createStruct->remoteId = 'countries-multiple-456';
74
        $createStruct->alwaysAvailable = false;
75
        $createStruct->setField(
76
            'countries',
77
            array('BE', 'DE', 'FR', 'HR', 'NO', 'PT', 'RU')
78
        );
79
80
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
81
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
82
        $content = $contentService->publishVersion($draft->getVersionInfo());
83
84
        $this->refreshSearch($repository);
85
86
        return $content;
87
    }
88
89
    /**
90
     * Test for the findLocations() method.
91
     *
92
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
93
     */
94 View Code Duplication
    public function testFieldCollectionContains()
95
    {
96
        $testContent = $this->createMultipleCountriesContent();
97
98
        $query = new LocationQuery(
99
            array(
100
                'query' => new Criterion\Field(
101
                    'countries',
102
                    Criterion\Operator::CONTAINS,
103
                    'Belgium'
104
                ),
105
            )
106
        );
107
108
        $repository = $this->getRepository();
109
        $searchService = $repository->getSearchService();
110
        $result = $searchService->findLocations($query);
111
112
        $this->assertEquals(1, $result->totalCount);
113
        $this->assertEquals(
114
            $testContent->contentInfo->mainLocationId,
115
            $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...
116
        );
117
    }
118
119
    /**
120
     * Test for the findLocations() method.
121
     *
122
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
123
     * @depends eZ\Publish\API\Repository\Tests\SearchServiceTest::testFieldCollectionContains
124
     */
125 View Code Duplication
    public function testFieldCollectionContainsNoMatch()
126
    {
127
        $this->createMultipleCountriesContent();
128
        $query = new LocationQuery(
129
            array(
130
                'query' => new Criterion\Field(
131
                    'countries',
132
                    Criterion\Operator::CONTAINS,
133
                    'Netherlands Antilles'
134
                ),
135
            )
136
        );
137
138
        $repository = $this->getRepository();
139
        $searchService = $repository->getSearchService();
140
        $result = $searchService->findLocations($query);
141
142
        $this->assertEquals(0, $result->totalCount);
143
    }
144
145
    /**
146
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
147
     */
148 View Code Duplication
    public function testInvalidFieldIdentifierRange()
149
    {
150
        $repository = $this->getRepository();
151
        $searchService = $repository->getSearchService();
152
153
        $searchService->findLocations(
154
            new LocationQuery(
155
                array(
156
                    'filter' => new Criterion\Field(
157
                        'some_hopefully_unknown_field',
158
                        Criterion\Operator::BETWEEN,
159
                        array(10, 1000)
160
                    ),
161
                    'sortClauses' => array(new SortClause\ContentId()),
162
                )
163
            )
164
        );
165
    }
166
167
    /**
168
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
169
     */
170
    public function testInvalidFieldIdentifierIn()
171
    {
172
        $repository = $this->getRepository();
173
        $searchService = $repository->getSearchService();
174
175
        $searchService->findLocations(
176
            new LocationQuery(
177
                array(
178
                    'filter' => new Criterion\Field(
179
                        'some_hopefully_unknown_field',
180
                        Criterion\Operator::EQ,
181
                        1000
182
                    ),
183
                    'sortClauses' => array(new SortClause\ContentId()),
184
                )
185
            )
186
        );
187
    }
188
189
    /**
190
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
191
     */
192
    public function testFindLocationsWithNonSearchableField()
193
    {
194
        $repository = $this->getRepository();
195
        $searchService = $repository->getSearchService();
196
197
        $searchService->findLocations(
198
            new LocationQuery(
199
                array(
200
                    'filter' => new Criterion\Field(
201
                        'tag_cloud_url',
202
                        Criterion\Operator::EQ,
203
                        'http://nimbus.com'
204
                    ),
205
                    'sortClauses' => array(new SortClause\ContentId()),
206
                )
207
            )
208
        );
209
    }
210
211
    /**
212
     * @param \eZ\Publish\API\Repository\Values\Content\Search\SearchResult $result
213
     *
214
     * @return array
215
     */
216
    protected function mapResultLocationIds(SearchResult $result)
217
    {
218
        return array_map(
219
            function (SearchHit $searchHit) {
220
                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...
221
            },
222
            $result->searchHits
223
        );
224
    }
225
226
    /**
227
     * Test for the findLocations() method.
228
     *
229
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
230
     */
231 View Code Duplication
    public function testQueryCustomField()
232
    {
233
        $query = new LocationQuery(
234
            array(
235
                'query' => new Criterion\CustomField(
236
                    'custom_field',
237
                    Criterion\Operator::EQ,
238
                    'AdMiNiStRaToR'
239
                ),
240
                'offset' => 0,
241
                'limit' => 10,
242
                'sortClauses' => array(new SortClause\ContentId()),
243
            )
244
        );
245
        $this->assertQueryFixture(
246
            $query,
247
            $this->getFixtureDir() . '/QueryCustomField.php',
248
            null,
249
            true
250
        );
251
    }
252
253
    /**
254
     * Test for the findLocations() method.
255
     *
256
     * This tests explicitly queries the first_name while user is contained in
257
     * the last_name of admin and anonymous. This is done to show the custom
258
     * copy field working.
259
     *
260
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
261
     */
262 View Code Duplication
    public function testQueryModifiedField()
263
    {
264
        // Check using get_class since the others extend SetupFactory\Legacy
265
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
266
            $this->markTestIncomplete(
267
                'Custom fields not supported by LegacySE ' .
268
                '(@todo: Legacy should fallback to just querying normal field so this should be tested here)'
269
            );
270
        }
271
272
        $query = new LocationQuery(
273
            array(
274
                'query' => new Criterion\Field(
275
                    'first_name',
276
                    Criterion\Operator::EQ,
277
                    'User'
278
                ),
279
                'offset' => 0,
280
                'limit' => 10,
281
                'sortClauses' => array(new SortClause\ContentId()),
282
            )
283
        );
284
        $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...
285
286
        $this->assertQueryFixture(
287
            $query,
288
            $this->getFixtureDir() . '/QueryModifiedField.php',
289
            null,
290
            true
291
        );
292
    }
293
294
    /**
295
     * @return \eZ\Publish\API\Repository\Values\ContentType\ContentType
296
     */
297 View Code Duplication
    protected function createTestPlaceContentType()
298
    {
299
        $repository = $this->getRepository();
300
        $contentTypeService = $repository->getContentTypeService();
301
302
        $createStruct = $contentTypeService->newContentTypeCreateStruct('testtype');
303
        $createStruct->mainLanguageCode = 'eng-GB';
304
        $createStruct->names = array('eng-GB' => 'Test type');
305
        $createStruct->creatorId = 14;
306
        $createStruct->creationDate = new \DateTime();
307
308
        $translatableFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('maplocation', 'ezgmaplocation');
309
        $translatableFieldCreate->names = array('eng-GB' => 'Map location field');
310
        $translatableFieldCreate->fieldGroup = 'main';
311
        $translatableFieldCreate->position = 1;
312
        $translatableFieldCreate->isTranslatable = false;
313
        $translatableFieldCreate->isSearchable = true;
314
315
        $createStruct->addFieldDefinition($translatableFieldCreate);
316
317
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
318
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, array($contentGroup));
319
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
320
        $contentType = $contentTypeService->loadContentType($contentTypeDraft->id);
321
322
        return $contentType;
323
    }
324
325
    /**
326
     * Test for the findLocations() method.
327
     *
328
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
329
     * @group maplocation
330
     */
331 View Code Duplication
    public function testMapLocationDistanceLessThanOrEqual()
332
    {
333
        $contentType = $this->createTestPlaceContentType();
334
335
        // Create a draft to account for behaviour with ContentType in different states
336
        $repository = $this->getRepository();
337
        $contentTypeService = $repository->getContentTypeService();
338
        $contentService = $repository->getContentService();
339
        $contentTypeService->createContentTypeDraft($contentType);
340
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
341
342
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
343
        $createStruct->alwaysAvailable = false;
344
        $createStruct->mainLanguageCode = 'eng-GB';
345
        $createStruct->setField(
346
            'maplocation',
347
            array(
348
                'latitude' => 45.894877,
349
                'longitude' => 15.972699,
350
                'address' => 'Here be wild boars',
351
            ),
352
            'eng-GB'
353
        );
354
355
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
356
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
357
358
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
359
        $createStruct->alwaysAvailable = false;
360
        $createStruct->mainLanguageCode = 'eng-GB';
361
        $createStruct->setField(
362
            'maplocation',
363
            array(
364
                'latitude' => 45.927334,
365
                'longitude' => 15.934847,
366
                'address' => 'A lone tree',
367
            ),
368
            'eng-GB'
369
        );
370
371
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
372
        $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...
373
374
        $this->refreshSearch($repository);
375
376
        $query = new LocationQuery(
377
            array(
378
                'filter' => new Criterion\LogicalAnd(
379
                    array(
380
                        new Criterion\ContentTypeId($contentType->id),
381
                        new Criterion\MapLocationDistance(
382
                            'maplocation',
383
                            Criterion\Operator::LTE,
384
                            240,
385
                            43.756825,
386
                            15.775074
387
                        ),
388
                    )
389
                ),
390
                'offset' => 0,
391
                'limit' => 10,
392
                'sortClauses' => array(),
393
            )
394
        );
395
396
        $searchService = $repository->getSearchService();
397
        $result = $searchService->findLocations($query);
398
399
        $this->assertEquals(1, $result->totalCount);
400
        $this->assertEquals(
401
            $wildBoars->contentInfo->mainLocationId,
402
            $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...
403
        );
404
    }
405
406
    /**
407
     * Test for the findLocations() method.
408
     *
409
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
410
     * @group maplocation
411
     */
412 View Code Duplication
    public function testMapLocationDistanceGreaterThanOrEqual()
413
    {
414
        $contentType = $this->createTestPlaceContentType();
415
416
        // Create a draft to account for behaviour with ContentType in different states
417
        $repository = $this->getRepository();
418
        $contentTypeService = $repository->getContentTypeService();
419
        $contentService = $repository->getContentService();
420
        $contentTypeService->createContentTypeDraft($contentType);
421
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
422
423
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
424
        $createStruct->alwaysAvailable = false;
425
        $createStruct->mainLanguageCode = 'eng-GB';
426
        $createStruct->setField(
427
            'maplocation',
428
            array(
429
                'latitude' => 45.894877,
430
                'longitude' => 15.972699,
431
                'address' => 'Here be wild boars',
432
            ),
433
            'eng-GB'
434
        );
435
436
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
437
        $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...
438
439
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
440
        $createStruct->alwaysAvailable = false;
441
        $createStruct->mainLanguageCode = 'eng-GB';
442
        $createStruct->setField(
443
            'maplocation',
444
            array(
445
                'latitude' => 45.927334,
446
                'longitude' => 15.934847,
447
                'address' => 'A lone tree',
448
            ),
449
            'eng-GB'
450
        );
451
452
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
453
        $tree = $contentService->publishVersion($draft->getVersionInfo());
454
455
        $this->refreshSearch($repository);
456
457
        $query = new LocationQuery(
458
            array(
459
                'filter' => new Criterion\LogicalAnd(
460
                    array(
461
                        new Criterion\ContentTypeId($contentType->id),
462
                        new Criterion\MapLocationDistance(
463
                            'maplocation',
464
                            Criterion\Operator::GTE,
465
                            240,
466
                            43.756825,
467
                            15.775074
468
                        ),
469
                    )
470
                ),
471
                'offset' => 0,
472
                'limit' => 10,
473
                'sortClauses' => array(),
474
            )
475
        );
476
477
        $searchService = $repository->getSearchService();
478
        $result = $searchService->findLocations($query);
479
480
        $this->assertEquals(1, $result->totalCount);
481
        $this->assertEquals(
482
            $tree->contentInfo->mainLocationId,
483
            $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...
484
        );
485
    }
486
487
    /**
488
     * Test for the findLocations() method.
489
     *
490
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
491
     * @group maplocation
492
     */
493
    public function testMapLocationDistanceBetween()
494
    {
495
        $contentType = $this->createTestPlaceContentType();
496
497
        // Create a draft to account for behaviour with ContentType in different states
498
        $repository = $this->getRepository();
499
        $contentTypeService = $repository->getContentTypeService();
500
        $contentService = $repository->getContentService();
501
        $contentTypeService->createContentTypeDraft($contentType);
502
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
503
504
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
505
        $createStruct->alwaysAvailable = false;
506
        $createStruct->mainLanguageCode = 'eng-GB';
507
        $createStruct->setField(
508
            'maplocation',
509
            array(
510
                'latitude' => 45.894877,
511
                'longitude' => 15.972699,
512
                'address' => 'Here be wild boars',
513
            ),
514
            'eng-GB'
515
        );
516
517
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
518
        $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...
519
520
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
521
        $createStruct->alwaysAvailable = false;
522
        $createStruct->mainLanguageCode = 'eng-GB';
523
        $createStruct->setField(
524
            'maplocation',
525
            array(
526
                'latitude' => 45.927334,
527
                'longitude' => 15.934847,
528
                'address' => 'A lone tree',
529
            ),
530
            'eng-GB'
531
        );
532
533
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
534
        $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...
535
536
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
537
        $createStruct->alwaysAvailable = false;
538
        $createStruct->mainLanguageCode = 'eng-GB';
539
        $createStruct->setField(
540
            'maplocation',
541
            array(
542
                'latitude' => 45.903777,
543
                'longitude' => 15.958788,
544
                'address' => 'Meadow with mushrooms',
545
            ),
546
            'eng-GB'
547
        );
548
549
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
550
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
551
552
        $this->refreshSearch($repository);
553
554
        $query = new LocationQuery(
555
            array(
556
                'filter' => new Criterion\LogicalAnd(
557
                    array(
558
                        new Criterion\ContentTypeId($contentType->id),
559
                        new Criterion\MapLocationDistance(
560
                            'maplocation',
561
                            Criterion\Operator::BETWEEN,
562
                            array(239, 241),
563
                            43.756825,
564
                            15.775074
565
                        ),
566
                    )
567
                ),
568
                'offset' => 0,
569
                'limit' => 10,
570
                'sortClauses' => array(),
571
            )
572
        );
573
574
        $searchService = $repository->getSearchService();
575
        $result = $searchService->findLocations($query);
576
577
        $this->assertEquals(1, $result->totalCount);
578
        $this->assertEquals(
579
            $mushrooms->contentInfo->mainLocationId,
580
            $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...
581
        );
582
    }
583
584
    /**
585
     * Test for the findLocations() method.
586
     *
587
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
588
     * @group maplocation
589
     */
590 View Code Duplication
    public function testMapLocationDistanceSortAscending()
591
    {
592
        $contentType = $this->createTestPlaceContentType();
593
594
        // Create a draft to account for behaviour with ContentType in different states
595
        $repository = $this->getRepository();
596
        $contentTypeService = $repository->getContentTypeService();
597
        $contentService = $repository->getContentService();
598
        $contentTypeService->createContentTypeDraft($contentType);
599
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
600
601
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
602
        $createStruct->alwaysAvailable = false;
603
        $createStruct->mainLanguageCode = 'eng-GB';
604
        $createStruct->setField(
605
            'maplocation',
606
            array(
607
                'latitude' => 45.894877,
608
                'longitude' => 15.972699,
609
                'address' => 'Here be wild boars',
610
            ),
611
            'eng-GB'
612
        );
613
614
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
615
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
616
617
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
618
        $createStruct->alwaysAvailable = false;
619
        $createStruct->mainLanguageCode = 'eng-GB';
620
        $createStruct->setField(
621
            'maplocation',
622
            array(
623
                'latitude' => 45.927334,
624
                'longitude' => 15.934847,
625
                'address' => 'A lone tree',
626
            ),
627
            'eng-GB'
628
        );
629
630
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
631
        $tree = $contentService->publishVersion($draft->getVersionInfo());
632
633
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
634
        $createStruct->alwaysAvailable = false;
635
        $createStruct->mainLanguageCode = 'eng-GB';
636
        $createStruct->setField(
637
            'maplocation',
638
            array(
639
                'latitude' => 45.903777,
640
                'longitude' => 15.958788,
641
                'address' => 'Meadow with mushrooms',
642
            ),
643
            'eng-GB'
644
        );
645
646
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
647
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
648
649
        $this->refreshSearch($repository);
650
651
        $wellInVodice = array(
652
            'latitude' => 43.756825,
653
            'longitude' => 15.775074,
654
        );
655
656
        $query = new LocationQuery(
657
            array(
658
                'filter' => new Criterion\LogicalAnd(
659
                    array(
660
                        new Criterion\ContentTypeId($contentType->id),
661
                        new Criterion\MapLocationDistance(
662
                            'maplocation',
663
                            Criterion\Operator::GTE,
664
                            235,
665
                            $wellInVodice['latitude'],
666
                            $wellInVodice['longitude']
667
                        ),
668
                    )
669
                ),
670
                'offset' => 0,
671
                'limit' => 10,
672
                'sortClauses' => array(
673
                    new SortClause\MapLocationDistance(
674
                        'testtype',
675
                        'maplocation',
676
                        $wellInVodice['latitude'],
677
                        $wellInVodice['longitude'],
678
                        LocationQuery::SORT_ASC
679
                    ),
680
                ),
681
            )
682
        );
683
684
        $searchService = $repository->getSearchService();
685
        $result = $searchService->findLocations($query);
686
687
        $this->assertEquals(3, $result->totalCount);
688
        $this->assertEquals(
689
            $wildBoars->contentInfo->mainLocationId,
690
            $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...
691
        );
692
        $this->assertEquals(
693
            $mushrooms->contentInfo->mainLocationId,
694
            $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...
695
        );
696
        $this->assertEquals(
697
            $tree->contentInfo->mainLocationId,
698
            $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...
699
        );
700
    }
701
702
    /**
703
     * Test for the findLocations() method.
704
     *
705
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
706
     * @group maplocation
707
     */
708 View Code Duplication
    public function testMapLocationDistanceSortDescending()
709
    {
710
        $contentType = $this->createTestPlaceContentType();
711
712
        // Create a draft to account for behaviour with ContentType in different states
713
        $repository = $this->getRepository();
714
        $contentTypeService = $repository->getContentTypeService();
715
        $contentService = $repository->getContentService();
716
        $contentTypeService->createContentTypeDraft($contentType);
717
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
718
719
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
720
        $createStruct->alwaysAvailable = false;
721
        $createStruct->mainLanguageCode = 'eng-GB';
722
        $createStruct->setField(
723
            'maplocation',
724
            array(
725
                'latitude' => 45.894877,
726
                'longitude' => 15.972699,
727
                'address' => 'Here be wild boars',
728
            ),
729
            'eng-GB'
730
        );
731
732
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
733
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
734
735
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
736
        $createStruct->alwaysAvailable = false;
737
        $createStruct->mainLanguageCode = 'eng-GB';
738
        $createStruct->setField(
739
            'maplocation',
740
            array(
741
                'latitude' => 45.927334,
742
                'longitude' => 15.934847,
743
                'address' => 'A lone tree',
744
            ),
745
            'eng-GB'
746
        );
747
748
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
749
        $tree = $contentService->publishVersion($draft->getVersionInfo());
750
751
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
752
        $createStruct->alwaysAvailable = false;
753
        $createStruct->mainLanguageCode = 'eng-GB';
754
        $createStruct->setField(
755
            'maplocation',
756
            array(
757
                'latitude' => 45.903777,
758
                'longitude' => 15.958788,
759
                'address' => 'Meadow with mushrooms',
760
            ),
761
            'eng-GB'
762
        );
763
764
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
765
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
766
767
        $this->refreshSearch($repository);
768
769
        $well = array(
770
            'latitude' => 43.756825,
771
            'longitude' => 15.775074,
772
        );
773
774
        $query = new LocationQuery(
775
            array(
776
                'filter' => new Criterion\LogicalAnd(
777
                    array(
778
                        new Criterion\ContentTypeId($contentType->id),
779
                        new Criterion\MapLocationDistance(
780
                            'maplocation',
781
                            Criterion\Operator::GTE,
782
                            235,
783
                            $well['latitude'],
784
                            $well['longitude']
785
                        ),
786
                    )
787
                ),
788
                'offset' => 0,
789
                'limit' => 10,
790
                'sortClauses' => array(
791
                    new SortClause\MapLocationDistance(
792
                        'testtype',
793
                        'maplocation',
794
                        $well['latitude'],
795
                        $well['longitude'],
796
                        LocationQuery::SORT_DESC
797
                    ),
798
                ),
799
            )
800
        );
801
802
        $searchService = $repository->getSearchService();
803
        $result = $searchService->findLocations($query);
804
805
        $this->assertEquals(3, $result->totalCount);
806
        $this->assertEquals(
807
            $wildBoars->contentInfo->mainLocationId,
808
            $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...
809
        );
810
        $this->assertEquals(
811
            $mushrooms->contentInfo->mainLocationId,
812
            $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...
813
        );
814
        $this->assertEquals(
815
            $tree->contentInfo->mainLocationId,
816
            $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...
817
        );
818
    }
819
820
    /**
821
     * Test for the findLocations() method.
822
     *
823
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
824
     * @group maplocation
825
     */
826
    public function testMapLocationDistanceWithCustomField()
827
    {
828
        $contentType = $this->createTestPlaceContentType();
829
830
        // Create a draft to account for behaviour with ContentType in different states
831
        $repository = $this->getRepository();
832
        $contentTypeService = $repository->getContentTypeService();
833
        $contentService = $repository->getContentService();
834
        $contentTypeService->createContentTypeDraft($contentType);
835
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
836
837
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
838
        $createStruct->alwaysAvailable = false;
839
        $createStruct->mainLanguageCode = 'eng-GB';
840
        $createStruct->setField(
841
            'maplocation',
842
            array(
843
                'latitude' => 45.894877,
844
                'longitude' => 15.972699,
845
                'address' => 'Here be wild boars',
846
            ),
847
            'eng-GB'
848
        );
849
850
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
851
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
852
853
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
854
        $createStruct->alwaysAvailable = false;
855
        $createStruct->mainLanguageCode = 'eng-GB';
856
        $createStruct->setField(
857
            'maplocation',
858
            array(
859
                'latitude' => 45.927334,
860
                'longitude' => 15.934847,
861
                'address' => 'A lone tree',
862
            ),
863
            'eng-GB'
864
        );
865
866
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
867
        $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...
868
869
        $this->refreshSearch($repository);
870
871
        $distanceCriterion = new Criterion\MapLocationDistance(
872
            'maplocation',
873
            Criterion\Operator::LTE,
874
            240,
875
            43.756825,
876
            15.775074
877
        );
878
        $distanceCriterion->setCustomField('testtype', 'maplocation', 'custom_geolocation_field');
879
880
        $query = new LocationQuery(
881
            array(
882
                'filter' => new Criterion\LogicalAnd(
883
                    array(
884
                        new Criterion\ContentTypeId($contentType->id),
885
                        $distanceCriterion,
886
                    )
887
                ),
888
                'offset' => 0,
889
                'limit' => 10,
890
                'sortClauses' => array(),
891
            )
892
        );
893
894
        $searchService = $repository->getSearchService();
895
        $result = $searchService->findLocations($query);
896
897
        $this->assertEquals(1, $result->totalCount);
898
        $this->assertEquals(
899
            $wildBoars->contentInfo->mainLocationId,
900
            $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...
901
        );
902
    }
903
904
    /**
905
     * Test for the findLocations() method.
906
     *
907
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
908
     * @group maplocation
909
     */
910
    public function testMapLocationDistanceWithCustomFieldSort()
911
    {
912
        $contentType = $this->createTestPlaceContentType();
913
914
        // Create a draft to account for behaviour with ContentType in different states
915
        $repository = $this->getRepository();
916
        $contentTypeService = $repository->getContentTypeService();
917
        $contentService = $repository->getContentService();
918
        $contentTypeService->createContentTypeDraft($contentType);
919
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
920
921
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
922
        $createStruct->alwaysAvailable = false;
923
        $createStruct->mainLanguageCode = 'eng-GB';
924
        $createStruct->setField(
925
            'maplocation',
926
            array(
927
                'latitude' => 45.894877,
928
                'longitude' => 15.972699,
929
                'address' => 'Here be wild boars',
930
            ),
931
            'eng-GB'
932
        );
933
934
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
935
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
936
937
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
938
        $createStruct->alwaysAvailable = false;
939
        $createStruct->mainLanguageCode = 'eng-GB';
940
        $createStruct->setField(
941
            'maplocation',
942
            array(
943
                'latitude' => 45.927334,
944
                'longitude' => 15.934847,
945
                'address' => 'A lone tree',
946
            ),
947
            'eng-GB'
948
        );
949
950
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
951
        $tree = $contentService->publishVersion($draft->getVersionInfo());
952
953
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
954
        $createStruct->alwaysAvailable = false;
955
        $createStruct->mainLanguageCode = 'eng-GB';
956
        $createStruct->setField(
957
            'maplocation',
958
            array(
959
                'latitude' => 45.903777,
960
                'longitude' => 15.958788,
961
                'address' => 'Meadow with mushrooms',
962
            ),
963
            'eng-GB'
964
        );
965
966
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
967
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
968
969
        $this->refreshSearch($repository);
970
971
        $well = array(
972
            'latitude' => 43.756825,
973
            'longitude' => 15.775074,
974
        );
975
976
        $sortClause = new SortClause\MapLocationDistance(
977
            'testtype',
978
            'maplocation',
979
            $well['latitude'],
980
            $well['longitude'],
981
            LocationQuery::SORT_DESC
982
        );
983
        $sortClause->setCustomField('testtype', 'maplocation', 'custom_geolocation_field');
984
985
        $query = new LocationQuery(
986
            array(
987
                'filter' => new Criterion\LogicalAnd(
988
                    array(
989
                        new Criterion\ContentTypeId($contentType->id),
990
                        new Criterion\MapLocationDistance(
991
                            'maplocation',
992
                            Criterion\Operator::GTE,
993
                            235,
994
                            $well['latitude'],
995
                            $well['longitude']
996
                        ),
997
                    )
998
                ),
999
                'offset' => 0,
1000
                'limit' => 10,
1001
                'sortClauses' => array(
1002
                    $sortClause,
1003
                ),
1004
            )
1005
        );
1006
1007
        $searchService = $repository->getSearchService();
1008
        $result = $searchService->findLocations($query);
1009
1010
        $this->assertEquals(3, $result->totalCount);
1011
        $this->assertEquals(
1012
            $wildBoars->contentInfo->mainLocationId,
1013
            $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...
1014
        );
1015
        $this->assertEquals(
1016
            $mushrooms->contentInfo->mainLocationId,
1017
            $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...
1018
        );
1019
        $this->assertEquals(
1020
            $tree->contentInfo->mainLocationId,
1021
            $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...
1022
        );
1023
    }
1024
1025
    /**
1026
     * Assert that query result matches the given fixture.
1027
     *
1028
     * @param LocationQuery $query
1029
     * @param string $fixture
1030
     * @param null|callable $closure
1031
     */
1032
    protected function assertQueryFixture(LocationQuery $query, $fixture, $closure = null, $ignoreScore = true)
1033
    {
1034
        $repository = $this->getRepository();
1035
        $searchService = $repository->getSearchService();
1036
1037
        try {
1038
            $result = $searchService->findLocations($query);
1039
            $this->simplifySearchResult($result);
1040
        } catch (NotImplementedException $e) {
1041
            $this->markTestSkipped(
1042
                'This feature is not supported by the current search backend: ' . $e->getMessage()
1043
            );
1044
        }
1045
1046 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...
1047
            if (isset($_ENV['ez_tests_record'])) {
1048
                file_put_contents(
1049
                    $record = $fixture . '.recording',
1050
                    "<?php\n\nreturn " . var_export($result, true) . ";\n\n"
1051
                );
1052
                $this->markTestIncomplete("No fixture available. Result recorded at $record. Result: \n" . $this->printResult($result));
1053
            } else {
1054
                $this->markTestIncomplete("No fixture available. Set \$_ENV['ez_tests_record'] to generate it.");
1055
            }
1056
        }
1057
1058
        $fixture = include $fixture;
1059
1060
        if ($closure !== null) {
1061
            $closure($result);
1062
        }
1063
1064 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...
1065
            foreach (array($fixture, $result) as $result) {
1066
                $property = new \ReflectionProperty(get_class($result), 'maxScore');
1067
                $property->setAccessible(true);
1068
                $property->setValue($result, 0.0);
1069
1070
                foreach ($result->searchHits as $hit) {
1071
                    $property = new \ReflectionProperty(get_class($hit), 'score');
1072
                    $property->setAccessible(true);
1073
                    $property->setValue($hit, 0.0);
1074
                }
1075
            }
1076
        }
1077
1078
        foreach ($result->searchHits as $hit) {
1079
            $property = new \ReflectionProperty(get_class($hit), 'index');
1080
            $property->setAccessible(true);
1081
            $property->setValue($hit, null);
1082
1083
            $property = new \ReflectionProperty(get_class($hit), 'matchedTranslation');
1084
            $property->setAccessible(true);
1085
            $property->setValue($hit, null);
1086
        }
1087
1088
        $this->assertEquals(
1089
            $fixture,
1090
            $result,
1091
            'Search results do not match.',
1092
            .2 // Be quite generous regarding delay -- most important for scores
1093
        );
1094
    }
1095
1096
    /**
1097
     * Show a simplified view of the search result for manual introspection.
1098
     *
1099
     * @param SearchResult $result
1100
     *
1101
     * @return string
1102
     */
1103 View Code Duplication
    protected function printResult(SearchResult $result)
1104
    {
1105
        $printed = '';
1106
        foreach ($result->searchHits as $hit) {
1107
            $printed .= sprintf(" - %s (%s)\n", $hit->valueObject['title'], $hit->valueObject['id']);
1108
        }
1109
1110
        return $printed;
1111
    }
1112
1113
    /**
1114
     * Simplify search result.
1115
     *
1116
     * This leads to saner comparisons of results, since we do not get the full
1117
     * content objects every time.
1118
     *
1119
     * @param SearchResult $result
1120
     */
1121
    protected function simplifySearchResult(SearchResult $result)
1122
    {
1123
        $result->time = 1;
1124
1125
        foreach ($result->searchHits as $hit) {
1126
            switch (true) {
1127 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...
1128
                    $hit->valueObject = array(
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...
1129
                        'id' => $hit->valueObject->contentInfo->id,
1130
                        'title' => $hit->valueObject->contentInfo->name,
1131
                    );
1132
                    break;
1133
1134
                default:
1135
                    throw new \RuntimeException('Unknown search result hit type: ' . get_class($hit->valueObject));
1136
            }
1137
        }
1138
    }
1139
1140
    /**
1141
     * Get fixture directory.
1142
     *
1143
     * @return string
1144
     */
1145
    protected function getFixtureDir()
1146
    {
1147
        return __DIR__ . '/_fixtures/' . getenv('fixtureDir') . '/';
1148
    }
1149
}
1150