Completed
Push — EZP-29891 ( 916cf6...0402ff )
by
unknown
16:53
created

SearchServiceTest::getLocationQuerySearches()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 69

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 69
rs 8.6763
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
namespace eZ\Publish\API\Repository\Tests;
10
11
use eZ\Publish\API\Repository\Tests\SetupFactory\LegacyElasticsearch;
12
use EzSystems\EzPlatformSolrSearchEngine\Tests\SetupFactory\LegacySetupFactory as LegacySolrSetupFactory;
13
use eZ\Publish\API\Repository\Values\Content\Content;
14
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
15
use eZ\Publish\API\Repository\Values\Content\Query;
16
use eZ\Publish\API\Repository\Values\Content\Location;
17
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
18
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
19
use eZ\Publish\API\Repository\Values\Content\Query\SortClause;
20
use eZ\Publish\API\Repository\Values\Content\Query\FacetBuilder;
21
use eZ\Publish\API\Repository\Values\Content\Search\SearchResult;
22
use eZ\Publish\API\Repository\Values\Content\Search\SearchHit;
23
use eZ\Publish\API\Repository\Exceptions\NotImplementedException;
24
25
/**
26
 * Test case for operations in the SearchService using in memory storage.
27
 *
28
 * @see eZ\Publish\API\Repository\SearchService
29
 * @group integration
30
 * @group search
31
 */
32
class SearchServiceTest extends BaseTest
33
{
34
    public function getFilterContentSearches()
35
    {
36
        $fixtureDir = $this->getFixtureDir();
37
38
        return array(
39
            0 => array(
40
                array(
41
                    'filter' => new Criterion\ContentId(
42
                        array(1, 4, 10)
43
                    ),
44
                    'sortClauses' => array(new SortClause\ContentId()),
45
                ),
46
                $fixtureDir . 'ContentId.php',
47
            ),
48
            1 => array(
49
                array(
50
                    'filter' => new Criterion\LogicalAnd(
51
                        array(
52
                            new Criterion\ContentId(
53
                                array(1, 4, 10)
54
                            ),
55
                            new Criterion\ContentId(
56
                                array(4, 12)
57
                            ),
58
                        )
59
                    ),
60
                    'sortClauses' => array(new SortClause\ContentId()),
61
                ),
62
                $fixtureDir . 'LogicalAnd.php',
63
            ),
64
            2 => array(
65
                array(
66
                    'filter' => new Criterion\LogicalOr(
67
                        array(
68
                            new Criterion\ContentId(
69
                                array(1, 4, 10)
70
                            ),
71
                            new Criterion\ContentId(
72
                                array(4, 12)
73
                            ),
74
                        )
75
                    ),
76
                    'sortClauses' => array(new SortClause\ContentId()),
77
                ),
78
                $fixtureDir . 'LogicalOr.php',
79
            ),
80
            3 => array(
81
                array(
82
                    'filter' => new Criterion\LogicalAnd(
83
                        array(
84
                            new Criterion\ContentId(
85
                                array(1, 4, 10)
86
                            ),
87
                            new Criterion\LogicalNot(
88
                                new Criterion\ContentId(
89
                                    array(10, 12)
90
                                )
91
                            ),
92
                        )
93
                    ),
94
                    'sortClauses' => array(new SortClause\ContentId()),
95
                ),
96
                $fixtureDir . 'LogicalNot.php',
97
            ),
98
            4 => array(
99
                array(
100
                    'filter' => new Criterion\LogicalAnd(
101
                        array(
102
                            new Criterion\ContentId(
103
                                array(1, 4, 10)
104
                            ),
105
                            new Criterion\LogicalAnd(
106
                                array(
107
                                    new Criterion\LogicalNot(
108
                                        new Criterion\ContentId(
109
                                            array(10, 12)
110
                                        )
111
                                    ),
112
                                )
113
                            ),
114
                        )
115
                    ),
116
                    'sortClauses' => array(new SortClause\ContentId()),
117
                ),
118
                $fixtureDir . 'LogicalNot.php',
119
            ),
120
            5 => array(
121
                array(
122
                    'filter' => new Criterion\ContentTypeId(
123
                        4
124
                    ),
125
                    'sortClauses' => array(new SortClause\ContentId()),
126
                ),
127
                $fixtureDir . 'ContentTypeId.php',
128
            ),
129
            6 => array(
130
                array(
131
                    'filter' => new Criterion\ContentTypeIdentifier(
132
                        'user'
133
                    ),
134
                    'sortClauses' => array(new SortClause\ContentId()),
135
                ),
136
                $fixtureDir . 'ContentTypeId.php',
137
            ),
138
            7 => array(
139
                array(
140
                    'filter' => new Criterion\MatchNone(),
141
                    'sortClauses' => array(new SortClause\ContentId()),
142
                ),
143
                $fixtureDir . 'MatchNone.php',
144
            ),
145
            8 => array(
146
                array(
147
                    'filter' => new Criterion\ContentTypeGroupId(
148
                        2
149
                    ),
150
                    'sortClauses' => array(new SortClause\ContentId()),
151
                ),
152
                $fixtureDir . 'ContentTypeGroupId.php',
153
            ),
154
            9 => array(
155
                array(
156
                    'filter' => new Criterion\DateMetadata(
157
                        Criterion\DateMetadata::MODIFIED,
158
                        Criterion\Operator::GT,
159
                        1343140540
160
                    ),
161
                    'sortClauses' => array(new SortClause\ContentId()),
162
                ),
163
                $fixtureDir . 'DateMetadataGt.php',
164
            ),
165
            10 => array(
166
                array(
167
                    'filter' => new Criterion\DateMetadata(
168
                        Criterion\DateMetadata::MODIFIED,
169
                        Criterion\Operator::GTE,
170
                        1311154215
171
                    ),
172
                    'sortClauses' => array(new SortClause\ContentId()),
173
                ),
174
                $fixtureDir . 'DateMetadataGte.php',
175
            ),
176
            11 => array(
177
                array(
178
                    'filter' => new Criterion\DateMetadata(
179
                        Criterion\DateMetadata::MODIFIED,
180
                        Criterion\Operator::LTE,
181
                        1311154215
182
                    ),
183
                    'limit' => 10,
184
                    'sortClauses' => array(new SortClause\ContentId()),
185
                ),
186
                $fixtureDir . 'DateMetadataLte.php',
187
            ),
188
            12 => array(
189
                array(
190
                    'filter' => new Criterion\DateMetadata(
191
                        Criterion\DateMetadata::MODIFIED,
192
                        Criterion\Operator::IN,
193
                        array(1033920794, 1060695457, 1343140540)
194
                    ),
195
                    'sortClauses' => array(new SortClause\ContentId()),
196
                ),
197
                $fixtureDir . 'DateMetadataIn.php',
198
            ),
199
            13 => array(
200
                array(
201
                    'filter' => new Criterion\DateMetadata(
202
                        Criterion\DateMetadata::MODIFIED,
203
                        Criterion\Operator::BETWEEN,
204
                        array(1033920776, 1072180276)
205
                    ),
206
                    'sortClauses' => array(new SortClause\ContentId()),
207
                ),
208
                $fixtureDir . 'DateMetadataBetween.php',
209
            ),
210
            14 => array(
211
                array(
212
                    'filter' => new Criterion\DateMetadata(
213
                        Criterion\DateMetadata::CREATED,
214
                        Criterion\Operator::BETWEEN,
215
                        array(1033920776, 1072180278)
216
                    ),
217
                    'sortClauses' => array(new SortClause\ContentId()),
218
                ),
219
                $fixtureDir . 'DateMetadataCreated.php',
220
            ),
221
            15 => array(
222
                array(
223
                    'filter' => new Criterion\CustomField(
224
                        'user_group_name_value_s',
225
                        Criterion\Operator::EQ,
226
                        'Members'
227
                    ),
228
                    'sortClauses' => array(new SortClause\ContentId()),
229
                ),
230
                $fixtureDir . 'Field.php',
231
            ),
232
            16 => array(
233
                array(
234
                    'filter' => new Criterion\CustomField(
235
                        'user_group_name_value_s',
236
                        Criterion\Operator::CONTAINS,
237
                        'Members'
238
                    ),
239
                    'sortClauses' => array(new SortClause\ContentId()),
240
                ),
241
                $fixtureDir . 'Field.php',
242
            ),
243
            17 => array(
244
                array(
245
                    'filter' => new Criterion\CustomField(
246
                        'user_group_name_value_s',
247
                        Criterion\Operator::LT,
248
                        'Members'
249
                    ),
250
                    'sortClauses' => array(new SortClause\ContentId()),
251
                ),
252
                $fixtureDir . 'CustomFieldLt.php',
253
            ),
254
            18 => array(
255
                array(
256
                    'filter' => new Criterion\CustomField(
257
                        'user_group_name_value_s',
258
                        Criterion\Operator::LTE,
259
                        'Members'
260
                    ),
261
                    'sortClauses' => array(new SortClause\ContentId()),
262
                ),
263
                $fixtureDir . 'CustomFieldLte.php',
264
            ),
265
            19 => array(
266
                array(
267
                    'filter' => new Criterion\CustomField(
268
                        'user_group_name_value_s',
269
                        Criterion\Operator::GT,
270
                        'Members'
271
                    ),
272
                    'sortClauses' => array(new SortClause\ContentId()),
273
                ),
274
                $fixtureDir . 'CustomFieldGt.php',
275
            ),
276
            20 => array(
277
                array(
278
                    'filter' => new Criterion\CustomField(
279
                        'user_group_name_value_s',
280
                        Criterion\Operator::GTE,
281
                        'Members'
282
                    ),
283
                    'sortClauses' => array(new SortClause\ContentId()),
284
                ),
285
                $fixtureDir . 'CustomFieldGte.php',
286
            ),
287
            21 => array(
288
                array(
289
                    'filter' => new Criterion\CustomField(
290
                        'user_group_name_value_s',
291
                        Criterion\Operator::BETWEEN,
292
                        array('Administrator users', 'Members')
293
                    ),
294
                    'sortClauses' => array(new SortClause\ContentId()),
295
                ),
296
                $fixtureDir . 'CustomFieldBetween.php',
297
            ),
298
            22 => array(
299
                array(
300
                    'filter' => new Criterion\RemoteId(
301
                        array('f5c88a2209584891056f987fd965b0ba', 'faaeb9be3bd98ed09f606fc16d144eca')
302
                    ),
303
                    'sortClauses' => array(new SortClause\ContentId()),
304
                ),
305
                $fixtureDir . 'RemoteId.php',
306
            ),
307
            23 => array(
308
                array(
309
                    'filter' => new Criterion\SectionId(
310
                        array(2)
311
                    ),
312
                    'sortClauses' => array(new SortClause\ContentId()),
313
                ),
314
                $fixtureDir . 'SectionId.php',
315
            ),
316
            24 => array(
317
                array(
318
                    'filter' => new Criterion\Field(
319
                        'name',
320
                        Criterion\Operator::EQ,
321
                        'Members'
322
                    ),
323
                    'sortClauses' => array(new SortClause\ContentId()),
324
                ),
325
                $fixtureDir . 'Field.php',
326
            ),
327
            25 => array(
328
                array(
329
                    'filter' => new Criterion\Field(
330
                        'name',
331
                        Criterion\Operator::IN,
332
                        array('Members', 'Anonymous Users')
333
                    ),
334
                    'sortClauses' => array(new SortClause\ContentId()),
335
                ),
336
                $fixtureDir . 'FieldIn.php',
337
            ),
338
            26 => array(
339
                array(
340
                    'filter' => new Criterion\DateMetadata(
341
                        Criterion\DateMetadata::MODIFIED,
342
                        Criterion\Operator::BETWEEN,
343
                        array(1033920275, 1033920794)
344
                    ),
345
                    'sortClauses' => array(new SortClause\ContentId()),
346
                ),
347
                $fixtureDir . 'FieldBetween.php',
348
            ),
349
            27 => array(
350
                array(
351
                    'filter' => new Criterion\LogicalOr(
352
                        array(
353
                            new Criterion\Field(
354
                                'name',
355
                                Criterion\Operator::EQ,
356
                                'Members'
357
                            ),
358
                            new Criterion\DateMetadata(
359
                                Criterion\DateMetadata::MODIFIED,
360
                                Criterion\Operator::BETWEEN,
361
                                array(1033920275, 1033920794)
362
                            ),
363
                        )
364
                    ),
365
                    'sortClauses' => array(new SortClause\ContentId()),
366
                ),
367
                $fixtureDir . 'FieldOr.php',
368
            ),
369
            28 => array(
370
                array(
371
                    'filter' => new Criterion\Subtree(
372
                        '/1/5/'
373
                    ),
374
                    'sortClauses' => array(new SortClause\ContentId()),
375
                ),
376
                $fixtureDir . 'Subtree.php',
377
            ),
378
            29 => array(
379
                array(
380
                    'filter' => new Criterion\LocationId(
381
                        array(1, 2, 5)
382
                    ),
383
                    'sortClauses' => array(new SortClause\ContentId()),
384
                ),
385
                $fixtureDir . 'LocationId.php',
386
            ),
387
            30 => array(
388
                array(
389
                    'filter' => new Criterion\ParentLocationId(
390
                        array(1)
391
                    ),
392
                    'sortClauses' => array(new SortClause\ContentId()),
393
                ),
394
                $fixtureDir . 'ParentLocationId.php',
395
            ),
396
            31 => array(
397
                array(
398
                    'filter' => new Criterion\LocationRemoteId(
399
                        array('3f6d92f8044aed134f32153517850f5a', 'f3e90596361e31d496d4026eb624c983')
400
                    ),
401
                    'sortClauses' => array(new SortClause\ContentId()),
402
                ),
403
                $fixtureDir . 'LocationRemoteId.php',
404
            ),
405
            32 => array(
406
                array(
407
                    // There is no Status Criterion anymore, this should match all published as well
408
                    'filter' => new Criterion\Subtree(
409
                        '/1/'
410
                    ),
411
                    'sortClauses' => array(new SortClause\ContentId()),
412
                    'limit' => 50,
413
                ),
414
                $fixtureDir . 'Status.php',
415
                // Result having the same sort level should be sorted between them to be system independent
416
                function (&$data) {
417
                    usort(
418
                        $data->searchHits,
419
                        function ($a, $b) {
420
                            if ($a->score == $b->score) {
421
                                if ($a->valueObject['id'] == $b->valueObject['id']) {
422
                                    return 0;
423
                                }
424
425
                                // Order by ascending ID
426
                                return ($a->valueObject['id'] < $b->valueObject['id']) ? -1 : 1;
427
                            }
428
429
                            // Order by descending score
430
                            return ($a->score > $b->score) ? -1 : 1;
431
                        }
432
                    );
433
                },
434
            ),
435
            33 => array(
436
                array(
437
                    'filter' => new Criterion\UserMetadata(
438
                        Criterion\UserMetadata::MODIFIER,
439
                        Criterion\Operator::EQ,
440
                        14
441
                    ),
442
                    'sortClauses' => array(
443
                        new SortClause\ContentId(),
444
                    ),
445
                    'limit' => 50,
446
                ),
447
                $fixtureDir . 'UserMetadata.php',
448
            ),
449
            34 => array(
450
                array(
451
                    'filter' => new Criterion\UserMetadata(
452
                        Criterion\UserMetadata::MODIFIER,
453
                        Criterion\Operator::IN,
454
                        array(14)
455
                    ),
456
                    'sortClauses' => array(
457
                        new SortClause\ContentId(),
458
                    ),
459
                    'limit' => 50,
460
                ),
461
                $fixtureDir . 'UserMetadata.php',
462
            ),
463
            35 => array(
464
                array(
465
                    'filter' => new Criterion\UserMetadata(
466
                        Criterion\UserMetadata::OWNER,
467
                        Criterion\Operator::EQ,
468
                        14
469
                    ),
470
                    'sortClauses' => array(
471
                        new SortClause\ContentId(),
472
                    ),
473
                    'limit' => 50,
474
                ),
475
                $fixtureDir . 'UserMetadata.php',
476
            ),
477
            36 => array(
478
                array(
479
                    'filter' => new Criterion\UserMetadata(
480
                        Criterion\UserMetadata::OWNER,
481
                        Criterion\Operator::IN,
482
                        array(14)
483
                    ),
484
                    'sortClauses' => array(
485
                        new SortClause\ContentId(),
486
                    ),
487
                    'limit' => 50,
488
                ),
489
                $fixtureDir . 'UserMetadata.php',
490
            ),
491
            37 => array(
492
                array(
493
                    'filter' => new Criterion\UserMetadata(
494
                        Criterion\UserMetadata::GROUP,
495
                        Criterion\Operator::EQ,
496
                        12
497
                    ),
498
                    'sortClauses' => array(
499
                        new SortClause\ContentId(),
500
                    ),
501
                    'limit' => 50,
502
                ),
503
                $fixtureDir . 'UserMetadata.php',
504
            ),
505
            38 => array(
506
                array(
507
                    'filter' => new Criterion\UserMetadata(
508
                        Criterion\UserMetadata::GROUP,
509
                        Criterion\Operator::IN,
510
                        array(12)
511
                    ),
512
                    'sortClauses' => array(
513
                        new SortClause\ContentId(),
514
                    ),
515
                    'limit' => 50,
516
                ),
517
                $fixtureDir . 'UserMetadata.php',
518
            ),
519
            39 => array(
520
                array(
521
                    'filter' => new Criterion\UserMetadata(
522
                        Criterion\UserMetadata::GROUP,
523
                        Criterion\Operator::EQ,
524
                        4
525
                    ),
526
                    'sortClauses' => array(
527
                        new SortClause\ContentId(),
528
                    ),
529
                    'limit' => 50,
530
                ),
531
                $fixtureDir . 'UserMetadata.php',
532
            ),
533
            40 => array(
534
                array(
535
                    'filter' => new Criterion\UserMetadata(
536
                        Criterion\UserMetadata::GROUP,
537
                        Criterion\Operator::IN,
538
                        array(4)
539
                    ),
540
                    'sortClauses' => array(
541
                        new SortClause\ContentId(),
542
                    ),
543
                    'limit' => 50,
544
                ),
545
                $fixtureDir . 'UserMetadata.php',
546
            ),
547
            41 => array(
548
                array(
549
                    'filter' => new Criterion\Ancestor(
550
                        array(
551
                            '/1/5/44/',
552
                            '/1/5/44/45/',
553
                        )
554
                    ),
555
                    'sortClauses' => array(
556
                        new SortClause\ContentId(),
557
                    ),
558
                    'limit' => 50,
559
                ),
560
                $fixtureDir . 'AncestorContent.php',
561
            ),
562
        );
563
    }
564
565
    public function getContentQuerySearches()
566
    {
567
        $fixtureDir = $this->getFixtureDir();
568
569
        return array(
570
            array(
571
                array(
572
                    'filter' => new Criterion\ContentId(
573
                        array(58, 10)
574
                    ),
575
                    'query' => new Criterion\FullText('contact'),
576
                    'sortClauses' => array(new SortClause\ContentId()),
577
                ),
578
                $fixtureDir . 'FullTextFiltered.php',
579
            ),
580
            array(
581
                array(
582
                    'query' => new Criterion\FullText(
583
                        'contact',
584
                        array(
585
                            'boost' => array(
586
                                'title' => 2,
587
                            ),
588
                            'fuzziness' => .5,
589
                        )
590
                    ),
591
                    'sortClauses' => array(new SortClause\ContentId()),
592
                ),
593
                $fixtureDir . 'FullText.php',
594
            ),
595
            array(
596
                array(
597
                    'query' => new Criterion\FullText(
598
                        'Contact*'
599
                    ),
600
                    'sortClauses' => array(new SortClause\ContentId()),
601
                ),
602
                $fixtureDir . 'FullTextWildcard.php',
603
            ),
604
            array(
605
                array(
606
                    'query' => new Criterion\LanguageCode('eng-GB', false),
607
                    'sortClauses' => array(new SortClause\ContentId()),
608
                ),
609
                $fixtureDir . 'LanguageCode.php',
610
            ),
611
            array(
612
                array(
613
                    'query' => new Criterion\LanguageCode(array('eng-US', 'eng-GB')),
614
                    'offset' => 10,
615
                    'sortClauses' => array(new SortClause\ContentId()),
616
                ),
617
                $fixtureDir . 'LanguageCodeIn.php',
618
            ),
619
            array(
620
                array(
621
                    'query' => new Criterion\LanguageCode('eng-GB'),
622
                    'offset' => 10,
623
                    'sortClauses' => array(new SortClause\ContentId()),
624
                ),
625
                $fixtureDir . 'LanguageCodeAlwaysAvailable.php',
626
            ),
627
            array(
628
                array(
629
                    'query' => new Criterion\Visibility(
630
                        Criterion\Visibility::VISIBLE
631
                    ),
632
                    'sortClauses' => array(new SortClause\ContentId()),
633
                    'limit' => 50,
634
                ),
635
                $fixtureDir . 'Visibility.php',
636
            ),
637
        );
638
    }
639
640
    public function getLocationQuerySearches()
641
    {
642
        $fixtureDir = $this->getFixtureDir();
643
644
        return array(
645
            array(
646
                array(
647
                    'query' => new Criterion\Location\Depth(Criterion\Operator::EQ, 1),
648
                    'sortClauses' => array(new SortClause\ContentId()),
649
                ),
650
                $fixtureDir . 'Depth.php',
651
            ),
652
            array(
653
                array(
654
                    'query' => new Criterion\Location\Depth(Criterion\Operator::IN, array(1, 3)),
655
                    'sortClauses' => array(new SortClause\ContentId()),
656
                ),
657
                $fixtureDir . 'DepthIn.php',
658
            ),
659
            array(
660
                array(
661
                    'query' => new Criterion\Location\Depth(Criterion\Operator::GT, 2),
662
                    'sortClauses' => array(new SortClause\ContentId()),
663
                ),
664
                $fixtureDir . 'DepthGt.php',
665
            ),
666
            array(
667
                array(
668
                    'query' => new Criterion\Location\Depth(Criterion\Operator::GTE, 2),
669
                    'sortClauses' => array(new SortClause\ContentId()),
670
                    'limit' => 50,
671
                ),
672
                $fixtureDir . 'DepthGte.php',
673
            ),
674
            array(
675
                array(
676
                    'query' => new Criterion\Location\Depth(Criterion\Operator::LT, 2),
677
                    'sortClauses' => array(new SortClause\ContentId()),
678
                ),
679
                $fixtureDir . 'Depth.php',
680
            ),
681
            array(
682
                array(
683
                    'query' => new Criterion\Location\Depth(Criterion\Operator::LTE, 2),
684
                    'sortClauses' => array(new SortClause\ContentId()),
685
                    'limit' => 50,
686
                ),
687
                $fixtureDir . 'DepthLte.php',
688
            ),
689
            array(
690
                array(
691
                    'query' => new Criterion\Location\Depth(Criterion\Operator::BETWEEN, array(1, 2)),
692
                    'sortClauses' => array(new SortClause\ContentId()),
693
                    'limit' => 50,
694
                ),
695
                $fixtureDir . 'DepthLte.php',
696
            ),
697
            array(
698
                array(
699
                    'filter' => new Criterion\Ancestor('/1/5/44/45/'),
700
                    'sortClauses' => array(
701
                        new SortClause\Location\Depth(),
702
                    ),
703
                    'limit' => 50,
704
                ),
705
                $fixtureDir . 'AncestorLocation.php',
706
            ),
707
        );
708
    }
709
710
    /**
711
     * Test for the findContent() method.
712
     *
713
     * @dataProvider getFilterContentSearches
714
     *
715
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
716
     */
717
    public function testFindContentFiltered($queryData, $fixture, $closure = null)
718
    {
719
        $query = new Query($queryData);
720
        $this->assertQueryFixture($query, $fixture, $closure);
721
    }
722
723
    /**
724
     * Test for the findContentInfo() method.
725
     *
726
     * @dataProvider getFilterContentSearches
727
     * @see \eZ\Publish\API\Repository\SearchService::findContentInfo()
728
     */
729
    public function testFindContentInfoFiltered($queryData, $fixture, $closure = null)
730
    {
731
        $query = new Query($queryData);
732
        $this->assertQueryFixture($query, $fixture, $this->getContentInfoFixtureClosure($closure), true);
733
    }
734
735
    /**
736
     * Test for the findLocations() method.
737
     *
738
     * @dataProvider getFilterContentSearches
739
     *
740
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
741
     */
742
    public function testFindLocationsContentFiltered($queryData, $fixture, $closure = null)
743
    {
744
        $query = new LocationQuery($queryData);
745
        $this->assertQueryFixture($query, $fixture, $closure);
746
    }
747
748
    /**
749
     * Test for deprecated $criterion property on query object.
750
     *
751
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
752
     * @deprecated
753
     */
754
    public function testDeprecatedCriteriaProperty()
755
    {
756
        $this->assertQueryFixture(
757
            new Query(
758
                array(
759
                    'query' => new Criterion\ContentId(
760
                        array(1, 4, 10)
761
                    ),
762
                    'sortClauses' => array(new SortClause\ContentId()),
763
                )
764
            ),
765
            $this->getFixtureDir() . 'DeprecatedContentIdQuery.php'
766
        );
767
    }
768
769
    /**
770
     * Test for the findContent() method.
771
     *
772
     * @dataProvider getContentQuerySearches
773
     *
774
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
775
     */
776
    public function testQueryContent($queryData, $fixture, $closure = null)
777
    {
778
        $query = new Query($queryData);
779
        $this->assertQueryFixture($query, $fixture, $closure);
780
    }
781
782
    /**
783
     * Test for the findContentInfo() method.
784
     *
785
     * @dataProvider getContentQuerySearches
786
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
787
     */
788
    public function testQueryContentInfo($queryData, $fixture, $closure = null)
789
    {
790
        $query = new Query($queryData);
791
        $this->assertQueryFixture($query, $fixture, $this->getContentInfoFixtureClosure($closure), true);
792
    }
793
794
    /**
795
     * Test for the findLocations() method.
796
     *
797
     * @dataProvider getContentQuerySearches
798
     *
799
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
800
     */
801
    public function testQueryContentLocations($queryData, $fixture, $closure = null)
802
    {
803
        $query = new LocationQuery($queryData);
804
        $this->assertQueryFixture($query, $fixture, $closure);
805
    }
806
807
    /**
808
     * Test for the findLocations() method.
809
     *
810
     * @dataProvider getLocationQuerySearches
811
     *
812
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
813
     */
814
    public function testQueryLocations($queryData, $fixture, $closure = null)
815
    {
816
        $query = new LocationQuery($queryData);
817
        $this->assertQueryFixture($query, $fixture, $closure);
818
    }
819
820
    public function getCaseInsensitiveSearches()
821
    {
822
        return array(
823
            array(
824
                array(
825
                    'filter' => new Criterion\Field(
826
                        'name',
827
                        Criterion\Operator::EQ,
828
                        'Members'
829
                    ),
830
                    'sortClauses' => array(new SortClause\ContentId()),
831
                ),
832
            ),
833
            array(
834
                array(
835
                    'filter' => new Criterion\Field(
836
                        'name',
837
                        Criterion\Operator::EQ,
838
                        'members'
839
                    ),
840
                    'sortClauses' => array(new SortClause\ContentId()),
841
                ),
842
            ),
843
            array(
844
                array(
845
                    'filter' => new Criterion\Field(
846
                        'name',
847
                        Criterion\Operator::EQ,
848
                        'MEMBERS'
849
                    ),
850
                    'sortClauses' => array(new SortClause\ContentId()),
851
                ),
852
            ),
853
        );
854
    }
855
856
    /**
857
     * Test for the findContent() method.
858
     *
859
     * @dataProvider getCaseInsensitiveSearches
860
     *
861
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
862
     */
863
    public function testFindContentFieldFiltersCaseSensitivity($queryData)
864
    {
865
        $query = new Query($queryData);
866
        $this->assertQueryFixture(
867
            $query,
868
            $this->getFixtureDir() . 'Field.php'
869
        );
870
    }
871
872
    /**
873
     * Test for the findLocations() method.
874
     *
875
     * @dataProvider getCaseInsensitiveSearches
876
     *
877
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
878
     */
879
    public function testFindLocationsFieldFiltersCaseSensitivity($queryData)
880
    {
881
        $query = new LocationQuery($queryData);
882
        $this->assertQueryFixture(
883
            $query,
884
            $this->getFixtureDir() . 'Field.php'
885
        );
886
    }
887
888
    public function getRelationFieldFilterSearches()
889
    {
890
        $fixtureDir = $this->getFixtureDir();
891
892
        return array(
893
            0 => array(
894
                array(
895
                    'filter' => new Criterion\FieldRelation(
896
                        'image',
897
                        Criterion\Operator::IN,
898
                        array(1, 4, 10)
899
                    ),
900
                    'sortClauses' => array(new SortClause\ContentId()),
901
                ),
902
                $fixtureDir . 'FieldRelation.php',
903
            ),
904
            1 => array(
905
                array(
906
                    'filter' => new Criterion\FieldRelation(
907
                        'image',
908
                        Criterion\Operator::IN,
909
                        array(4, 49)
910
                    ),
911
                    'sortClauses' => array(new SortClause\ContentId()),
912
                ),
913
                $fixtureDir . 'FieldRelationAll.php',
914
            ),
915
            2 => array(
916
                array(
917
                    'filter' => new Criterion\FieldRelation(
918
                        'image',
919
                        Criterion\Operator::IN,
920
                        array(4)
921
                    ),
922
                    'sortClauses' => array(new SortClause\ContentId()),
923
                ),
924
                $fixtureDir . 'FieldRelation.php',
925
            ),
926
            3 => array(
927
                array(
928
                    'filter' => new Criterion\FieldRelation(
929
                        'image',
930
                        Criterion\Operator::CONTAINS,
931
                        array(1, 4, 10)
932
                    ),
933
                    'sortClauses' => array(new SortClause\ContentId()),
934
                ),
935
                $fixtureDir . 'MatchNone.php',
936
            ),
937
            4 => array(
938
                array(
939
                    'filter' => new Criterion\FieldRelation(
940
                        'image',
941
                        Criterion\Operator::CONTAINS,
942
                        array(4, 49)
943
                    ),
944
                    'sortClauses' => array(new SortClause\ContentId()),
945
                ),
946
                $fixtureDir . 'MatchNone.php',
947
            ),
948
            5 => array(
949
                array(
950
                    'filter' => new Criterion\FieldRelation(
951
                        'image',
952
                        Criterion\Operator::CONTAINS,
953
                        array(4)
954
                    ),
955
                    'sortClauses' => array(new SortClause\ContentId()),
956
                ),
957
                $fixtureDir . 'FieldRelation.php',
958
            ),
959
        );
960
    }
961
962
    /**
963
     * Purely for creating relation data needed for testFindRelationFieldContentInfoFiltered()
964
     * and testFindRelationFieldLocationsFiltered().
965
     */
966
    public function testRelationContentCreation()
967
    {
968
        $repository = $this->getRepository();
969
        $galleryType = $repository->getContentTypeService()->loadContentTypeByIdentifier('gallery');
970
        $contentService = $repository->getContentService();
971
        $locationService = $repository->getLocationService();
972
973
        $locationCreateStruct = $locationService->newLocationCreateStruct(2); // Home
974
975
        $createStruct = $contentService->newContentCreateStruct($galleryType, 'eng-GB');
976
        $createStruct->setField('name', 'Image gallery');
977
        $createStruct->setField('image', 49); // Images folder
978
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
979
        $contentService->publishVersion($draft->getVersionInfo());
980
981
        $createStruct = $contentService->newContentCreateStruct($galleryType, 'eng-GB');
982
        $createStruct->setField('name', 'User gallery');
983
        $createStruct->setField('image', 4); // User folder
984
        $draft = $contentService->createContent($createStruct, [$locationCreateStruct]);
985
        $contentService->publishVersion($draft->getVersionInfo());
986
987
        $this->refreshSearch($repository);
988
    }
989
990
    /**
991
     * Test for FieldRelation using findContentInfo() method.
992
     *
993
     * @dataProvider getRelationFieldFilterSearches
994
     * @see \eZ\Publish\API\Repository\SearchService::findContentInfo()
995
     * @depends eZ\Publish\API\Repository\Tests\SearchServiceTest::testRelationContentCreation
996
     */
997
    public function testFindRelationFieldContentInfoFiltered($queryData, $fixture)
998
    {
999
        $this->getRepository(false); // To make sure repo is setup w/o removing data from getRelationFieldFilterContentSearches
1000
        $query = new Query($queryData);
1001
        $this->assertQueryFixture($query, $fixture, null, true, true, false);
1002
    }
1003
1004
    /**
1005
     * Test for FieldRelation using findLocations() method.
1006
     *
1007
     * @dataProvider getRelationFieldFilterSearches
1008
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
1009
     * @depends eZ\Publish\API\Repository\Tests\SearchServiceTest::testRelationContentCreation
1010
     */
1011
    public function testFindRelationFieldLocationsFiltered($queryData, $fixture)
1012
    {
1013
        $this->getRepository(false); // To make sure repo is setup w/o removing data from getRelationFieldFilterContentSearches
1014
        $query = new LocationQuery($queryData);
1015
        $this->assertQueryFixture($query, $fixture, null, true, false, false);
1016
    }
1017
1018 View Code Duplication
    public function testFindSingle()
1019
    {
1020
        $repository = $this->getRepository();
1021
        $searchService = $repository->getSearchService();
1022
1023
        $content = $searchService->findSingle(
1024
            new Criterion\ContentId(
1025
                array(4)
1026
            )
1027
        );
1028
1029
        $this->assertEquals(
1030
            4,
1031
            $content->id
1032
        );
1033
    }
1034
1035 View Code Duplication
    public function testFindNoPerformCount()
1036
    {
1037
        $repository = $this->getRepository();
1038
        $searchService = $repository->getSearchService();
1039
1040
        $query = new Query();
1041
        $query->performCount = false;
1042
        $query->query = new Criterion\ContentTypeId(
1043
            array(4)
1044
        );
1045
1046
        $searchHit = $searchService->findContent($query);
1047
1048
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
1049
            $this->assertNull(
1050
                $searchHit->totalCount
1051
            );
1052
        } else {
1053
            $this->assertEquals(
1054
                2,
1055
                $searchHit->totalCount
1056
            );
1057
        }
1058
    }
