Completed
Push — ezp24624-query_controller_take... ( f346e1...647162 )
by
unknown
23:39
created

SearchServiceTest   F

Complexity

Total Complexity 143

Size/Duplication

Total Lines 4438
Duplicated Lines 21.36 %

Coupling/Cohesion

Components 1
Dependencies 69

Importance

Changes 0
Metric Value
dl 948
loc 4438
rs 0.5217
c 0
b 0
f 0
wmc 143
lcom 1
cbo 69

83 Methods

Rating   Name   Duplication   Size   Complexity  
B getFilterContentSearches() 0 530 5
A getContentQuerySearches() 0 74 1
A getLocationQuerySearches() 0 69 1
A testFindContentFiltered() 0 5 1
A testFindContentInfoFiltered() 0 5 1
A testFindLocationsContentFiltered() 0 5 1
A testDeprecatedCriteriaProperty() 0 14 1
A testQueryContent() 0 5 1
A testQueryContentInfo() 0 5 1
A testQueryContentLocations() 0 5 1
A testQueryLocations() 0 5 1
B getCaseInsensitiveSearches() 0 35 1
A testFindContentFieldFiltersCaseSensitivity() 0 8 1
A testFindLocationsFieldFiltersCaseSensitivity() 0 8 1
A testFindSingle() 16 16 1
B testFindNoPerformCount() 25 25 2
A testFindNoPerformCountException() 18 18 2
B testFindLocationsNoPerformCount() 25 25 2
A testFindLocationsNoPerformCountException() 18 18 2
B createMultipleCountriesContent() 0 43 1
B testFieldCollectionContains() 24 24 1
A testFieldCollectionContainsNoMatch() 19 19 1
A testInvalidFieldIdentifierRange() 18 18 1
A testInvalidFieldIdentifierIn() 18 18 1
A testFindContentWithNonSearchableField() 18 18 1
A testSortFieldWithNonSearchableField() 13 13 1
A testSortMapLocationDistanceWithNonSearchableField() 20 20 1
A testFindSingleFailMultiple() 11 11 1
A testFindSingleWithNonSearchableField() 0 13 1
B getSortedContentSearches() 0 147 2
B createMultilingualContent() 0 30 3
A checkPrioritizedLanguagesSupport() 0 7 2
B providerForTestMultilingualFieldSort() 0 305 1
A testMultilingualFieldSortContent() 0 13 1
A testMultilingualFieldSortLocation() 0 14 1
B assertMultilingualFieldSort() 19 71 4
B providerForTestMultilingualFieldFilter() 0 158 1
A testMultilingualFieldFilterContent() 0 13 1
A testMultilingualFieldFilterLocation() 0 14 1
B assertMultilingualFieldFilter() 19 76 4
A mapResultContentIds() 0 13 2
A testFindAndSortContent() 0 5 1
A testFindAndSortContentInfo() 0 5 1
A testFindAndSortContentLocations() 0 5 1
A testFindAndSortLocations() 0 5 1
A testFindFacettedContent() 0 4 1
A testFindFacettedContentInfo() 0 4 1
A testQueryCustomField() 19 19 1
B testQueryModifiedField() 29 29 2
B testSortModifiedField() 0 30 2
B createTestPlaceContentType() 27 27 1
A testMapLocationDistanceLessThanOrEqual() 73 73 1
A testMapLocationDistanceGreaterThanOrEqual() 73 73 1
B testMapLocationDistanceBetween() 0 89 1
A testMapLocationDistanceBetweenPolar() 0 57 1
B testMapLocationDistanceSortAscending() 110 110 1
B testMapLocationDistanceSortDescending() 110 110 1
B testMapLocationDistanceWithCustomField() 0 81 2
B testMapLocationDistanceWithCustomFieldSort() 0 118 2
B testFindMainLocation() 39 39 1
B testFindNonMainLocation() 38 38 1
B testSortMainLocationAscending() 37 37 1
B testSortMainLocationDescending() 37 37 1
B testContentWithMultipleLocations() 0 45 1
A createContentForTestUserMetadataGroupHorizontal() 0 52 1
B testUserMetadataGroupHorizontalFilterContent() 0 73 6
A testUserMetadataGroupHorizontalQueryContent() 0 4 1
B testUserMetadataGroupHorizontalFilterLocation() 0 83 6
A testUserMetadataGroupHorizontalQueryLocation() 0 4 1
A testLanguageAnalysisSeparateContent() 0 61 2
A printResult() 9 9 2
B simplifySearchResult() 6 26 5
A getFixtureDir() 0 4 1
A getContentInfoFixtureClosure() 0 15 4
A getRelationFieldFilterContentSearches() 0 73 1
A testRelationContentCreation() 0 20 1
A testFindRelationFieldContentInfoFiltered() 0 6 1
A getSortedLocationSearches() 0 72 2
B createTestContentType() 36 36 1
B getFacettedSearches() 0 237 1
A testLanguageAnalysisSameContent() 0 47 2
A testLanguageAnalysisSameContentNotFound() 0 48 2
F assertQueryFixture() 24 90 16

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like SearchServiceTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SearchServiceTest, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * File containing the SearchServiceTest 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
 * @version //autogentag//
10
 */
11
namespace eZ\Publish\API\Repository\Tests;
12
13
use eZ\Publish\API\Repository\Tests\SetupFactory\LegacyElasticsearch;
14
use EzSystems\EzPlatformSolrSearchEngine\Tests\SetupFactory\LegacySetupFactory as LegacySolrSetupFactory;
15
use eZ\Publish\API\Repository\Values\Content\Content;
16
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
17
use eZ\Publish\API\Repository\Values\Content\Query;
18
use eZ\Publish\API\Repository\Values\Content\Location;
19
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
20
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
21
use eZ\Publish\API\Repository\Values\Content\Query\SortClause;
22
use eZ\Publish\API\Repository\Values\Content\Query\FacetBuilder;
23
use eZ\Publish\API\Repository\Values\Content\Search\SearchResult;
24
use eZ\Publish\API\Repository\Values\Content\Search\SearchHit;
25
use eZ\Publish\API\Repository\Exceptions\NotImplementedException;
26
27
/**
28
 * Test case for operations in the SearchService using in memory storage.
29
 *
30
 * @see eZ\Publish\API\Repository\SearchService
31
 * @group integration
32
 * @group search
33
 */