1059
1060
    /**
1061
     * @expectedException \RuntimeException
1062
     */
1063 View Code Duplication
    public function testFindNoPerformCountException()
1064
    {
1065
        if (ltrim(get_class($this->getSetupFactory()), '\\') !== 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
1066
            $this->markTestSkipped('Only applicable to Legacy/DB based search');
1067
        }
1068
1069
        $repository = $this->getRepository();
1070
        $searchService = $repository->getSearchService();
1071
1072
        $query = new Query();
1073
        $query->performCount = false;
1074
        $query->limit = 0;
1075
        $query->query = new Criterion\ContentTypeId(
1076
            array(4)
1077
        );
1078
1079
        $searchService->findContent($query);
1080
    }
1081
1082 View Code Duplication
    public function testFindLocationsNoPerformCount()
1083
    {
1084
        $repository = $this->getRepository();
1085
        $searchService = $repository->getSearchService();
1086
1087
        $query = new LocationQuery();
1088
        $query->performCount = false;
1089
        $query->query = new Criterion\ContentTypeId(
1090
            array(4)
1091
        );
1092
1093
        $searchHit = $searchService->findLocations($query);
1094
1095
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
1096
            $this->assertNull(
1097
                $searchHit->totalCount
1098
            );
1099
        } else {
1100
            $this->assertEquals(
1101
                2,
1102
                $searchHit->totalCount
1103
            );
1104
        }
1105
    }
1106
1107
    /**
1108
     * @expectedException \RuntimeException
1109
     */
1110 View Code Duplication
    public function testFindLocationsNoPerformCountException()
1111
    {
1112
        if (ltrim(get_class($this->getSetupFactory()), '\\') !== 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
1113
            $this->markTestSkipped('Only applicable to Legacy/DB based search');
1114
        }
1115
1116
        $repository = $this->getRepository();
1117
        $searchService = $repository->getSearchService();
1118
1119
        $query = new LocationQuery();
1120
        $query->performCount = false;
1121
        $query->limit = 0;
1122
        $query->query = new Criterion\ContentTypeId(
1123
            array(4)
1124
        );
1125
1126
        $searchService->findLocations($query);
1127
    }
1128
1129
    /**
1130
     * Create test Content with ezcountry field having multiple countries selected.
1131
     *
1132
     * @return Content
1133
     */
1134
    protected function createMultipleCountriesContent()
1135
    {
1136
        $repository = $this->getRepository();
1137
        $contentTypeService = $repository->getContentTypeService();
1138
        $contentService = $repository->getContentService();
1139
1140
        $createStruct = $contentTypeService->newContentTypeCreateStruct('countries-multiple');
1141
        $createStruct->mainLanguageCode = 'eng-GB';
1142
        $createStruct->remoteId = 'countries-multiple-123';
1143
        $createStruct->names = array('eng-GB' => 'Multiple countries');
1144
        $createStruct->creatorId = 14;
1145
        $createStruct->creationDate = new \DateTime();
1146
1147
        $fieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('countries', 'ezcountry');
1148
        $fieldCreate->names = array('eng-GB' => 'Countries');
1149
        $fieldCreate->fieldGroup = 'main';
1150
        $fieldCreate->position = 1;
1151
        $fieldCreate->isTranslatable = false;
1152
        $fieldCreate->isSearchable = true;
1153
        $fieldCreate->fieldSettings = array('isMultiple' => true);
1154
1155
        $createStruct->addFieldDefinition($fieldCreate);
1156
1157
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
1158
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, array($contentGroup));
1159
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
1160
        $contentType = $contentTypeService->loadContentType($contentTypeDraft->id);
1161
1162
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
1163
        $createStruct->remoteId = 'countries-multiple-456';
1164
        $createStruct->alwaysAvailable = false;
1165
        $createStruct->setField(
1166
            'countries',
1167
            array('BE', 'DE', 'FR', 'HR', 'NO', 'PT', 'RU')
1168
        );
1169
1170
        $draft = $contentService->createContent($createStruct);
1171
        $content = $contentService->publishVersion($draft->getVersionInfo());
1172
1173
        $this->refreshSearch($repository);
1174
1175
        return $content;
1176
    }
1177
1178
    /**
1179
     * Test for the findContent() method.
1180
     *
1181
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
1182
     */
1183 View Code Duplication
    public function testFieldCollectionContains()
1184
    {
1185
        $testContent = $this->createMultipleCountriesContent();
1186
1187
        $query = new Query(
1188
            array(
1189
                'query' => new Criterion\Field(
1190
                    'countries',
1191
                    Criterion\Operator::CONTAINS,
1192
                    'Belgium'
1193
                ),
1194
            )
1195
        );
1196
1197
        $repository = $this->getRepository();
1198
        $searchService = $repository->getSearchService();
1199
        $result = $searchService->findContent($query);
1200
1201
        $this->assertEquals(1, $result->totalCount);
1202
        $this->assertEquals(
1203
            $testContent->id,
1204
            $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...
1205
        );
1206
    }
1207
1208
    /**
1209
     * Test for the findContent() method.
1210
     *
1211
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
1212
     * @depends eZ\Publish\API\Repository\Tests\SearchServiceTest::testFieldCollectionContains
1213
     */
1214 View Code Duplication
    public function testFieldCollectionContainsNoMatch()
1215
    {
1216
        $this->createMultipleCountriesContent();
1217
        $query = new Query(
1218
            array(
1219
                'query' => new Criterion\Field(
1220
                    'countries',
1221
                    Criterion\Operator::CONTAINS,
1222
                    'Netherlands Antilles'
1223
                ),
1224
            )
1225
        );
1226
1227
        $repository = $this->getRepository();
1228
        $searchService = $repository->getSearchService();
1229
        $result = $searchService->findContent($query);
1230
1231
        $this->assertEquals(0, $result->totalCount);
1232
    }
1233
1234
    /**
1235
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1236
     * @expectedExceptionMessage Argument '$criterion->target' is invalid: No searchable fields found for the given criterion target 'some_hopefully_unknown_field'
1237
     */
1238 View Code Duplication
    public function testInvalidFieldIdentifierRange()
1239
    {
1240
        $repository = $this->getRepository();
1241
        $searchService = $repository->getSearchService();
1242
1243
        $searchService->findContent(
1244
            new Query(
1245
                array(
1246
                    'filter' => new Criterion\Field(
1247
                        'some_hopefully_unknown_field',
1248
                        Criterion\Operator::BETWEEN,
1249
                        array(10, 1000)
1250
                    ),
1251
                    'sortClauses' => array(new SortClause\ContentId()),
1252
                )
1253
            )
1254
        );
1255
    }
1256
1257
    /**
1258
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1259
     * @expectedExceptionMessage Argument '$criterion->target' is invalid: No searchable fields found for the given criterion target 'some_hopefully_unknown_field'
1260
     */
1261 View Code Duplication
    public function testInvalidFieldIdentifierIn()
1262
    {
1263
        $repository = $this->getRepository();
1264
        $searchService = $repository->getSearchService();
1265
1266
        $searchService->findContent(
1267
            new Query(
1268
                array(
1269
                    'filter' => new Criterion\Field(
1270
                        'some_hopefully_unknown_field',
1271
                        Criterion\Operator::EQ,
1272
                        1000
1273
                    ),
1274
                    'sortClauses' => array(new SortClause\ContentId()),
1275
                )
1276
            )
1277
        );
1278
    }
1279
1280
    /**
1281
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1282
     * @expectedExceptionMessage Argument '$criterion->target' is invalid: No searchable fields found for the given criterion target 'tag_cloud_url'
1283
     */
1284 View Code Duplication
    public function testFindContentWithNonSearchableField()
1285
    {
1286
        $repository = $this->getRepository();
1287
        $searchService = $repository->getSearchService();
1288
1289
        $searchService->findContent(
1290
            new Query(
1291
                array(
1292
                    'filter' => new Criterion\Field(
1293
                        'tag_cloud_url',
1294
                        Criterion\Operator::EQ,
1295
                        'http://nimbus.com'
1296
                    ),
1297
                    'sortClauses' => array(new SortClause\ContentId()),
1298
                )
1299
            )
1300
        );
1301
    }
1302
1303
    /**
1304
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1305
     * @expectedExceptionMessage Argument '$sortClause->targetData' is invalid: No searchable fields found for the given sort clause target 'title' on 'template_look'
1306
     */
1307 View Code Duplication
    public function testSortFieldWithNonSearchableField()
1308
    {
1309
        $repository = $this->getRepository();
1310
        $searchService = $repository->getSearchService();
1311
1312
        $searchService->findContent(
1313
            new Query(
1314
                array(
1315
                    'sortClauses' => array(new SortClause\Field('template_look', 'title')),
1316
                )
1317
            )
1318
        );
1319
    }
1320
1321
    /**
1322
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1323
     * @expectedExceptionMessage Argument '$sortClause->targetData' is invalid: No searchable fields found for the given sort clause target 'title' on 'template_look'
1324
     */
1325 View Code Duplication
    public function testSortMapLocationDistanceWithNonSearchableField()
1326
    {
1327
        $repository = $this->getRepository();
1328
        $searchService = $repository->getSearchService();
1329
1330
        $searchService->findContent(
1331
            new Query(
1332
                array(
1333
                    'sortClauses' => array(
1334
                        new SortClause\MapLocationDistance(
1335
                            'template_look',
1336
                            'title',
1337
                            1,
1338
                            2
1339
                        ),
1340
                    ),
1341
                )
1342
            )
1343
        );
1344
    }
1345
1346
    /**
1347
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1348
     */
1349 View Code Duplication
    public function testFindSingleFailMultiple()
1350
    {
1351
        $repository = $this->getRepository();
1352
        $searchService = $repository->getSearchService();
1353
1354
        $searchService->findSingle(
1355
            new Criterion\ContentId(
1356
                array(4, 10)
1357
            )
1358
        );
1359
    }
1360
1361
    /**
1362
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1363
     */
1364
    public function testFindSingleWithNonSearchableField()
1365
    {
1366
        $repository = $this->getRepository();
1367
        $searchService = $repository->getSearchService();
1368
1369
        $searchService->findSingle(
1370
            new Criterion\Field(
1371
                'tag_cloud_url',
1372
                Criterion\Operator::EQ,
1373
                'http://nimbus.com'
1374
            )
1375
        );
1376
    }
1377
1378
    public function getSortedContentSearches()
1379
    {
1380
        $fixtureDir = $this->getFixtureDir();
1381
1382
        return array(
1383
            0 => array(
1384
                array(
1385
                    'filter' => new Criterion\SectionId(array(2)),
1386
                    'offset' => 0,
1387
                    'limit' => 10,
1388
                    'sortClauses' => array(),
1389
                ),
1390
                $fixtureDir . 'SortNone.php',
1391
                // Result having the same sort level should be sorted between them to be system independent
1392
                function (&$data) {
1393
                    usort(
1394
                        $data->searchHits,
1395
                        function ($a, $b) {
1396
                            return ($a->valueObject['id'] < $b->valueObject['id']) ? -1 : 1;
1397
                        }
1398
                    );
1399
                },
1400
            ),
1401
            1 => array(
1402
                array(
1403
                    'filter' => new Criterion\SectionId(array(2)),
1404
                    'offset' => 0,
1405
                    'limit' => 10,
1406
                    'sortClauses' => array(
1407
                        new SortClause\DatePublished(),
1408
                        new SortClause\ContentId(),
1409
                    ),
1410
                ),
1411
                $fixtureDir . 'SortDatePublished.php',
1412
            ),
1413
            2 => array(
1414
                array(
1415
                    'filter' => new Criterion\SectionId(array(2)),
1416
                    'offset' => 0,
1417
                    'limit' => 50,
1418
                    'sortClauses' => array(
1419
                        new SortClause\DateModified(),
1420
                        new SortClause\ContentId(),
1421
                    ),
1422
                ),
1423
                $fixtureDir . 'SortDateModified.php',
1424
            ),
1425
            3 => array(
1426
                array(
1427
                    'filter' => new Criterion\SectionId(array(4, 2, 6, 3)),
1428
                    'offset' => 0,
1429
                    'limit' => 50,
1430
                    'sortClauses' => array(
1431
                        new SortClause\SectionIdentifier(),
1432
                        new SortClause\ContentId(),
1433
                    ),
1434
                ),
1435
                $fixtureDir . 'SortSectionIdentifier.php',
1436
            ),
1437
            4 => array(
1438
                array(
1439
                    'filter' => new Criterion\SectionId(array(4, 2, 6, 3)),
1440
                    'offset' => 0,
1441
                    'limit' => 50,
1442
                    'sortClauses' => array(
1443
                        new SortClause\SectionName(),
1444
                        new SortClause\ContentId(),
1445
                    ),
1446
                ),
1447
                $fixtureDir . 'SortSectionName.php',
1448
            ),
1449
            5 => array(
1450
                array(
1451
                    'filter' => new Criterion\SectionId(array(2, 3)),
1452
                    'offset' => 0,
1453
                    'limit' => 50,
1454
                    'sortClauses' => array(
1455
                        new SortClause\ContentName(),
1456
                        new SortClause\ContentId(),
1457
                    ),
1458
                ),
1459
                $fixtureDir . 'SortContentName.php',
1460
            ),
1461
            6 => array(
1462
                array(
1463
                    'filter' => new Criterion\ContentTypeId(1),
1464
                    'offset' => 0,
1465
                    'limit' => 50,
1466
                    'sortClauses' => array(
1467
                        new SortClause\Field('folder', 'name', Query::SORT_ASC),
1468
                        new SortClause\ContentId(),
1469
                    ),
1470
                ),
1471
                $fixtureDir . 'SortFolderName.php',
1472
            ),
1473
            7 => array(
1474
                array(
1475
                    'filter' => new Criterion\ContentTypeId(array(1, 3)),
1476
                    'offset' => 0,
1477
                    'limit' => 50,
1478
                    'sortClauses' => array(
1479
                        new SortClause\Field('folder', 'name', Query::SORT_ASC),
1480
                        new SortClause\ContentId(),
1481
                    ),
1482
                ),
1483
                $fixtureDir . 'SortFieldMultipleTypes.php',
1484
            ),
1485
            8 => array(
1486
                array(
1487
                    'filter' => new Criterion\ContentTypeId(array(1, 3)),
1488
                    'offset' => 0,
1489
                    'limit' => 50,
1490
                    'sortClauses' => array(
1491
                        new SortClause\Field('folder', 'name', Query::SORT_DESC),
1492
                        new SortClause\ContentId(),
1493
                    ),
1494
                ),
1495
                $fixtureDir . 'SortFieldMultipleTypesReverse.php',
1496
            ),
1497
            9 => array(
1498
                array(
1499
                    'filter' => new Criterion\ContentTypeId(array(1, 3)),
1500
                    'offset' => 3,
1501
                    'limit' => 5,
1502
                    'sortClauses' => array(
1503
                        new SortClause\Field('folder', 'name', Query::SORT_ASC),
1504
                        new SortClause\Field('user', 'first_name', Query::SORT_ASC),
1505
                        new SortClause\ContentId(),
1506
                    ),
1507
                ),
1508
                $fixtureDir . 'SortFieldMultipleTypesSlice.php',
1509
            ),
1510
            10 => array(
1511
                array(
1512
                    'filter' => new Criterion\ContentTypeId(array(1, 3)),
1513
                    'offset' => 3,
1514
                    'limit' => 5,
1515
                    'sortClauses' => array(
1516
                        new SortClause\Field('folder', 'name', Query::SORT_DESC),
1517
                        new SortClause\Field('user', 'first_name', Query::SORT_ASC),
1518
                        new SortClause\ContentId(),
1519
                    ),
1520
                ),
1521
                $fixtureDir . 'SortFieldMultipleTypesSliceReverse.php',
1522
            ),
1523
        );
1524
    }
1525
1526
    public function getSortedLocationSearches()
1527
    {
1528
        $fixtureDir = $this->getFixtureDir();
1529
1530
        return array(
1531
            array(
1532
                array(
1533
                    'filter' => new Criterion\SectionId(array(2)),
1534
                    'offset' => 0,
1535
                    'limit' => 10,
1536
                    'sortClauses' => array(new SortClause\Location\Path(Query::SORT_DESC)),
1537
                ),
1538
                $fixtureDir . 'SortPathString.php',
1539
            ),
1540
            array(
1541
                array(
1542
                    'filter' => new Criterion\SectionId(array(2)),
1543
                    'offset' => 0,
1544
                    'limit' => 10,
1545
                    'sortClauses' => array(new SortClause\Location\Depth(Query::SORT_ASC)),
1546
                ),
1547
                $fixtureDir . 'SortLocationDepth.php',
1548
                // Result having the same sort level should be sorted between them to be system independent
1549
                function (&$data) {
1550
                    // Result with ids:
1551
                    //     4 has depth = 1
1552
                    //     11, 12, 13, 42, 59 have depth = 2
1553
                    //     10, 14 have depth = 3
1554
                    $map = array(
1555
                        4 => 0,
1556
                        11 => 1,
1557
                        12 => 2,
1558
                        13 => 3,
1559
                        42 => 4,
1560
                        59 => 5,
1561
                        10 => 6,
1562
                        14 => 7,
1563
                    );
1564
                    usort(
1565
                        $data->searchHits,
1566
                        function ($a, $b) use ($map) {
1567
                            return ($map[$a->valueObject['id']] < $map[$b->valueObject['id']]) ? -1 : 1;
1568
                        }
1569
                    );
1570
                },
1571
            ),
1572
            array(
1573
                array(
1574
                    'filter' => new Criterion\SectionId(array(3)),
1575
                    'offset' => 0,
1576
                    'limit' => 10,
1577
                    'sortClauses' => array(
1578
                        new SortClause\Location\Path(Query::SORT_DESC),
1579
                        new SortClause\ContentName(Query::SORT_ASC),
1580
                    ),
1581
                ),
1582
                $fixtureDir . 'SortMultiple.php',
1583
            ),
1584
            array(
1585
                array(
1586
                    'filter' => new Criterion\SectionId(array(2)),
1587
                    'offset' => 0,
1588
                    'limit' => 10,
1589
                    'sortClauses' => array(
1590
                        new SortClause\Location\Priority(Query::SORT_DESC),
1591
                        new SortClause\ContentId(),
1592
                    ),
1593
                ),
1594
                $fixtureDir . 'SortDesc.php',
1595
            ),
1596
        );
1597
    }
1598
1599
    /**
1600
     * @return \eZ\Publish\API\Repository\Values\ContentType\ContentType
1601
     */
1602 View Code Duplication
    protected function createTestContentType()
1603
    {
1604
        $repository = $this->getRepository();
1605
        $contentTypeService = $repository->getContentTypeService();
1606
1607
        $createStruct = $contentTypeService->newContentTypeCreateStruct('test-type');
1608
        $createStruct->mainLanguageCode = 'eng-GB';
1609
        $createStruct->names = array('eng-GB' => 'Test type');
1610
        $createStruct->creatorId = 14;
1611
        $createStruct->creationDate = new \DateTime();
1612
1613
        $translatableFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('integer', 'ezinteger');
1614
        $translatableFieldCreate->names = array('eng-GB' => 'Simple translatable integer field');
1615
        $translatableFieldCreate->fieldGroup = 'main';
1616
        $translatableFieldCreate->position = 1;
1617
        $translatableFieldCreate->isTranslatable = true;
1618
        $translatableFieldCreate->isSearchable = true;
1619
1620
        $createStruct->addFieldDefinition($translatableFieldCreate);
1621
1622
        $nonTranslatableFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('integer2', 'ezinteger');
1623
        $nonTranslatableFieldCreate->names = array('eng-GB' => 'Simple non-translatable integer field');
1624
        $nonTranslatableFieldCreate->fieldGroup = 'main';
1625
        $nonTranslatableFieldCreate->position = 2;
1626
        $nonTranslatableFieldCreate->isTranslatable = false;
1627
        $nonTranslatableFieldCreate->isSearchable = true;
1628
1629
        $createStruct->addFieldDefinition($nonTranslatableFieldCreate);
1630
1631
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
1632
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, array($contentGroup));
1633
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
1634
        $contentType = $contentTypeService->loadContentType($contentTypeDraft->id);
1635
1636
        return $contentType;
1637
    }
1638
1639
    /**
1640
     * @param \eZ\Publish\API\Repository\Values\ContentType\ContentType $contentType
1641
     * @param int $fieldValue11 Value for translatable field in first language
1642
     * @param int $fieldValue12 Value for translatable field in second language
1643
     * @param int $fieldValue2 Value for non translatable field
1644
     * @param string $mainLanguageCode
1645
     * @param bool $alwaysAvailable
1646
     *
1647
     * @return Content
1648
     */
1649
    protected function createMultilingualContent(
1650
        $contentType,
1651
        $fieldValue11 = null,
1652
        $fieldValue12 = null,
1653
        $fieldValue2 = null,
1654
        $mainLanguageCode = 'eng-GB',
1655
        $alwaysAvailable = false
1656
    ) {
1657
        $repository = $this->getRepository();
1658
        $contentService = $repository->getContentService();
1659
1660
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
1661
        $createStruct->alwaysAvailable = $alwaysAvailable;
1662
        $createStruct->mainLanguageCode = $mainLanguageCode;
1663
        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...
1664
            $createStruct->setField('integer', $fieldValue11, 'eng-GB');
1665
        }
1666
        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...
1667
            $createStruct->setField('integer', $fieldValue12, 'ger-DE');
1668
        }
1669
        $createStruct->setField('integer2', $fieldValue2, $mainLanguageCode);
1670
1671
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
1672
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
1673
        $content = $contentService->publishVersion($draft->getVersionInfo());
1674
1675
        $this->refreshSearch($repository);
1676
1677
        return $content;
1678
    }
1679
1680
    protected function checkPrioritizedLanguagesSupport()
1681
    {
1682
        $setupFactory = $this->getSetupFactory();
1683
        if ($setupFactory instanceof LegacyElasticsearch) {
1684
            $this->markTestIncomplete('Prioritized languages are not supported with Elasticsearch engine');
1685
        }
1686
    }
1687
1688
    public function providerForTestMultilingualFieldSort()