34
class SearchServiceTest extends BaseTest
35
{
36
    public function getFilterContentSearches()
37
    {
38
        $fixtureDir = $this->getFixtureDir();
39
40
        return array(
41
            0 => array(
42
                array(
43
                    'filter' => new Criterion\ContentId(
44
                        array(1, 4, 10)
45
                    ),
46
                    'sortClauses' => array(new SortClause\ContentId()),
47
                ),
48
                $fixtureDir . 'ContentId.php',
49
            ),
50
            1 => array(
51
                array(
52
                    'filter' => new Criterion\LogicalAnd(
53
                        array(
54
                            new Criterion\ContentId(
55
                                array(1, 4, 10)
56
                            ),
57
                            new Criterion\ContentId(
58
                                array(4, 12)
59
                            ),
60
                        )
61
                    ),
62
                    'sortClauses' => array(new SortClause\ContentId()),
63
                ),
64
                $fixtureDir . 'LogicalAnd.php',
65
            ),
66
            2 => array(
67
                array(
68
                    'filter' => new Criterion\LogicalOr(
69
                        array(
70
                            new Criterion\ContentId(
71
                                array(1, 4, 10)
72
                            ),
73
                            new Criterion\ContentId(
74
                                array(4, 12)
75
                            ),
76
                        )
77
                    ),
78
                    'sortClauses' => array(new SortClause\ContentId()),
79
                ),
80
                $fixtureDir . 'LogicalOr.php',
81
            ),
82
            3 => array(
83
                array(
84
                    'filter' => new Criterion\LogicalAnd(
85
                        array(
86
                            new Criterion\ContentId(
87
                                array(1, 4, 10)
88
                            ),
89
                            new Criterion\LogicalNot(
90
                                new Criterion\ContentId(
91
                                    array(10, 12)
92
                                )
93
                            ),
94
                        )
95
                    ),
96
                    'sortClauses' => array(new SortClause\ContentId()),
97
                ),
98
                $fixtureDir . 'LogicalNot.php',
99
            ),
100
            4 => array(
101
                array(
102
                    'filter' => new Criterion\LogicalAnd(
103
                        array(
104
                            new Criterion\ContentId(
105
                                array(1, 4, 10)
106
                            ),
107
                            new Criterion\LogicalAnd(
108
                                array(
109
                                    new Criterion\LogicalNot(
110
                                        new Criterion\ContentId(
111
                                            array(10, 12)
112
                                        )
113
                                    ),
114
                                )
115
                            ),
116
                        )
117
                    ),
118
                    'sortClauses' => array(new SortClause\ContentId()),
119
                ),
120
                $fixtureDir . 'LogicalNot.php',
121
            ),
122
            5 => array(
123
                array(
124
                    'filter' => new Criterion\ContentTypeId(
125
                        4
126
                    ),
127
                    'sortClauses' => array(new SortClause\ContentId()),
128
                ),
129
                $fixtureDir . 'ContentTypeId.php',
130
            ),
131
            6 => array(
132
                array(
133
                    'filter' => new Criterion\ContentTypeIdentifier(
134
                        'user'
135
                    ),
136
                    'sortClauses' => array(new SortClause\ContentId()),
137
                ),
138
                $fixtureDir . 'ContentTypeId.php',
139
            ),
140
            7 => array(
141
                array(
142
                    'filter' => new Criterion\MatchNone(),
143
                    'sortClauses' => array(new SortClause\ContentId()),
144
                ),
145
                $fixtureDir . 'MatchNone.php',
146
            ),
147
            8 => array(
148
                array(
149
                    'filter' => new Criterion\ContentTypeGroupId(
150
                        2
151
                    ),
152
                    'sortClauses' => array(new SortClause\ContentId()),
153
                ),
154
                $fixtureDir . 'ContentTypeGroupId.php',
155
            ),
156
            9 => array(
157
                array(
158
                    'filter' => new Criterion\DateMetadata(
159
                        Criterion\DateMetadata::MODIFIED,
160
                        Criterion\Operator::GT,
161
                        1343140540
162
                    ),
163
                    'sortClauses' => array(new SortClause\ContentId()),
164
                ),
165
                $fixtureDir . 'DateMetadataGt.php',
166
            ),
167
            10 => array(
168
                array(
169
                    'filter' => new Criterion\DateMetadata(
170
                        Criterion\DateMetadata::MODIFIED,
171
                        Criterion\Operator::GTE,
172
                        1311154215
173
                    ),
174
                    'sortClauses' => array(new SortClause\ContentId()),
175
                ),
176
                $fixtureDir . 'DateMetadataGte.php',
177
            ),
178
            11 => array(
179
                array(
180
                    'filter' => new Criterion\DateMetadata(
181
                        Criterion\DateMetadata::MODIFIED,
182
                        Criterion\Operator::LTE,
183
                        1311154215
184
                    ),
185
                    'limit' => 10,
186
                    'sortClauses' => array(new SortClause\ContentId()),
187
                ),
188
                $fixtureDir . 'DateMetadataLte.php',
189
            ),
190
            12 => array(
191
                array(
192
                    'filter' => new Criterion\DateMetadata(
193
                        Criterion\DateMetadata::MODIFIED,
194
                        Criterion\Operator::IN,
195
                        array(1033920794, 1060695457, 1343140540)
196
                    ),
197
                    'sortClauses' => array(new SortClause\ContentId()),
198
                ),
199
                $fixtureDir . 'DateMetadataIn.php',
200
            ),
201
            13 => array(
202
                array(
203
                    'filter' => new Criterion\DateMetadata(
204
                        Criterion\DateMetadata::MODIFIED,
205
                        Criterion\Operator::BETWEEN,
206
                        array(1033920776, 1072180276)
207
                    ),
208
                    'sortClauses' => array(new SortClause\ContentId()),
209
                ),
210
                $fixtureDir . 'DateMetadataBetween.php',
211
            ),
212
            14 => array(
213
                array(
214
                    'filter' => new Criterion\DateMetadata(
215
                        Criterion\DateMetadata::CREATED,
216
                        Criterion\Operator::BETWEEN,
217
                        array(1033920776, 1072180278)
218
                    ),
219
                    'sortClauses' => array(new SortClause\ContentId()),
220
                ),
221
                $fixtureDir . 'DateMetadataCreated.php',
222
            ),
223
            15 => array(
224
                array(
225
                    'filter' => new Criterion\CustomField(
226
                        'user_group_name_value_s',
227
                        Criterion\Operator::EQ,
228
                        'Members'
229
                    ),
230
                    'sortClauses' => array(new SortClause\ContentId()),
231
                ),
232
                $fixtureDir . 'Field.php',
233
            ),
234
            16 => array(
235
                array(
236
                    'filter' => new Criterion\CustomField(
237
                        'user_group_name_value_s',
238
                        Criterion\Operator::CONTAINS,
239
                        'Members'
240
                    ),
241
                    'sortClauses' => array(new SortClause\ContentId()),
242
                ),
243
                $fixtureDir . 'Field.php',
244
            ),
245
            17 => array(
246
                array(
247
                    'filter' => new Criterion\CustomField(
248
                        'user_group_name_value_s',
249
                        Criterion\Operator::LT,
250
                        'Members'
251
                    ),
252
                    'sortClauses' => array(new SortClause\ContentId()),
253
                ),
254
                $fixtureDir . 'CustomFieldLt.php',
255
            ),
256
            18 => array(
257
                array(
258
                    'filter' => new Criterion\CustomField(
259
                        'user_group_name_value_s',
260
                        Criterion\Operator::LTE,
261
                        'Members'
262
                    ),
263
                    'sortClauses' => array(new SortClause\ContentId()),
264
                ),
265
                $fixtureDir . 'CustomFieldLte.php',
266
            ),
267
            19 => array(
268
                array(
269
                    'filter' => new Criterion\CustomField(
270
                        'user_group_name_value_s',
271
                        Criterion\Operator::GT,
272
                        'Members'
273
                    ),
274
                    'sortClauses' => array(new SortClause\ContentId()),
275
                ),
276
                $fixtureDir . 'CustomFieldGt.php',
277
            ),
278
            20 => array(
279
                array(
280
                    'filter' => new Criterion\CustomField(
281
                        'user_group_name_value_s',
282
                        Criterion\Operator::GTE,
283
                        'Members'
284
                    ),
285
                    'sortClauses' => array(new SortClause\ContentId()),
286
                ),
287
                $fixtureDir . 'CustomFieldGte.php',
288
            ),
289
            21 => array(
290
                array(
291
                    'filter' => new Criterion\CustomField(
292
                        'user_group_name_value_s',
293
                        Criterion\Operator::BETWEEN,
294
                        array('Administrator users', 'Members')
295
                    ),
296
                    'sortClauses' => array(new SortClause\ContentId()),
297
                ),
298
                $fixtureDir . 'CustomFieldBetween.php',
299
            ),
300
            22 => array(
301
                array(
302
                    'filter' => new Criterion\RemoteId(
303
                        array('f5c88a2209584891056f987fd965b0ba', 'faaeb9be3bd98ed09f606fc16d144eca')
304
                    ),
305
                    'sortClauses' => array(new SortClause\ContentId()),
306
                ),
307
                $fixtureDir . 'RemoteId.php',
308
            ),
309
            23 => array(
310
                array(
311
                    'filter' => new Criterion\SectionId(
312
                        array(2)
313
                    ),
314
                    'sortClauses' => array(new SortClause\ContentId()),
315
                ),
316
                $fixtureDir . 'SectionId.php',
317
            ),
318
            24 => array(
319
                array(
320
                    'filter' => new Criterion\Field(
321
                        'name',
322
                        Criterion\Operator::EQ,
323
                        'Members'
324
                    ),
325
                    'sortClauses' => array(new SortClause\ContentId()),
326
                ),
327
                $fixtureDir . 'Field.php',
328
            ),
329
            25 => array(
330
                array(
331
                    'filter' => new Criterion\Field(
332
                        'name',
333
                        Criterion\Operator::IN,
334
                        array('Members', 'Anonymous Users')
335
                    ),
336
                    'sortClauses' => array(new SortClause\ContentId()),
337
                ),
338
                $fixtureDir . 'FieldIn.php',
339
            ),
340
            26 => array(
341
                array(
342
                    'filter' => new Criterion\DateMetadata(
343
                        Criterion\DateMetadata::MODIFIED,
344
                        Criterion\Operator::BETWEEN,
345
                        array(1033920275, 1033920794)
346
                    ),
347
                    'sortClauses' => array(new SortClause\ContentId()),
348
                ),
349
                $fixtureDir . 'FieldBetween.php',
350
            ),
351
            27 => array(
352
                array(
353
                    'filter' => new Criterion\LogicalOr(
354
                        array(
355
                            new Criterion\Field(
356
                                'name',
357
                                Criterion\Operator::EQ,
358
                                'Members'
359
                            ),
360
                            new Criterion\DateMetadata(
361
                                Criterion\DateMetadata::MODIFIED,
362
                                Criterion\Operator::BETWEEN,
363
                                array(1033920275, 1033920794)
364
                            ),
365
                        )
366
                    ),
367
                    'sortClauses' => array(new SortClause\ContentId()),
368
                ),
369
                $fixtureDir . 'FieldOr.php',
370
            ),
371
            28 => array(
372
                array(
373
                    'filter' => new Criterion\Subtree(
374
                        '/1/5/'
375
                    ),
376
                    'sortClauses' => array(new SortClause\ContentId()),
377
                ),
378
                $fixtureDir . 'Subtree.php',
379
            ),
380
            29 => array(
381
                array(
382
                    'filter' => new Criterion\LocationId(
383
                        array(1, 2, 5)
384
                    ),
385
                    'sortClauses' => array(new SortClause\ContentId()),
386
                ),
387
                $fixtureDir . 'LocationId.php',
388
            ),
389
            30 => array(
390
                array(
391
                    'filter' => new Criterion\ParentLocationId(
392
                        array(1)
393
                    ),
394
                    'sortClauses' => array(new SortClause\ContentId()),
395
                ),
396
                $fixtureDir . 'ParentLocationId.php',
397
            ),
398
            31 => array(
399
                array(
400
                    'filter' => new Criterion\LocationRemoteId(
401
                        array('3f6d92f8044aed134f32153517850f5a', 'f3e90596361e31d496d4026eb624c983')
402
                    ),
403
                    'sortClauses' => array(new SortClause\ContentId()),
404
                ),
405
                $fixtureDir . 'LocationRemoteId.php',
406
            ),
407
            32 => array(
408
                array(
409
                    // There is no Status Criterion anymore, this should match all published as well
410
                    'filter' => new Criterion\Subtree(
411
                        '/1/'
412
                    ),
413
                    'sortClauses' => array(new SortClause\ContentId()),
414
                    'limit' => 50,
415
                ),
416
                $fixtureDir . 'Status.php',
417
                // Result having the same sort level should be sorted between them to be system independent
418
                function (&$data) {
419
                    usort(
420
                        $data->searchHits,
421
                        function ($a, $b) {
422
                            if ($a->score == $b->score) {
423
                                if ($a->valueObject['id'] == $b->valueObject['id']) {
424
                                    return 0;
425
                                }
426
427
                                // Order by ascending ID
428
                                return ($a->valueObject['id'] < $b->valueObject['id']) ? -1 : 1;
429
                            }
430
431
                            // Order by descending score
432
                            return ($a->score > $b->score) ? -1 : 1;
433
                        }
434
                    );
435
                },
436
            ),
437
            33 => array(
438
                array(
439
                    'filter' => new Criterion\UserMetadata(
440
                        Criterion\UserMetadata::MODIFIER,
441
                        Criterion\Operator::EQ,
442
                        14
443
                    ),
444
                    'sortClauses' => array(
445
                        new SortClause\ContentId(),
446
                    ),
447
                    'limit' => 50,
448
                ),
449
                $fixtureDir . 'UserMetadata.php',
450
            ),
451
            34 => array(
452
                array(
453
                    'filter' => new Criterion\UserMetadata(
454
                        Criterion\UserMetadata::MODIFIER,
455
                        Criterion\Operator::IN,
456
                        array(14)
457
                    ),
458
                    'sortClauses' => array(
459
                        new SortClause\ContentId(),
460
                    ),
461
                    'limit' => 50,
462
                ),
463
                $fixtureDir . 'UserMetadata.php',
464
            ),
465
            35 => array(
466
                array(
467
                    'filter' => new Criterion\UserMetadata(
468
                        Criterion\UserMetadata::OWNER,
469
                        Criterion\Operator::EQ,
470
                        14
471
                    ),
472
                    'sortClauses' => array(
473
                        new SortClause\ContentId(),
474
                    ),
475
                    'limit' => 50,
476
                ),
477
                $fixtureDir . 'UserMetadata.php',
478
            ),
479
            36 => array(
480
                array(
481
                    'filter' => new Criterion\UserMetadata(
482
                        Criterion\UserMetadata::OWNER,
483
                        Criterion\Operator::IN,
484
                        array(14)
485
                    ),
486
                    'sortClauses' => array(
487
                        new SortClause\ContentId(),
488
                    ),
489
                    'limit' => 50,
490
                ),
491
                $fixtureDir . 'UserMetadata.php',
492
            ),
493
            37 => array(
494
                array(
495
                    'filter' => new Criterion\UserMetadata(
496
                        Criterion\UserMetadata::GROUP,
497
                        Criterion\Operator::EQ,
498
                        12
499
                    ),
500
                    'sortClauses' => array(
501
                        new SortClause\ContentId(),
502
                    ),
503
                    'limit' => 50,
504
                ),
505
                $fixtureDir . 'UserMetadata.php',
506
            ),
507
            38 => array(
508
                array(
509
                    'filter' => new Criterion\UserMetadata(
510
                        Criterion\UserMetadata::GROUP,
511
                        Criterion\Operator::IN,
512
                        array(12)
513
                    ),
514
                    'sortClauses' => array(
515
                        new SortClause\ContentId(),
516
                    ),
517
                    'limit' => 50,
518
                ),
519
                $fixtureDir . 'UserMetadata.php',
520
            ),
521
            39 => array(
522
                array(
523
                    'filter' => new Criterion\UserMetadata(
524
                        Criterion\UserMetadata::GROUP,
525
                        Criterion\Operator::EQ,
526
                        4
527
                    ),
528
                    'sortClauses' => array(
529
                        new SortClause\ContentId(),
530
                    ),
531
                    'limit' => 50,
532
                ),
533
                $fixtureDir . 'UserMetadata.php',
534
            ),
535
            40 => array(
536
                array(
537
                    'filter' => new Criterion\UserMetadata(
538
                        Criterion\UserMetadata::GROUP,
539
                        Criterion\Operator::IN,
540
                        array(4)
541
                    ),
542
                    'sortClauses' => array(
543
                        new SortClause\ContentId(),
544
                    ),
545
                    'limit' => 50,
546
                ),
547
                $fixtureDir . 'UserMetadata.php',
548
            ),
549
            41 => array(
550
                array(
551
                    'filter' => new Criterion\Ancestor(
552
                        array(
0 ignored issues
show
Documentation introduced by
array('/1/5/44/', '/1/5/44/45/') is of type array<integer,string,{"0":"string","1":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
553
                            '/1/5/44/',
554
                            '/1/5/44/45/',
555
                        )
556
                    ),
557
                    'sortClauses' => array(
558
                        new SortClause\ContentId(),
559
                    ),
560
                    'limit' => 50,
561
                ),
562
                $fixtureDir . 'AncestorContent.php',
563
            ),
564
        );
565
    }
566
567
    public function getContentQuerySearches()
568
    {
569
        $fixtureDir = $this->getFixtureDir();
570
571
        return array(
572
            array(
573
                array(
574
                    'filter' => new Criterion\ContentId(
575
                        array(58, 10)
576
                    ),
577
                    'query' => new Criterion\FullText('contact'),
578
                    'sortClauses' => array(new SortClause\ContentId()),
579
                ),
580
                $fixtureDir . 'FullTextFiltered.php',
581
            ),
582
            array(
583
                array(
584
                    'query' => new Criterion\FullText(
585
                        'contact',
586
                        array(
587
                            'boost' => array(
588
                                'title' => 2,
589
                            ),
590
                            'fuzziness' => .5,
591
                        )
592
                    ),
593
                    'sortClauses' => array(new SortClause\ContentId()),
594
                ),
595
                $fixtureDir . 'FullText.php',
596
            ),
597
            array(
598
                array(
599
                    'query' => new Criterion\FullText(
600
                        'Contact*'
601
                    ),
602
                    'sortClauses' => array(new SortClause\ContentId()),
603
                ),
604
                $fixtureDir . 'FullTextWildcard.php',
605
            ),
606
            array(
607
                array(
608
                    'query' => new Criterion\LanguageCode('eng-GB', false),
609
                    'sortClauses' => array(new SortClause\ContentId()),
610
                ),
611
                $fixtureDir . 'LanguageCode.php',
612
            ),
613
            array(
614
                array(
615
                    'query' => new Criterion\LanguageCode(array('eng-US', 'eng-GB')),
616
                    'offset' => 10,
617
                    'sortClauses' => array(new SortClause\ContentId()),
618
                ),
619
                $fixtureDir . 'LanguageCodeIn.php',
620
            ),
621
            array(
622
                array(
623
                    'query' => new Criterion\LanguageCode('eng-GB'),
624
                    'offset' => 10,
625
                    'sortClauses' => array(new SortClause\ContentId()),
626
                ),
627
                $fixtureDir . 'LanguageCodeAlwaysAvailable.php',
628
            ),
629
            array(
630
                array(
631
                    'query' => new Criterion\Visibility(
632
                        Criterion\Visibility::VISIBLE
633
                    ),
634
                    'sortClauses' => array(new SortClause\ContentId()),
635
                    'limit' => 50,
636
                ),
637
                $fixtureDir . 'Visibility.php',
638
            ),
639
        );
640
    }
641
642
    public function getLocationQuerySearches()
643
    {
644
        $fixtureDir = $this->getFixtureDir();
645
646
        return array(
647
            array(
648
                array(
649
                    'query' => new Criterion\Location\Depth(Criterion\Operator::EQ, 1),
650
                    'sortClauses' => array(new SortClause\ContentId()),
651
                ),
652
                $fixtureDir . 'Depth.php',
653
            ),
654
            array(
655
                array(
656
                    'query' => new Criterion\Location\Depth(Criterion\Operator::IN, array(1, 3)),
657
                    'sortClauses' => array(new SortClause\ContentId()),
658
                ),
659
                $fixtureDir . 'DepthIn.php',
660
            ),
661
            array(
662
                array(
663
                    'query' => new Criterion\Location\Depth(Criterion\Operator::GT, 2),
664
                    'sortClauses' => array(new SortClause\ContentId()),
665
                ),
666
                $fixtureDir . 'DepthGt.php',
667
            ),
668
            array(
669
                array(
670
                    'query' => new Criterion\Location\Depth(Criterion\Operator::GTE, 2),
671
                    'sortClauses' => array(new SortClause\ContentId()),
672
                    'limit' => 50,
673
                ),
674
                $fixtureDir . 'DepthGte.php',
675
            ),
676
            array(
677
                array(
678
                    'query' => new Criterion\Location\Depth(Criterion\Operator::LT, 2),
679
                    'sortClauses' => array(new SortClause\ContentId()),
680
                ),
681
                $fixtureDir . 'Depth.php',
682
            ),
683
            array(
684
                array(
685
                    'query' => new Criterion\Location\Depth(Criterion\Operator::LTE, 2),
686
                    'sortClauses' => array(new SortClause\ContentId()),
687
                    'limit' => 50,
688
                ),
689
                $fixtureDir . 'DepthLte.php',
690
            ),
691
            array(
692
                array(
693
                    'query' => new Criterion\Location\Depth(Criterion\Operator::BETWEEN, array(1, 2)),
694
                    'sortClauses' => array(new SortClause\ContentId()),
695
                    'limit' => 50,
696
                ),
697
                $fixtureDir . 'DepthLte.php',
698
            ),
699
            array(
700
                array(
701
                    'filter' => new Criterion\Ancestor('/1/5/44/45/'),
702
                    'sortClauses' => array(
703
                        new SortClause\Location\Depth(),
704
                    ),
705
                    'limit' => 50,
706
                ),
707
                $fixtureDir . 'AncestorLocation.php',
708
            ),
709
        );
710
    }
711
712
    /**
713
     * Test for the findContent() method.
714
     *
715
     * @dataProvider getFilterContentSearches
716
     *
717
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
718
     */
719
    public function testFindContentFiltered($queryData, $fixture, $closure = null)
720
    {
721
        $query = new Query($queryData);
722
        $this->assertQueryFixture($query, $fixture, $closure);
723
    }
724
725
    /**
726
     * Test for the findContentInfo() method.
727
     *
728
     * @dataProvider getFilterContentSearches
729
     * @see \eZ\Publish\API\Repository\SearchService::findContentInfo()
730
     */
731
    public function testFindContentInfoFiltered($queryData, $fixture, $closure = null)
732
    {
733
        $query = new Query($queryData);
734
        $this->assertQueryFixture($query, $fixture, $this->getContentInfoFixtureClosure($closure), true);
735
    }
736
737
    /**
738
     * Test for the findLocations() method.
739
     *
740
     * @dataProvider getFilterContentSearches
741
     *
742
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
743
     */
744
    public function testFindLocationsContentFiltered($queryData, $fixture, $closure = null)
745
    {
746
        $query = new LocationQuery($queryData);
747
        $this->assertQueryFixture($query, $fixture, $closure);
748
    }
749
750
    /**
751
     * Test for deprecated $criterion property on query object.
752
     *
753
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
754
     * @deprecated
755
     */
756
    public function testDeprecatedCriteriaProperty()
757
    {
758
        $this->assertQueryFixture(
759
            new Query(
760
                array(
761
                    'query' => new Criterion\ContentId(
762
                        array(1, 4, 10)
763
                    ),
764
                    'sortClauses' => array(new SortClause\ContentId()),
765
                )
766
            ),
767
            $this->getFixtureDir() . 'DeprecatedContentIdQuery.php'
768
        );
769
    }
770
771
    /**
772
     * Test for the findContent() method.
773
     *
774
     * @dataProvider getContentQuerySearches
775
     *
776
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
777
     */
778
    public function testQueryContent($queryData, $fixture, $closure = null)
779
    {
780
        $query = new Query($queryData);
781
        $this->assertQueryFixture($query, $fixture, $closure);
782
    }
783
784
    /**
785
     * Test for the findContentInfo() method.
786
     *
787
     * @dataProvider getContentQuerySearches
788
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
789
     */
790
    public function testQueryContentInfo($queryData, $fixture, $closure = null)
791
    {
792
        $query = new Query($queryData);
793
        $this->assertQueryFixture($query, $fixture, $this->getContentInfoFixtureClosure($closure), true);
794
    }
795
796
    /**
797
     * Test for the findLocations() method.
798
     *
799
     * @dataProvider getContentQuerySearches
800
     *
801
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
802
     */
803
    public function testQueryContentLocations($queryData, $fixture, $closure = null)
804
    {
805
        $query = new LocationQuery($queryData);
806
        $this->assertQueryFixture($query, $fixture, $closure);
807
    }
808
809
    /**
810
     * Test for the findLocations() method.
811
     *
812
     * @dataProvider getLocationQuerySearches
813
     *
814
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
815
     */
816
    public function testQueryLocations($queryData, $fixture, $closure = null)
817
    {
818
        $query = new LocationQuery($queryData);
819
        $this->assertQueryFixture($query, $fixture, $closure);
820
    }
821
822
    public function getCaseInsensitiveSearches()
823
    {
824
        return array(
825
            array(
826
                array(
827
                    'filter' => new Criterion\Field(
828
                        'name',
829
                        Criterion\Operator::EQ,
830
                        'Members'
831
                    ),
832
                    'sortClauses' => array(new SortClause\ContentId()),
833
                ),
834
            ),
835
            array(
836
                array(
837
                    'filter' => new Criterion\Field(
838
                        'name',
839
                        Criterion\Operator::EQ,
840
                        'members'
841
                    ),
842
                    'sortClauses' => array(new SortClause\ContentId()),
843
                ),
844
            ),
845
            array(
846
                array(
847
                    'filter' => new Criterion\Field(
848
                        'name',
849
                        Criterion\Operator::EQ,
850
                        'MEMBERS'
851
                    ),
852
                    'sortClauses' => array(new SortClause\ContentId()),
853
                ),
854
            ),
855
        );
856
    }
857
858
    /**
859
     * Test for the findContent() method.
860
     *
861
     * @dataProvider getCaseInsensitiveSearches
862
     *
863
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
864
     */
865
    public function testFindContentFieldFiltersCaseSensitivity($queryData)
866
    {
867
        $query = new Query($queryData);
868
        $this->assertQueryFixture(
869
            $query,
870
            $this->getFixtureDir() . 'Field.php'
871
        );
872
    }
873
874
    /**
875
     * Test for the findLocations() method.
876
     *
877
     * @dataProvider getCaseInsensitiveSearches
878
     *
879
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
880
     */
881
    public function testFindLocationsFieldFiltersCaseSensitivity($queryData)
882
    {
883
        $query = new LocationQuery($queryData);
884
        $this->assertQueryFixture(
885
            $query,
886
            $this->getFixtureDir() . 'Field.php'
887
        );
888
    }
889
890
    public function getRelationFieldFilterContentSearches()
891
    {
892
        $fixtureDir = $this->getFixtureDir();
893
894
        return array(
895
            0 => array(
896
                array(
897
                    'filter' => new Criterion\FieldRelation(
898
                        'image',
899
                        Criterion\Operator::IN,
900
                        array(1, 4, 10)
901
                    ),
902
                    'sortClauses' => array(new SortClause\ContentId()),
903
                ),
904
                $fixtureDir . 'FieldRelation.php',
905
            ),
906
            1 => array(
907
                array(
908
                    'filter' => new Criterion\FieldRelation(
909
                        'image',
910
                        Criterion\Operator::IN,
911
                        array(4, 49)
912
                    ),
913
                    'sortClauses' => array(new SortClause\ContentId()),
914
                ),
915
                $fixtureDir . 'FieldRelationAll.php',
916
            ),
917
            2 => array(
918
                array(
919
                    'filter' => new Criterion\FieldRelation(
920
                        'image',
921
                        Criterion\Operator::IN,
922
                        array(4)
923
                    ),
924
                    'sortClauses' => array(new SortClause\ContentId()),
925
                ),
926
                $fixtureDir . 'FieldRelation.php',
927
            ),
928
            3 => array(
929
                array(
930
                    'filter' => new Criterion\FieldRelation(
931
                        'image',
932
                        Criterion\Operator::CONTAINS,
933
                        array(1, 4, 10)
934
                    ),
935
                    'sortClauses' => array(new SortClause\ContentId()),
936
                ),
937
                $fixtureDir . 'MatchNone.php',
938
            ),
939
            4 => array(
940
                array(
941
                    'filter' => new Criterion\FieldRelation(
942
                        'image',
943
                        Criterion\Operator::CONTAINS,
944
                        array(4, 49)
945
                    ),
946
                    'sortClauses' => array(new SortClause\ContentId()),
947
                ),
948
                $fixtureDir . 'MatchNone.php',
949
            ),
950
            5 => array(
951
                array(
952
                    'filter' => new Criterion\FieldRelation(
953
                        'image',
954
                        Criterion\Operator::CONTAINS,
955
                        array(4)
956
                    ),
957
                    'sortClauses' => array(new SortClause\ContentId()),
958
                ),
959
                $fixtureDir . 'FieldRelation.php',
960
            ),
961
        );
962
    }
963
964
    /**
965
     * Purely for creating relation data needed for testFindRelationFieldContentInfoFiltered().
966
     */
967
    public function testRelationContentCreation()
968
    {
969
        $repository = $this->getRepository();
970
        $galleryType = $repository->getContentTypeService()->loadContentTypeByIdentifier('gallery');
971
        $contentService = $repository->getContentService();
972
973
        $createStruct = $contentService->newContentCreateStruct($galleryType, 'eng-GB');
974
        $createStruct->setField('name', 'Image gallery');
975
        $createStruct->setField('image', 49);// Images folder
976
        $draft = $contentService->createContent($createStruct);
977
        $contentService->publishVersion($draft->getVersionInfo());
978
979
        $createStruct = $contentService->newContentCreateStruct($galleryType, 'eng-GB');
980
        $createStruct->setField('name', 'User gallery');
981
        $createStruct->setField('image', 4);// User folder
982
        $draft = $contentService->createContent($createStruct);
983
        $contentService->publishVersion($draft->getVersionInfo());
984
985
        $this->refreshSearch($repository);
986
    }
987
988
    /**
989
     * Test for FieldRelation using findContentInfo() method.
990
     *
991
     * @dataProvider getRelationFieldFilterContentSearches
992
     * @see \eZ\Publish\API\Repository\SearchService::findContentInfo()
993
     * @depends eZ\Publish\API\Repository\Tests\SearchServiceTest::testRelationContentCreation
994
     */
995
    public function testFindRelationFieldContentInfoFiltered($queryData, $fixture, $closure = null)
996
    {
997
        $this->getRepository(false);// To make sure repo is setup w/o removing data from testRelationContentCreation
998
        $query = new Query($queryData);
999
        $this->assertQueryFixture($query, $fixture, $this->getContentInfoFixtureClosure($closure), true, true, false);
1000
    }
1001
1002 View Code Duplication
    public function testFindSingle()
1003
    {
1004
        $repository = $this->getRepository();
1005
        $searchService = $repository->getSearchService();
1006
1007
        $content = $searchService->findSingle(
1008
            new Criterion\ContentId(
1009
                array(4)
1010
            )
1011
        );
1012
1013
        $this->assertEquals(
1014
            4,
1015
            $content->id
1016
        );
1017
    }
1018
1019 View Code Duplication
    public function testFindNoPerformCount()
1020
    {
1021
        $repository = $this->getRepository();
1022
        $searchService = $repository->getSearchService();
1023
1024
        $query = new Query();
1025
        $query->performCount = false;
1026
        $query->query = new Criterion\ContentTypeId(
1027
            array(4)
1028
        );
1029
1030
        $searchHit = $searchService->findContent($query);
1031
1032
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
1033
            $this->assertEquals(
1034
                null,
1035
                $searchHit->totalCount
1036
            );
1037
        } else {
1038
            $this->assertEquals(
1039
                2,
1040
                $searchHit->totalCount
1041
            );
1042
        }
1043
    }
1044
1045
    /**
1046
     * @expectedException \RuntimeException
1047
     */
1048 View Code Duplication
    public function testFindNoPerformCountException()
1049
    {
1050
        if (ltrim(get_class($this->getSetupFactory()), '\\') !== 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
1051
            $this->markTestSkipped('Only applicable to Legacy/DB based search');
1052
        }
1053
1054
        $repository = $this->getRepository();
1055
        $searchService = $repository->getSearchService();
1056
1057
        $query = new Query();
1058
        $query->performCount = false;
1059
        $query->limit = 0;
1060
        $query->query = new Criterion\ContentTypeId(
1061
            array(4)
1062
        );
1063
1064
        $searchService->findContent($query);
1065
    }
1066
1067 View Code Duplication
    public function testFindLocationsNoPerformCount()
1068
    {
1069
        $repository = $this->getRepository();
1070
        $searchService = $repository->getSearchService();
1071
1072
        $query = new LocationQuery();
1073
        $query->performCount = false;
1074
        $query->query = new Criterion\ContentTypeId(
1075
            array(4)
1076
        );
1077
1078
        $searchHit = $searchService->findLocations($query);
1079
1080
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
1081
            $this->assertEquals(
1082
                null,
1083
                $searchHit->totalCount
1084
            );
1085
        } else {
1086
            $this->assertEquals(
1087
                2,
1088
                $searchHit->totalCount
1089
            );
1090
        }
1091
    }