1689
    {
1690
        return array(
1691
            0 => array(
1692
                array(
1693
                    1 => array(1, 2, 1),
1694
                    2 => array(2, 1, 2),
1695
                    3 => array(2, 1, 3),
1696
                    4 => array(1, 2, 4),
1697
                ),
1698
                array(
1699
                    'languages' => array(
1700
                        'eng-GB',
1701
                        'ger-DE',
1702
                    ),
1703
                ),
1704
                array(
1705
                    new SortClause\Field('test-type', 'integer', Query::SORT_ASC),
1706
                    new SortClause\Field('test-type', 'integer2', Query::SORT_DESC),
1707
                ),
1708
                /**
1709
                 * Expected order, Value eng-GB, Value ger-DE.
1710
                 *
1711
                 * Content 4, 1, 2, 4
1712
                 * Content 1, 1, 2, 1
1713
                 * Content 3, 2, 1, 3
1714
                 * Content 2, 2, 1, 2
1715
                 */
1716
                array(4, 1, 3, 2),
1717
            ),
1718
            1 => array(
1719
                array(
1720
                    1 => array(1, 2, 1),
1721
                    2 => array(2, 1, 2),
1722
                    3 => array(2, 1, 3),
1723
                    4 => array(1, 2, 4),
1724
                ),
1725
                array(
1726
                    'languages' => array(
1727
                        'ger-DE',
1728
                        'eng-GB',
1729
                    ),
1730
                ),
1731
                array(
1732
                    new SortClause\Field('test-type', 'integer', Query::SORT_ASC),
1733
                    new SortClause\Field('test-type', 'integer2', Query::SORT_DESC),
1734
                ),
1735
                /**
1736
                 * Expected order, Value eng-GB, Value ger-DE.
1737
                 *
1738
                 * Content 3, 2, 1, 3
1739
                 * Content 2, 2, 1, 2
1740
                 * Content 4, 1, 2, 4
1741
                 * Content 1, 1, 2, 1
1742
                 */
1743
                array(3, 2, 4, 1),
1744
            ),
1745
            2 => array(
1746
                array(
1747
                    1 => array(null, 2, null, 'ger-DE'),
1748
                    2 => array(3, null, null, 'eng-GB'),
1749
                    3 => array(4, null, null, 'eng-GB'),
1750
                    4 => array(null, 1, null, 'ger-DE'),
1751
                ),
1752
                array(
1753
                    'languages' => array(
1754
                        'eng-GB',
1755
                    ),
1756
                ),
1757
                array(
1758
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1759
                ),
1760
                /**
1761
                 * Expected order, Value eng-GB, Value ger-DE.
1762
                 *
1763
                 * Content 3, 4, -
1764
                 * Content 2, 3, -
1765
                 */
1766
                array(3, 2),
1767
            ),
1768
            3 => array(
1769
                array(
1770
                    1 => array(null, 2, null, 'ger-DE'),
1771
                    2 => array(3, null, null, 'eng-GB'),
1772
                    3 => array(4, null, null, 'eng-GB'),
1773
                    4 => array(null, 1, null, 'ger-DE'),
1774
                ),
1775
                array(
1776
                    'languages' => array(
1777
                        'ger-DE',
1778
                    ),
1779
                ),
1780
                array(
1781
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1782
                ),
1783
                /**
1784
                 * Expected order, Value eng-GB, Value ger-DE.
1785
                 *
1786
                 * Content 1, -, 2
1787
                 * Content 4, -, 1
1788
                 */
1789
                array(1, 4),
1790
            ),
1791
            4 => array(
1792
                array(
1793
                    1 => array(null, 2, null, 'ger-DE'),
1794
                    2 => array(3, null, null, 'eng-GB'),
1795
                    3 => array(4, null, null, 'eng-GB'),
1796
                    4 => array(null, 1, null, 'ger-DE'),
1797
                ),
1798
                array(
1799
                    'languages' => array(
1800
                        'eng-GB',
1801
                        'ger-DE',
1802
                    ),
1803
                ),
1804
                array(
1805
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1806
                ),
1807
                /**
1808
                 * Expected order, Value eng-GB, Value ger-DE.
1809
                 *
1810
                 * Content 3, 4, -
1811
                 * Content 2, 3, -
1812
                 * Content 1, -, 2
1813
                 * Content 4, -, 1
1814
                 */
1815
                array(3, 2, 1, 4),
1816
            ),
1817
            5 => array(
1818
                array(
1819
                    1 => array(null, 2, null, 'ger-DE'),
1820
                    2 => array(3, null, null, 'eng-GB'),
1821
                    3 => array(4, null, null, 'eng-GB'),
1822
                    4 => array(null, 1, null, 'ger-DE'),
1823
                ),
1824
                array(
1825
                    'languages' => array(
1826
                        'ger-DE',
1827
                        'eng-GB',
1828
                    ),
1829
                ),
1830
                array(
1831
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1832
                ),
1833
                /**
1834
                 * Expected order, Value eng-GB, Value ger-DE.
1835
                 *
1836
                 * Content 3, 4, -
1837
                 * Content 2, 3, -
1838
                 * Content 1, -, 2
1839
                 * Content 4, -, 1
1840
                 */
1841
                array(3, 2, 1, 4),
1842
            ),
1843
            6 => array(
1844
                array(
1845
                    1 => array(null, 2, null, 'ger-DE'),
1846
                    2 => array(3, 4, null, 'eng-GB'),
1847
                    3 => array(4, 3, null, 'eng-GB'),
1848
                    4 => array(null, 1, null, 'ger-DE'),
1849
                ),
1850
                array(
1851
                    'languages' => array(
1852
                        'eng-GB',
1853
                        'ger-DE',
1854
                    ),
1855
                ),
1856
                array(
1857
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1858
                ),
1859
                /**
1860
                 * Expected order, Value eng-GB, Value ger-DE.
1861
                 *
1862
                 * Content 3, 4, 3
1863
                 * Content 2, 3, 4
1864
                 * Content 1, -, 2
1865
                 * Content 4, -, 1
1866
                 */
1867
                array(3, 2, 1, 4),
1868
            ),
1869
            7 => array(
1870
                array(
1871
                    1 => array(null, 2, null, 'ger-DE'),
1872
                    2 => array(3, 4, null, 'eng-GB'),
1873
                    3 => array(4, 3, null, 'eng-GB'),
1874
                    4 => array(null, 1, null, 'ger-DE'),
1875
                ),
1876
                array(
1877
                    'languages' => array(
1878
                        'ger-DE',
1879
                        'eng-GB',
1880
                    ),
1881
                ),
1882
                array(
1883
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1884
                ),
1885
                /**
1886
                 * Expected order, Value eng-GB, Value ger-DE.
1887
                 *
1888
                 * Content 2, 3, 4
1889
                 * Content 3, 4, 3
1890
                 * Content 1, -, 2
1891
                 * Content 4, -, 1
1892
                 */
1893
                array(2, 3, 1, 4),
1894
            ),
1895
            8 => array(
1896
                array(
1897
                    1 => array(null, 1, null, 'ger-DE', true),
1898
                    2 => array(4, null, null, 'eng-GB', true),
1899
                    3 => array(3, null, null, 'eng-GB', false),
1900
                    4 => array(null, 2, null, 'ger-DE', false),
1901
                ),
1902
                array(
1903
                    'languages' => array(
1904
                        'eng-GB',
1905
                    ),
1906
                ),
1907
                array(
1908
                    new SortClause\Field('test-type', 'integer', Query::SORT_ASC),
1909
                ),
1910
                /**
1911
                 * Expected order, Value eng-GB, Value ger-DE.
1912
                 *
1913
                 * Content 1, -, 1
1914
                 * Content 3, 3, -
1915
                 * Content 2, 4, -
1916
                 */
1917
                array(1, 3, 2),
1918
            ),
1919
            9 => array(
1920
                array(
1921
                    1 => array(null, 1, null, 'ger-DE', true),
1922
                    2 => array(4, null, null, 'eng-GB', true),
1923
                    3 => array(3, null, null, 'eng-GB', false),
1924
                    4 => array(null, 2, null, 'ger-DE', false),
1925
                ),
1926
                array(
1927
                    'languages' => array(
1928
                        'ger-DE',
1929
                    ),
1930
                ),
1931
                array(
1932
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1933
                ),
1934
                /**
1935
                 * Expected order, Value eng-GB, Value ger-DE.
1936
                 *
1937
                 * Content 2, 4, -
1938
                 * Content 4, -, 2
1939
                 * Content 1, -, 1
1940
                 */
1941
                array(2, 4, 1),
1942
            ),
1943
            10 => array(
1944
                array(
1945
                    1 => array(null, 1, null, 'ger-DE', true),
1946
                    2 => array(4, null, null, 'eng-GB', true),
1947
                    3 => array(3, null, null, 'eng-GB', false),
1948
                    4 => array(null, 2, null, 'ger-DE', false),
1949
                ),
1950
                array(
1951
                    'languages' => array(
1952
                        'eng-GB',
1953
                    ),
1954
                    'useAlwaysAvailable' => false,
1955
                ),
1956
                array(
1957
                    new SortClause\Field('test-type', 'integer', Query::SORT_ASC),
1958
                ),
1959
                /**
1960
                 * Expected order, Value eng-GB, Value ger-DE.
1961
                 *
1962
                 * Content 3, 3, -
1963
                 * Content 2, 4, -
1964
                 */
1965
                array(3, 2),
1966
            ),
1967
            11 => array(
1968
                array(
1969
                    1 => array(null, 1, null, 'ger-DE', true),
1970
                    2 => array(4, null, null, 'eng-GB', true),
1971
                    3 => array(3, null, null, 'eng-GB', false),
1972
                    4 => array(null, 2, null, 'ger-DE', false),
1973
                ),
1974
                array(
1975
                    'languages' => array(
1976
                        'ger-DE',
1977
                    ),
1978
                    'useAlwaysAvailable' => false,
1979
                ),
1980
                array(
1981
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1982
                ),
1983
                /**
1984
                 * Expected order, Value eng-GB, Value ger-DE.
1985
                 *
1986
                 * Content 4, -, 2
1987
                 * Content 1, -, 1
1988
                 */
1989
                array(4, 1),
1990
            ),
1991
        );
1992
    }
1993
1994
    /**
1995
     * Test for the findContent() method.
1996
     *
1997
     * @group rrr
1998
     * @dataProvider providerForTestMultilingualFieldSort
1999
     *
2000
     * @param array $contentDataList
2001
     * @param array $languageSettings
2002
     * @param \eZ\Publish\API\Repository\Values\Content\Query\SortClause[] $sortClauses
2003
     * @param array $expected
2004
     */
2005
    public function testMultilingualFieldSortContent(
2006
        array $contentDataList,
2007
        $languageSettings,
2008
        array $sortClauses,
2009
        $expected
2010
    ) {
2011
        $this->assertMultilingualFieldSort(
2012
            $contentDataList,
2013
            $languageSettings,
2014
            $sortClauses,
2015
            $expected
2016
        );
2017
    }
2018
2019
    /**
2020
     * Test for the findLocations() method.
2021
     *
2022
     * @group rrr
2023
     * @dataProvider providerForTestMultilingualFieldSort
2024
     *
2025
     * @param array $contentDataList
2026
     * @param array $languageSettings
2027
     * @param \eZ\Publish\API\Repository\Values\Content\Query\SortClause[] $sortClauses
2028
     * @param array $expected
2029
     */
2030
    public function testMultilingualFieldSortLocation(
2031
        array $contentDataList,
2032
        $languageSettings,
2033
        array $sortClauses,
2034
        $expected
2035
    ) {
2036
        $this->assertMultilingualFieldSort(
2037
            $contentDataList,
2038
            $languageSettings,
2039
            $sortClauses,
2040
            $expected,
2041
            false
2042
        );
2043
    }
2044
2045
    /**
2046
     * @param array $contentDataList
2047
     * @param array $languageSettings
2048
     * @param \eZ\Publish\API\Repository\Values\Content\Query\SortClause[] $sortClauses
2049
     * @param array $expected
2050
     * @param bool $contentSearch
2051
     */
2052
    protected function assertMultilingualFieldSort(
2053
        array $contentDataList,
2054
        $languageSettings,
2055
        array $sortClauses,
2056
        $expected,
2057
        $contentSearch = true
2058
    ) {
2059
        $this->checkPrioritizedLanguagesSupport();
2060
        $contentType = $this->createTestContentType();
2061
2062
        // Create a draft to account for behaviour with ContentType in different states
2063
        $repository = $this->getRepository();
2064
        $contentTypeService = $repository->getContentTypeService();
2065
        $contentTypeService->createContentTypeDraft($contentType);
2066
2067
        $defaults = array(null, null, null, 'eng-GB', false);
2068
        $contentIdList = array();
2069 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...
2070
            $contentData = $contentData + $defaults;
2071
            list(
2072
                $fieldValue11,
2073
                $fieldValue12,
2074
                $fieldValue2,
2075
                $mainLanguageCode,
2076
                $alwaysAvailable
2077
            ) = $contentData;
2078
2079
            $contentIdList[$key] = $this->createMultilingualContent(
2080
                $contentType,
2081
                $fieldValue11,
2082
                $fieldValue12,
2083
                $fieldValue2,
2084
                $mainLanguageCode,
2085
                $alwaysAvailable
2086
            )->id;
2087
        }
2088
2089
        // "article" type Content is not matched, this ensures that non-matched
2090
        // field does not affect sort
2091
        $dummySortClause = new SortClause\Field('article', 'title', Query::SORT_ASC);
2092
        array_unshift($sortClauses, $dummySortClause);
2093
        array_push($sortClauses, $dummySortClause);
2094
2095
        $searchService = $repository->getSearchService();
2096
        if ($contentSearch) {
2097
            $query = new Query(
2098
                array(
2099
                    'query' => new Criterion\ContentTypeId($contentType->id),
2100
                    'sortClauses' => $sortClauses,
2101
                )
2102
            );
2103
            $result = $searchService->findContent($query, $languageSettings);
2104
        } else {
2105
            $query = new LocationQuery(
2106
                array(
2107
                    'query' => new Criterion\ContentTypeId($contentType->id),
2108
                    'sortClauses' => $sortClauses,
2109
                )
2110
            );
2111
            $result = $searchService->findLocations($query, $languageSettings);
2112
        }
2113
2114
        $this->assertEquals(count($expected), $result->totalCount);
2115
2116
        $expectedIdList = array();
2117
        foreach ($expected as $contentNumber) {
2118
            $expectedIdList[] = $contentIdList[$contentNumber];
2119
        }
2120
2121
        $this->assertEquals($expectedIdList, $this->mapResultContentIds($result));
2122
    }
2123
2124
    public function providerForTestMultilingualFieldFilter()
2125
    {
2126
        return array(
2127
            0 => array(
2128
                $fixture = array(
2129
                    1 => array(null, 1, null, 'ger-DE', true),
2130
                    2 => array(4, null, null, 'eng-GB', true),
2131
                    3 => array(3, null, null, 'eng-GB', false),
2132
                    4 => array(null, 2, null, 'ger-DE', false),
2133
                    5 => array(5, null, null, 'eng-GB', true),
2134
                ),
2135
                $languageSettings = array(
2136
                    'languages' => array(
2137
                        'ger-DE',
2138
                    ),
2139
                ),
2140
                new Criterion\Field('integer', Criterion\Operator::LT, 5),
2141
                /**
2142
                 * Expected order, Value eng-GB, Value ger-DE.
2143
                 *
2144
                 * Content 2, 4, -
2145
                 * Content 4, -, 2
2146
                 * Content 1, -, 1
2147
                 */
2148
                array(2, 4, 1),
2149
            ),
2150
            1 => array(
2151
                $fixture,
2152
                array(
2153
                    'languages' => array(
2154
                        'ger-DE',
2155
                    ),
2156
                    'useAlwaysAvailable' => false,
2157
                ),
2158
                new Criterion\Field('integer', Criterion\Operator::LT, 2),
2159
                /**
2160
                 * Expected order, Value eng-GB, Value ger-DE.
2161
                 *
2162
                 * Content 1, -, 1
2163
                 */
2164
                array(1),
2165
            ),
2166
            2 => array(
2167
                $fixture,
2168
                array(
2169
                    'languages' => array(
2170
                        'eng-GB',
2171
                    ),
2172
                ),
2173
                new Criterion\Field('integer', Criterion\Operator::LTE, 4),
2174
                /**
2175
                 * Expected order, Value eng-GB, Value ger-DE.
2176
                 *
2177
                 * Content 5, 5, -
2178
                 * Content 2, 4, -
2179
                 * Content 3, 3, -
2180
                 * Content 1, -, 1
2181
                 */
2182
                array(2, 3, 1),
2183
            ),
2184
            3 => array(
2185
                $fixture,
2186
                array(
2187
                    'languages' => array(
2188
                        'eng-GB',
2189
                    ),
2190
                    'useAlwaysAvailable' => false,
2191
                ),
2192
                new Criterion\Field('integer', Criterion\Operator::LTE, 4),
2193
                /**
2194
                 * Expected order, Value eng-GB, Value ger-DE.
2195
                 *
2196
                 * Content 2, 4, -
2197
                 * Content 3, 3, -
2198
                 */
2199
                array(2, 3),
2200
            ),
2201
            4 => array(
2202
                $fixture,
2203
                $languageSettings,
2204
                new Criterion\Field('integer', Criterion\Operator::LTE, 4),
2205
                /**
2206
                 * Expected order, Value eng-GB, Value ger-DE.
2207
                 *
2208
                 * Content 2, 4, -
2209
                 * Content 4, -, 2
2210
                 * Content 1, -, 1
2211
                 */
2212
                array(2, 4, 1),
2213
            ),
2214
            5 => array(
2215
                $fixture,
2216
                $languageSettings,
2217
                new Criterion\Field('integer', Criterion\Operator::GT, 1),
2218
                /**
2219
                 * Expected order, Value eng-GB, Value ger-DE.
2220
                 *
2221
                 * Content 5, 5, -
2222
                 * Content 2, 4, -
2223
                 * Content 4, -, 2
2224
                 */
2225
                array(5, 2, 4),
2226
            ),
2227
            6 => array(
2228
                $fixture,
2229
                $languageSettings,
2230
                new Criterion\Field('integer', Criterion\Operator::GTE, 2),
2231
                /**
2232
                 * Expected order, Value eng-GB, Value ger-DE.
2233
                 *
2234
                 * Content 5, 5, -
2235
                 * Content 2, 4, -
2236
                 * Content 4, -, 2
2237
                 */
2238
                array(5, 2, 4),
2239
            ),
2240
            7 => array(
2241
                $fixture,
2242
                $languageSettings,
2243
                new Criterion\Field('integer', Criterion\Operator::BETWEEN, array(2, 4)),
2244
                /**
2245
                 * Expected order, Value eng-GB, Value ger-DE.
2246
                 *
2247
                 * Content 2, 4, -
2248
                 * Content 4, -, 2
2249
                 */
2250
                array(2, 4),
2251
            ),
2252
            8 => array(
2253
                $fixture,
2254
                $languageSettings,
2255
                new Criterion\Field('integer', Criterion\Operator::BETWEEN, array(4, 2)),
2256
                array(),
2257
            ),
2258
            9 => array(
2259
                $fixture,
2260
                $languageSettings,
2261
                new Criterion\Field('integer', Criterion\Operator::EQ, 4),
2262
                /**
2263
                 * Expected order, Value eng-GB, Value ger-DE.
2264
                 *
2265
                 * Content 4, -, 2
2266
                 */
2267
                array(2),
2268
            ),
2269
            10 => array(
2270
                $fixture,
2271
                $languageSettings,
2272
                new Criterion\Field('integer', Criterion\Operator::EQ, 2),
2273
                /**
2274
                 * Expected order, Value eng-GB, Value ger-DE.
2275
                 *
2276
                 * Content 2, 4, -
2277
                 */
2278
                array(4),
2279
            ),
2280
        );
2281
    }
2282
2283
    /**
2284
     * Test for the findContent() method.
2285
     *
2286
     * @group ttt
2287
     * @dataProvider providerForTestMultilingualFieldFilter
2288
     *
2289
     * @param array $contentDataList
2290
     * @param array $languageSettings
2291
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
2292
     * @param array $expected
2293
     */