1092
1093
    /**
1094
     * @expectedException \RuntimeException
1095
     */
1096 View Code Duplication
    public function testFindLocationsNoPerformCountException()
1097
    {
1098
        if (ltrim(get_class($this->getSetupFactory()), '\\') !== 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
1099
            $this->markTestSkipped('Only applicable to Legacy/DB based search');
1100
        }
1101
1102
        $repository = $this->getRepository();
1103
        $searchService = $repository->getSearchService();
1104
1105
        $query = new LocationQuery();
1106
        $query->performCount = false;
1107
        $query->limit = 0;
1108
        $query->query = new Criterion\ContentTypeId(
1109
            array(4)
1110
        );
1111
1112
        $searchService->findLocations($query);
1113
    }
1114
1115
    /**
1116
     * Create test Content with ezcountry field having multiple countries selected.
1117
     *
1118
     * @return Content
1119
     */
1120
    protected function createMultipleCountriesContent()
1121
    {
1122
        $repository = $this->getRepository();
1123
        $contentTypeService = $repository->getContentTypeService();
1124
        $contentService = $repository->getContentService();
1125
1126
        $createStruct = $contentTypeService->newContentTypeCreateStruct('countries-multiple');
1127
        $createStruct->mainLanguageCode = 'eng-GB';
1128
        $createStruct->remoteId = 'countries-multiple-123';
1129
        $createStruct->names = array('eng-GB' => 'Multiple countries');
1130
        $createStruct->creatorId = 14;
1131
        $createStruct->creationDate = new \DateTime();
1132
1133
        $fieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('countries', 'ezcountry');
1134
        $fieldCreate->names = array('eng-GB' => 'Countries');
1135
        $fieldCreate->fieldGroup = 'main';
1136
        $fieldCreate->position = 1;
1137
        $fieldCreate->isTranslatable = false;
1138
        $fieldCreate->isSearchable = true;
1139
        $fieldCreate->fieldSettings = array('isMultiple' => true);
1140
1141
        $createStruct->addFieldDefinition($fieldCreate);
1142
1143
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
1144
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, array($contentGroup));
1145
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
1146
        $contentType = $contentTypeService->loadContentType($contentTypeDraft->id);
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repositor...ContentType\ContentType. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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

<?php

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

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

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

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

}

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

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

See also the PhpDoc documentation for @property.

Loading history...
1147
1148
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
1149
        $createStruct->remoteId = 'countries-multiple-456';
1150
        $createStruct->alwaysAvailable = false;
1151
        $createStruct->setField(
1152
            'countries',
1153
            array('BE', 'DE', 'FR', 'HR', 'NO', 'PT', 'RU')
1154
        );
1155
1156
        $draft = $contentService->createContent($createStruct);
1157
        $content = $contentService->publishVersion($draft->getVersionInfo());
1158
1159
        $this->refreshSearch($repository);
1160
1161
        return $content;
1162
    }
1163
1164
    /**
1165
     * Test for the findContent() method.
1166
     *
1167
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
1168
     */
1169 View Code Duplication
    public function testFieldCollectionContains()
1170
    {
1171
        $testContent = $this->createMultipleCountriesContent();
1172
1173
        $query = new Query(
1174
            array(
1175
                'query' => new Criterion\Field(
1176
                    'countries',
1177
                    Criterion\Operator::CONTAINS,
1178
                    'Belgium'
1179
                ),
1180
            )
1181
        );
1182
1183
        $repository = $this->getRepository();
1184
        $searchService = $repository->getSearchService();
1185
        $result = $searchService->findContent($query);
1186
1187
        $this->assertEquals(1, $result->totalCount);
1188
        $this->assertEquals(
1189
            $testContent->id,
1190
            $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...
1191
        );
1192
    }
1193
1194
    /**
1195
     * Test for the findContent() method.
1196
     *
1197
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
1198
     * @depends eZ\Publish\API\Repository\Tests\SearchServiceTest::testFieldCollectionContains
1199
     */
1200 View Code Duplication
    public function testFieldCollectionContainsNoMatch()
1201
    {
1202
        $this->createMultipleCountriesContent();
1203
        $query = new Query(
1204
            array(
1205
                'query' => new Criterion\Field(
1206
                    'countries',
1207
                    Criterion\Operator::CONTAINS,
1208
                    'Netherlands Antilles'
1209
                ),
1210
            )
1211
        );
1212
1213
        $repository = $this->getRepository();
1214
        $searchService = $repository->getSearchService();
1215
        $result = $searchService->findContent($query);
1216
1217
        $this->assertEquals(0, $result->totalCount);
1218
    }
1219
1220
    /**
1221
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1222
     * @expectedExceptionMessage Argument '$criterion->target' is invalid: No searchable fields found for the given criterion target 'some_hopefully_unknown_field'
1223
     */
1224 View Code Duplication
    public function testInvalidFieldIdentifierRange()
1225
    {
1226
        $repository = $this->getRepository();
1227
        $searchService = $repository->getSearchService();
1228
1229
        $searchService->findContent(
1230
            new Query(
1231
                array(
1232
                    'filter' => new Criterion\Field(
1233
                        'some_hopefully_unknown_field',
1234
                        Criterion\Operator::BETWEEN,
1235
                        array(10, 1000)
1236
                    ),
1237
                    'sortClauses' => array(new SortClause\ContentId()),
1238
                )
1239
            )
1240
        );
1241
    }
1242
1243
    /**
1244
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1245
     * @expectedExceptionMessage Argument '$criterion->target' is invalid: No searchable fields found for the given criterion target 'some_hopefully_unknown_field'
1246
     */
1247 View Code Duplication
    public function testInvalidFieldIdentifierIn()
1248
    {
1249
        $repository = $this->getRepository();
1250
        $searchService = $repository->getSearchService();
1251
1252
        $searchService->findContent(
1253
            new Query(
1254
                array(
1255
                    'filter' => new Criterion\Field(
1256
                        'some_hopefully_unknown_field',
1257
                        Criterion\Operator::EQ,
1258
                        1000
1259
                    ),
1260
                    'sortClauses' => array(new SortClause\ContentId()),
1261
                )
1262
            )
1263
        );
1264
    }
1265
1266
    /**
1267
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1268
     * @expectedExceptionMessage Argument '$criterion->target' is invalid: No searchable fields found for the given criterion target 'tag_cloud_url'
1269
     */
1270 View Code Duplication
    public function testFindContentWithNonSearchableField()
1271
    {
1272
        $repository = $this->getRepository();
1273
        $searchService = $repository->getSearchService();
1274
1275
        $searchService->findContent(
1276
            new Query(
1277
                array(
1278
                    'filter' => new Criterion\Field(
1279
                        'tag_cloud_url',
1280
                        Criterion\Operator::EQ,
1281
                        'http://nimbus.com'
1282
                    ),
1283
                    'sortClauses' => array(new SortClause\ContentId()),
1284
                )
1285
            )
1286
        );
1287
    }
1288
1289
    /**
1290
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1291
     * @expectedExceptionMessage Argument '$sortClause->targetData' is invalid: No searchable fields found for the given sort clause target 'title' on 'template_look'
1292
     */
1293 View Code Duplication
    public function testSortFieldWithNonSearchableField()
1294
    {
1295
        $repository = $this->getRepository();
1296
        $searchService = $repository->getSearchService();
1297
1298
        $searchService->findContent(
1299
            new Query(
1300
                array(
1301
                    'sortClauses' => array(new SortClause\Field('template_look', 'title')),
1302
                )
1303
            )
1304
        );
1305
    }
1306
1307
    /**
1308
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1309
     * @expectedExceptionMessage Argument '$sortClause->targetData' is invalid: No searchable fields found for the given sort clause target 'title' on 'template_look'
1310
     */
1311 View Code Duplication
    public function testSortMapLocationDistanceWithNonSearchableField()
1312
    {
1313
        $repository = $this->getRepository();
1314
        $searchService = $repository->getSearchService();
1315
1316
        $searchService->findContent(
1317
            new Query(
1318
                array(
1319
                    'sortClauses' => array(
1320
                        new SortClause\MapLocationDistance(
1321
                            'template_look',
1322
                            'title',
1323
                            1,
1324
                            2
1325
                        ),
1326
                    ),
1327
                )
1328
            )
1329
        );
1330
    }
1331
1332
    /**
1333
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1334
     */
1335 View Code Duplication
    public function testFindSingleFailMultiple()
1336
    {
1337
        $repository = $this->getRepository();
1338
        $searchService = $repository->getSearchService();
1339
1340
        $searchService->findSingle(
1341
            new Criterion\ContentId(
1342
                array(4, 10)
1343
            )
1344
        );
1345
    }
1346
1347
    /**
1348
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1349
     */
1350
    public function testFindSingleWithNonSearchableField()
1351
    {
1352
        $repository = $this->getRepository();
1353
        $searchService = $repository->getSearchService();
1354
1355
        $searchService->findSingle(
1356
            new Criterion\Field(
1357
                'tag_cloud_url',
1358
                Criterion\Operator::EQ,
1359
                'http://nimbus.com'
1360
            )
1361
        );
1362
    }
1363
1364
    public function getSortedContentSearches()
1365
    {
1366
        $fixtureDir = $this->getFixtureDir();
1367
1368
        return array(
1369
            0 => array(
1370
                array(
1371
                    'filter' => new Criterion\SectionId(array(2)),
1372
                    'offset' => 0,
1373
                    'limit' => 10,
1374
                    'sortClauses' => array(),
1375
                ),
1376
                $fixtureDir . 'SortNone.php',
1377
                // Result having the same sort level should be sorted between them to be system independent
1378
                function (&$data) {
1379
                    usort(
1380
                        $data->searchHits,
1381
                        function ($a, $b) {
1382
                            return ($a->valueObject['id'] < $b->valueObject['id']) ? -1 : 1;
1383
                        }
1384
                    );
1385
                },
1386
            ),
1387
            1 => array(
1388
                array(
1389
                    'filter' => new Criterion\SectionId(array(2)),
1390
                    'offset' => 0,
1391
                    'limit' => 10,
1392
                    'sortClauses' => array(
1393
                        new SortClause\DatePublished(),
1394
                        new SortClause\ContentId(),
1395
                    ),
1396
                ),
1397
                $fixtureDir . 'SortDatePublished.php',
1398
            ),
1399
            2 => array(
1400
                array(
1401
                    'filter' => new Criterion\SectionId(array(2)),
1402
                    'offset' => 0,
1403
                    'limit' => 50,
1404
                    'sortClauses' => array(
1405
                        new SortClause\DateModified(),
1406
                        new SortClause\ContentId(),
1407
                    ),
1408
                ),
1409
                $fixtureDir . 'SortDateModified.php',
1410
            ),
1411
            3 => array(
1412
                array(
1413
                    'filter' => new Criterion\SectionId(array(4, 2, 6, 3)),
1414
                    'offset' => 0,
1415
                    'limit' => 50,
1416
                    'sortClauses' => array(
1417
                        new SortClause\SectionIdentifier(),
1418
                        new SortClause\ContentId(),
1419
                    ),
1420
                ),
1421
                $fixtureDir . 'SortSectionIdentifier.php',
1422
            ),
1423
            4 => array(
1424
                array(
1425
                    'filter' => new Criterion\SectionId(array(4, 2, 6, 3)),
1426
                    'offset' => 0,
1427
                    'limit' => 50,
1428
                    'sortClauses' => array(
1429
                        new SortClause\SectionName(),
1430
                        new SortClause\ContentId(),
1431
                    ),
1432
                ),
1433
                $fixtureDir . 'SortSectionName.php',
1434
            ),
1435
            5 => array(
1436
                array(
1437
                    'filter' => new Criterion\SectionId(array(2, 3)),
1438
                    'offset' => 0,
1439
                    'limit' => 50,
1440
                    'sortClauses' => array(
1441
                        new SortClause\ContentName(),
1442
                        new SortClause\ContentId(),
1443
                    ),
1444
                ),
1445
                $fixtureDir . 'SortContentName.php',
1446
            ),
1447
            6 => array(
1448
                array(
1449
                    'filter' => new Criterion\ContentTypeId(1),
1450
                    'offset' => 0,
1451
                    'limit' => 50,
1452
                    'sortClauses' => array(
1453
                        new SortClause\Field('folder', 'name', Query::SORT_ASC),
1454
                        new SortClause\ContentId(),
1455
                    ),
1456
                ),
1457
                $fixtureDir . 'SortFolderName.php',
1458
            ),
1459
            7 => array(
1460
                array(
1461
                    'filter' => new Criterion\ContentTypeId(array(1, 3)),
1462
                    'offset' => 0,
1463
                    'limit' => 50,
1464
                    'sortClauses' => array(
1465
                        new SortClause\Field('folder', 'name', Query::SORT_ASC),
1466
                        new SortClause\ContentId(),
1467
                    ),
1468
                ),
1469
                $fixtureDir . 'SortFieldMultipleTypes.php',
1470
            ),
1471
            8 => array(
1472
                array(
1473
                    'filter' => new Criterion\ContentTypeId(array(1, 3)),
1474
                    'offset' => 0,
1475
                    'limit' => 50,
1476
                    'sortClauses' => array(
1477
                        new SortClause\Field('folder', 'name', Query::SORT_DESC),
1478
                        new SortClause\ContentId(),
1479
                    ),
1480
                ),
1481
                $fixtureDir . 'SortFieldMultipleTypesReverse.php',
1482
            ),
1483
            9 => array(
1484
                array(
1485
                    'filter' => new Criterion\ContentTypeId(array(1, 3)),
1486
                    'offset' => 3,
1487
                    'limit' => 5,
1488
                    'sortClauses' => array(
1489
                        new SortClause\Field('folder', 'name', Query::SORT_ASC),
1490
                        new SortClause\Field('user', 'first_name', Query::SORT_ASC),
1491
                        new SortClause\ContentId(),
1492
                    ),
1493
                ),
1494
                $fixtureDir . 'SortFieldMultipleTypesSlice.php',
1495
            ),
1496
            10 => array(
1497
                array(
1498
                    'filter' => new Criterion\ContentTypeId(array(1, 3)),
1499
                    'offset' => 3,
1500
                    'limit' => 5,
1501
                    'sortClauses' => array(
1502
                        new SortClause\Field('folder', 'name', Query::SORT_DESC),
1503
                        new SortClause\Field('user', 'first_name', Query::SORT_ASC),
1504
                        new SortClause\ContentId(),
1505
                    ),
1506
                ),
1507
                $fixtureDir . 'SortFieldMultipleTypesSliceReverse.php',
1508
            ),
1509
        );
1510
    }
1511
1512
    public function getSortedLocationSearches()
1513
    {
1514
        $fixtureDir = $this->getFixtureDir();
1515
1516
        return array(
1517
            array(
1518
                array(
1519
                    'filter' => new Criterion\SectionId(array(2)),
1520
                    'offset' => 0,
1521
                    'limit' => 10,
1522
                    'sortClauses' => array(new SortClause\Location\Path(Query::SORT_DESC)),
1523
                ),
1524
                $fixtureDir . 'SortPathString.php',
1525
            ),
1526
            array(
1527
                array(
1528
                    'filter' => new Criterion\SectionId(array(2)),
1529
                    'offset' => 0,
1530
                    'limit' => 10,
1531
                    'sortClauses' => array(new SortClause\Location\Depth(Query::SORT_ASC)),
1532
                ),
1533
                $fixtureDir . 'SortLocationDepth.php',
1534
                // Result having the same sort level should be sorted between them to be system independent
1535
                function (&$data) {
1536
                    // Result with ids:
1537
                    //     4 has depth = 1
1538
                    //     11, 12, 13, 42, 59 have depth = 2
1539
                    //     10, 14 have depth = 3
1540
                    $map = array(
1541
                        4 => 0,
1542
                        11 => 1,
1543
                        12 => 2,
1544
                        13 => 3,
1545
                        42 => 4,
1546
                        59 => 5,
1547
                        10 => 6,
1548
                        14 => 7,
1549
                    );
1550
                    usort(
1551
                        $data->searchHits,
1552
                        function ($a, $b) use ($map) {
1553
                            return ($map[$a->valueObject['id']] < $map[$b->valueObject['id']]) ? -1 : 1;
1554
                        }
1555
                    );
1556
                },
1557
            ),
1558
            array(
1559
                array(
1560
                    'filter' => new Criterion\SectionId(array(3)),
1561
                    'offset' => 0,
1562
                    'limit' => 10,
1563
                    'sortClauses' => array(
1564
                        new SortClause\Location\Path(Query::SORT_DESC),
1565
                        new SortClause\ContentName(Query::SORT_ASC),
1566
                    ),
1567
                ),
1568
                $fixtureDir . 'SortMultiple.php',
1569
            ),
1570
            array(
1571
                array(
1572
                    'filter' => new Criterion\SectionId(array(2)),
1573
                    'offset' => 0,
1574
                    'limit' => 10,
1575
                    'sortClauses' => array(
1576
                        new SortClause\Location\Priority(Query::SORT_DESC),
1577
                        new SortClause\ContentId(),
1578
                    ),
1579
                ),
1580
                $fixtureDir . 'SortDesc.php',
1581
            ),
1582
        );
1583
    }
1584
1585
    /**
1586
     * @return \eZ\Publish\API\Repository\Values\ContentType\ContentType
1587
     */
1588 View Code Duplication
    protected function createTestContentType()
1589
    {
1590
        $repository = $this->getRepository();
1591
        $contentTypeService = $repository->getContentTypeService();
1592
1593
        $createStruct = $contentTypeService->newContentTypeCreateStruct('test-type');
1594
        $createStruct->mainLanguageCode = 'eng-GB';
1595
        $createStruct->names = array('eng-GB' => 'Test type');
1596
        $createStruct->creatorId = 14;
1597
        $createStruct->creationDate = new \DateTime();
1598
1599
        $translatableFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('integer', 'ezinteger');
1600
        $translatableFieldCreate->names = array('eng-GB' => 'Simple translatable integer field');
1601
        $translatableFieldCreate->fieldGroup = 'main';
1602
        $translatableFieldCreate->position = 1;
1603
        $translatableFieldCreate->isTranslatable = true;
1604
        $translatableFieldCreate->isSearchable = true;
1605
1606
        $createStruct->addFieldDefinition($translatableFieldCreate);
1607
1608
        $nonTranslatableFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('integer2', 'ezinteger');
1609
        $nonTranslatableFieldCreate->names = array('eng-GB' => 'Simple non-translatable integer field');
1610
        $nonTranslatableFieldCreate->fieldGroup = 'main';
1611
        $nonTranslatableFieldCreate->position = 2;
1612
        $nonTranslatableFieldCreate->isTranslatable = false;
1613
        $nonTranslatableFieldCreate->isSearchable = true;
1614
1615
        $createStruct->addFieldDefinition($nonTranslatableFieldCreate);
1616
1617
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
1618
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, array($contentGroup));
1619
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
1620
        $contentType = $contentTypeService->loadContentType($contentTypeDraft->id);
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repositor...ContentType\ContentType. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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

<?php

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

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

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

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

}

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

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

See also the PhpDoc documentation for @property.

Loading history...
1621
1622
        return $contentType;
1623
    }
1624
1625
    /**
1626
     * @param \eZ\Publish\API\Repository\Values\ContentType\ContentType $contentType
1627
     * @param int $fieldValue11 Value for translatable field in first language
1628
     * @param int $fieldValue12 Value for translatable field in second language
1629
     * @param int $fieldValue2 Value for non translatable field
1630
     * @param string $mainLanguageCode
1631
     * @param bool $alwaysAvailable
1632
     *
1633
     * @return Content
1634
     */
1635
    protected function createMultilingualContent(
1636
        $contentType,
1637
        $fieldValue11 = null,
1638
        $fieldValue12 = null,
1639
        $fieldValue2 = null,
1640
        $mainLanguageCode = 'eng-GB',
1641
        $alwaysAvailable = false
1642
    ) {
1643
        $repository = $this->getRepository();
1644
        $contentService = $repository->getContentService();
1645
1646
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
1647
        $createStruct->alwaysAvailable = $alwaysAvailable;
1648
        $createStruct->mainLanguageCode = $mainLanguageCode;
1649
        if ($fieldValue11) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $fieldValue11 of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1650
            $createStruct->setField('integer', $fieldValue11, 'eng-GB');
1651
        }
1652
        if ($fieldValue12) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $fieldValue12 of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1653
            $createStruct->setField('integer', $fieldValue12, 'ger-DE');
1654
        }
1655
        $createStruct->setField('integer2', $fieldValue2, $mainLanguageCode);
1656
1657
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
1658
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
1659
        $content = $contentService->publishVersion($draft->getVersionInfo());
1660
1661
        $this->refreshSearch($repository);
1662
1663
        return $content;
1664
    }
1665
1666
    protected function checkPrioritizedLanguagesSupport()
1667
    {
1668
        $setupFactory = $this->getSetupFactory();
1669
        if ($setupFactory instanceof LegacyElasticsearch) {
1670
            $this->markTestIncomplete('Prioritized languages are not supported with Elasticsearch engine');
1671
        }
1672
    }
1673
1674
    public function providerForTestMultilingualFieldSort()
1675
    {
1676
        return array(
1677
            0 => array(
1678
                array(
1679
                    1 => array(1, 2, 1),
1680
                    2 => array(2, 1, 2),
1681
                    3 => array(2, 1, 3),
1682
                    4 => array(1, 2, 4),
1683
                ),
1684
                array(
1685
                    'languages' => array(
1686
                        'eng-GB',
1687
                        'ger-DE',
1688
                    ),
1689
                ),
1690
                array(
1691
                    new SortClause\Field('test-type', 'integer', Query::SORT_ASC),
1692
                    new SortClause\Field('test-type', 'integer2', Query::SORT_DESC),
1693
                ),
1694
                /**
1695
                 * Expected order, Value eng-GB, Value ger-DE.
1696
                 *
1697
                 * Content 4, 1, 2, 4
1698
                 * Content 1, 1, 2, 1
1699
                 * Content 3, 2, 1, 3
1700
                 * Content 2, 2, 1, 2
1701
                 */
1702
                array(4, 1, 3, 2),
1703
            ),
1704
            1 => array(
1705
                array(
1706
                    1 => array(1, 2, 1),
1707
                    2 => array(2, 1, 2),
1708
                    3 => array(2, 1, 3),
1709
                    4 => array(1, 2, 4),
1710
                ),
1711
                array(
1712
                    'languages' => array(
1713
                        'ger-DE',
1714
                        'eng-GB',
1715
                    ),
1716
                ),
1717
                array(
1718
                    new SortClause\Field('test-type', 'integer', Query::SORT_ASC),
1719
                    new SortClause\Field('test-type', 'integer2', Query::SORT_DESC),
1720
                ),
1721
                /**
1722
                 * Expected order, Value eng-GB, Value ger-DE.
1723
                 *
1724
                 * Content 3, 2, 1, 3
1725
                 * Content 2, 2, 1, 2
1726
                 * Content 4, 1, 2, 4
1727
                 * Content 1, 1, 2, 1
1728
                 */
1729
                array(3, 2, 4, 1),
1730
            ),
1731
            2 => array(
1732
                array(
1733
                    1 => array(null, 2, null, 'ger-DE'),
1734
                    2 => array(3, null, null, 'eng-GB'),
1735
                    3 => array(4, null, null, 'eng-GB'),
1736
                    4 => array(null, 1, null, 'ger-DE'),
1737
                ),
1738
                array(
1739
                    'languages' => array(
1740
                        'eng-GB',
1741
                    ),
1742
                ),
1743
                array(
1744
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1745
                ),
1746
                /**
1747
                 * Expected order, Value eng-GB, Value ger-DE.
1748
                 *
1749
                 * Content 3, 4, -
1750
                 * Content 2, 3, -
1751
                 */
1752
                array(3, 2),
1753
            ),
1754
            3 => array(
1755
                array(
1756
                    1 => array(null, 2, null, 'ger-DE'),
1757
                    2 => array(3, null, null, 'eng-GB'),
1758
                    3 => array(4, null, null, 'eng-GB'),
1759
                    4 => array(null, 1, null, 'ger-DE'),
1760
                ),
1761
                array(
1762
                    'languages' => array(
1763
                        'ger-DE',
1764
                    ),
1765
                ),
1766
                array(
1767
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1768
                ),
1769
                /**
1770
                 * Expected order, Value eng-GB, Value ger-DE.
1771
                 *
1772
                 * Content 1, -, 2
1773
                 * Content 4, -, 1
1774
                 */
1775
                array(1, 4),
1776
            ),
1777
            4 => array(
1778
                array(
1779
                    1 => array(null, 2, null, 'ger-DE'),
1780
                    2 => array(3, null, null, 'eng-GB'),
1781
                    3 => array(4, null, null, 'eng-GB'),
1782
                    4 => array(null, 1, null, 'ger-DE'),
1783
                ),
1784
                array(
1785
                    'languages' => array(
1786
                        'eng-GB',
1787
                        'ger-DE',
1788
                    ),
1789
                ),
1790
                array(
1791
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1792
                ),
1793
                /**
1794
                 * Expected order, Value eng-GB, Value ger-DE.
1795
                 *
1796
                 * Content 3, 4, -
1797
                 * Content 2, 3, -
1798
                 * Content 1, -, 2
1799
                 * Content 4, -, 1
1800
                 */
1801
                array(3, 2, 1, 4),
1802
            ),
1803
            5 => array(
1804
                array(
1805
                    1 => array(null, 2, null, 'ger-DE'),
1806
                    2 => array(3, null, null, 'eng-GB'),
1807
                    3 => array(4, null, null, 'eng-GB'),
1808
                    4 => array(null, 1, null, 'ger-DE'),
1809
                ),
1810
                array(
1811
                    'languages' => array(
1812
                        'ger-DE',
1813
                        'eng-GB',
1814
                    ),
1815
                ),
1816
                array(
1817
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1818
                ),
1819
                /**
1820
                 * Expected order, Value eng-GB, Value ger-DE.
1821
                 *
1822
                 * Content 3, 4, -
1823
                 * Content 2, 3, -
1824
                 * Content 1, -, 2
1825
                 * Content 4, -, 1
1826
                 */
1827
                array(3, 2, 1, 4),
1828
            ),
1829
            6 => array(
1830
                array(
1831
                    1 => array(null, 2, null, 'ger-DE'),
1832
                    2 => array(3, 4, null, 'eng-GB'),
1833
                    3 => array(4, 3, null, 'eng-GB'),
1834
                    4 => array(null, 1, null, 'ger-DE'),
1835
                ),
1836
                array(
1837
                    'languages' => array(
1838
                        'eng-GB',
1839
                        'ger-DE',
1840
                    ),
1841
                ),
1842
                array(
1843
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1844
                ),
1845
                /**
1846
                 * Expected order, Value eng-GB, Value ger-DE.
1847
                 *
1848
                 * Content 3, 4, 3
1849
                 * Content 2, 3, 4
1850
                 * Content 1, -, 2
1851
                 * Content 4, -, 1
1852
                 */
1853
                array(3, 2, 1, 4),
1854
            ),
1855
            7 => array(
1856
                array(
1857
                    1 => array(null, 2, null, 'ger-DE'),
1858
                    2 => array(3, 4, null, 'eng-GB'),
1859
                    3 => array(4, 3, null, 'eng-GB'),
1860
                    4 => array(null, 1, null, 'ger-DE'),
1861
                ),
1862
                array(
1863
                    'languages' => array(
1864
                        'ger-DE',
1865
                        'eng-GB',
1866
                    ),
1867
                ),
1868
                array(
1869
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1870
                ),
1871
                /**
1872
                 * Expected order, Value eng-GB, Value ger-DE.
1873
                 *
1874
                 * Content 2, 3, 4
1875
                 * Content 3, 4, 3
1876
                 * Content 1, -, 2
1877
                 * Content 4, -, 1
1878
                 */
1879
                array(2, 3, 1, 4),
1880
            ),
1881
            8 => array(
1882
                array(
1883
                    1 => array(null, 1, null, 'ger-DE', true),
1884
                    2 => array(4, null, null, 'eng-GB', true),
1885
                    3 => array(3, null, null, 'eng-GB', false),
1886
                    4 => array(null, 2, null, 'ger-DE', false),
1887
                ),
1888
                array(
1889
                    'languages' => array(
1890
                        'eng-GB',
1891
                    ),
1892
                ),
1893
                array(
1894
                    new SortClause\Field('test-type', 'integer', Query::SORT_ASC),
1895
                ),
1896
                /**
1897
                 * Expected order, Value eng-GB, Value ger-DE.
1898
                 *
1899
                 * Content 1, -, 1
1900
                 * Content 3, 3, -
1901
                 * Content 2, 4, -
1902
                 */
1903
                array(1, 3, 2),
1904
            ),
1905
            9 => array(
1906
                array(
1907
                    1 => array(null, 1, null, 'ger-DE', true),
1908
                    2 => array(4, null, null, 'eng-GB', true),
1909
                    3 => array(3, null, null, 'eng-GB', false),
1910
                    4 => array(null, 2, null, 'ger-DE', false),
1911
                ),
1912
                array(
1913
                    'languages' => array(
1914
                        'ger-DE',
1915
                    ),
1916
                ),
1917
                array(
1918
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1919
                ),
1920
                /**
1921
                 * Expected order, Value eng-GB, Value ger-DE.
1922
                 *
1923
                 * Content 2, 4, -
1924
                 * Content 4, -, 2
1925
                 * Content 1, -, 1
1926
                 */
1927
                array(2, 4, 1),
1928
            ),
1929
            10 => array(
1930
                array(
1931
                    1 => array(null, 1, null, 'ger-DE', true),
1932
                    2 => array(4, null, null, 'eng-GB', true),
1933
                    3 => array(3, null, null, 'eng-GB', false),
1934
                    4 => array(null, 2, null, 'ger-DE', false),
1935
                ),
1936
                array(
1937
                    'languages' => array(
1938
                        'eng-GB',
1939
                    ),
1940
                    'useAlwaysAvailable' => false,
1941
                ),
1942
                array(
1943
                    new SortClause\Field('test-type', 'integer', Query::SORT_ASC),
1944
                ),
1945
                /**
1946
                 * Expected order, Value eng-GB, Value ger-DE.
1947
                 *
1948
                 * Content 3, 3, -
1949
                 * Content 2, 4, -
1950
                 */
1951
                array(3, 2),
1952
            ),
1953
            11 => array(
1954
                array(
1955
                    1 => array(null, 1, null, 'ger-DE', true),
1956
                    2 => array(4, null, null, 'eng-GB', true),
1957
                    3 => array(3, null, null, 'eng-GB', false),
1958
                    4 => array(null, 2, null, 'ger-DE', false),
1959
                ),
1960
                array(
1961
                    'languages' => array(
1962
                        'ger-DE',
1963
                    ),
1964
                    'useAlwaysAvailable' => false,
1965
                ),
1966
                array(
1967
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1968
                ),
1969
                /**
1970
                 * Expected order, Value eng-GB, Value ger-DE.
1971
                 *
1972
                 * Content 4, -, 2
1973
                 * Content 1, -, 1
1974
                 */
1975
                array(4, 1),
1976
            ),
1977
        );
1978
    }
1979
1980
    /**
1981
     * Test for the findContent() method.
1982
     *
1983
     * @group rrr
1984
     * @dataProvider providerForTestMultilingualFieldSort
1985
     *
1986
     * @param array $contentDataList
1987
     * @param array $languageSettings
1988
     * @param \eZ\Publish\API\Repository\Values\Content\Query\SortClause[] $sortClauses
1989
     * @param array $expected
1990
     */
1991
    public function testMultilingualFieldSortContent(
1992
        array $contentDataList,
1993
        $languageSettings,
1994
        array $sortClauses,
1995
        $expected
1996
    ) {
1997
        $this->assertMultilingualFieldSort(
1998
            $contentDataList,
1999
            $languageSettings,
2000
            $sortClauses,
2001
            $expected
2002
        );
2003
    }
2004
2005
    /**
2006
     * Test for the findLocations() method.
2007
     *
2008
     * @group rrr
2009
     * @dataProvider providerForTestMultilingualFieldSort
2010
     *
2011
     * @param array $contentDataList
2012
     * @param array $languageSettings
2013
     * @param \eZ\Publish\API\Repository\Values\Content\Query\SortClause[] $sortClauses
2014
     * @param array $expected
2015
     */
2016
    public function testMultilingualFieldSortLocation(
2017
        array $contentDataList,
2018
        $languageSettings,
2019
        array $sortClauses,
2020
        $expected
2021
    ) {
2022
        $this->assertMultilingualFieldSort(
2023
            $contentDataList,
2024
            $languageSettings,
2025
            $sortClauses,
2026
            $expected,
2027
            false
2028
        );
2029
    }
2030
2031
    /**
2032
     * @param array $contentDataList
2033
     * @param array $languageSettings
2034
     * @param \eZ\Publish\API\Repository\Values\Content\Query\SortClause[] $sortClauses
2035
     * @param array $expected
2036
     * @param bool $contentSearch
2037
     */
2038
    protected function assertMultilingualFieldSort(
2039
        array $contentDataList,
2040
        $languageSettings,
2041
        array $sortClauses,
2042
        $expected,
2043
        $contentSearch = true
2044
    ) {
2045
        $this->checkPrioritizedLanguagesSupport();
2046
        $contentType = $this->createTestContentType();
2047
2048
        // Create a draft to account for behaviour with ContentType in different states
2049
        $repository = $this->getRepository();
2050
        $contentTypeService = $repository->getContentTypeService();
2051
        $contentTypeService->createContentTypeDraft($contentType);
2052
2053
        $defaults = array(null, null, null, 'eng-GB', false);
2054
        $contentIdList = array();
2055 View Code Duplication
        foreach ($contentDataList as $key => $contentData) {
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...
2056
            $contentData = $contentData + $defaults;
2057
            list(
2058
                $fieldValue11,
2059
                $fieldValue12,
2060
                $fieldValue2,
2061
                $mainLanguageCode,
2062
                $alwaysAvailable
2063
            ) = $contentData;
2064
2065
            $contentIdList[$key] = $this->createMultilingualContent(
2066
                $contentType,
2067
                $fieldValue11,
2068
                $fieldValue12,
2069
                $fieldValue2,
2070
                $mainLanguageCode,
2071
                $alwaysAvailable
2072
            )->id;
2073
        }
2074
2075
        // "article" type Content is not matched, this ensures that non-matched
2076
        // field does not affect sort
2077
        $dummySortClause = new SortClause\Field('article', 'title', Query::SORT_ASC);
2078
        array_unshift($sortClauses, $dummySortClause);
2079
        array_push($sortClauses, $dummySortClause);
2080
2081
        $searchService = $repository->getSearchService();
2082
        if ($contentSearch) {
2083
            $query = new Query(
2084
                array(
2085
                    'query' => new Criterion\ContentTypeId($contentType->id),
2086
                    'sortClauses' => $sortClauses,
2087
                )
2088
            );
2089
            $result = $searchService->findContent($query, $languageSettings);
2090
        } else {
2091
            $query = new LocationQuery(
2092
                array(
2093
                    'query' => new Criterion\ContentTypeId($contentType->id),
2094
                    'sortClauses' => $sortClauses,
2095
                )
2096
            );
2097
            $result = $searchService->findLocations($query, $languageSettings);
2098
        }
2099
2100
        $this->assertEquals(count($expected), $result->totalCount);
2101
2102
        $expectedIdList = array();
2103
        foreach ($expected as $contentNumber) {
2104
            $expectedIdList[] = $contentIdList[$contentNumber];
2105
        }
2106
2107
        $this->assertEquals($expectedIdList, $this->mapResultContentIds($result));
2108
    }
2109
2110
    public function providerForTestMultilingualFieldFilter()