2294
    public function testMultilingualFieldFilterContent(
2295
        array $contentDataList,
2296
        $languageSettings,
2297
        Criterion $criterion,
2298
        $expected
2299
    ) {
2300
        $this->assertMultilingualFieldFilter(
2301
            $contentDataList,
2302
            $languageSettings,
2303
            $criterion,
2304
            $expected
2305
        );
2306
    }
2307
2308
    /**
2309
     * Test for the findLocations() method.
2310
     *
2311
     * @group ttt
2312
     * @dataProvider providerForTestMultilingualFieldFilter
2313
     *
2314
     * @param array $contentDataList
2315
     * @param array $languageSettings
2316
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
2317
     * @param array $expected
2318
     */
2319
    public function testMultilingualFieldFilterLocation(
2320
        array $contentDataList,
2321
        $languageSettings,
2322
        Criterion $criterion,
2323
        $expected
2324
    ) {
2325
        $this->assertMultilingualFieldFilter(
2326
            $contentDataList,
2327
            $languageSettings,
2328
            $criterion,
2329
            $expected,
2330
            false
2331
        );
2332
    }
2333
2334
    /**
2335
     * @param array $contentDataList
2336
     * @param array $languageSettings
2337
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
2338
     * @param array $expected
2339
     * @param bool $contentSearch
2340
     */
2341
    protected function assertMultilingualFieldFilter(
2342
        array $contentDataList,
2343
        $languageSettings,
2344
        Criterion $criterion,
2345
        $expected,
2346
        $contentSearch = true
2347
    ) {
2348
        $this->checkPrioritizedLanguagesSupport();
2349
        $contentType = $this->createTestContentType();
2350
2351
        // Create a draft to account for behaviour with ContentType in different states
2352
        $repository = $this->getRepository();
2353
        $contentTypeService = $repository->getContentTypeService();
2354
        $contentTypeService->createContentTypeDraft($contentType);
2355
2356
        $defaults = array(null, null, null, 'eng-GB', false);
2357
        $contentIdList = array();
2358 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...
2359
            $contentData = $contentData + $defaults;
2360
            list(
2361
                $fieldValue11,
2362
                $fieldValue12,
2363
                $fieldValue2,
2364
                $mainLanguageCode,
2365
                $alwaysAvailable
2366
            ) = $contentData;
2367
2368
            $contentIdList[$key] = $this->createMultilingualContent(
2369
                $contentType,
2370
                $fieldValue11,
2371
                $fieldValue12,
2372
                $fieldValue2,
2373
                $mainLanguageCode,
2374
                $alwaysAvailable
2375
            )->id;
2376
        }
2377
2378
        $sortClause = new SortClause\Field('test-type', 'integer', Query::SORT_DESC);
2379
        $searchService = $repository->getSearchService();
2380
        if ($contentSearch) {
2381
            $query = new Query(
2382
                array(
2383
                    'query' => new Criterion\LogicalAnd(
2384
                        array(
2385
                            new Criterion\ContentTypeId($contentType->id),
2386
                            $criterion,
2387
                        )
2388
                    ),
2389
                    'sortClauses' => array($sortClause),
2390
                )
2391
            );
2392
            $result = $searchService->findContent($query, $languageSettings);
2393
        } else {
2394
            $query = new LocationQuery(
2395
                array(
2396
                    'query' => new Criterion\LogicalAnd(
2397
                        array(
2398
                            new Criterion\ContentTypeId($contentType->id),
2399
                            $criterion,
2400
                        )
2401
                    ),
2402
                    'sortClauses' => array($sortClause),
2403
                )
2404
            );
2405
            $result = $searchService->findLocations($query, $languageSettings);
2406
        }
2407
2408
        $this->assertEquals(count($expected), $result->totalCount);
2409
2410
        $expectedIdList = array();
2411
        foreach ($expected as $contentNumber) {
2412
            $expectedIdList[] = $contentIdList[$contentNumber];
2413
        }
2414
2415
        $this->assertEquals($expectedIdList, $this->mapResultContentIds($result));
2416
    }
2417
2418
    /**
2419
     * @param \eZ\Publish\API\Repository\Values\Content\Search\SearchResult $result
2420
     *
2421
     * @return array
2422
     */
2423
    protected function mapResultContentIds(SearchResult $result)
2424
    {
2425
        return array_map(
2426
            function (SearchHit $searchHit) {
2427
                if ($searchHit->valueObject instanceof Location) {
2428
                    return $searchHit->valueObject->contentInfo->id;
2429
                }
2430
2431
                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...
2432
            },
2433
            $result->searchHits
2434
        );
2435
    }
2436
2437
    /**
2438
     * Test for the findContent() method.
2439
     *
2440
     * @dataProvider getSortedContentSearches
2441
     *
2442
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2443
     */
2444
    public function testFindAndSortContent($queryData, $fixture, $closure = null)
2445
    {
2446
        $query = new Query($queryData);
2447
        $this->assertQueryFixture($query, $fixture, $closure);
2448
    }
2449
2450
    /**
2451
     * Test for the findContentInfo() method.
2452
     *
2453
     * @dataProvider getSortedContentSearches
2454
     * @see \eZ\Publish\API\Repository\SearchService::findContentInfo()
2455
     */
2456
    public function testFindAndSortContentInfo($queryData, $fixture, $closure = null)
2457
    {
2458
        $query = new Query($queryData);
2459
        $this->assertQueryFixture($query, $fixture, $this->getContentInfoFixtureClosure($closure), true);
2460
    }
2461
2462
    /**
2463
     * Test for the findLocations() method.
2464
     *
2465
     * @dataProvider getSortedContentSearches
2466
     *
2467
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
2468
     */
2469
    public function testFindAndSortContentLocations($queryData, $fixture, $closure = null)
2470
    {
2471
        $query = new LocationQuery($queryData);
2472
        $this->assertQueryFixture($query, $fixture, $closure);
2473
    }
2474
2475
    /**
2476
     * Test for the findLocations() method.
2477
     *
2478
     * @dataProvider getSortedLocationSearches
2479
     *
2480
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
2481
     */
2482
    public function testFindAndSortLocations($queryData, $fixture, $closure = null)
2483
    {
2484
        $query = new LocationQuery($queryData);
2485
        $this->assertQueryFixture($query, $fixture, $closure);
2486
    }
2487
2488
    public function getFacettedSearches()
2489
    {
2490
        $fixtureDir = $this->getFixtureDir();
2491
2492
        return array(
2493
            array(
2494
                new Query(
2495
                    array(
2496
                        'filter' => new Criterion\SectionId(array(1)),
2497
                        'offset' => 0,
2498
                        'limit' => 10,
2499
                        'facetBuilders' => array(
2500
                            new FacetBuilder\ContentTypeFacetBuilder(
2501
                                array(
2502
                                    'name' => 'type',
2503
                                )
2504
                            ),
2505
                        ),
2506
                        'sortClauses' => array(new SortClause\ContentId()),
2507
                    )
2508
                ),
2509
                $fixtureDir . '/FacetContentType.php',
2510
            ),
2511
            array(
2512
                new Query(
2513
                    array(
2514
                        'filter' => new Criterion\SectionId(array(1)),
2515
                        'offset' => 0,
2516
                        'limit' => 10,
2517
                        'facetBuilders' => array(
2518
                            new FacetBuilder\ContentTypeFacetBuilder(
2519
                                array(
2520
                                    'name' => 'type',
2521
                                    'minCount' => 3,
2522
                                )
2523
                            ),
2524
                        ),
2525
                        'sortClauses' => array(new SortClause\ContentId()),
2526
                    )
2527
                ),
2528
                $fixtureDir . '/FacetContentTypeMinCount.php',
2529
            ),
2530
            array(
2531
                new Query(
2532
                    array(
2533
                        'filter' => new Criterion\SectionId(array(1)),
2534
                        'offset' => 0,
2535
                        'limit' => 10,
2536
                        'facetBuilders' => array(
2537
                            new FacetBuilder\ContentTypeFacetBuilder(
2538
                                array(
2539
                                    'name' => 'type',
2540
                                    'limit' => 5,
2541
                                )
2542
                            ),
2543
                        ),
2544
                        'sortClauses' => array(new SortClause\ContentId()),
2545
                    )
2546
                ),
2547
                $fixtureDir . '/FacetContentTypeMinLimit.php',
2548
            ),
2549
            array(
2550
                new Query(
2551
                    array(
2552
                        'filter' => new Criterion\SectionId(array(1)),
2553
                        'offset' => 0,
2554
                        'limit' => 10,
2555
                        'facetBuilders' => array(
2556
                            new FacetBuilder\SectionFacetBuilder(
2557
                                array(
2558
                                    'name' => 'section',
2559
                                )
2560
                            ),
2561
                        ),
2562
                        'sortClauses' => array(new SortClause\ContentId()),
2563
                    )
2564
                ),
2565
                $fixtureDir . '/FacetSection.php',
2566
            ),
2567
            array(
2568
                new Query(
2569
                    array(
2570
                        'filter' => new Criterion\SectionId(array(1)),
2571
                        'offset' => 0,
2572
                        'limit' => 10,
2573
                        'facetBuilders' => array(
2574
                            new FacetBuilder\UserFacetBuilder(
2575
                                array(
2576
                                    'name' => 'creator',
2577
                                )
2578
                            ),
2579
                        ),
2580
                        'sortClauses' => array(new SortClause\ContentId()),
2581
                    )
2582
                ),
2583
                $fixtureDir . '/FacetUser.php',
2584
            ),
2585
            array(
2586
                new Query(
2587
                    array(
2588
                        'filter' => new Criterion\SectionId(array(1)),
2589
                        'offset' => 0,
2590
                        'limit' => 10,
2591
                        'facetBuilders' => array(
2592
                            new FacetBuilder\TermFacetBuilder(),
2593
                        ),
2594
                        'sortClauses' => array(new SortClause\ContentId()),
2595
                    )
2596
                ),
2597
                $fixtureDir . '/FacetTerm.php',
2598
            ),
2599
            /* @todo: It needs to be defined how this one is supposed to work.
2600
            array(
2601
                new Query(
2602
                    array(
2603
                        'filter'      => new Criterion\SectionId( array( 1 ) ),
2604
                        'offset'      => 0,
2605
                        'limit'       => 10,
2606
                        'facetBuilders' => array(
2607
                            new FacetBuilder\CriterionFacetBuilder()
2608
                        ),
2609
                        'sortClauses' => array( new SortClause\ContentId() )
2610
                    )
2611
                ),
2612
                $fixtureDir . '/FacetCriterion.php',
2613
            ), // */
2614
            /* @todo: Add sane ranges here:
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\DateRangeFacetBuilder( array() )
2623
                        ),
2624
                        'sortClauses' => array( new SortClause\ContentId() )
2625
                    )
2626
                ),
2627
                $fixtureDir . '/FacetDateRange.php',
2628
            ), // */
2629
            array(
2630
                new Query(
2631
                    array(
2632
                        'filter' => new Criterion\SectionId(array(1)),
2633
                        'offset' => 0,
2634
                        'limit' => 10,
2635
                        'facetBuilders' => array(
2636
                            new FacetBuilder\FieldFacetBuilder(
2637
                                array(
2638
                                    'fieldPaths' => array('article/title'),
2639
                                )
2640
                            ),
2641
                        ),
2642
                        'sortClauses' => array(new SortClause\ContentId()),
2643
                    )
2644
                ),
2645
                $fixtureDir . '/FacetFieldSimple.php',
2646
            ),
2647
            array(
2648
                new Query(
2649
                    array(
2650
                        'filter' => new Criterion\SectionId(array(1)),
2651
                        'offset' => 0,
2652
                        'limit' => 10,
2653
                        'facetBuilders' => array(
2654
                            new FacetBuilder\FieldFacetBuilder(
2655
                                array(
2656
                                    'fieldPaths' => array('article/title'),
2657
                                    'regex' => '(a|b|c)',
2658
                                )
2659
                            ),
2660
                        ),
2661
                        'sortClauses' => array(new SortClause\ContentId()),
2662
                    )
2663
                ),
2664
                $fixtureDir . '/FacetFieldRegexp.php',
2665
            ),
2666
            array(
2667
                new Query(
2668
                    array(
2669
                        'filter' => new Criterion\SectionId(array(1)),
2670
                        'offset' => 0,
2671
                        'limit' => 10,
2672
                        'facetBuilders' => array(
2673
                            new FacetBuilder\FieldFacetBuilder(
2674
                                array(
2675
                                    'fieldPaths' => array('article/title'),
2676
                                    'regex' => '(a|b|c)',
2677
                                    'sort' => FacetBuilder\FieldFacetBuilder::TERM_DESC,
2678
                                )
2679
                            ),
2680
                        ),
2681
                        'sortClauses' => array(new SortClause\ContentId()),
2682
                    )
2683
                ),
2684
                $fixtureDir . '/FacetFieldRegexpSortTerm.php',
2685
            ),
2686
            array(
2687
                new Query(
2688
                    array(
2689
                        'filter' => new Criterion\SectionId(array(1)),
2690
                        'offset' => 0,
2691
                        'limit' => 10,
2692
                        'facetBuilders' => array(
2693
                            new FacetBuilder\FieldFacetBuilder(
2694
                                array(
2695
                                    'fieldPaths' => array('article/title'),
2696
                                    'regex' => '(a|b|c)',
2697
                                    'sort' => FacetBuilder\FieldFacetBuilder::COUNT_DESC,
2698
                                )
2699
                            ),
2700
                        ),
2701
                        'sortClauses' => array(new SortClause\ContentId()),
2702
                    )
2703
                ),
2704
                $fixtureDir . '/FacetFieldRegexpSortCount.php',
2705
            ),
2706
            /* @todo: Add sane ranges here:
2707
            array(
2708
                new Query(
2709
                    array(
2710
                        'filter'      => new Criterion\SectionId( array( 1 ) ),
2711
                        'offset'      => 0,
2712
                        'limit'       => 10,
2713
                        'facetBuilders' => array(
2714
                            new FacetBuilder\FieldRangeFacetBuilder( array(
2715
                                'fieldPath' => 'product/price',
2716
                            ) )
2717
                        ),
2718
                        'sortClauses' => array( new SortClause\ContentId() )
2719
                    )
2720
                ),
2721
                $fixtureDir . '/FacetFieldRegexpSortCount.php',
2722
            ), // */
2723
        );
2724
    }
2725
2726
    /**
2727
     * Test for the findContent() method.
2728
     *
2729
     * @dataProvider getFacettedSearches
2730
     *
2731
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2732
     */
2733
    public function testFindFacettedContent(Query $query, $fixture)
2734
    {
2735
        $this->assertQueryFixture($query, $fixture);
2736
    }
2737
2738
    /**
2739
     * Test for the findContentInfo() method.
2740
     *
2741
     * @dataProvider getFacettedSearches
2742
     * @see \eZ\Publish\API\Repository\SearchService::findContentInfo()
2743
     */
2744
    public function testFindFacettedContentInfo(Query $query, $fixture)
2745
    {
2746
        $this->assertQueryFixture($query, $fixture, $this->getContentInfoFixtureClosure(), true);
2747
    }
2748
2749
    /**
2750
     * Test for the findContent() method.
2751
     *
2752
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2753
     */
2754 View Code Duplication
    public function testQueryCustomField()
2755
    {
2756
        $query = new Query(
2757
            array(
2758
                'query' => new Criterion\CustomField(
2759
                    'custom_field',
2760
                    Criterion\Operator::EQ,
2761
                    'AdMiNiStRaToR'
2762
                ),
2763
                'offset' => 0,
2764
                'limit' => 10,
2765
                'sortClauses' => array(new SortClause\ContentId()),
2766
            )
2767
        );
2768
        $this->assertQueryFixture(
2769
            $query,
2770
            $this->getFixtureDir() . '/QueryCustomField.php'
2771
        );
2772
    }
2773
2774
    /**
2775
     * Test for the findContent() method.
2776
     *
2777
     * This tests explicitely queries the first_name while user is contained in
2778
     * the last_name of admin and anonymous. This is done to show the custom
2779
     * copy field working.
2780
     *
2781
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2782
     */
2783 View Code Duplication
    public function testQueryModifiedField()
2784
    {
2785
        // Check using get_class since the others extend SetupFactory\Legacy
2786
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
2787
            $this->markTestIncomplete(
2788
                'Custom fields not supported by LegacySE ' .
2789
                '(@todo: Legacy should fallback to just querying normal field so this should be tested here)'
2790
            );
2791
        }
2792
2793
        $query = new Query(
2794
            array(
2795
                'query' => new Criterion\Field(
2796
                    'first_name',
2797
                    Criterion\Operator::EQ,
2798
                    'User'
2799
                ),
2800
                'offset' => 0,
2801
                'limit' => 10,
2802
                'sortClauses' => array(new SortClause\ContentId()),
2803
            )
2804
        );
2805
        $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...
2806
2807
        $this->assertQueryFixture(
2808
            $query,
2809
            $this->getFixtureDir() . '/QueryModifiedField.php'
2810
        );
2811
    }
2812
2813
    /**
2814
     * Test for the findContent() method.
2815
     *
2816
     * This tests first explicitly creates sort clause on the 'short_name' which is empty
2817
     * for all Content instances of 'folder' ContentType. Custom sort field is then set
2818
     * to the index storage name of folder's 'name' field, in order to show the custom
2819
     * sort field working.
2820
     *
2821
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2822
     */
2823
    public function testSortModifiedField()
2824
    {
2825
        // Check using get_class since the others extend SetupFactory\Legacy
2826
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
2827
            $this->markTestIncomplete(
2828
                'Custom field sort not supported by LegacySE ' .
2829
                '(@todo: Legacy should fallback to just querying normal field so this should be tested here)'
2830
            );
2831
        }
2832
2833
        $sortClause = new SortClause\Field('folder', 'short_name', Query::SORT_ASC);
2834
        $sortClause->setCustomField('folder', 'short_name', 'folder_name_value_s');
2835
2836
        $query = new Query(
2837
            array(
2838
                'filter' => new Criterion\ContentTypeId(1),
2839
                'offset' => 0,
2840
                'limit' => 10,
2841
                'sortClauses' => array(
2842
                    $sortClause,
2843
                    new SortClause\ContentId(),
2844
                ),
2845
            )
2846
        );
2847
2848
        $this->assertQueryFixture(
2849
            $query,
2850
            $this->getFixtureDir() . '/SortFolderName.php'
2851
        );
2852
    }
2853
2854
    /**
2855
     * @return \eZ\Publish\API\Repository\Values\ContentType\ContentType
2856
     */
2857 View Code Duplication
    protected function createTestPlaceContentType()