2111
    {
2112
        return array(
2113
            0 => array(
2114
                $fixture = array(
2115
                    1 => array(null, 1, null, 'ger-DE', true),
2116
                    2 => array(4, null, null, 'eng-GB', true),
2117
                    3 => array(3, null, null, 'eng-GB', false),
2118
                    4 => array(null, 2, null, 'ger-DE', false),
2119
                    5 => array(5, null, null, 'eng-GB', true),
2120
                ),
2121
                $languageSettings = array(
2122
                    'languages' => array(
2123
                        'ger-DE',
2124
                    ),
2125
                ),
2126
                new Criterion\Field('integer', Criterion\Operator::LT, 5),
2127
                /**
2128
                 * Expected order, Value eng-GB, Value ger-DE.
2129
                 *
2130
                 * Content 2, 4, -
2131
                 * Content 4, -, 2
2132
                 * Content 1, -, 1
2133
                 */
2134
                array(2, 4, 1),
2135
            ),
2136
            1 => array(
2137
                $fixture,
2138
                array(
2139
                    'languages' => array(
2140
                        'ger-DE',
2141
                    ),
2142
                    'useAlwaysAvailable' => false,
2143
                ),
2144
                new Criterion\Field('integer', Criterion\Operator::LT, 2),
2145
                /**
2146
                 * Expected order, Value eng-GB, Value ger-DE.
2147
                 *
2148
                 * Content 1, -, 1
2149
                 */
2150
                array(1),
2151
            ),
2152
            2 => array(
2153
                $fixture,
2154
                array(
2155
                    'languages' => array(
2156
                        'eng-GB',
2157
                    ),
2158
                ),
2159
                new Criterion\Field('integer', Criterion\Operator::LTE, 4),
2160
                /**
2161
                 * Expected order, Value eng-GB, Value ger-DE.
2162
                 *
2163
                 * Content 5, 5, -
2164
                 * Content 2, 4, -
2165
                 * Content 3, 3, -
2166
                 * Content 1, -, 1
2167
                 */
2168
                array(2, 3, 1),
2169
            ),
2170
            3 => array(
2171
                $fixture,
2172
                array(
2173
                    'languages' => array(
2174
                        'eng-GB',
2175
                    ),
2176
                    'useAlwaysAvailable' => false,
2177
                ),
2178
                new Criterion\Field('integer', Criterion\Operator::LTE, 4),
2179
                /**
2180
                 * Expected order, Value eng-GB, Value ger-DE.
2181
                 *
2182
                 * Content 2, 4, -
2183
                 * Content 3, 3, -
2184
                 */
2185
                array(2, 3),
2186
            ),
2187
            4 => array(
2188
                $fixture,
2189
                $languageSettings,
2190
                new Criterion\Field('integer', Criterion\Operator::LTE, 4),
2191
                /**
2192
                 * Expected order, Value eng-GB, Value ger-DE.
2193
                 *
2194
                 * Content 2, 4, -
2195
                 * Content 4, -, 2
2196
                 * Content 1, -, 1
2197
                 */
2198
                array(2, 4, 1),
2199
            ),
2200
            5 => array(
2201
                $fixture,
2202
                $languageSettings,
2203
                new Criterion\Field('integer', Criterion\Operator::GT, 1),
2204
                /**
2205
                 * Expected order, Value eng-GB, Value ger-DE.
2206
                 *
2207
                 * Content 5, 5, -
2208
                 * Content 2, 4, -
2209
                 * Content 4, -, 2
2210
                 */
2211
                array(5, 2, 4),
2212
            ),
2213
            6 => array(
2214
                $fixture,
2215
                $languageSettings,
2216
                new Criterion\Field('integer', Criterion\Operator::GTE, 2),
2217
                /**
2218
                 * Expected order, Value eng-GB, Value ger-DE.
2219
                 *
2220
                 * Content 5, 5, -
2221
                 * Content 2, 4, -
2222
                 * Content 4, -, 2
2223
                 */
2224
                array(5, 2, 4),
2225
            ),
2226
            7 => array(
2227
                $fixture,
2228
                $languageSettings,
2229
                new Criterion\Field('integer', Criterion\Operator::BETWEEN, array(2, 4)),
2230
                /**
2231
                 * Expected order, Value eng-GB, Value ger-DE.
2232
                 *
2233
                 * Content 2, 4, -
2234
                 * Content 4, -, 2
2235
                 */
2236
                array(2, 4),
2237
            ),
2238
            8 => array(
2239
                $fixture,
2240
                $languageSettings,
2241
                new Criterion\Field('integer', Criterion\Operator::BETWEEN, array(4, 2)),
2242
                array(),
2243
            ),
2244
            9 => array(
2245
                $fixture,
2246
                $languageSettings,
2247
                new Criterion\Field('integer', Criterion\Operator::EQ, 4),
2248
                /**
2249
                 * Expected order, Value eng-GB, Value ger-DE.
2250
                 *
2251
                 * Content 4, -, 2
2252
                 */
2253
                array(2),
2254
            ),
2255
            10 => array(
2256
                $fixture,
2257
                $languageSettings,
2258
                new Criterion\Field('integer', Criterion\Operator::EQ, 2),
2259
                /**
2260
                 * Expected order, Value eng-GB, Value ger-DE.
2261
                 *
2262
                 * Content 2, 4, -
2263
                 */
2264
                array(4),
2265
            ),
2266
        );
2267
    }
2268
2269
    /**
2270
     * Test for the findContent() method.
2271
     *
2272
     * @group ttt
2273
     * @dataProvider providerForTestMultilingualFieldFilter
2274
     *
2275
     * @param array $contentDataList
2276
     * @param array $languageSettings
2277
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
2278
     * @param array $expected
2279
     */
2280
    public function testMultilingualFieldFilterContent(
2281
        array $contentDataList,
2282
        $languageSettings,
2283
        Criterion $criterion,
2284
        $expected
2285
    ) {
2286
        $this->assertMultilingualFieldFilter(
2287
            $contentDataList,
2288
            $languageSettings,
2289
            $criterion,
2290
            $expected
2291
        );
2292
    }
2293
2294
    /**
2295
     * Test for the findLocations() method.
2296
     *
2297
     * @group ttt
2298
     * @dataProvider providerForTestMultilingualFieldFilter
2299
     *
2300
     * @param array $contentDataList
2301
     * @param array $languageSettings
2302
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
2303
     * @param array $expected
2304
     */
2305
    public function testMultilingualFieldFilterLocation(
2306
        array $contentDataList,
2307
        $languageSettings,
2308
        Criterion $criterion,
2309
        $expected
2310
    ) {
2311
        $this->assertMultilingualFieldFilter(
2312
            $contentDataList,
2313
            $languageSettings,
2314
            $criterion,
2315
            $expected,
2316
            false
2317
        );
2318
    }
2319
2320
    /**
2321
     * @param array $contentDataList
2322
     * @param array $languageSettings
2323
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
2324
     * @param array $expected
2325
     * @param bool $contentSearch
2326
     */
2327
    protected function assertMultilingualFieldFilter(
2328
        array $contentDataList,
2329
        $languageSettings,
2330
        Criterion $criterion,
2331
        $expected,
2332
        $contentSearch = true
2333
    ) {
2334
        $this->checkPrioritizedLanguagesSupport();
2335
        $contentType = $this->createTestContentType();
2336
2337
        // Create a draft to account for behaviour with ContentType in different states
2338
        $repository = $this->getRepository();
2339
        $contentTypeService = $repository->getContentTypeService();
2340
        $contentTypeService->createContentTypeDraft($contentType);
2341
2342
        $defaults = array(null, null, null, 'eng-GB', false);
2343
        $contentIdList = array();
2344 View Code Duplication
        foreach ($contentDataList as $key => $contentData) {
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...
2345
            $contentData = $contentData + $defaults;
2346
            list(
2347
                $fieldValue11,
2348
                $fieldValue12,
2349
                $fieldValue2,
2350
                $mainLanguageCode,
2351
                $alwaysAvailable
2352
            ) = $contentData;
2353
2354
            $contentIdList[$key] = $this->createMultilingualContent(
2355
                $contentType,
2356
                $fieldValue11,
2357
                $fieldValue12,
2358
                $fieldValue2,
2359
                $mainLanguageCode,
2360
                $alwaysAvailable
2361
            )->id;
2362
        }
2363
2364
        $sortClause = new SortClause\Field('test-type', 'integer', Query::SORT_DESC);
2365
        $searchService = $repository->getSearchService();
2366
        if ($contentSearch) {
2367
            $query = new Query(
2368
                array(
2369
                    'query' => new Criterion\LogicalAnd(
2370
                        array(
2371
                            new Criterion\ContentTypeId($contentType->id),
2372
                            $criterion,
2373
                        )
2374
                    ),
2375
                    'sortClauses' => array($sortClause),
2376
                )
2377
            );
2378
            $result = $searchService->findContent($query, $languageSettings);
2379
        } else {
2380
            $query = new LocationQuery(
2381
                array(
2382
                    'query' => new Criterion\LogicalAnd(
2383
                        array(
2384
                            new Criterion\ContentTypeId($contentType->id),
2385
                            $criterion,
2386
                        )
2387
                    ),
2388
                    'sortClauses' => array($sortClause),
2389
                )
2390
            );
2391
            $result = $searchService->findLocations($query, $languageSettings);
2392
        }
2393
2394
        $this->assertEquals(count($expected), $result->totalCount);
2395
2396
        $expectedIdList = array();
2397
        foreach ($expected as $contentNumber) {
2398
            $expectedIdList[] = $contentIdList[$contentNumber];
2399
        }
2400
2401
        $this->assertEquals($expectedIdList, $this->mapResultContentIds($result));
2402
    }
2403
2404
    /**
2405
     * @param \eZ\Publish\API\Repository\Values\Content\Search\SearchResult $result
2406
     *
2407
     * @return array
2408
     */
2409
    protected function mapResultContentIds(SearchResult $result)
2410
    {
2411
        return array_map(
2412
            function (SearchHit $searchHit) {
2413
                if ($searchHit->valueObject instanceof Location) {
2414
                    return $searchHit->valueObject->contentInfo->id;
2415
                }
2416
2417
                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...
2418
            },
2419
            $result->searchHits
2420
        );
2421
    }
2422
2423
    /**
2424
     * Test for the findContent() method.
2425
     *
2426
     * @dataProvider getSortedContentSearches
2427
     *
2428
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2429
     */
2430
    public function testFindAndSortContent($queryData, $fixture, $closure = null)
2431
    {
2432
        $query = new Query($queryData);
2433
        $this->assertQueryFixture($query, $fixture, $closure);
2434
    }
2435
2436
    /**
2437
     * Test for the findContentInfo() method.
2438
     *
2439
     * @dataProvider getSortedContentSearches
2440
     * @see \eZ\Publish\API\Repository\SearchService::findContentInfo()
2441
     */
2442
    public function testFindAndSortContentInfo($queryData, $fixture, $closure = null)
2443
    {
2444
        $query = new Query($queryData);
2445
        $this->assertQueryFixture($query, $fixture, $this->getContentInfoFixtureClosure($closure), true);
2446
    }
2447
2448
    /**
2449
     * Test for the findLocations() method.
2450
     *
2451
     * @dataProvider getSortedContentSearches
2452
     *
2453
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
2454
     */
2455
    public function testFindAndSortContentLocations($queryData, $fixture, $closure = null)
2456
    {
2457
        $query = new LocationQuery($queryData);
2458
        $this->assertQueryFixture($query, $fixture, $closure);
2459
    }
2460
2461
    /**
2462
     * Test for the findLocations() method.
2463
     *
2464
     * @dataProvider getSortedLocationSearches
2465
     *
2466
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
2467
     */
2468
    public function testFindAndSortLocations($queryData, $fixture, $closure = null)
2469
    {
2470
        $query = new LocationQuery($queryData);
2471
        $this->assertQueryFixture($query, $fixture, $closure);
2472
    }
2473
2474
    public function getFacettedSearches()
2475
    {
2476
        $fixtureDir = $this->getFixtureDir();
2477
2478
        return array(
2479
            array(
2480
                new Query(
2481
                    array(
2482
                        'filter' => new Criterion\SectionId(array(1)),
2483
                        'offset' => 0,
2484
                        'limit' => 10,
2485
                        'facetBuilders' => array(
2486
                            new FacetBuilder\ContentTypeFacetBuilder(
2487
                                array(
2488
                                    'name' => 'type',
2489
                                )
2490
                            ),
2491
                        ),
2492
                        'sortClauses' => array(new SortClause\ContentId()),
2493
                    )
2494
                ),
2495
                $fixtureDir . '/FacetContentType.php',
2496
            ),
2497
            array(
2498
                new Query(
2499
                    array(
2500
                        'filter' => new Criterion\SectionId(array(1)),
2501
                        'offset' => 0,
2502
                        'limit' => 10,
2503
                        'facetBuilders' => array(
2504
                            new FacetBuilder\ContentTypeFacetBuilder(
2505
                                array(
2506
                                    'name' => 'type',
2507
                                    'minCount' => 3,
2508
                                )
2509
                            ),
2510
                        ),
2511
                        'sortClauses' => array(new SortClause\ContentId()),
2512
                    )
2513
                ),
2514
                $fixtureDir . '/FacetContentTypeMinCount.php',
2515
            ),
2516
            array(
2517
                new Query(
2518
                    array(
2519
                        'filter' => new Criterion\SectionId(array(1)),
2520
                        'offset' => 0,
2521
                        'limit' => 10,
2522
                        'facetBuilders' => array(
2523
                            new FacetBuilder\ContentTypeFacetBuilder(
2524
                                array(
2525
                                    'name' => 'type',
2526
                                    'limit' => 5,
2527
                                )
2528
                            ),
2529
                        ),
2530
                        'sortClauses' => array(new SortClause\ContentId()),
2531
                    )
2532
                ),
2533
                $fixtureDir . '/FacetContentTypeMinLimit.php',
2534
            ),
2535
            array(
2536
                new Query(
2537
                    array(
2538
                        'filter' => new Criterion\SectionId(array(1)),
2539
                        'offset' => 0,
2540
                        'limit' => 10,
2541
                        'facetBuilders' => array(
2542
                            new FacetBuilder\SectionFacetBuilder(
2543
                                array(
2544
                                    'name' => 'section',
2545
                                )
2546
                            ),
2547
                        ),
2548
                        'sortClauses' => array(new SortClause\ContentId()),
2549
                    )
2550
                ),
2551
                $fixtureDir . '/FacetSection.php',
2552
            ),
2553
            array(
2554
                new Query(
2555
                    array(
2556
                        'filter' => new Criterion\SectionId(array(1)),
2557
                        'offset' => 0,
2558
                        'limit' => 10,
2559
                        'facetBuilders' => array(
2560
                            new FacetBuilder\UserFacetBuilder(
2561
                                array(
2562
                                    'name' => 'creator',
2563
                                )
2564
                            ),
2565
                        ),
2566
                        'sortClauses' => array(new SortClause\ContentId()),
2567
                    )
2568
                ),
2569
                $fixtureDir . '/FacetUser.php',
2570
            ),
2571
            array(
2572
                new Query(
2573
                    array(
2574
                        'filter' => new Criterion\SectionId(array(1)),
2575
                        'offset' => 0,
2576
                        'limit' => 10,
2577
                        'facetBuilders' => array(
2578
                            new FacetBuilder\TermFacetBuilder(),
2579
                        ),
2580
                        'sortClauses' => array(new SortClause\ContentId()),
2581
                    )
2582
                ),
2583
                $fixtureDir . '/FacetTerm.php',
2584
            ),
2585
            /* @todo: It needs to be defined how this one is supposed to work.
2586
            array(
2587
                new Query(
2588
                    array(
2589
                        'filter'      => new Criterion\SectionId( array( 1 ) ),
2590
                        'offset'      => 0,
2591
                        'limit'       => 10,
2592
                        'facetBuilders' => array(
2593
                            new FacetBuilder\CriterionFacetBuilder()
2594
                        ),
2595
                        'sortClauses' => array( new SortClause\ContentId() )
2596
                    )
2597
                ),
2598
                $fixtureDir . '/FacetCriterion.php',
2599
            ), // */
2600
            /* @todo: Add sane ranges here:
2601
            array(
2602
                new Query(
2603
                    array(
2604
                        'filter'      => new Criterion\SectionId( array( 1 ) ),
2605
                        'offset'      => 0,
2606
                        'limit'       => 10,
2607
                        'facetBuilders' => array(
2608
                            new FacetBuilder\DateRangeFacetBuilder( array() )
2609
                        ),
2610
                        'sortClauses' => array( new SortClause\ContentId() )
2611
                    )
2612
                ),
2613
                $fixtureDir . '/FacetDateRange.php',
2614
            ), // */
2615
            array(
2616
                new Query(
2617
                    array(
2618
                        'filter' => new Criterion\SectionId(array(1)),
2619
                        'offset' => 0,
2620
                        'limit' => 10,
2621
                        'facetBuilders' => array(
2622
                            new FacetBuilder\FieldFacetBuilder(
2623
                                array(
2624
                                    'fieldPaths' => array('article/title'),
2625
                                )
2626
                            ),
2627
                        ),
2628
                        'sortClauses' => array(new SortClause\ContentId()),
2629
                    )
2630
                ),
2631
                $fixtureDir . '/FacetFieldSimple.php',
2632
            ),
2633
            array(
2634
                new Query(
2635
                    array(
2636
                        'filter' => new Criterion\SectionId(array(1)),
2637
                        'offset' => 0,
2638
                        'limit' => 10,
2639
                        'facetBuilders' => array(
2640
                            new FacetBuilder\FieldFacetBuilder(
2641
                                array(
2642
                                    'fieldPaths' => array('article/title'),
2643
                                    'regex' => '(a|b|c)',
2644
                                )
2645
                            ),
2646
                        ),
2647
                        'sortClauses' => array(new SortClause\ContentId()),
2648
                    )
2649
                ),
2650
                $fixtureDir . '/FacetFieldRegexp.php',
2651
            ),
2652
            array(
2653
                new Query(
2654
                    array(
2655
                        'filter' => new Criterion\SectionId(array(1)),
2656
                        'offset' => 0,
2657
                        'limit' => 10,
2658
                        'facetBuilders' => array(
2659
                            new FacetBuilder\FieldFacetBuilder(
2660
                                array(
2661
                                    'fieldPaths' => array('article/title'),
2662
                                    'regex' => '(a|b|c)',
2663
                                    'sort' => FacetBuilder\FieldFacetBuilder::TERM_DESC,
2664
                                )
2665
                            ),
2666
                        ),
2667
                        'sortClauses' => array(new SortClause\ContentId()),
2668
                    )
2669
                ),
2670
                $fixtureDir . '/FacetFieldRegexpSortTerm.php',
2671
            ),
2672
            array(
2673
                new Query(
2674
                    array(
2675
                        'filter' => new Criterion\SectionId(array(1)),
2676
                        'offset' => 0,
2677
                        'limit' => 10,
2678
                        'facetBuilders' => array(
2679
                            new FacetBuilder\FieldFacetBuilder(
2680
                                array(
2681
                                    'fieldPaths' => array('article/title'),
2682
                                    'regex' => '(a|b|c)',
2683
                                    'sort' => FacetBuilder\FieldFacetBuilder::COUNT_DESC,
2684
                                )
2685
                            ),
2686
                        ),
2687
                        'sortClauses' => array(new SortClause\ContentId()),
2688
                    )
2689
                ),
2690
                $fixtureDir . '/FacetFieldRegexpSortCount.php',
2691
            ),
2692
            /* @todo: Add sane ranges here:
2693
            array(
2694
                new Query(
2695
                    array(
2696
                        'filter'      => new Criterion\SectionId( array( 1 ) ),
2697
                        'offset'      => 0,
2698
                        'limit'       => 10,
2699
                        'facetBuilders' => array(
2700
                            new FacetBuilder\FieldRangeFacetBuilder( array(
2701
                                'fieldPath' => 'product/price',
2702
                            ) )
2703
                        ),
2704
                        'sortClauses' => array( new SortClause\ContentId() )
2705
                    )
2706
                ),
2707
                $fixtureDir . '/FacetFieldRegexpSortCount.php',
2708
            ), // */
2709
        );
2710
    }
2711
2712
    /**
2713
     * Test for the findContent() method.
2714
     *
2715
     * @dataProvider getFacettedSearches
2716
     *
2717
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2718
     */
2719
    public function testFindFacettedContent(Query $query, $fixture)
2720
    {
2721
        $this->assertQueryFixture($query, $fixture);
2722
    }
2723
2724
    /**
2725
     * Test for the findContentInfo() method.
2726
     *
2727
     * @dataProvider getFacettedSearches
2728
     * @see \eZ\Publish\API\Repository\SearchService::findContentInfo()
2729
     */
2730
    public function testFindFacettedContentInfo(Query $query, $fixture)
2731
    {
2732
        $this->assertQueryFixture($query, $fixture, $this->getContentInfoFixtureClosure(), true);
2733
    }
2734
2735
    /**
2736
     * Test for the findContent() method.
2737
     *
2738
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2739
     */
2740 View Code Duplication
    public function testQueryCustomField()
2741
    {
2742
        $query = new Query(
2743
            array(
2744
                'query' => new Criterion\CustomField(
2745
                    'custom_field',
2746
                    Criterion\Operator::EQ,
2747
                    'AdMiNiStRaToR'
2748
                ),
2749
                'offset' => 0,
2750
                'limit' => 10,
2751
                'sortClauses' => array(new SortClause\ContentId()),
2752
            )
2753
        );
2754
        $this->assertQueryFixture(
2755
            $query,
2756
            $this->getFixtureDir() . '/QueryCustomField.php'
2757
        );
2758
    }
2759
2760
    /**
2761
     * Test for the findContent() method.
2762
     *
2763
     * This tests explicitely queries the first_name while user is contained in
2764
     * the last_name of admin and anonymous. This is done to show the custom
2765
     * copy field working.
2766
     *
2767
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2768
     */
2769 View Code Duplication
    public function testQueryModifiedField()
2770
    {
2771
        // Check using get_class since the others extend SetupFactory\Legacy
2772
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
2773
            $this->markTestIncomplete(
2774
                'Custom fields not supported by LegacySE ' .
2775
                '(@todo: Legacy should fallback to just querying normal field so this should be tested here)'
2776
            );
2777
        }
2778
2779
        $query = new Query(
2780
            array(
2781
                'query' => new Criterion\Field(
2782
                    'first_name',
2783
                    Criterion\Operator::EQ,
2784
                    'User'
2785
                ),
2786
                'offset' => 0,
2787
                'limit' => 10,
2788
                'sortClauses' => array(new SortClause\ContentId()),
2789
            )
2790
        );
2791
        $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...
2792
2793
        $this->assertQueryFixture(
2794
            $query,
2795
            $this->getFixtureDir() . '/QueryModifiedField.php'
2796
        );
2797
    }
2798
2799
    /**
2800
     * Test for the findContent() method.
2801
     *
2802
     * This tests first explicitly creates sort clause on the 'short_name' which is empty
2803
     * for all Content instances of 'folder' ContentType. Custom sort field is then set
2804
     * to the index storage name of folder's 'name' field, in order to show the custom
2805
     * sort field working.
2806
     *
2807
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2808
     */
2809
    public function testSortModifiedField()
2810
    {
2811
        // Check using get_class since the others extend SetupFactory\Legacy
2812
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
2813
            $this->markTestIncomplete(
2814
                'Custom field sort not supported by LegacySE ' .
2815
                '(@todo: Legacy should fallback to just querying normal field so this should be tested here)'
2816
            );
2817
        }
2818
2819
        $sortClause = new SortClause\Field('folder', 'short_name', Query::SORT_ASC);
2820
        $sortClause->setCustomField('folder', 'short_name', 'folder_name_value_s');
2821
2822
        $query = new Query(
2823
            array(
2824
                'filter' => new Criterion\ContentTypeId(1),
2825
                'offset' => 0,
2826
                'limit' => 10,
2827
                'sortClauses' => array(
2828
                    $sortClause,
2829
                    new SortClause\ContentId(),
2830
                ),
2831
            )
2832
        );
2833
2834
        $this->assertQueryFixture(
2835
            $query,
2836
            $this->getFixtureDir() . '/SortFolderName.php'
2837
        );
2838
    }
2839
2840
    /**
2841
     * @return \eZ\Publish\API\Repository\Values\ContentType\ContentType
2842
     */
2843 View Code Duplication
    protected function createTestPlaceContentType()
2844
    {
2845
        $repository = $this->getRepository();
2846
        $contentTypeService = $repository->getContentTypeService();
2847
2848
        $createStruct = $contentTypeService->newContentTypeCreateStruct('testtype');
2849
        $createStruct->mainLanguageCode = 'eng-GB';
2850
        $createStruct->names = array('eng-GB' => 'Test type');
2851
        $createStruct->creatorId = 14;
2852
        $createStruct->creationDate = new \DateTime();
2853
2854
        $translatableFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('maplocation', 'ezgmaplocation');
2855
        $translatableFieldCreate->names = array('eng-GB' => 'Map location field');
2856
        $translatableFieldCreate->fieldGroup = 'main';
2857
        $translatableFieldCreate->position = 1;
2858
        $translatableFieldCreate->isTranslatable = false;
2859
        $translatableFieldCreate->isSearchable = true;
2860
2861
        $createStruct->addFieldDefinition($translatableFieldCreate);
2862
2863
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
2864
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, array($contentGroup));
2865
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
2866
        $contentType = $contentTypeService->loadContentType($contentTypeDraft->id);
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repositor...ContentType\ContentType. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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

<?php

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

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

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

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

}

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

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

See also the PhpDoc documentation for @property.

Loading history...
2867
2868
        return $contentType;
2869
    }
2870
2871
    /**
2872
     * Test for the findContent() method.
2873
     *
2874
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2875
     * @group maplocation
2876
     */
2877 View Code Duplication
    public function testMapLocationDistanceLessThanOrEqual()
2878
    {
2879
        $contentType = $this->createTestPlaceContentType();
2880
2881
        // Create a draft to account for behaviour with ContentType in different states
2882
        $repository = $this->getRepository();
2883
        $contentTypeService = $repository->getContentTypeService();
2884
        $contentService = $repository->getContentService();
2885
        $contentTypeService->createContentTypeDraft($contentType);
2886
2887
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2888
        $createStruct->alwaysAvailable = false;
2889
        $createStruct->mainLanguageCode = 'eng-GB';
2890
        $createStruct->setField(
2891
            'maplocation',
2892
            array(
2893
                'latitude' => 45.894877,
2894
                'longitude' => 15.972699,
2895
                'address' => 'Here be wild boars',
2896
            ),
2897
            'eng-GB'
2898
        );
2899
2900
        $draft = $contentService->createContent($createStruct);
2901
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
2902
2903
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2904
        $createStruct->alwaysAvailable = false;
2905
        $createStruct->mainLanguageCode = 'eng-GB';
2906
        $createStruct->setField(
2907
            'maplocation',
2908
            array(
2909
                'latitude' => 45.927334,
2910
                'longitude' => 15.934847,
2911
                'address' => 'A lone tree',
2912
            ),
2913
            'eng-GB'
2914
        );
2915
2916
        $draft = $contentService->createContent($createStruct);
2917
        $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...
2918
2919
        $this->refreshSearch($repository);
2920
2921
        $query = new Query(
2922
            array(
2923
                'filter' => new Criterion\LogicalAnd(
2924
                    array(
2925
                        new Criterion\ContentTypeId($contentType->id),
2926
                        new Criterion\MapLocationDistance(
2927
                            'maplocation',
2928
                            Criterion\Operator::LTE,
2929
                            240,
2930
                            43.756825,
2931
                            15.775074
2932
                        ),
2933
                    )
2934
                ),
2935
                'offset' => 0,
2936
                'limit' => 10,
2937
                'sortClauses' => array(),
2938
            )
2939
        );
2940
2941
        $searchService = $repository->getSearchService();
2942
        $result = $searchService->findContent($query);
2943
2944
        $this->assertEquals(1, $result->totalCount);
2945
        $this->assertEquals(
2946
            $wildBoars->id,
2947
            $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...
2948
        );
2949
    }
2950
2951
    /**
2952
     * Test for the findContent() method.
2953
     *
2954
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2955
     * @group maplocation
2956
     */
2957 View Code Duplication
    public function testMapLocationDistanceGreaterThanOrEqual()
2958
    {
2959
        $contentType = $this->createTestPlaceContentType();
2960
2961
        // Create a draft to account for behaviour with ContentType in different states
2962
        $repository = $this->getRepository();
2963
        $contentTypeService = $repository->getContentTypeService();
2964
        $contentService = $repository->getContentService();
2965
        $contentTypeService->createContentTypeDraft($contentType);
2966
2967
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2968
        $createStruct->alwaysAvailable = false;
2969
        $createStruct->mainLanguageCode = 'eng-GB';
2970
        $createStruct->setField(
2971
            'maplocation',
2972
            array(
2973
                'latitude' => 45.894877,
2974
                'longitude' => 15.972699,
2975
                'address' => 'Here be wild boars',
2976
            ),
2977
            'eng-GB'
2978
        );
2979
2980
        $draft = $contentService->createContent($createStruct);
2981
        $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...
2982
2983
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2984
        $createStruct->alwaysAvailable = false;
2985
        $createStruct->mainLanguageCode = 'eng-GB';
2986
        $createStruct->setField(
2987
            'maplocation',
2988
            array(
2989
                'latitude' => 45.927334,
2990
                'longitude' => 15.934847,
2991
                'address' => 'A lone tree',
2992
            ),
2993
            'eng-GB'
2994
        );
2995
2996
        $draft = $contentService->createContent($createStruct);
2997
        $tree = $contentService->publishVersion($draft->getVersionInfo());
2998
2999
        $this->refreshSearch($repository);
3000
3001
        $query = new Query(
3002
            array(
3003
                'filter' => new Criterion\LogicalAnd(
3004
                    array(
3005
                        new Criterion\ContentTypeId($contentType->id),
3006
                        new Criterion\MapLocationDistance(
3007
                            'maplocation',
3008
                            Criterion\Operator::GTE,
3009
                            240,
3010
                            43.756825,
3011
                            15.775074
3012
                        ),
3013
                    )
3014
                ),
3015
                'offset' => 0,
3016
                'limit' => 10,
3017
                'sortClauses' => array(),
3018
            )
3019
        );
3020
3021
        $searchService = $repository->getSearchService();
3022
        $result = $searchService->findContent($query);
3023
3024
        $this->assertEquals(1, $result->totalCount);
3025
        $this->assertEquals(
3026
            $tree->id,
3027
            $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...
3028
        );
3029
    }
3030
3031
    /**
3032
     * Test for the findContent() method.
3033
     *
3034
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3035
     * @group maplocation
3036
     */
3037
    public function testMapLocationDistanceBetween()
3038
    {
3039
        $contentType = $this->createTestPlaceContentType();
3040
3041
        // Create a draft to account for behaviour with ContentType in different states
3042
        $repository = $this->getRepository();
3043
        $contentTypeService = $repository->getContentTypeService();
3044
        $contentService = $repository->getContentService();
3045
        $contentTypeService->createContentTypeDraft($contentType);
3046
3047
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3048
        $createStruct->alwaysAvailable = false;
3049
        $createStruct->mainLanguageCode = 'eng-GB';
3050
        $createStruct->setField(
3051
            'maplocation',
3052
            array(
3053
                'latitude' => 45.894877,
3054
                'longitude' => 15.972699,
3055
                'address' => 'Here be wild boars',
3056
            ),
3057
            'eng-GB'
3058
        );
3059
3060
        $draft = $contentService->createContent($createStruct);
3061
        $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...
3062
3063
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3064
        $createStruct->alwaysAvailable = false;
3065
        $createStruct->mainLanguageCode = 'eng-GB';
3066
        $createStruct->setField(
3067
            'maplocation',
3068
            array(
3069
                'latitude' => 45.927334,
3070
                'longitude' => 15.934847,
3071
                'address' => 'A lone tree',
3072
            ),
3073
            'eng-GB'
3074
        );
3075
3076
        $draft = $contentService->createContent($createStruct);
3077
        $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...
3078
3079
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3080
        $createStruct->alwaysAvailable = false;
3081
        $createStruct->mainLanguageCode = 'eng-GB';
3082
        $createStruct->setField(
3083
            'maplocation',
3084
            array(
3085
                'latitude' => 45.903777,
3086
                'longitude' => 15.958788,
3087
                'address' => 'Meadow with mushrooms',
3088
            ),
3089
            'eng-GB'
3090
        );
3091
3092
        $draft = $contentService->createContent($createStruct);
3093
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3094
3095
        $this->refreshSearch($repository);
3096
3097
        $query = new Query(
3098
            array(
3099
                'filter' => new Criterion\LogicalAnd(
3100
                    array(
3101
                        new Criterion\ContentTypeId($contentType->id),
3102
                        new Criterion\MapLocationDistance(
3103
                            'maplocation',
3104
                            Criterion\Operator::BETWEEN,
3105
                            array(239, 241),
3106
                            43.756825,
3107
                            15.775074
3108
                        ),
3109
                    )
3110
                ),
3111
                'offset' => 0,
3112
                'limit' => 10,
3113
                'sortClauses' => array(),
3114
            )
3115
        );
3116
3117
        $searchService = $repository->getSearchService();
3118
        $result = $searchService->findContent($query);
3119
3120
        $this->assertEquals(1, $result->totalCount);
3121
        $this->assertEquals(
3122
            $mushrooms->id,
3123
            $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...
3124
        );
3125
    }
3126
3127
    /**
3128
     * Test for the findContent() method.
3129
     *
3130
     * This tests the distance over the pole. The tests intentionally uses large range,
3131
     * as the flat Earth model used in Legacy Storage Search is not precise for the use case.
3132
     * What is tested here is that outer bounding box is correctly calculated, so that
3133
     * location is not excluded.
3134
     *
3135
     * Range between 222km and 350km shows the magnitude of error between great-circle
3136
     * (always very precise) and flat Earth (very imprecise for this use case) models.
3137
     *
3138
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3139
     * @group maplocation
3140
     */
3141
    public function testMapLocationDistanceBetweenPolar()
3142
    {
3143
        $contentType = $this->createTestPlaceContentType();
3144
3145
        // Create a draft to account for behaviour with ContentType in different states
3146
        $repository = $this->getRepository();
3147
        $contentTypeService = $repository->getContentTypeService();
3148
        $contentService = $repository->getContentService();
3149
        $contentTypeService->createContentTypeDraft($contentType);
3150
3151
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3152
        $createStruct->alwaysAvailable = false;
3153
        $createStruct->mainLanguageCode = 'eng-GB';
3154
        $createStruct->setField(
3155
            'maplocation',
3156
            array(
3157
                'latitude' => 89,
3158
                'longitude' => -164,
3159
                'address' => 'Polar bear media tower',
3160
            ),
3161
            'eng-GB'
3162
        );
3163
3164
        $draft = $contentService->createContent($createStruct);
3165
        $polarBear = $contentService->publishVersion($draft->getVersionInfo());
3166
3167
        $this->refreshSearch($repository);
3168
3169
        $query = new Query(
3170
            array(
3171
                'filter' => new Criterion\LogicalAnd(
3172
                    array(
3173
                        new Criterion\ContentTypeId($contentType->id),
3174
                        new Criterion\MapLocationDistance(
3175
                            'maplocation',
3176
                            Criterion\Operator::BETWEEN,
3177
                            array(221, 350),
3178
                            89,
3179
                            16
3180
                        ),
3181
                    )
3182
                ),
3183
                'offset' => 0,
3184
                'limit' => 10,
3185
                'sortClauses' => array(),
3186
            )
3187
        );
3188
3189
        $searchService = $repository->getSearchService();
3190
        $result = $searchService->findContent($query);
3191
3192
        $this->assertEquals(1, $result->totalCount);
3193
        $this->assertEquals(
3194
            $polarBear->id,
3195
            $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...
3196
        );
3197
    }
3198
3199
    /**
3200
     * Test for the findContent() method.
3201
     *
3202
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3203
     * @group maplocation
3204
     */
3205 View Code Duplication
    public function testMapLocationDistanceSortAscending()
3206
    {
3207
        $contentType = $this->createTestPlaceContentType();
3208
3209
        // Create a draft to account for behaviour with ContentType in different states
3210
        $repository = $this->getRepository();
3211
        $contentTypeService = $repository->getContentTypeService();
3212
        $contentService = $repository->getContentService();
3213
        $contentTypeService->createContentTypeDraft($contentType);
3214
3215
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3216
        $createStruct->alwaysAvailable = false;
3217
        $createStruct->mainLanguageCode = 'eng-GB';
3218
        $createStruct->setField(
3219
            'maplocation',
3220
            array(
3221
                'latitude' => 45.894877,
3222
                'longitude' => 15.972699,
3223
                'address' => 'Here be wild boars',
3224
            ),
3225
            'eng-GB'
3226
        );
3227
3228
        $draft = $contentService->createContent($createStruct);
3229
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3230
3231
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3232
        $createStruct->alwaysAvailable = false;
3233
        $createStruct->mainLanguageCode = 'eng-GB';
3234
        $createStruct->setField(
3235
            'maplocation',
3236
            array(
3237
                'latitude' => 45.927334,
3238
                'longitude' => 15.934847,
3239
                'address' => 'A lone tree',
3240
            ),
3241
            'eng-GB'
3242
        );
3243
3244
        $draft = $contentService->createContent($createStruct);
3245
        $tree = $contentService->publishVersion($draft->getVersionInfo());
3246
3247
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3248
        $createStruct->alwaysAvailable = false;
3249
        $createStruct->mainLanguageCode = 'eng-GB';
3250
        $createStruct->setField(
3251
            'maplocation',
3252
            array(
3253
                'latitude' => 45.903777,
3254
                'longitude' => 15.958788,
3255
                'address' => 'Meadow with mushrooms',
3256
            ),
3257
            'eng-GB'
3258
        );
3259
3260
        $draft = $contentService->createContent($createStruct);
3261
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3262
3263
        $this->refreshSearch($repository);
3264
3265
        $wellInVodice = array(
3266
            'latitude' => 43.756825,
3267
            'longitude' => 15.775074,
3268
        );
3269
3270
        $query = new Query(
3271
            array(
3272
                'filter' => new Criterion\LogicalAnd(
3273
                    array(
3274
                        new Criterion\ContentTypeId($contentType->id),
3275
                        new Criterion\MapLocationDistance(
3276
                            'maplocation',
3277
                            Criterion\Operator::GTE,
3278
                            235,
3279
                            $wellInVodice['latitude'],
3280
                            $wellInVodice['longitude']
3281
                        ),
3282
                    )
3283
                ),
3284
                'offset' => 0,
3285
                'limit' => 10,
3286
                'sortClauses' => array(
3287
                    new SortClause\MapLocationDistance(
3288
                        'testtype',
3289
                        'maplocation',
3290
                        $wellInVodice['latitude'],
3291
                        $wellInVodice['longitude'],
3292
                        Query::SORT_ASC
3293
                    ),
3294
                ),
3295
            )
3296
        );
3297
3298
        $searchService = $repository->getSearchService();
3299
        $result = $searchService->findContent($query);
3300
3301
        $this->assertEquals(3, $result->totalCount);
3302
        $this->assertEquals(
3303
            $wildBoars->id,
3304
            $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...
3305
        );
3306
        $this->assertEquals(
3307
            $mushrooms->id,
3308
            $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...
3309
        );
3310
        $this->assertEquals(
3311
            $tree->id,
3312
            $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...
3313
        );
3314
    }
3315
3316
    /**
3317
     * Test for the findContent() method.
3318
     *
3319
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3320
     * @group maplocation
3321
     */
3322 View Code Duplication
    public function testMapLocationDistanceSortDescending()