2858
    {
2859
        $repository = $this->getRepository();
2860
        $contentTypeService = $repository->getContentTypeService();
2861
2862
        $createStruct = $contentTypeService->newContentTypeCreateStruct('testtype');
2863
        $createStruct->mainLanguageCode = 'eng-GB';
2864
        $createStruct->names = array('eng-GB' => 'Test type');
2865
        $createStruct->creatorId = 14;
2866
        $createStruct->creationDate = new \DateTime();
2867
2868
        $translatableFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('maplocation', 'ezgmaplocation');
2869
        $translatableFieldCreate->names = array('eng-GB' => 'Map location field');
2870
        $translatableFieldCreate->fieldGroup = 'main';
2871
        $translatableFieldCreate->position = 1;
2872
        $translatableFieldCreate->isTranslatable = false;
2873
        $translatableFieldCreate->isSearchable = true;
2874
2875
        $createStruct->addFieldDefinition($translatableFieldCreate);
2876
2877
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
2878
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, array($contentGroup));
2879
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
2880
        $contentType = $contentTypeService->loadContentType($contentTypeDraft->id);
2881
2882
        return $contentType;
2883
    }
2884
2885
    /**
2886
     * Test for the findContent() method.
2887
     *
2888
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2889
     * @group maplocation
2890
     */
2891 View Code Duplication
    public function testMapLocationDistanceLessThanOrEqual()
2892
    {
2893
        $contentType = $this->createTestPlaceContentType();
2894
2895
        // Create a draft to account for behaviour with ContentType in different states
2896
        $repository = $this->getRepository();
2897
        $contentTypeService = $repository->getContentTypeService();
2898
        $contentService = $repository->getContentService();
2899
        $contentTypeService->createContentTypeDraft($contentType);
2900
2901
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2902
        $createStruct->alwaysAvailable = false;
2903
        $createStruct->mainLanguageCode = 'eng-GB';
2904
        $createStruct->setField(
2905
            'maplocation',
2906
            array(
2907
                'latitude' => 45.894877,
2908
                'longitude' => 15.972699,
2909
                'address' => 'Here be wild boars',
2910
            ),
2911
            'eng-GB'
2912
        );
2913
2914
        $draft = $contentService->createContent($createStruct);
2915
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
2916
2917
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2918
        $createStruct->alwaysAvailable = false;
2919
        $createStruct->mainLanguageCode = 'eng-GB';
2920
        $createStruct->setField(
2921
            'maplocation',
2922
            array(
2923
                'latitude' => 45.927334,
2924
                'longitude' => 15.934847,
2925
                'address' => 'A lone tree',
2926
            ),
2927
            'eng-GB'
2928
        );
2929
2930
        $draft = $contentService->createContent($createStruct);
2931
        $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...
2932
2933
        $this->refreshSearch($repository);
2934
2935
        $query = new Query(
2936
            array(
2937
                'filter' => new Criterion\LogicalAnd(
2938
                    array(
2939
                        new Criterion\ContentTypeId($contentType->id),
2940
                        new Criterion\MapLocationDistance(
2941
                            'maplocation',
2942
                            Criterion\Operator::LTE,
2943
                            240,
2944
                            43.756825,
2945
                            15.775074
2946
                        ),
2947
                    )
2948
                ),
2949
                'offset' => 0,
2950
                'limit' => 10,
2951
                'sortClauses' => array(),
2952
            )
2953
        );
2954
2955
        $searchService = $repository->getSearchService();
2956
        $result = $searchService->findContent($query);
2957
2958
        $this->assertEquals(1, $result->totalCount);
2959
        $this->assertEquals(
2960
            $wildBoars->id,
2961
            $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...
2962
        );
2963
    }
2964
2965
    /**
2966
     * Test for the findContent() method.
2967
     *
2968
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2969
     * @group maplocation
2970
     */
2971 View Code Duplication
    public function testMapLocationDistanceGreaterThanOrEqual()
2972
    {
2973
        $contentType = $this->createTestPlaceContentType();
2974
2975
        // Create a draft to account for behaviour with ContentType in different states
2976
        $repository = $this->getRepository();
2977
        $contentTypeService = $repository->getContentTypeService();
2978
        $contentService = $repository->getContentService();
2979
        $contentTypeService->createContentTypeDraft($contentType);
2980
2981
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2982
        $createStruct->alwaysAvailable = false;
2983
        $createStruct->mainLanguageCode = 'eng-GB';
2984
        $createStruct->setField(
2985
            'maplocation',
2986
            array(
2987
                'latitude' => 45.894877,
2988
                'longitude' => 15.972699,
2989
                'address' => 'Here be wild boars',
2990
            ),
2991
            'eng-GB'
2992
        );
2993
2994
        $draft = $contentService->createContent($createStruct);
2995
        $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...
2996
2997
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2998
        $createStruct->alwaysAvailable = false;
2999
        $createStruct->mainLanguageCode = 'eng-GB';
3000
        $createStruct->setField(
3001
            'maplocation',
3002
            array(
3003
                'latitude' => 45.927334,
3004
                'longitude' => 15.934847,
3005
                'address' => 'A lone tree',
3006
            ),
3007
            'eng-GB'
3008
        );
3009
3010
        $draft = $contentService->createContent($createStruct);
3011
        $tree = $contentService->publishVersion($draft->getVersionInfo());
3012
3013
        $this->refreshSearch($repository);
3014
3015
        $query = new Query(
3016
            array(
3017
                'filter' => new Criterion\LogicalAnd(
3018
                    array(
3019
                        new Criterion\ContentTypeId($contentType->id),
3020
                        new Criterion\MapLocationDistance(
3021
                            'maplocation',
3022
                            Criterion\Operator::GTE,
3023
                            240,
3024
                            43.756825,
3025
                            15.775074
3026
                        ),
3027
                    )
3028
                ),
3029
                'offset' => 0,
3030
                'limit' => 10,
3031
                'sortClauses' => array(),
3032
            )
3033
        );
3034
3035
        $searchService = $repository->getSearchService();
3036
        $result = $searchService->findContent($query);
3037
3038
        $this->assertEquals(1, $result->totalCount);
3039
        $this->assertEquals(
3040
            $tree->id,
3041
            $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...
3042
        );
3043
    }
3044
3045
    /**
3046
     * Test for the findContent() method.
3047
     *
3048
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3049
     * @group maplocation
3050
     */
3051
    public function testMapLocationDistanceBetween()
3052
    {
3053
        $contentType = $this->createTestPlaceContentType();
3054
3055
        // Create a draft to account for behaviour with ContentType in different states
3056
        $repository = $this->getRepository();
3057
        $contentTypeService = $repository->getContentTypeService();
3058
        $contentService = $repository->getContentService();
3059
        $contentTypeService->createContentTypeDraft($contentType);
3060
3061
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3062
        $createStruct->alwaysAvailable = false;
3063
        $createStruct->mainLanguageCode = 'eng-GB';
3064
        $createStruct->setField(
3065
            'maplocation',
3066
            array(
3067
                'latitude' => 45.894877,
3068
                'longitude' => 15.972699,
3069
                'address' => 'Here be wild boars',
3070
            ),
3071
            'eng-GB'
3072
        );
3073
3074
        $draft = $contentService->createContent($createStruct);
3075
        $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...
3076
3077
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3078
        $createStruct->alwaysAvailable = false;
3079
        $createStruct->mainLanguageCode = 'eng-GB';
3080
        $createStruct->setField(
3081
            'maplocation',
3082
            array(
3083
                'latitude' => 45.927334,
3084
                'longitude' => 15.934847,
3085
                'address' => 'A lone tree',
3086
            ),
3087
            'eng-GB'
3088
        );
3089
3090
        $draft = $contentService->createContent($createStruct);
3091
        $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...
3092
3093
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3094
        $createStruct->alwaysAvailable = false;
3095
        $createStruct->mainLanguageCode = 'eng-GB';
3096
        $createStruct->setField(
3097
            'maplocation',
3098
            array(
3099
                'latitude' => 45.903777,
3100
                'longitude' => 15.958788,
3101
                'address' => 'Meadow with mushrooms',
3102
            ),
3103
            'eng-GB'
3104
        );
3105
3106
        $draft = $contentService->createContent($createStruct);
3107
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3108
3109
        $this->refreshSearch($repository);
3110
3111
        $query = new Query(
3112
            array(
3113
                'filter' => new Criterion\LogicalAnd(
3114
                    array(
3115
                        new Criterion\ContentTypeId($contentType->id),
3116
                        new Criterion\MapLocationDistance(
3117
                            'maplocation',
3118
                            Criterion\Operator::BETWEEN,
3119
                            array(239, 241),
3120
                            43.756825,
3121
                            15.775074
3122
                        ),
3123
                    )
3124
                ),
3125
                'offset' => 0,
3126
                'limit' => 10,
3127
                'sortClauses' => array(),
3128
            )
3129
        );
3130
3131
        $searchService = $repository->getSearchService();
3132
        $result = $searchService->findContent($query);
3133
3134
        $this->assertEquals(1, $result->totalCount);
3135
        $this->assertEquals(
3136
            $mushrooms->id,
3137
            $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...
3138
        );
3139
    }
3140
3141
    /**
3142
     * Test for the findContent() method.
3143
     *
3144
     * This tests the distance over the pole. The tests intentionally uses large range,
3145
     * as the flat Earth model used in Legacy Storage Search is not precise for the use case.
3146
     * What is tested here is that outer bounding box is correctly calculated, so that
3147
     * location is not excluded.
3148
     *
3149
     * Range between 222km and 350km shows the magnitude of error between great-circle
3150
     * (always very precise) and flat Earth (very imprecise for this use case) models.
3151
     *
3152
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3153
     * @group maplocation
3154
     */
3155
    public function testMapLocationDistanceBetweenPolar()
3156
    {
3157
        $contentType = $this->createTestPlaceContentType();
3158
3159
        // Create a draft to account for behaviour with ContentType in different states
3160
        $repository = $this->getRepository();
3161
        $contentTypeService = $repository->getContentTypeService();
3162
        $contentService = $repository->getContentService();
3163
        $contentTypeService->createContentTypeDraft($contentType);
3164
3165
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3166
        $createStruct->alwaysAvailable = false;
3167
        $createStruct->mainLanguageCode = 'eng-GB';
3168
        $createStruct->setField(
3169
            'maplocation',
3170
            array(
3171
                'latitude' => 89,
3172
                'longitude' => -164,
3173
                'address' => 'Polar bear media tower',
3174
            ),
3175
            'eng-GB'
3176
        );
3177
3178
        $draft = $contentService->createContent($createStruct);
3179
        $polarBear = $contentService->publishVersion($draft->getVersionInfo());
3180
3181
        $this->refreshSearch($repository);
3182
3183
        $query = new Query(
3184
            array(
3185
                'filter' => new Criterion\LogicalAnd(
3186
                    array(
3187
                        new Criterion\ContentTypeId($contentType->id),
3188
                        new Criterion\MapLocationDistance(
3189
                            'maplocation',
3190
                            Criterion\Operator::BETWEEN,
3191
                            array(221, 350),
3192
                            89,
3193
                            16
3194
                        ),
3195
                    )
3196
                ),
3197
                'offset' => 0,
3198
                'limit' => 10,
3199
                'sortClauses' => array(),
3200
            )
3201
        );
3202
3203
        $searchService = $repository->getSearchService();
3204
        $result = $searchService->findContent($query);
3205
3206
        $this->assertEquals(1, $result->totalCount);
3207
        $this->assertEquals(
3208
            $polarBear->id,
3209
            $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...
3210
        );
3211
    }
3212
3213
    /**
3214
     * Test for the findContent() method.
3215
     *
3216
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3217
     * @group maplocation
3218
     */
3219 View Code Duplication
    public function testMapLocationDistanceSortAscending()
3220
    {
3221
        $contentType = $this->createTestPlaceContentType();
3222
3223
        // Create a draft to account for behaviour with ContentType in different states
3224
        $repository = $this->getRepository();
3225
        $contentTypeService = $repository->getContentTypeService();
3226
        $contentService = $repository->getContentService();
3227
        $contentTypeService->createContentTypeDraft($contentType);
3228
3229
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3230
        $createStruct->alwaysAvailable = false;
3231
        $createStruct->mainLanguageCode = 'eng-GB';
3232
        $createStruct->setField(
3233
            'maplocation',
3234
            array(
3235
                'latitude' => 45.894877,
3236
                'longitude' => 15.972699,
3237
                'address' => 'Here be wild boars',
3238
            ),
3239
            'eng-GB'
3240
        );
3241
3242
        $draft = $contentService->createContent($createStruct);
3243
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3244
3245
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3246
        $createStruct->alwaysAvailable = false;
3247
        $createStruct->mainLanguageCode = 'eng-GB';
3248
        $createStruct->setField(
3249
            'maplocation',
3250
            array(
3251
                'latitude' => 45.927334,
3252
                'longitude' => 15.934847,
3253
                'address' => 'A lone tree',
3254
            ),
3255
            'eng-GB'
3256
        );
3257
3258
        $draft = $contentService->createContent($createStruct);
3259
        $tree = $contentService->publishVersion($draft->getVersionInfo());
3260
3261
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3262
        $createStruct->alwaysAvailable = false;
3263
        $createStruct->mainLanguageCode = 'eng-GB';
3264
        $createStruct->setField(
3265
            'maplocation',
3266
            array(
3267
                'latitude' => 45.903777,
3268
                'longitude' => 15.958788,
3269
                'address' => 'Meadow with mushrooms',
3270
            ),
3271
            'eng-GB'
3272
        );
3273
3274
        $draft = $contentService->createContent($createStruct);
3275
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3276
3277
        $this->refreshSearch($repository);
3278
3279
        $wellInVodice = array(
3280
            'latitude' => 43.756825,
3281
            'longitude' => 15.775074,
3282
        );
3283
3284
        $query = new Query(
3285
            array(
3286
                'filter' => new Criterion\LogicalAnd(
3287
                    array(
3288
                        new Criterion\ContentTypeId($contentType->id),
3289
                        new Criterion\MapLocationDistance(
3290
                            'maplocation',
3291
                            Criterion\Operator::GTE,
3292
                            235,
3293
                            $wellInVodice['latitude'],
3294
                            $wellInVodice['longitude']
3295
                        ),
3296
                    )
3297
                ),
3298
                'offset' => 0,
3299
                'limit' => 10,
3300
                'sortClauses' => array(
3301
                    new SortClause\MapLocationDistance(
3302
                        'testtype',
3303
                        'maplocation',
3304
                        $wellInVodice['latitude'],
3305
                        $wellInVodice['longitude'],
3306
                        Query::SORT_ASC
3307
                    ),
3308
                ),
3309
            )
3310
        );
3311
3312
        $searchService = $repository->getSearchService();
3313
        $result = $searchService->findContent($query);
3314
3315
        $this->assertEquals(3, $result->totalCount);
3316
        $this->assertEquals(
3317
            $wildBoars->id,
3318
            $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...
3319
        );
3320
        $this->assertEquals(
3321
            $mushrooms->id,
3322
            $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...
3323
        );
3324
        $this->assertEquals(
3325
            $tree->id,
3326
            $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...
3327
        );
3328
    }
3329
3330
    /**
3331
     * Test for the findContent() method.
3332
     *
3333
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3334
     * @group maplocation
3335
     */
3336 View Code Duplication
    public function testMapLocationDistanceSortDescending()
3337
    {
3338
        $contentType = $this->createTestPlaceContentType();
3339
3340
        // Create a draft to account for behaviour with ContentType in different states
3341
        $repository = $this->getRepository();
3342
        $contentTypeService = $repository->getContentTypeService();
3343
        $contentService = $repository->getContentService();
3344
        $contentTypeService->createContentTypeDraft($contentType);
3345
3346
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3347
        $createStruct->alwaysAvailable = false;
3348
        $createStruct->mainLanguageCode = 'eng-GB';
3349
        $createStruct->setField(
3350
            'maplocation',
3351
            array(
3352
                'latitude' => 45.894877,
3353
                'longitude' => 15.972699,
3354
                'address' => 'Here be wild boars',
3355
            ),
3356
            'eng-GB'
3357
        );
3358
3359
        $draft = $contentService->createContent($createStruct);
3360
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3361
3362
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3363
        $createStruct->alwaysAvailable = false;
3364
        $createStruct->mainLanguageCode = 'eng-GB';
3365
        $createStruct->setField(
3366
            'maplocation',
3367
            array(
3368
                'latitude' => 45.927334,
3369
                'longitude' => 15.934847,
3370
                'address' => 'A lone tree',
3371
            ),
3372
            'eng-GB'
3373
        );
3374
3375
        $draft = $contentService->createContent($createStruct);
3376
        $tree = $contentService->publishVersion($draft->getVersionInfo());
3377
3378
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3379
        $createStruct->alwaysAvailable = false;
3380
        $createStruct->mainLanguageCode = 'eng-GB';
3381
        $createStruct->setField(
3382
            'maplocation',
3383
            array(
3384
                'latitude' => 45.903777,
3385
                'longitude' => 15.958788,
3386
                'address' => 'Meadow with mushrooms',
3387
            ),
3388
            'eng-GB'
3389
        );
3390
3391
        $draft = $contentService->createContent($createStruct);
3392
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3393
3394
        $this->refreshSearch($repository);
3395
3396
        $well = array(
3397
            'latitude' => 43.756825,
3398
            'longitude' => 15.775074,
3399
        );
3400
3401
        $query = new Query(
3402
            array(
3403
                'filter' => new Criterion\LogicalAnd(
3404
                    array(
3405
                        new Criterion\ContentTypeId($contentType->id),
3406
                        new Criterion\MapLocationDistance(
3407
                            'maplocation',
3408
                            Criterion\Operator::GTE,
3409
                            235,
3410
                            $well['latitude'],
3411
                            $well['longitude']
3412
                        ),
3413
                    )
3414
                ),
3415
                'offset' => 0,
3416
                'limit' => 10,
3417
                'sortClauses' => array(
3418
                    new SortClause\MapLocationDistance(
3419
                        'testtype',
3420
                        'maplocation',
3421
                        $well['latitude'],
3422
                        $well['longitude'],
3423
                        Query::SORT_DESC
3424
                    ),
3425
                ),
3426
            )
3427
        );
3428
3429
        $searchService = $repository->getSearchService();
3430
        $result = $searchService->findContent($query);
3431
3432
        $this->assertEquals(3, $result->totalCount);
3433
        $this->assertEquals(
3434
            $wildBoars->id,
3435
            $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...
3436
        );
3437
        $this->assertEquals(
3438
            $mushrooms->id,
3439
            $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...
3440
        );
3441
        $this->assertEquals(
3442
            $tree->id,
3443
            $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...
3444
        );
3445
    }
3446
3447
    /**
3448
     * Test for the findContent() method.
3449
     *
3450
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3451
     * @group maplocation
3452
     */
3453
    public function testMapLocationDistanceWithCustomField()