3323
    {
3324
        $contentType = $this->createTestPlaceContentType();
3325
3326
        // Create a draft to account for behaviour with ContentType in different states
3327
        $repository = $this->getRepository();
3328
        $contentTypeService = $repository->getContentTypeService();
3329
        $contentService = $repository->getContentService();
3330
        $contentTypeService->createContentTypeDraft($contentType);
3331
3332
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3333
        $createStruct->alwaysAvailable = false;
3334
        $createStruct->mainLanguageCode = 'eng-GB';
3335
        $createStruct->setField(
3336
            'maplocation',
3337
            array(
3338
                'latitude' => 45.894877,
3339
                'longitude' => 15.972699,
3340
                'address' => 'Here be wild boars',
3341
            ),
3342
            'eng-GB'
3343
        );
3344
3345
        $draft = $contentService->createContent($createStruct);
3346
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3347
3348
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3349
        $createStruct->alwaysAvailable = false;
3350
        $createStruct->mainLanguageCode = 'eng-GB';
3351
        $createStruct->setField(
3352
            'maplocation',
3353
            array(
3354
                'latitude' => 45.927334,
3355
                'longitude' => 15.934847,
3356
                'address' => 'A lone tree',
3357
            ),
3358
            'eng-GB'
3359
        );
3360
3361
        $draft = $contentService->createContent($createStruct);
3362
        $tree = $contentService->publishVersion($draft->getVersionInfo());
3363
3364
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3365
        $createStruct->alwaysAvailable = false;
3366
        $createStruct->mainLanguageCode = 'eng-GB';
3367
        $createStruct->setField(
3368
            'maplocation',
3369
            array(
3370
                'latitude' => 45.903777,
3371
                'longitude' => 15.958788,
3372
                'address' => 'Meadow with mushrooms',
3373
            ),
3374
            'eng-GB'
3375
        );
3376
3377
        $draft = $contentService->createContent($createStruct);
3378
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3379
3380
        $this->refreshSearch($repository);
3381
3382
        $well = array(
3383
            'latitude' => 43.756825,
3384
            'longitude' => 15.775074,
3385
        );
3386
3387
        $query = new Query(
3388
            array(
3389
                'filter' => new Criterion\LogicalAnd(
3390
                    array(
3391
                        new Criterion\ContentTypeId($contentType->id),
3392
                        new Criterion\MapLocationDistance(
3393
                            'maplocation',
3394
                            Criterion\Operator::GTE,
3395
                            235,
3396
                            $well['latitude'],
3397
                            $well['longitude']
3398
                        ),
3399
                    )
3400
                ),
3401
                'offset' => 0,
3402
                'limit' => 10,
3403
                'sortClauses' => array(
3404
                    new SortClause\MapLocationDistance(
3405
                        'testtype',
3406
                        'maplocation',
3407
                        $well['latitude'],
3408
                        $well['longitude'],
3409
                        Query::SORT_DESC
3410
                    ),
3411
                ),
3412
            )
3413
        );
3414
3415
        $searchService = $repository->getSearchService();
3416
        $result = $searchService->findContent($query);
3417
3418
        $this->assertEquals(3, $result->totalCount);
3419
        $this->assertEquals(
3420
            $wildBoars->id,
3421
            $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...
3422
        );
3423
        $this->assertEquals(
3424
            $mushrooms->id,
3425
            $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...
3426
        );
3427
        $this->assertEquals(
3428
            $tree->id,
3429
            $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...
3430
        );
3431
    }
3432
3433
    /**
3434
     * Test for the findContent() method.
3435
     *
3436
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3437
     * @group maplocation
3438
     */
3439
    public function testMapLocationDistanceWithCustomField()
3440
    {
3441
        $setupFactory = $this->getSetupFactory();
3442
        if ($setupFactory instanceof LegacyElasticsearch) {
3443
            $this->markTestIncomplete("TODO: Some issues with 'copy_to' and 'geo_point'");
3444
        }
3445
3446
        $contentType = $this->createTestPlaceContentType();
3447
3448
        // Create a draft to account for behaviour with ContentType in different states
3449
        $repository = $this->getRepository();
3450
        $contentTypeService = $repository->getContentTypeService();
3451
        $contentService = $repository->getContentService();
3452
        $contentTypeService->createContentTypeDraft($contentType);
3453
3454
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3455
        $createStruct->alwaysAvailable = false;
3456
        $createStruct->mainLanguageCode = 'eng-GB';
3457
        $createStruct->setField(
3458
            'maplocation',
3459
            array(
3460
                'latitude' => 45.894877,
3461
                'longitude' => 15.972699,
3462
                'address' => 'Here be wild boars',
3463
            ),
3464
            'eng-GB'
3465
        );
3466
3467
        $draft = $contentService->createContent($createStruct);
3468
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3469
3470
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3471
        $createStruct->alwaysAvailable = false;
3472
        $createStruct->mainLanguageCode = 'eng-GB';
3473
        $createStruct->setField(
3474
            'maplocation',
3475
            array(
3476
                'latitude' => 45.927334,
3477
                'longitude' => 15.934847,
3478
                'address' => 'A lone tree',
3479
            ),
3480
            'eng-GB'
3481
        );
3482
3483
        $draft = $contentService->createContent($createStruct);
3484
        $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...
3485
3486
        $this->refreshSearch($repository);
3487
3488
        $distanceCriterion = new Criterion\MapLocationDistance(
3489
            'maplocation',
3490
            Criterion\Operator::LTE,
3491
            240,
3492
            43.756825,
3493
            15.775074
3494
        );
3495
        $distanceCriterion->setCustomField('testtype', 'maplocation', 'custom_geolocation_field');
3496
3497
        $query = new Query(
3498
            array(
3499
                'filter' => new Criterion\LogicalAnd(
3500
                    array(
3501
                        new Criterion\ContentTypeId($contentType->id),
3502
                        $distanceCriterion,
3503
                    )
3504
                ),
3505
                'offset' => 0,
3506
                'limit' => 10,
3507
                'sortClauses' => array(),
3508
            )
3509
        );
3510
3511
        $searchService = $repository->getSearchService();
3512
        $result = $searchService->findContent($query);
3513
3514
        $this->assertEquals(1, $result->totalCount);
3515
        $this->assertEquals(
3516
            $wildBoars->id,
3517
            $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...
3518
        );
3519
    }
3520
3521
    /**
3522
     * Test for the findContent() method.
3523
     *
3524
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3525
     * @group maplocation
3526
     */
3527
    public function testMapLocationDistanceWithCustomFieldSort()
3528
    {
3529
        $setupFactory = $this->getSetupFactory();
3530
        if ($setupFactory instanceof LegacyElasticsearch) {
3531
            $this->markTestIncomplete("TODO: Some issues with 'copy_to' and 'geo_point'");
3532
        }
3533
3534
        $contentType = $this->createTestPlaceContentType();
3535
3536
        // Create a draft to account for behaviour with ContentType in different states
3537
        $repository = $this->getRepository();
3538
        $contentTypeService = $repository->getContentTypeService();
3539
        $contentService = $repository->getContentService();
3540
        $contentTypeService->createContentTypeDraft($contentType);
3541
3542
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3543
        $createStruct->alwaysAvailable = false;
3544
        $createStruct->mainLanguageCode = 'eng-GB';
3545
        $createStruct->setField(
3546
            'maplocation',
3547
            array(
3548
                'latitude' => 45.894877,
3549
                'longitude' => 15.972699,
3550
                'address' => 'Here be wild boars',
3551
            ),
3552
            'eng-GB'
3553
        );
3554
3555
        $draft = $contentService->createContent($createStruct);
3556
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3557
3558
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3559
        $createStruct->alwaysAvailable = false;
3560
        $createStruct->mainLanguageCode = 'eng-GB';
3561
        $createStruct->setField(
3562
            'maplocation',
3563
            array(
3564
                'latitude' => 45.927334,
3565
                'longitude' => 15.934847,
3566
                'address' => 'A lone tree',
3567
            ),
3568
            'eng-GB'
3569
        );
3570
3571
        $draft = $contentService->createContent($createStruct);
3572
        $tree = $contentService->publishVersion($draft->getVersionInfo());
3573
3574
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3575
        $createStruct->alwaysAvailable = false;
3576
        $createStruct->mainLanguageCode = 'eng-GB';
3577
        $createStruct->setField(
3578
            'maplocation',
3579
            array(
3580
                'latitude' => 45.903777,
3581
                'longitude' => 15.958788,
3582
                'address' => 'Meadow with mushrooms',
3583
            ),
3584
            'eng-GB'
3585
        );
3586
3587
        $draft = $contentService->createContent($createStruct);
3588
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3589
3590
        $this->refreshSearch($repository);
3591
3592
        $well = array(
3593
            'latitude' => 43.756825,
3594
            'longitude' => 15.775074,
3595
        );
3596
3597
        $sortClause = new SortClause\MapLocationDistance(
3598
            'testtype',
3599
            'maplocation',
3600
            $well['latitude'],
3601
            $well['longitude'],
3602
            Query::SORT_DESC
3603
        );
3604
        $sortClause->setCustomField('testtype', 'maplocation', 'custom_geolocation_field');
3605
3606
        $query = new Query(
3607
            array(
3608
                'filter' => new Criterion\LogicalAnd(
3609
                    array(
3610
                        new Criterion\ContentTypeId($contentType->id),
3611
                        new Criterion\MapLocationDistance(
3612
                            'maplocation',
3613
                            Criterion\Operator::GTE,
3614
                            235,
3615
                            $well['latitude'],
3616
                            $well['longitude']
3617
                        ),
3618
                    )
3619
                ),
3620
                'offset' => 0,
3621
                'limit' => 10,
3622
                'sortClauses' => array(
3623
                    $sortClause,
3624
                ),
3625
            )
3626
        );
3627
3628
        $searchService = $repository->getSearchService();
3629
        $result = $searchService->findContent($query);
3630
3631
        $this->assertEquals(3, $result->totalCount);
3632
        $this->assertEquals(
3633
            $wildBoars->id,
3634
            $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...
3635
        );
3636
        $this->assertEquals(
3637
            $mushrooms->id,
3638
            $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...
3639
        );
3640
        $this->assertEquals(
3641
            $tree->id,
3642
            $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...
3643
        );
3644
    }
3645
3646
    /**
3647
     * Test for the findLocations() method.
3648
     *
3649
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3650
     */
3651 View Code Duplication
    public function testFindMainLocation()