3454
    {
3455
        $setupFactory = $this->getSetupFactory();
3456
        if ($setupFactory instanceof LegacyElasticsearch) {
3457
            $this->markTestIncomplete("TODO: Some issues with 'copy_to' and 'geo_point'");
3458
        }
3459
3460
        $contentType = $this->createTestPlaceContentType();
3461
3462
        // Create a draft to account for behaviour with ContentType in different states
3463
        $repository = $this->getRepository();
3464
        $contentTypeService = $repository->getContentTypeService();
3465
        $contentService = $repository->getContentService();
3466
        $contentTypeService->createContentTypeDraft($contentType);
3467
3468
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3469
        $createStruct->alwaysAvailable = false;
3470
        $createStruct->mainLanguageCode = 'eng-GB';
3471
        $createStruct->setField(
3472
            'maplocation',
3473
            array(
3474
                'latitude' => 45.894877,
3475
                'longitude' => 15.972699,
3476
                'address' => 'Here be wild boars',
3477
            ),
3478
            'eng-GB'
3479
        );
3480
3481
        $draft = $contentService->createContent($createStruct);
3482
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3483
3484
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3485
        $createStruct->alwaysAvailable = false;
3486
        $createStruct->mainLanguageCode = 'eng-GB';
3487
        $createStruct->setField(
3488
            'maplocation',
3489
            array(
3490
                'latitude' => 45.927334,
3491
                'longitude' => 15.934847,
3492
                'address' => 'A lone tree',
3493
            ),
3494
            'eng-GB'
3495
        );
3496
3497
        $draft = $contentService->createContent($createStruct);
3498
        $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...
3499
3500
        $this->refreshSearch($repository);
3501
3502
        $distanceCriterion = new Criterion\MapLocationDistance(
3503
            'maplocation',
3504
            Criterion\Operator::LTE,
3505
            240,
3506
            43.756825,
3507
            15.775074
3508
        );
3509
        $distanceCriterion->setCustomField('testtype', 'maplocation', 'custom_geolocation_field');
3510
3511
        $query = new Query(
3512
            array(
3513
                'filter' => new Criterion\LogicalAnd(
3514
                    array(
3515
                        new Criterion\ContentTypeId($contentType->id),
3516
                        $distanceCriterion,
3517
                    )
3518
                ),
3519
                'offset' => 0,
3520
                'limit' => 10,
3521
                'sortClauses' => array(),
3522
            )
3523
        );
3524
3525
        $searchService = $repository->getSearchService();
3526
        $result = $searchService->findContent($query);
3527
3528
        $this->assertEquals(1, $result->totalCount);
3529
        $this->assertEquals(
3530
            $wildBoars->id,
3531
            $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...
3532
        );
3533
    }
3534
3535
    /**
3536
     * Test for the findContent() method.
3537
     *
3538
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3539
     * @group maplocation
3540
     */
3541
    public function testMapLocationDistanceWithCustomFieldSort()
3542
    {
3543
        $setupFactory = $this->getSetupFactory();
3544
        if ($setupFactory instanceof LegacyElasticsearch) {
3545
            $this->markTestIncomplete("TODO: Some issues with 'copy_to' and 'geo_point'");
3546
        }
3547
3548
        $contentType = $this->createTestPlaceContentType();
3549
3550
        // Create a draft to account for behaviour with ContentType in different states
3551
        $repository = $this->getRepository();
3552
        $contentTypeService = $repository->getContentTypeService();
3553
        $contentService = $repository->getContentService();
3554
        $contentTypeService->createContentTypeDraft($contentType);
3555
3556
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3557
        $createStruct->alwaysAvailable = false;
3558
        $createStruct->mainLanguageCode = 'eng-GB';
3559
        $createStruct->setField(
3560
            'maplocation',
3561
            array(
3562
                'latitude' => 45.894877,
3563
                'longitude' => 15.972699,
3564
                'address' => 'Here be wild boars',
3565
            ),
3566
            'eng-GB'
3567
        );
3568
3569
        $draft = $contentService->createContent($createStruct);
3570
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3571
3572
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3573
        $createStruct->alwaysAvailable = false;
3574
        $createStruct->mainLanguageCode = 'eng-GB';
3575
        $createStruct->setField(
3576
            'maplocation',
3577
            array(
3578
                'latitude' => 45.927334,
3579
                'longitude' => 15.934847,
3580
                'address' => 'A lone tree',
3581
            ),
3582
            'eng-GB'
3583
        );
3584
3585
        $draft = $contentService->createContent($createStruct);
3586
        $tree = $contentService->publishVersion($draft->getVersionInfo());
3587
3588
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3589
        $createStruct->alwaysAvailable = false;
3590
        $createStruct->mainLanguageCode = 'eng-GB';
3591
        $createStruct->setField(
3592
            'maplocation',
3593
            array(
3594
                'latitude' => 45.903777,
3595
                'longitude' => 15.958788,
3596
                'address' => 'Meadow with mushrooms',
3597
            ),
3598
            'eng-GB'
3599
        );
3600
3601
        $draft = $contentService->createContent($createStruct);
3602
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3603
3604
        $this->refreshSearch($repository);
3605
3606
        $well = array(
3607
            'latitude' => 43.756825,
3608
            'longitude' => 15.775074,
3609
        );
3610
3611
        $sortClause = new SortClause\MapLocationDistance(
3612
            'testtype',
3613
            'maplocation',
3614
            $well['latitude'],
3615
            $well['longitude'],
3616
            Query::SORT_DESC
3617
        );
3618
        $sortClause->setCustomField('testtype', 'maplocation', 'custom_geolocation_field');
3619
3620
        $query = new Query(
3621
            array(
3622
                'filter' => new Criterion\LogicalAnd(
3623
                    array(
3624
                        new Criterion\ContentTypeId($contentType->id),
3625
                        new Criterion\MapLocationDistance(
3626
                            'maplocation',
3627
                            Criterion\Operator::GTE,
3628
                            235,
3629
                            $well['latitude'],
3630
                            $well['longitude']
3631
                        ),
3632
                    )
3633
                ),
3634
                'offset' => 0,
3635
                'limit' => 10,
3636
                'sortClauses' => array(
3637
                    $sortClause,
3638
                ),
3639
            )
3640
        );
3641
3642
        $searchService = $repository->getSearchService();
3643
        $result = $searchService->findContent($query);
3644
3645
        $this->assertEquals(3, $result->totalCount);
3646
        $this->assertEquals(
3647
            $wildBoars->id,
3648
            $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...
3649
        );
3650
        $this->assertEquals(
3651
            $mushrooms->id,
3652
            $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...
3653
        );
3654
        $this->assertEquals(
3655
            $tree->id,
3656
            $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...
3657
        );
3658
    }
3659
3660
    /**
3661
     * Test for the findLocations() method.
3662
     *
3663
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3664
     */
3665 View Code Duplication
    public function testFindMainLocation()
3666
    {
3667
        $plainSiteLocationId = 56;
3668
        $designLocationId = 58;
3669
        $partnersContentId = 59;
3670
        $repository = $this->getRepository();
3671
        $locationService = $repository->getLocationService();
3672
        $contentService = $repository->getContentService();
3673
3674
        // Add secondary Location for "Partners" user group, under "Design" page
3675
        $locationService->createLocation(
3676
            $contentService->loadContentInfo($partnersContentId),
3677
            $locationService->newLocationCreateStruct($designLocationId)
3678
        );
3679
3680
        $this->refreshSearch($repository);
3681
3682
        $query = new LocationQuery(
3683
            array(
3684
                'filter' => new Criterion\LogicalAnd(
3685
                    array(
3686
                        new Criterion\ParentLocationId($designLocationId),
3687
                        new Criterion\Location\IsMainLocation(
3688
                            Criterion\Location\IsMainLocation::MAIN
3689
                        ),
3690
                    )
3691
                ),
3692
                'offset' => 0,
3693
                'limit' => 10,
3694
                'sortClauses' => array(),
3695
            )
3696
        );
3697
3698
        $searchService = $repository->getSearchService();
3699
        $result = $searchService->findLocations($query);
3700
3701
        $this->assertEquals(1, $result->totalCount);
3702
        $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...
3703
    }
3704
3705
    /**
3706
     * Test for the findLocations() method.
3707
     *
3708
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3709
     */
3710 View Code Duplication
    public function testFindNonMainLocation()
3711
    {
3712
        $designLocationId = 58;
3713
        $partnersContentId = 59;
3714
        $repository = $this->getRepository();
3715
        $locationService = $repository->getLocationService();
3716
        $contentService = $repository->getContentService();
3717
3718
        // Add secondary Location for "Partners" user group, under "Design" page
3719
        $newLocation = $locationService->createLocation(
3720
            $contentService->loadContentInfo($partnersContentId),
3721
            $locationService->newLocationCreateStruct($designLocationId)
3722
        );
3723
3724
        $this->refreshSearch($repository);
3725
3726
        $query = new LocationQuery(
3727
            array(
3728
                'filter' => new Criterion\LogicalAnd(
3729
                    array(
3730
                        new Criterion\ParentLocationId($designLocationId),
3731
                        new Criterion\Location\IsMainLocation(
3732
                            Criterion\Location\IsMainLocation::NOT_MAIN
3733
                        ),
3734
                    )
3735
                ),
3736
                'offset' => 0,
3737
                'limit' => 10,
3738
                'sortClauses' => array(),
3739
            )
3740
        );
3741
3742
        $searchService = $repository->getSearchService();
3743
        $result = $searchService->findLocations($query);
3744
3745
        $this->assertEquals(1, $result->totalCount);
3746
        $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...
3747
    }
3748
3749
    /**
3750
     * Test for the findLocations() method.
3751
     *
3752
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3753
     */
3754 View Code Duplication
    public function testSortMainLocationAscending()
3755
    {
3756
        $plainSiteLocationId = 56;
3757
        $designLocationId = 58;
3758
        $partnersContentId = 59;
3759
        $repository = $this->getRepository();
3760
        $locationService = $repository->getLocationService();
3761
        $contentService = $repository->getContentService();
3762
3763
        // Add secondary Location for "Partners" user group, under "Design" page
3764
        $newLocation = $locationService->createLocation(
3765
            $contentService->loadContentInfo($partnersContentId),
3766
            $locationService->newLocationCreateStruct($designLocationId)
3767
        );
3768
3769
        $this->refreshSearch($repository);
3770
3771
        $query = new LocationQuery(
3772
            array(
3773
                'filter' => new Criterion\ParentLocationId($designLocationId),
3774
                'offset' => 0,
3775
                'limit' => 10,
3776
                'sortClauses' => array(
3777
                    new SortClause\Location\IsMainLocation(
3778
                        LocationQuery::SORT_ASC
3779
                    ),
3780
                ),
3781
            )
3782
        );
3783
3784
        $searchService = $repository->getSearchService();
3785
        $result = $searchService->findLocations($query);
3786
3787
        $this->assertEquals(2, $result->totalCount);
3788
        $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...
3789
        $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...
3790
    }
3791
3792
    /**
3793
     * Test for the findLocations() method.
3794
     *
3795
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3796
     */
3797 View Code Duplication
    public function testSortMainLocationDescending()
3798
    {
3799
        $plainSiteLocationId = 56;
3800
        $designLocationId = 58;
3801
        $partnersContentId = 59;
3802
        $repository = $this->getRepository();
3803
        $locationService = $repository->getLocationService();
3804
        $contentService = $repository->getContentService();
3805
3806
        // Add secondary Location for "Partners" user group, under "Design" page
3807
        $newLocation = $locationService->createLocation(
3808
            $contentService->loadContentInfo($partnersContentId),
3809
            $locationService->newLocationCreateStruct($designLocationId)
3810
        );
3811
3812
        $this->refreshSearch($repository);
3813
3814
        $query = new LocationQuery(
3815
            array(
3816
                'filter' => new Criterion\ParentLocationId($designLocationId),
3817
                'offset' => 0,
3818
                'limit' => 10,
3819
                'sortClauses' => array(
3820
                    new SortClause\Location\IsMainLocation(
3821
                        LocationQuery::SORT_DESC
3822
                    ),
3823
                ),
3824
            )
3825
        );
3826
3827
        $searchService = $repository->getSearchService();
3828
        $result = $searchService->findLocations($query);
3829
3830
        $this->assertEquals(2, $result->totalCount);
3831
        $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...
3832
        $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...
3833
    }
3834
3835
    /**
3836
     * Test for the findLocations() method.
3837
     *
3838
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3839
     */
3840
    public function testContentWithMultipleLocations()
3841
    {
3842
        $repository = $this->getRepository();
3843
        $contentService = $repository->getContentService();
3844
        $contentTypeService = $repository->getContentTypeService();
3845
        $locationService = $repository->getLocationService();
3846
3847
        $forumType = $contentTypeService->loadContentTypeByIdentifier('forum');
3848
3849
        $createStruct = $contentService->newContentCreateStruct($forumType, 'eng-GB');
3850
        $createStruct->alwaysAvailable = false;
3851
        $createStruct->setField('name', 'An awesome duplicate forum');
3852
3853
        $draft = $contentService->createContent($createStruct);
3854
        $content = $contentService->publishVersion($draft->getVersionInfo());
3855
3856
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
3857
        $location1 = $locationService->createLocation($content->contentInfo, $locationCreateStruct);
3858
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(5);
3859
        $location2 = $locationService->createLocation($content->contentInfo, $locationCreateStruct);
3860
3861
        $this->refreshSearch($repository);
3862
3863
        $query = new LocationQuery(
3864
            array(
3865
                'filter' => new Criterion\ContentId($content->id),
3866
                'sortClauses' => array(
3867
                    new SortClause\Location\Id(LocationQuery::SORT_ASC),
3868
                ),
3869
            )
3870
        );
3871
3872
        $searchService = $repository->getSearchService();
3873
        $result = $searchService->findLocations($query);
3874
3875
        $this->assertEquals(2, $result->totalCount);
3876
        $this->assertEquals(
3877
            $location1->id,
3878
            $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...
3879
        );
3880
        $this->assertEquals(
3881
            $location2->id,
3882
            $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...
3883
        );
3884
    }
3885
3886
    protected function createContentForTestUserMetadataGroupHorizontal()
3887
    {
3888
        $repository = $this->getRepository();
3889
        $contentService = $repository->getContentService();
3890
        $contentTypeService = $repository->getContentTypeService();
3891
        $locationService = $repository->getLocationService();
3892
        $userService = $repository->getUserService();
3893
        $administratorUser = $repository->getCurrentUser();
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...itory::getCurrentUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::getCurrentUserReference() instead. Get current user. Loads the full user object if not already loaded, if you only need to know user id use {@see getCurrentUserReference()}

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
3894
        // ID of the "Administrators" user group in an eZ Publish demo installation
3895
        $administratorsUserGroupId = 12;
3896
        // ID of the "Editors" user group in an eZ Publish demo installation
3897
        $editorsUserGroupId = 13;
3898
3899
        $administratorsUserGroup = $userService->loadUserGroup($administratorsUserGroupId);
3900
        $editorsUserGroup = $userService->loadUserGroup($editorsUserGroupId);
3901
3902
        // Add additional Location for Administrators UserGroup under Editors UserGroup Location
3903
        $locationCreateStruct = $locationService->newLocationCreateStruct(
3904
            $editorsUserGroup->contentInfo->mainLocationId
3905
        );
3906
        $newAdministratorsUserGroupLocation = $locationService->createLocation(
3907
            $administratorsUserGroup->contentInfo,
3908
            $locationCreateStruct
3909
        );
3910
3911
        // Add additional Location for administrator user under newly created UserGroup Location
3912
        $locationCreateStruct = $locationService->newLocationCreateStruct(
3913
            $newAdministratorsUserGroupLocation->id
3914
        );
3915
        $locationService->createLocation(
3916
            $administratorUser->contentInfo,
3917
            $locationCreateStruct
3918
        );
3919
3920
        // Create a Content to be found through Editors UserGroup id.
3921
        // This ensures data is indexed, it could also be done by updating metadata of
3922
        // an existing Content, but slot would need to reindex Content and that should
3923
        // be tested elsewhere (dedicated indexing integration tests, missing ATM).
3924
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
3925
3926
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3927
        $createStruct->setField('name', 'test');
3928
3929
        $locationCreateStruct = $locationService->newLocationCreateStruct(2);
3930
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
3931
        $content = $contentService->publishVersion($draft->getVersionInfo());
3932
        $contentTypeService->createContentTypeDraft($contentType);
3933
3934
        $this->refreshSearch($repository);
3935
3936
        return $content;
3937
    }
3938
3939
    /**
3940
     * Test for the findContent() method.
3941
     *
3942
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3943
     */
3944
    public function testUserMetadataGroupHorizontalFilterContent($queryType = null)
3945
    {
3946
        if ($queryType === null) {
3947
            $queryType = 'filter';
3948
        }
3949
3950
        $repository = $this->getRepository();
3951
        $searchService = $repository->getSearchService();
3952
        $editorsUserGroupId = 13;
3953
3954
        $content = $this->createContentForTestUserMetadataGroupHorizontal();
3955
3956
        $criteria = array();
3957
        $setupFactory = $this->getSetupFactory();
3958
3959
        // Do not limit for LSE, as it does not not require reindexing.
3960
        // See explanation below.
3961
        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...
3962
            $criteria[] = new Criterion\ContentTypeIdentifier('folder');
3963
        }
3964
3965
        $criteria[] = new Criterion\UserMetadata(
3966
            Criterion\UserMetadata::GROUP,
3967
            Criterion\Operator::EQ,
3968
            $editorsUserGroupId
3969
        );
3970
3971
        $query = new Query(
3972
            array(
3973
                $queryType => new Criterion\LogicalAnd($criteria),
3974
                'sortClauses' => array(
3975
                    new SortClause\ContentId(),
3976
                ),
3977
                'limit' => 50,
3978
            )
3979
        );
3980
3981
        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...
3982
            $result = $searchService->findContent($query);
3983
3984
            // Administrator User is owned by itself, when additional Locations are added
3985
            // it should be reindexed and its UserGroups will updated, which means it should
3986
            // also be found as a Content of Editors UserGroup. However we do not handle this
3987
            // in slots yet, and also miss SPI methods to do it without using Search (also
3988
            // needed to decouple services), because as indexing is asynchronous Search
3989
            // should not eat its own dog food for reindexing.
3990
            $this->assertEquals(1, $result->totalCount);
3991
3992
            $this->assertEquals(
3993
                $content->id,
3994
                $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...
3995
            );
3996
        } else {
3997
            // This is how it should eventually work for all search engines,
3998
            // with required reindexing slots properly implemented.
3999
4000
            $result = $searchService->findContent($query);
4001
4002
            // Assert last hit manually, as id will change because it is created in test
4003
            // and not present it base fixture.
4004
            $foundContent1 = array_pop($result->searchHits);
4005
            $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...
4006
            $this->assertEquals($content->id, $foundContent1->valueObject->id);
4007
4008
            $this->simplifySearchResult($result);
4009
            $this->assertEquals(
4010
                include $this->getFixtureDir() . '/UserMetadata.php',
4011
                $result,
4012
                'Search results do not match.',
4013
                .1 // Be quite generous regarding delay -- most important for scores
4014
            );
4015
        }
4016
    }
4017
4018
    /**
4019
     * Test for the findContent() method.
4020
     *
4021
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4022
     */
4023
    public function testUserMetadataGroupHorizontalQueryContent()
4024
    {
4025
        $this->testUserMetadataGroupHorizontalFilterContent('query');
4026
    }
4027
4028
    /**
4029
     * Test for the findLocations() method.
4030
     *
4031
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
4032
     */
4033
    public function testUserMetadataGroupHorizontalFilterLocation($queryType = null)
4034
    {
4035
        if ($queryType === null) {
4036
            $queryType = 'filter';
4037
        }
4038
4039
        $repository = $this->getRepository();
4040
        $searchService = $repository->getSearchService();
4041
        $editorsUserGroupId = 13;
4042
4043
        $content = $this->createContentForTestUserMetadataGroupHorizontal();
4044
4045
        $criteria = array();
4046
        $setupFactory = $this->getSetupFactory();
4047
4048
        // Do not limit for LSE, as it does not not require reindexing.
4049
        // See explanation below.
4050
        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...
4051
            $criteria[] = new Criterion\ContentTypeIdentifier('folder');
4052
        }
4053
4054
        $criteria[] = new Criterion\UserMetadata(
4055
            Criterion\UserMetadata::GROUP,
4056
            Criterion\Operator::EQ,
4057
            $editorsUserGroupId
4058
        );
4059
4060
        $query = new LocationQuery(
4061
            array(
4062
                $queryType => new Criterion\LogicalAnd($criteria),
4063
                'sortClauses' => array(
4064
                    new SortClause\Location\Id(),
4065
                ),
4066
                'limit' => 50,
4067
            )
4068
        );
4069
4070
        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...
4071
            $result = $searchService->findLocations($query);
4072
4073
            // Administrator User is owned by itself, when additional Locations are added
4074
            // it should be reindexed and its UserGroups will updated, which means it should
4075
            // also be found as a Content of Editors UserGroup. However we do not handle this
4076
            // in slots yet, and also miss SPI methods to do it without using Search (also
4077
            // needed to decouple services), because as indexing is asynchronous Search
4078
            // should not eat its own dog food for reindexing.
4079
            $this->assertEquals(1, $result->totalCount);
4080
4081
            $this->assertEquals(
4082
                $content->contentInfo->mainLocationId,
4083
                $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...
4084
            );
4085
        } else {
4086
            // This is how it should eventually work for all search engines,
4087
            // with required reindexing slots properly implemented.
4088
4089
            $result = $searchService->findLocations($query);
4090
4091
            // Assert last two hits manually, as ids will change because they are created
4092
            // in test and not present in base fixture.
4093
            $foundLocation1 = array_pop($result->searchHits);
4094
            $foundLocation2 = array_pop($result->searchHits);
4095
            // Remove additional Administrators UserGroup Location
4096
            array_pop($result->searchHits);
4097
            $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...
4098
            $this->assertEquals(
4099
                $content->versionInfo->contentInfo->mainLocationId,
4100
                $foundLocation1->valueObject->id
4101
            );
4102
            $this->assertEquals(
4103
                $repository->getCurrentUser()->id,
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...itory::getCurrentUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::getCurrentUserReference() instead. Get current user. Loads the full user object if not already loaded, if you only need to know user id use {@see getCurrentUserReference()}

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
4104
                $foundLocation2->valueObject->contentId
4105
            );
4106
4107
            $this->simplifySearchResult($result);
4108
            $this->assertEquals(
4109
                include $this->getFixtureDir() . '/UserMetadataLocation.php',
4110
                $result,
4111
                'Search results do not match.',
4112
                .1 // Be quite generous regarding delay -- most important for scores
4113
            );
4114
        }
4115
    }
4116
4117
    /**
4118
     * Test for the findLocations() method.
4119
     *
4120
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
4121
     */
4122
    public function testUserMetadataGroupHorizontalQueryLocation()
4123
    {
4124
        $this->testUserMetadataGroupHorizontalFilterLocation('query');
4125
    }
4126
4127
    /**
4128
     * Test for FullText on the findContent() method.
4129
     *
4130
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4131
     */
4132
    public function testFullTextOnNewContent()
4133
    {
4134
        $repository = $this->getRepository();
4135
        $contentService = $repository->getContentService();
4136
        $contentTypeService = $repository->getContentTypeService();
4137
        $locationService = $repository->getLocationService();
4138
        $searchService = $repository->getSearchService();
4139
4140
        $contentCreateStruct = $contentService->newContentCreateStruct(
4141
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4142
            'eng-GB'
4143
        );
4144
4145
        $contentCreateStruct->setField('name', 'foxes');
4146
4147
        $englishContent = $contentService->publishVersion(
4148
            $contentService->createContent(
4149
                $contentCreateStruct,
4150
                array($locationService->newLocationCreateStruct(2))
4151
            )->versionInfo
4152
        );
4153
4154
        $this->refreshSearch($repository);
4155
4156
        $query = new Query(
4157
            array(
4158
                'query' => new Criterion\FullText('foxes'),
4159
            )
4160
        );
4161
4162
        $searchResult = $searchService->findContentInfo($query);
4163
4164
        $this->assertEquals(1, $searchResult->totalCount);
4165
        $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...
4166
    }
4167
4168
    /**
4169
     * Test for the findContent() method.
4170
     *
4171
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4172
     */
4173
    public function testLanguageAnalysisSeparateContent()
4174
    {
4175
        $setupFactory = $this->getSetupFactory();
4176
        if (!$setupFactory instanceof LegacyElasticsearch) {
4177
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4178
        }
4179
4180
        $repository = $this->getRepository();
4181
        $contentService = $repository->getContentService();
4182
        $contentTypeService = $repository->getContentTypeService();
4183
        $locationService = $repository->getLocationService();
4184
        $searchService = $repository->getSearchService();
4185
        $languageService = $repository->getContentLanguageService();
4186
4187
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4188
        $languageCreateStruct->languageCode = 'rus-RU';
4189
        $languageCreateStruct->name = 'Russian';
4190
4191
        $languageService->createLanguage($languageCreateStruct);
4192
4193
        $contentCreateStruct = $contentService->newContentCreateStruct(
4194
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4195
            'eng-GB'
4196
        );
4197
4198
        $contentCreateStruct->setField('name', 'foxes');
4199
4200
        $englishContent = $contentService->publishVersion(
4201
            $contentService->createContent(
4202
                $contentCreateStruct,
4203
                array($locationService->newLocationCreateStruct(2))
4204
            )->versionInfo
4205
        );
4206
4207
        $contentCreateStruct = $contentService->newContentCreateStruct(
4208
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4209
            'rus-RU'
4210
        );
4211
4212
        $contentCreateStruct->setField('name', 'foxes');
4213
4214
        $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...
4215
            $contentService->createContent(
4216
                $contentCreateStruct,
4217
                array($locationService->newLocationCreateStruct(2))
4218
            )->versionInfo
4219
        );
4220
4221
        // Only Content in English should be found, because Content in Russian
4222
        // will not be correctly stemmed
4223
        $query = new Query(
4224
            array(
4225
                'query' => new Criterion\FullText('foxing'),
4226
            )
4227
        );
4228
4229
        $searchResult = $searchService->findContent($query);
4230
4231
        $this->assertEquals(1, $searchResult->totalCount);
4232
        $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...
4233
    }
4234
4235
    /**
4236
     * Test for the findContent() method.
4237
     *
4238
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4239
     */
4240
    public function testLanguageAnalysisSameContent()
4241
    {
4242
        $setupFactory = $this->getSetupFactory();
4243
        if (!$setupFactory instanceof LegacyElasticsearch) {
4244
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4245
        }
4246
4247
        $repository = $this->getRepository();
4248
        $contentService = $repository->getContentService();
4249
        $contentTypeService = $repository->getContentTypeService();
4250
        $locationService = $repository->getLocationService();
4251
        $searchService = $repository->getSearchService();
4252
        $languageService = $repository->getContentLanguageService();
4253
4254
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4255
        $languageCreateStruct->languageCode = 'rus-RU';
4256
        $languageCreateStruct->name = 'Russian';
4257
4258
        $languageService->createLanguage($languageCreateStruct);
4259
4260
        $contentCreateStruct = $contentService->newContentCreateStruct(
4261
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4262
            'eng-GB'
4263
        );
4264
4265
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'eng-GB');
4266
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'rus-RU');
4267
4268
        $mixedContent = $contentService->publishVersion(
4269
            $contentService->createContent(
4270
                $contentCreateStruct,
4271
                array($locationService->newLocationCreateStruct(2))
4272
            )->versionInfo
4273
        );
4274
4275
        // Content will be found because translation in Russian will be correctly stemmed
4276
        $query = new Query(
4277
            array(
4278
                'query' => new Criterion\FullText('важнее'),
4279
            )
4280
        );
4281
4282
        $searchResult = $searchService->findContent($query);
4283
4284
        $this->assertEquals(1, $searchResult->totalCount);
4285
        $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...
4286
    }
4287
4288
    /**
4289
     * Test for the findContent() method.
4290
     *
4291
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4292
     */
4293
    public function testLanguageAnalysisSameContentNotFound()
4294
    {
4295
        $setupFactory = $this->getSetupFactory();
4296
        if (!$setupFactory instanceof LegacyElasticsearch) {
4297
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4298
        }
4299
4300
        $repository = $this->getRepository();
4301
        $contentService = $repository->getContentService();
4302
        $contentTypeService = $repository->getContentTypeService();
4303
        $locationService = $repository->getLocationService();
4304
        $searchService = $repository->getSearchService();
4305
        $languageService = $repository->getContentLanguageService();
4306
4307
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4308
        $languageCreateStruct->languageCode = 'rus-RU';
4309
        $languageCreateStruct->name = 'Russian';
4310
4311
        $languageService->createLanguage($languageCreateStruct);
4312
4313
        $contentCreateStruct = $contentService->newContentCreateStruct(
4314
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4315
            'eng-GB'
4316
        );
4317
4318
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'eng-GB');
4319
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'rus-RU');
4320
4321
        $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...
4322
            $contentService->createContent(
4323
                $contentCreateStruct,
4324
                array($locationService->newLocationCreateStruct(2))
4325
            )->versionInfo
4326
        );
4327
4328
        // Content should be found because translation in Russian will be correctly stemmed
4329
        $query = new Query(
4330
            array(
4331
                'query' => new Criterion\FullText('важнее'),
4332
            )
4333
        );
4334
4335
        // Filtering fields for only English will cause no match because the term will
4336
        // not be correctly stemmed
4337
        $searchResult = $searchService->findContent($query, array('languages' => array('eng-GB')));
4338
4339
        $this->assertEquals(0, $searchResult->totalCount);
4340
    }
4341
4342
    /**
4343
     * Test for the findContent() method.
4344
     *
4345
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4346
     */
4347
    public function testFulltextComplex()
4348
    {
4349
        $repository = $this->getRepository();
4350
        $contentService = $repository->getContentService();
4351
        $contentTypeService = $repository->getContentTypeService();
4352
        $locationService = $repository->getLocationService();
4353
        $searchService = $repository->getSearchService();
4354
4355
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
4356
        $contentCreateStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
4357
4358
        $contentCreateStruct->setField('name', 'red');
4359
        $contentCreateStruct->setField('short_name', 'red apple');
4360
        $content1 = $contentService->publishVersion(
4361
            $contentService->createContent(
4362
                $contentCreateStruct,
4363
                [$locationService->newLocationCreateStruct(2)]
4364
            )->versionInfo
4365
        );
4366
4367
        $contentCreateStruct->setField('name', 'apple');
4368
        $contentCreateStruct->setField('short_name', 'two');
4369
        $content2 = $contentService->publishVersion(
4370
            $contentService->createContent(
4371
                $contentCreateStruct,
4372
                [$locationService->newLocationCreateStruct(2)]
4373
            )->versionInfo
4374
        );
4375
4376
        $contentCreateStruct->setField('name', 'red apple');
4377
        $contentCreateStruct->setField('short_name', 'three');
4378
        $content3 = $contentService->publishVersion(
4379
            $contentService->createContent(
4380
                $contentCreateStruct,
4381
                [$locationService->newLocationCreateStruct(2)]
4382
            )->versionInfo
4383
        );
4384
4385
        $this->refreshSearch($repository);
4386
4387
        $query = new Query(
4388
            [
4389
                'query' => new Criterion\FullText(
4390
                    'red apple',
4391
                    [
4392
                        'boost' => [
4393
                            'short_name' => 2,
4394
                        ],
4395
                        'fuzziness' => .1,
4396
                    ]
4397
                ),
4398
            ]
4399
        );
4400
4401
        $searchResult = $searchService->findContent($query, ['languages' => ['eng-GB']]);
4402
4403
        $this->assertEquals(3, $searchResult->totalCount);
4404
4405
        // Legacy search engine does have scoring, sorting the results by ID in that case
4406
        $setupFactory = $this->getSetupFactory();
4407
        if (get_class($setupFactory) === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
4408
            usort(
4409
                $searchResult->searchHits,
4410
                function ($a, $b) {
4411
                    return ($a->valueObject->id < $b->valueObject->id) ? -1 : 1;
4412
                }
4413
            );
4414
4415
            $this->assertEquals($content1->id, $searchResult->searchHits[0]->valueObject->id);
4416
            $this->assertEquals($content2->id, $searchResult->searchHits[1]->valueObject->id);
4417
            $this->assertEquals($content3->id, $searchResult->searchHits[2]->valueObject->id);
4418
4419
            return;
4420
        }
4421
4422
        $this->assertEquals($content1->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...
4423
        $this->assertEquals($content3->id, $searchResult->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...
4424
        $this->assertEquals($content2->id, $searchResult->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...
4425
    }
4426
4427
    /**
4428
     * Assert that query result matches the given fixture.
4429
     *
4430
     * @param Query $query
4431
     * @param string $fixture
4432
     * @param null|callable $closure
4433
     * @param bool $info
4434
     * @param bool $id
4435
     */
4436
    protected function assertQueryFixture(Query $query, $fixture, $closure = null, $ignoreScore = true, $info = false, $id = true)
4437
    {
4438
        $repository = $this->getRepository();
4439
        $searchService = $repository->getSearchService();
4440
4441
        try {
4442
            if ($query instanceof LocationQuery) {
4443
                $setupFactory = $this->getSetupFactory();
4444
                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...
4445
                    // @todo When we want to test score again by default we will need fixtures for Solr
4446
                }
4447
4448
                if ($setupFactory instanceof LegacyElasticsearch) {
4449
                    $position = strrpos($fixture, '/');
4450
                    $fixture = substr_replace($fixture, '/Location', $position, 0);
4451
                }
4452
4453
                $result = $searchService->findLocations($query);
4454
            } elseif ($query instanceof Query) {
4455
                if ($info) {
4456
                    $result = $searchService->findContentInfo($query);
4457
                } else {
4458
                    $result = $searchService->findContent($query);
4459
                }
4460
            } else {
4461
                $this->fail('Expected instance of LocationQuery or Query, got: ' . gettype($query));
4462
            }
4463
            $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...
4464
        } catch (NotImplementedException $e) {
4465
            $this->markTestSkipped(
4466
                'This feature is not supported by the current search backend: ' . $e->getMessage()
4467
            );
4468
        }
4469
4470 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...
4471
            if (isset($_ENV['ez_tests_record'])) {
4472
                file_put_contents(
4473
                    $record = $fixture . '.recording',
4474
                    "<?php\n\nreturn " . var_export($result, true) . ";\n\n"
4475
                );
4476
                $this->markTestIncomplete("No fixture available. Result recorded at $record. Result: \n" . $this->printResult($result));
4477
            } else {
4478
                $this->markTestIncomplete("No fixture available. Set \$_ENV['ez_tests_record'] to generate it.");
4479
            }
4480
        }
4481
4482
        $fixture = include $fixture;
4483
4484
        if ($closure !== null) {
4485
            $closure($fixture);
4486
            $closure($result);
4487
        }
4488
4489 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...
4490
            foreach (array($fixture, $result) as $set) {
4491
                $property = new \ReflectionProperty(get_class($set), 'maxScore');
4492
                $property->setAccessible(true);
4493
                $property->setValue($set, 0.0);
4494
4495
                foreach ($set->searchHits as $hit) {
4496
                    $property = new \ReflectionProperty(get_class($hit), 'score');
4497
                    $property->setAccessible(true);
4498
                    $property->setValue($hit, 0.0);
4499
                }
4500
            }
4501
        }
4502
4503
        foreach (array($fixture, $result) as $set) {
4504
            foreach ($set->searchHits as $hit) {
4505
                $property = new \ReflectionProperty(get_class($hit), 'index');
4506
                $property->setAccessible(true);
4507
                $property->setValue($hit, null);
4508
4509
                $property = new \ReflectionProperty(get_class($hit), 'matchedTranslation');
4510
                $property->setAccessible(true);
4511
                $property->setValue($hit, null);
4512
4513
                if (!$id) {
4514
                    $hit->valueObject['id'] = null;
4515
                }
4516
            }
4517
        }
4518
4519
        $this->assertEquals(
4520
            $fixture,
4521
            $result,
4522
            'Search results do not match.',
4523
            .99 // Be quite generous regarding delay -- most important for scores
4524
        );
4525
    }
4526
4527
    /**
4528
     * Show a simplified view of the search result for manual introspection.
4529
     *
4530
     * @param SearchResult $result
4531
     *
4532
     * @return string
4533
     */
4534 View Code Duplication
    protected function printResult(SearchResult $result)
4535
    {
4536
        $printed = '';
4537
        foreach ($result->searchHits as $hit) {
4538
            $printed .= sprintf(" - %s (%s)\n", $hit->valueObject['title'], $hit->valueObject['id']);
4539
        }
4540
4541
        return $printed;
4542
    }
4543
4544
    /**
4545
     * Simplify search result.
4546
     *
4547
     * This leads to saner comparisons of results, since we do not get the full
4548
     * content objects every time.
4549
     *
4550
     * @param SearchResult $result
4551
     */
4552
    protected function simplifySearchResult(SearchResult $result)
4553
    {
4554
        $result->time = 1;
4555
4556
        foreach ($result->searchHits as $hit) {
4557
            switch (true) {
4558
                case $hit->valueObject instanceof Content:
4559 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...
4560
                    $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...
4561
                        'id' => $hit->valueObject->contentInfo->id,
4562
                        'title' => $hit->valueObject->contentInfo->name,
4563
                    );
4564
                    break;
4565
4566
                case $hit->valueObject instanceof ContentInfo:
4567
                    $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...
4568
                        'id' => $hit->valueObject->id,
4569
                        'title' => $hit->valueObject->name,
4570
                    );
4571
                    break;
4572
4573
                default:
4574
                    throw new \RuntimeException('Unknown search result hit type: ' . get_class($hit->valueObject));
4575
            }
4576
        }
4577
    }
4578
4579
    /**
4580
     * Get fixture directory.
4581
     *
4582
     * @return string
4583
     */
4584
    protected function getFixtureDir()
4585
    {
4586
        return __DIR__ . '/_fixtures/' . getenv('fixtureDir') . '/';
4587
    }
4588
4589
    /**
4590
     * For findContentInfo tests, to reuse fixtures for findContent tests.
4591
     *
4592
     * @param null|callable $closure
4593
     *
4594
     * @return callable
4595
     */
4596
    private function getContentInfoFixtureClosure($closure = null)
4597
    {
4598
        /** @var $data \eZ\Publish\API\Repository\Values\Content\Search\SearchResult */
4599
        return function (&$data) use ($closure) {
4600
            foreach ($data->searchHits as $searchHit) {
4601
                if ($searchHit->valueObject instanceof Content) {
4602
                    $searchHit->valueObject = $searchHit->valueObject->getVersionInfo()->getContentInfo();
4603
                }
4604
            }
4605
4606
            if (isset($closure)) {
4607
                $closure($data);
4608
            }
4609
        };
4610
    }
4611
}
4612