3652
    {
3653
        $plainSiteLocationId = 56;
3654
        $designLocationId = 58;
3655
        $partnersContentId = 59;
3656
        $repository = $this->getRepository();
3657
        $locationService = $repository->getLocationService();
3658
        $contentService = $repository->getContentService();
3659
3660
        // Add secondary Location for "Partners" user group, under "Design" page
3661
        $locationService->createLocation(
3662
            $contentService->loadContentInfo($partnersContentId),
3663
            $locationService->newLocationCreateStruct($designLocationId)
3664
        );
3665
3666
        $this->refreshSearch($repository);
3667
3668
        $query = new LocationQuery(
3669
            array(
3670
                'filter' => new Criterion\LogicalAnd(
3671
                    array(
3672
                        new Criterion\ParentLocationId($designLocationId),
3673
                        new Criterion\Location\IsMainLocation(
3674
                            Criterion\Location\IsMainLocation::MAIN
3675
                        ),
3676
                    )
3677
                ),
3678
                'offset' => 0,
3679
                'limit' => 10,
3680
                'sortClauses' => array(),
3681
            )
3682
        );
3683
3684
        $searchService = $repository->getSearchService();
3685
        $result = $searchService->findLocations($query);
3686
3687
        $this->assertEquals(1, $result->totalCount);
3688
        $this->assertEquals($plainSiteLocationId, $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...
3689
    }
3690
3691
    /**
3692
     * Test for the findLocations() method.
3693
     *
3694
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3695
     */
3696 View Code Duplication
    public function testFindNonMainLocation()
3697
    {
3698
        $designLocationId = 58;
3699
        $partnersContentId = 59;
3700
        $repository = $this->getRepository();
3701
        $locationService = $repository->getLocationService();
3702
        $contentService = $repository->getContentService();
3703
3704
        // Add secondary Location for "Partners" user group, under "Design" page
3705
        $newLocation = $locationService->createLocation(
3706
            $contentService->loadContentInfo($partnersContentId),
3707
            $locationService->newLocationCreateStruct($designLocationId)
3708
        );
3709
3710
        $this->refreshSearch($repository);
3711
3712
        $query = new LocationQuery(
3713
            array(
3714
                'filter' => new Criterion\LogicalAnd(
3715
                    array(
3716
                        new Criterion\ParentLocationId($designLocationId),
3717
                        new Criterion\Location\IsMainLocation(
3718
                            Criterion\Location\IsMainLocation::NOT_MAIN
3719
                        ),
3720
                    )
3721
                ),
3722
                'offset' => 0,
3723
                'limit' => 10,
3724
                'sortClauses' => array(),
3725
            )
3726
        );
3727
3728
        $searchService = $repository->getSearchService();
3729
        $result = $searchService->findLocations($query);
3730
3731
        $this->assertEquals(1, $result->totalCount);
3732
        $this->assertEquals($newLocation->id, $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...
3733
    }
3734
3735
    /**
3736
     * Test for the findLocations() method.
3737
     *
3738
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3739
     */
3740 View Code Duplication
    public function testSortMainLocationAscending()
3741
    {
3742
        $plainSiteLocationId = 56;
3743
        $designLocationId = 58;
3744
        $partnersContentId = 59;
3745
        $repository = $this->getRepository();
3746
        $locationService = $repository->getLocationService();
3747
        $contentService = $repository->getContentService();
3748
3749
        // Add secondary Location for "Partners" user group, under "Design" page
3750
        $newLocation = $locationService->createLocation(
3751
            $contentService->loadContentInfo($partnersContentId),
3752
            $locationService->newLocationCreateStruct($designLocationId)
3753
        );
3754
3755
        $this->refreshSearch($repository);
3756
3757
        $query = new LocationQuery(
3758
            array(
3759
                'filter' => new Criterion\ParentLocationId($designLocationId),
3760
                'offset' => 0,
3761
                'limit' => 10,
3762
                'sortClauses' => array(
3763
                    new SortClause\Location\IsMainLocation(
3764
                        LocationQuery::SORT_ASC
3765
                    ),
3766
                ),
3767
            )
3768
        );
3769
3770
        $searchService = $repository->getSearchService();
3771
        $result = $searchService->findLocations($query);
3772
3773
        $this->assertEquals(2, $result->totalCount);
3774
        $this->assertEquals($newLocation->id, $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...
3775
        $this->assertEquals($plainSiteLocationId, $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...
3776
    }
3777
3778
    /**
3779
     * Test for the findLocations() method.
3780
     *
3781
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3782
     */
3783 View Code Duplication
    public function testSortMainLocationDescending()
3784
    {
3785
        $plainSiteLocationId = 56;
3786
        $designLocationId = 58;
3787
        $partnersContentId = 59;
3788
        $repository = $this->getRepository();
3789
        $locationService = $repository->getLocationService();
3790
        $contentService = $repository->getContentService();
3791
3792
        // Add secondary Location for "Partners" user group, under "Design" page
3793
        $newLocation = $locationService->createLocation(
3794
            $contentService->loadContentInfo($partnersContentId),
3795
            $locationService->newLocationCreateStruct($designLocationId)
3796
        );
3797
3798
        $this->refreshSearch($repository);
3799
3800
        $query = new LocationQuery(
3801
            array(
3802
                'filter' => new Criterion\ParentLocationId($designLocationId),
3803
                'offset' => 0,
3804
                'limit' => 10,
3805
                'sortClauses' => array(
3806
                    new SortClause\Location\IsMainLocation(
3807
                        LocationQuery::SORT_DESC
3808
                    ),
3809
                ),
3810
            )
3811
        );
3812
3813
        $searchService = $repository->getSearchService();
3814
        $result = $searchService->findLocations($query);
3815
3816
        $this->assertEquals(2, $result->totalCount);
3817
        $this->assertEquals($plainSiteLocationId, $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...
3818
        $this->assertEquals($newLocation->id, $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...
3819
    }
3820
3821
    /**
3822
     * Test for the findLocations() method.
3823
     *
3824
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3825
     */
3826
    public function testContentWithMultipleLocations()
3827
    {
3828
        $repository = $this->getRepository();
3829
        $contentService = $repository->getContentService();
3830
        $contentTypeService = $repository->getContentTypeService();
3831
        $locationService = $repository->getLocationService();
3832
3833
        $forumType = $contentTypeService->loadContentTypeByIdentifier('forum');
3834
3835
        $createStruct = $contentService->newContentCreateStruct($forumType, 'eng-GB');
3836
        $createStruct->alwaysAvailable = false;
3837
        $createStruct->setField('name', 'An awesome duplicate forum');
3838
3839
        $draft = $contentService->createContent($createStruct);
3840
        $content = $contentService->publishVersion($draft->getVersionInfo());
3841
3842
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
3843
        $location1 = $locationService->createLocation($content->contentInfo, $locationCreateStruct);
3844
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(5);
3845
        $location2 = $locationService->createLocation($content->contentInfo, $locationCreateStruct);
3846
3847
        $this->refreshSearch($repository);
3848
3849
        $query = new LocationQuery(
3850
            array(
3851
                'filter' => new Criterion\ContentId($content->id),
3852
                'sortClauses' => array(
3853
                    new SortClause\Location\Id(LocationQuery::SORT_ASC),
3854
                ),
3855
            )
3856
        );
3857
3858
        $searchService = $repository->getSearchService();
3859
        $result = $searchService->findLocations($query);
3860
3861
        $this->assertEquals(2, $result->totalCount);
3862
        $this->assertEquals(
3863
            $location1->id,
3864
            $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...
3865
        );
3866
        $this->assertEquals(
3867
            $location2->id,
3868
            $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...
3869
        );
3870
    }
3871
3872
    protected function createContentForTestUserMetadataGroupHorizontal()
3873
    {
3874
        $repository = $this->getRepository();
3875
        $contentService = $repository->getContentService();
3876
        $contentTypeService = $repository->getContentTypeService();
3877
        $locationService = $repository->getLocationService();
3878
        $userService = $repository->getUserService();
3879
        $administratorUser = $repository->getCurrentUser();
3880
        // ID of the "Administrators" user group in an eZ Publish demo installation
3881
        $administratorsUserGroupId = 12;
3882
        // ID of the "Editors" user group in an eZ Publish demo installation
3883
        $editorsUserGroupId = 13;
3884
3885
        $administratorsUserGroup = $userService->loadUserGroup($administratorsUserGroupId);
3886
        $editorsUserGroup = $userService->loadUserGroup($editorsUserGroupId);
3887
3888
        // Add additional Location for Administrators UserGroup under Editors UserGroup Location
3889
        $locationCreateStruct = $locationService->newLocationCreateStruct(
3890
            $editorsUserGroup->contentInfo->mainLocationId
3891
        );
3892
        $newAdministratorsUserGroupLocation = $locationService->createLocation(
3893
            $administratorsUserGroup->contentInfo,
3894
            $locationCreateStruct
3895
        );
3896
3897
        // Add additional Location for administrator user under newly created UserGroup Location
3898
        $locationCreateStruct = $locationService->newLocationCreateStruct(
3899
            $newAdministratorsUserGroupLocation->id
3900
        );
3901
        $locationService->createLocation(
3902
            $administratorUser->contentInfo,
3903
            $locationCreateStruct
3904
        );
3905
3906
        // Create a Content to be found through Editors UserGroup id.
3907
        // This ensures data is indexed, it could also be done by updating metadata of
3908
        // an existing Content, but slot would need to reindex Content and that should
3909
        // be tested elsewhere (dedicated indexing integration tests, missing ATM).
3910
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
3911
3912
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3913
        $createStruct->setField('name', 'test');
3914
3915
        $locationCreateStruct = $locationService->newLocationCreateStruct(2);
3916
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
3917
        $content = $contentService->publishVersion($draft->getVersionInfo());
3918
        $contentTypeService->createContentTypeDraft($contentType);
3919
3920
        $this->refreshSearch($repository);
3921
3922
        return $content;
3923
    }
3924
3925
    /**
3926
     * Test for the findContent() method.
3927
     *
3928
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3929
     */
3930
    public function testUserMetadataGroupHorizontalFilterContent($queryType = null)
3931
    {
3932
        if ($queryType === null) {
3933
            $queryType = 'filter';
3934
        }
3935
3936
        $repository = $this->getRepository();
3937
        $searchService = $repository->getSearchService();
3938
        $editorsUserGroupId = 13;
3939
3940
        $content = $this->createContentForTestUserMetadataGroupHorizontal();
3941
3942
        $criteria = array();
3943
        $setupFactory = $this->getSetupFactory();
3944
3945
        // Do not limit for LSE, as it does not not require reindexing.
3946
        // See explanation below.
3947
        if ($setupFactory instanceof LegacySolrSetupFactory || $setupFactory instanceof LegacyElasticsearch) {
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...
3948
            $criteria[] = new Criterion\ContentTypeIdentifier('folder');
3949
        }
3950
3951
        $criteria[] = new Criterion\UserMetadata(
3952
            Criterion\UserMetadata::GROUP,
3953
            Criterion\Operator::EQ,
3954
            $editorsUserGroupId
3955
        );
3956
3957
        $query = new Query(
3958
            array(
3959
                $queryType => new Criterion\LogicalAnd($criteria),
3960
                'sortClauses' => array(
3961
                    new SortClause\ContentId(),
3962
                ),
3963
                'limit' => 50,
3964
            )
3965
        );
3966
3967
        if ($setupFactory instanceof LegacySolrSetupFactory || $setupFactory instanceof LegacyElasticsearch) {
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...
3968
            $result = $searchService->findContent($query);
3969
3970
            // Administrator User is owned by itself, when additional Locations are added
3971
            // it should be reindexed and its UserGroups will updated, which means it should
3972
            // also be found as a Content of Editors UserGroup. However we do not handle this
3973
            // in slots yet, and also miss SPI methods to do it without using Search (also
3974
            // needed to decouple services), because as indexing is asynchronous Search
3975
            // should not eat its own dog food for reindexing.
3976
            $this->assertEquals(1, $result->totalCount);
3977
3978
            $this->assertEquals(
3979
                $content->id,
3980
                $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...
3981
            );
3982
        } else {
3983
            // This is how it should eventually work for all search engines,
3984
            // with required reindexing slots properly implemented.
3985
3986
            $result = $searchService->findContent($query);
3987
3988
            // Assert last hit manually, as id will change because it is created in test
3989
            // and not present it base fixture.
3990
            $foundContent1 = array_pop($result->searchHits);
3991
            $result->totalCount = $result->totalCount - 1;
0 ignored issues
show
Documentation Bug introduced by
It seems like $result->totalCount - 1 can also be of type double. However, the property $totalCount is declared as type integer|null. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
3992
            $this->assertEquals($content->id, $foundContent1->valueObject->id);
3993
3994
            $this->simplifySearchResult($result);
3995
            $this->assertEquals(
3996
                include $this->getFixtureDir() . '/UserMetadata.php',
3997
                $result,
3998
                'Search results do not match.',
3999
                .1 // Be quite generous regarding delay -- most important for scores
4000
            );
4001
        }
4002
    }
4003
4004
    /**
4005
     * Test for the findContent() method.
4006
     *
4007
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4008
     */
4009
    public function testUserMetadataGroupHorizontalQueryContent()
4010
    {
4011
        $this->testUserMetadataGroupHorizontalFilterContent('query');
4012
    }
4013
4014
    /**
4015
     * Test for the findLocations() method.
4016
     *
4017
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
4018
     */
4019
    public function testUserMetadataGroupHorizontalFilterLocation($queryType = null)
4020
    {
4021
        if ($queryType === null) {
4022
            $queryType = 'filter';
4023
        }
4024
4025
        $repository = $this->getRepository();
4026
        $searchService = $repository->getSearchService();
4027
        $editorsUserGroupId = 13;
4028
4029
        $content = $this->createContentForTestUserMetadataGroupHorizontal();
4030
4031
        $criteria = array();
4032
        $setupFactory = $this->getSetupFactory();
4033
4034
        // Do not limit for LSE, as it does not not require reindexing.
4035
        // See explanation below.
4036
        if ($setupFactory instanceof LegacySolrSetupFactory || $setupFactory instanceof LegacyElasticsearch) {
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...
4037
            $criteria[] = new Criterion\ContentTypeIdentifier('folder');
4038
        }
4039
4040
        $criteria[] = new Criterion\UserMetadata(
4041
            Criterion\UserMetadata::GROUP,
4042
            Criterion\Operator::EQ,
4043
            $editorsUserGroupId
4044
        );
4045
4046
        $query = new LocationQuery(
4047
            array(
4048
                $queryType => new Criterion\LogicalAnd($criteria),
4049
                'sortClauses' => array(
4050
                    new SortClause\Location\Id(),
4051
                ),
4052
                'limit' => 50,
4053
            )
4054
        );
4055
4056
        if ($setupFactory instanceof LegacySolrSetupFactory || $setupFactory instanceof LegacyElasticsearch) {
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...
4057
            $result = $searchService->findLocations($query);
4058
4059
            // Administrator User is owned by itself, when additional Locations are added
4060
            // it should be reindexed and its UserGroups will updated, which means it should
4061
            // also be found as a Content of Editors UserGroup. However we do not handle this
4062
            // in slots yet, and also miss SPI methods to do it without using Search (also
4063
            // needed to decouple services), because as indexing is asynchronous Search
4064
            // should not eat its own dog food for reindexing.
4065
            $this->assertEquals(1, $result->totalCount);
4066
4067
            $this->assertEquals(
4068
                $content->contentInfo->mainLocationId,
4069
                $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...
4070
            );
4071
        } else {
4072
            // This is how it should eventually work for all search engines,
4073
            // with required reindexing slots properly implemented.
4074
4075
            $result = $searchService->findLocations($query);
4076
4077
            // Assert last two hits manually, as ids will change because they are created
4078
            // in test and not present in base fixture.
4079
            $foundLocation1 = array_pop($result->searchHits);
4080
            $foundLocation2 = array_pop($result->searchHits);
4081
            // Remove additional Administrators UserGroup Location
4082
            array_pop($result->searchHits);
4083
            $result->totalCount = $result->totalCount - 2;
0 ignored issues
show
Documentation Bug introduced by
It seems like $result->totalCount - 2 can also be of type double. However, the property $totalCount is declared as type integer|null. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
4084
            $this->assertEquals(
4085
                $content->versionInfo->contentInfo->mainLocationId,
4086
                $foundLocation1->valueObject->id
4087
            );
4088
            $this->assertEquals(
4089
                $repository->getCurrentUser()->id,
4090
                $foundLocation2->valueObject->contentId
4091
            );
4092
4093
            $this->simplifySearchResult($result);
4094
            $this->assertEquals(
4095
                include $this->getFixtureDir() . '/UserMetadataLocation.php',
4096
                $result,
4097
                'Search results do not match.',
4098
                .1 // Be quite generous regarding delay -- most important for scores
4099
            );
4100
        }
4101
    }
4102
4103
    /**
4104
     * Test for the findLocations() method.
4105
     *
4106
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
4107
     */
4108
    public function testUserMetadataGroupHorizontalQueryLocation()
4109
    {
4110
        $this->testUserMetadataGroupHorizontalFilterLocation('query');
4111
    }
4112
4113
    /**
4114
     * Test for the findContent() method.
4115
     *
4116
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4117
     */
4118
    public function testLanguageAnalysisSeparateContent()
4119
    {
4120
        $setupFactory = $this->getSetupFactory();
4121
        if (!$setupFactory instanceof LegacyElasticsearch) {
4122
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4123
        }
4124
4125
        $repository = $this->getRepository();
4126
        $contentService = $repository->getContentService();
4127
        $contentTypeService = $repository->getContentTypeService();
4128
        $locationService = $repository->getLocationService();
4129
        $searchService = $repository->getSearchService();
4130
        $languageService = $repository->getContentLanguageService();
4131
4132
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4133
        $languageCreateStruct->languageCode = 'rus-RU';
4134
        $languageCreateStruct->name = 'Russian';
4135
4136
        $languageService->createLanguage($languageCreateStruct);
4137
4138
        $contentCreateStruct = $contentService->newContentCreateStruct(
4139
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4140
            'eng-GB'
4141
        );
4142
4143
        $contentCreateStruct->setField('name', 'foxes');
4144
4145
        $englishContent = $contentService->publishVersion(
4146
            $contentService->createContent(
4147
                $contentCreateStruct,
4148
                array($locationService->newLocationCreateStruct(2))
4149
            )->versionInfo
4150
        );
4151
4152
        $contentCreateStruct = $contentService->newContentCreateStruct(
4153
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4154
            'rus-RU'
4155
        );
4156
4157
        $contentCreateStruct->setField('name', 'foxes');
4158
4159
        $russianContent = $contentService->publishVersion(
0 ignored issues
show
Unused Code introduced by
$russianContent 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...
4160
            $contentService->createContent(
4161
                $contentCreateStruct,
4162
                array($locationService->newLocationCreateStruct(2))
4163
            )->versionInfo
4164
        );
4165
4166
        // Only Content in English should be found, because Content in Russian
4167
        // will not be correctly stemmed
4168
        $query = new Query(
4169
            array(
4170
                'query' => new Criterion\FullText('foxing'),
4171
            )
4172
        );
4173
4174
        $searchResult = $searchService->findContent($query);
4175
4176
        $this->assertEquals(1, $searchResult->totalCount);
4177
        $this->assertEquals($englishContent->id, $searchResult->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...
4178
    }
4179
4180
    /**
4181
     * Test for the findContent() method.
4182
     *
4183
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4184
     */
4185
    public function testLanguageAnalysisSameContent()
4186
    {
4187
        $setupFactory = $this->getSetupFactory();
4188
        if (!$setupFactory instanceof LegacyElasticsearch) {
4189
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4190
        }
4191
4192
        $repository = $this->getRepository();
4193
        $contentService = $repository->getContentService();
4194
        $contentTypeService = $repository->getContentTypeService();
4195
        $locationService = $repository->getLocationService();
4196
        $searchService = $repository->getSearchService();
4197
        $languageService = $repository->getContentLanguageService();
4198
4199
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4200
        $languageCreateStruct->languageCode = 'rus-RU';
4201
        $languageCreateStruct->name = 'Russian';
4202
4203
        $languageService->createLanguage($languageCreateStruct);
4204
4205
        $contentCreateStruct = $contentService->newContentCreateStruct(
4206
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4207
            'eng-GB'
4208
        );
4209
4210
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'eng-GB');
4211
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'rus-RU');
4212
4213
        $mixedContent = $contentService->publishVersion(
4214
            $contentService->createContent(
4215
                $contentCreateStruct,
4216
                array($locationService->newLocationCreateStruct(2))
4217
            )->versionInfo
4218
        );
4219
4220
        // Content will be found because translation in Russian will be correctly stemmed
4221
        $query = new Query(
4222
            array(
4223
                'query' => new Criterion\FullText('важнее'),
4224
            )
4225
        );
4226
4227
        $searchResult = $searchService->findContent($query);
4228
4229
        $this->assertEquals(1, $searchResult->totalCount);
4230
        $this->assertEquals($mixedContent->id, $searchResult->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...
4231
    }
4232
4233
    /**
4234
     * Test for the findContent() method.
4235
     *
4236
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4237
     */
4238
    public function testLanguageAnalysisSameContentNotFound()
4239
    {
4240
        $setupFactory = $this->getSetupFactory();
4241
        if (!$setupFactory instanceof LegacyElasticsearch) {
4242
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4243
        }
4244
4245
        $repository = $this->getRepository();
4246
        $contentService = $repository->getContentService();
4247
        $contentTypeService = $repository->getContentTypeService();
4248
        $locationService = $repository->getLocationService();
4249
        $searchService = $repository->getSearchService();
4250
        $languageService = $repository->getContentLanguageService();
4251
4252
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4253
        $languageCreateStruct->languageCode = 'rus-RU';
4254
        $languageCreateStruct->name = 'Russian';
4255
4256
        $languageService->createLanguage($languageCreateStruct);
4257
4258
        $contentCreateStruct = $contentService->newContentCreateStruct(
4259
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4260
            'eng-GB'
4261
        );
4262
4263
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'eng-GB');
4264
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'rus-RU');
4265
4266
        $mixedContent = $contentService->publishVersion(
0 ignored issues
show
Unused Code introduced by
$mixedContent 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...
4267
            $contentService->createContent(
4268
                $contentCreateStruct,
4269
                array($locationService->newLocationCreateStruct(2))
4270
            )->versionInfo
4271
        );
4272
4273
        // Content should be found because translation in Russian will be correctly stemmed
4274
        $query = new Query(
4275
            array(
4276
                'query' => new Criterion\FullText('важнее'),
4277
            )
4278
        );
4279
4280
        // Filtering fields for only English will cause no match because the term will
4281
        // not be correctly stemmed
4282
        $searchResult = $searchService->findContent($query, array('languages' => array('eng-GB')));
4283
4284
        $this->assertEquals(0, $searchResult->totalCount);
4285
    }
4286
4287
    /**
4288
     * Assert that query result matches the given fixture.
4289
     *
4290
     * @param Query $query
4291
     * @param string $fixture
4292
     * @param null|callable $closure
4293
     * @param bool $info
4294
     * @param bool $id
4295
     */
4296
    protected function assertQueryFixture(Query $query, $fixture, $closure = null, $ignoreScore = true, $info = false, $id = true)
4297
    {
4298
        $repository = $this->getRepository();
4299
        $searchService = $repository->getSearchService();
4300
4301
        try {
4302
            if ($query instanceof LocationQuery) {
4303
                $setupFactory = $this->getSetupFactory();
4304
                if ($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...
4305
                    // @todo When we want to test score again by default we will need fixtures for Solr
4306
                }
4307
4308
                if ($setupFactory instanceof LegacyElasticsearch) {
4309
                    $position = strrpos($fixture, '/');
4310
                    $fixture = substr_replace($fixture, '/Location', $position, 0);
4311
                }
4312
4313
                $result = $searchService->findLocations($query);
4314
            } elseif ($query instanceof Query) {
4315
                if ($info) {
4316
                    $result = $searchService->findContentInfo($query);
4317
                } else {
4318
                    $result = $searchService->findContent($query);
4319
                }
4320
            } else {
4321
                $this->fail('Expected instance of LocationQuery or Query, got: ' . gettype($query));
4322
            }
4323
            $this->simplifySearchResult($result);
0 ignored issues
show
Bug introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
4324
        } catch (NotImplementedException $e) {
4325
            $this->markTestSkipped(
4326
                'This feature is not supported by the current search backend: ' . $e->getMessage()
4327
            );
4328
        }
4329
4330 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...
4331
            if (isset($_ENV['ez_tests_record'])) {
4332
                file_put_contents(
4333
                    $record = $fixture . '.recording',
4334
                    "<?php\n\nreturn " . var_export($result, true) . ";\n\n"
4335
                );
4336
                $this->markTestIncomplete("No fixture available. Result recorded at $record. Result: \n" . $this->printResult($result));
4337
            } else {
4338
                $this->markTestIncomplete("No fixture available. Set \$_ENV['ez_tests_record'] to generate it.");
4339
            }
4340
        }
4341
4342
        $fixture = include $fixture;
4343
4344
        if ($closure !== null) {
4345
            $closure($fixture);
4346
            $closure($result);
4347
        }
4348
4349 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...
4350
            foreach (array($fixture, $result) as $set) {
4351
                $property = new \ReflectionProperty(get_class($set), 'maxScore');
4352
                $property->setAccessible(true);
4353
                $property->setValue($set, 0.0);
4354
4355
                foreach ($set->searchHits as $hit) {
4356
                    $property = new \ReflectionProperty(get_class($hit), 'score');
4357
                    $property->setAccessible(true);
4358
                    $property->setValue($hit, 0.0);
4359
                }
4360
            }
4361
        }
4362
4363
        foreach (array($fixture, $result) as $set) {
4364
            foreach ($set->searchHits as $hit) {
4365
                $property = new \ReflectionProperty(get_class($hit), 'index');
4366
                $property->setAccessible(true);
4367
                $property->setValue($hit, null);
4368
4369
                $property = new \ReflectionProperty(get_class($hit), 'matchedTranslation');
4370
                $property->setAccessible(true);
4371
                $property->setValue($hit, null);
4372
4373
                if (!$id) {
4374
                    $hit->valueObject['id'] = null;
4375
                }
4376
            }
4377
        }
4378
4379
        $this->assertEquals(
4380
            $fixture,
4381
            $result,
4382
            'Search results do not match.',
4383
            .99 // Be quite generous regarding delay -- most important for scores
4384
        );
4385
    }
4386
4387
    /**
4388
     * Show a simplified view of the search result for manual introspection.
4389
     *
4390
     * @param SearchResult $result
4391
     *
4392
     * @return string
4393
     */
4394 View Code Duplication
    protected function printResult(SearchResult $result)
4395
    {
4396
        $printed = '';
4397
        foreach ($result->searchHits as $hit) {
4398
            $printed .= sprintf(" - %s (%s)\n", $hit->valueObject['title'], $hit->valueObject['id']);
4399
        }
4400
4401
        return $printed;
4402
    }
4403
4404
    /**
4405
     * Simplify search result.
4406
     *
4407
     * This leads to saner comparisons of results, since we do not get the full
4408
     * content objects every time.
4409
     *
4410
     * @param SearchResult $result
4411
     */
4412
    protected function simplifySearchResult(SearchResult $result)
4413
    {
4414
        $result->time = 1;
4415
4416
        foreach ($result->searchHits as $hit) {
4417
            switch (true) {
4418
                case $hit->valueObject instanceof Content:
4419 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...
4420
                    $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":"?"}> 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...
4421
                        'id' => $hit->valueObject->contentInfo->id,
4422
                        'title' => $hit->valueObject->contentInfo->name,
4423
                    );
4424
                    break;
4425
4426
                case $hit->valueObject instanceof ContentInfo:
4427
                    $hit->valueObject = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('id' => $hit->valu...hit->valueObject->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...
4428
                        'id' => $hit->valueObject->id,
4429
                        'title' => $hit->valueObject->name,
4430
                    );
4431
                    break;
4432
4433
                default:
4434
                    throw new \RuntimeException('Unknown search result hit type: ' . get_class($hit->valueObject));
4435
            }
4436
        }
4437
    }
4438
4439
    /**
4440
     * Get fixture directory.
4441
     *
4442
     * @return string
4443
     */
4444
    protected function getFixtureDir()
4445
    {
4446
        return __DIR__ . '/_fixtures/' . getenv('fixtureDir') . '/';
4447
    }
4448
4449
    /**
4450
     * For findContentInfo tests, to reuse fixtures for findContent tests.
4451
     *
4452
     * @param null|callable $closure
4453
     *
4454
     * @return callable
4455
     */
4456
    private function getContentInfoFixtureClosure($closure = null)
4457
    {
4458
        /** @var $data \eZ\Publish\API\Repository\Values\Content\Search\SearchResult */
4459
        return function (&$data) use ($closure) {
4460
            foreach ($data->searchHits as $searchHit) {
4461
                if ($searchHit->valueObject instanceof Content) {
4462
                    $searchHit->valueObject = $searchHit->valueObject->getVersionInfo()->getContentInfo();
4463
                }
4464
            }
4465
4466
            if (isset($closure)) {
4467
                $closure($data);
4468
            }
4469
        };
4470
    }
4471
}
4472