Completed
Push — master ( 80bf1d...db22b5 )
by André
18:59
created

checkPrioritizedLanguagesSupport()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

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

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

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

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

<?php

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

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

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

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

}

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

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

See also the PhpDoc documentation for @property.

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

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

<?php

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

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

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

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

}

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

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

See also the PhpDoc documentation for @property.

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

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

<?php

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

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

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

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

}

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

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

See also the PhpDoc documentation for @property.

Loading history...
2865
2866
        return $contentType;
2867
    }
2868
2869
    /**
2870
     * Test for the findContent() method.
2871
     *
2872
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2873
     * @group maplocation
2874
     */
2875 View Code Duplication
    public function testMapLocationDistanceLessThanOrEqual()
2876
    {
2877
        $contentType = $this->createTestPlaceContentType();
2878
2879
        // Create a draft to account for behaviour with ContentType in different states
2880
        $repository = $this->getRepository();
2881
        $contentTypeService = $repository->getContentTypeService();
2882
        $contentService = $repository->getContentService();
2883
        $contentTypeService->createContentTypeDraft($contentType);
2884
2885
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2886
        $createStruct->alwaysAvailable = false;
2887
        $createStruct->mainLanguageCode = 'eng-GB';
2888
        $createStruct->setField(
2889
            'maplocation',
2890
            array(
2891
                'latitude' => 45.894877,
2892
                'longitude' => 15.972699,
2893
                'address' => 'Here be wild boars',
2894
            ),
2895
            'eng-GB'
2896
        );
2897
2898
        $draft = $contentService->createContent($createStruct);
2899
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
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.927334,
2908
                'longitude' => 15.934847,
2909
                'address' => 'A lone tree',
2910
            ),
2911
            'eng-GB'
2912
        );
2913
2914
        $draft = $contentService->createContent($createStruct);
2915
        $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...
2916
2917
        $this->refreshSearch($repository);
2918
2919
        $query = new Query(
2920
            array(
2921
                'filter' => new Criterion\LogicalAnd(
2922
                    array(
2923
                        new Criterion\ContentTypeId($contentType->id),
2924
                        new Criterion\MapLocationDistance(
2925
                            'maplocation',
2926
                            Criterion\Operator::LTE,
2927
                            240,
2928
                            43.756825,
2929
                            15.775074
2930
                        ),
2931
                    )
2932
                ),
2933
                'offset' => 0,
2934
                'limit' => 10,
2935
                'sortClauses' => array(),
2936
            )
2937
        );
2938
2939
        $searchService = $repository->getSearchService();
2940
        $result = $searchService->findContent($query);
2941
2942
        $this->assertEquals(1, $result->totalCount);
2943
        $this->assertEquals(
2944
            $wildBoars->id,
2945
            $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...
2946
        );
2947
    }
2948
2949
    /**
2950
     * Test for the findContent() method.
2951
     *
2952
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2953
     * @group maplocation
2954
     */
2955 View Code Duplication
    public function testMapLocationDistanceGreaterThanOrEqual()
2956
    {
2957
        $contentType = $this->createTestPlaceContentType();
2958
2959
        // Create a draft to account for behaviour with ContentType in different states
2960
        $repository = $this->getRepository();
2961
        $contentTypeService = $repository->getContentTypeService();
2962
        $contentService = $repository->getContentService();
2963
        $contentTypeService->createContentTypeDraft($contentType);
2964
2965
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2966
        $createStruct->alwaysAvailable = false;
2967
        $createStruct->mainLanguageCode = 'eng-GB';
2968
        $createStruct->setField(
2969
            'maplocation',
2970
            array(
2971
                'latitude' => 45.894877,
2972
                'longitude' => 15.972699,
2973
                'address' => 'Here be wild boars',
2974
            ),
2975
            'eng-GB'
2976
        );
2977
2978
        $draft = $contentService->createContent($createStruct);
2979
        $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...
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.927334,
2988
                'longitude' => 15.934847,
2989
                'address' => 'A lone tree',
2990
            ),
2991
            'eng-GB'
2992
        );
2993
2994
        $draft = $contentService->createContent($createStruct);
2995
        $tree = $contentService->publishVersion($draft->getVersionInfo());
2996
2997
        $this->refreshSearch($repository);
2998
2999
        $query = new Query(
3000
            array(
3001
                'filter' => new Criterion\LogicalAnd(
3002
                    array(
3003
                        new Criterion\ContentTypeId($contentType->id),
3004
                        new Criterion\MapLocationDistance(
3005
                            'maplocation',
3006
                            Criterion\Operator::GTE,
3007
                            240,
3008
                            43.756825,
3009
                            15.775074
3010
                        ),
3011
                    )
3012
                ),
3013
                'offset' => 0,
3014
                'limit' => 10,
3015
                'sortClauses' => array(),
3016
            )
3017
        );
3018
3019
        $searchService = $repository->getSearchService();
3020
        $result = $searchService->findContent($query);
3021
3022
        $this->assertEquals(1, $result->totalCount);
3023
        $this->assertEquals(
3024
            $tree->id,
3025
            $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...
3026
        );
3027
    }
3028
3029
    /**
3030
     * Test for the findContent() method.
3031
     *
3032
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3033
     * @group maplocation
3034
     */
3035
    public function testMapLocationDistanceBetween()
3036
    {
3037
        $contentType = $this->createTestPlaceContentType();
3038
3039
        // Create a draft to account for behaviour with ContentType in different states
3040
        $repository = $this->getRepository();
3041
        $contentTypeService = $repository->getContentTypeService();
3042
        $contentService = $repository->getContentService();
3043
        $contentTypeService->createContentTypeDraft($contentType);
3044
3045
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3046
        $createStruct->alwaysAvailable = false;
3047
        $createStruct->mainLanguageCode = 'eng-GB';
3048
        $createStruct->setField(
3049
            'maplocation',
3050
            array(
3051
                'latitude' => 45.894877,
3052
                'longitude' => 15.972699,
3053
                'address' => 'Here be wild boars',
3054
            ),
3055
            'eng-GB'
3056
        );
3057
3058
        $draft = $contentService->createContent($createStruct);
3059
        $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...
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.927334,
3068
                'longitude' => 15.934847,
3069
                'address' => 'A lone tree',
3070
            ),
3071
            'eng-GB'
3072
        );
3073
3074
        $draft = $contentService->createContent($createStruct);
3075
        $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...
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.903777,
3084
                'longitude' => 15.958788,
3085
                'address' => 'Meadow with mushrooms',
3086
            ),
3087
            'eng-GB'
3088
        );
3089
3090
        $draft = $contentService->createContent($createStruct);
3091
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3092
3093
        $this->refreshSearch($repository);
3094
3095
        $query = new Query(
3096
            array(
3097
                'filter' => new Criterion\LogicalAnd(
3098
                    array(
3099
                        new Criterion\ContentTypeId($contentType->id),
3100
                        new Criterion\MapLocationDistance(
3101
                            'maplocation',
3102
                            Criterion\Operator::BETWEEN,
3103
                            array(239, 241),
3104
                            43.756825,
3105
                            15.775074
3106
                        ),
3107
                    )
3108
                ),
3109
                'offset' => 0,
3110
                'limit' => 10,
3111
                'sortClauses' => array(),
3112
            )
3113
        );
3114
3115
        $searchService = $repository->getSearchService();
3116
        $result = $searchService->findContent($query);
3117
3118
        $this->assertEquals(1, $result->totalCount);
3119
        $this->assertEquals(
3120
            $mushrooms->id,
3121
            $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...
3122
        );
3123
    }
3124
3125
    /**
3126
     * Test for the findContent() method.
3127
     *
3128
     * This tests the distance over the pole. The tests intentionally uses large range,
3129
     * as the flat Earth model used in Legacy Storage Search is not precise for the use case.
3130
     * What is tested here is that outer bounding box is correctly calculated, so that
3131
     * location is not excluded.
3132
     *
3133
     * Range between 222km and 350km shows the magnitude of error between great-circle
3134
     * (always very precise) and flat Earth (very imprecise for this use case) models.
3135
     *
3136
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3137
     * @group maplocation
3138
     */
3139
    public function testMapLocationDistanceBetweenPolar()
3140
    {
3141
        $contentType = $this->createTestPlaceContentType();
3142
3143
        // Create a draft to account for behaviour with ContentType in different states
3144
        $repository = $this->getRepository();
3145
        $contentTypeService = $repository->getContentTypeService();
3146
        $contentService = $repository->getContentService();
3147
        $contentTypeService->createContentTypeDraft($contentType);
3148
3149
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3150
        $createStruct->alwaysAvailable = false;
3151
        $createStruct->mainLanguageCode = 'eng-GB';
3152
        $createStruct->setField(
3153
            'maplocation',
3154
            array(
3155
                'latitude' => 89,
3156
                'longitude' => -164,
3157
                'address' => 'Polar bear media tower',
3158
            ),
3159
            'eng-GB'
3160
        );
3161
3162
        $draft = $contentService->createContent($createStruct);
3163
        $polarBear = $contentService->publishVersion($draft->getVersionInfo());
3164
3165
        $this->refreshSearch($repository);
3166
3167
        $query = new Query(
3168
            array(
3169
                'filter' => new Criterion\LogicalAnd(
3170
                    array(
3171
                        new Criterion\ContentTypeId($contentType->id),
3172
                        new Criterion\MapLocationDistance(
3173
                            'maplocation',
3174
                            Criterion\Operator::BETWEEN,
3175
                            array(221, 350),
3176
                            89,
3177
                            16
3178
                        ),
3179
                    )
3180
                ),
3181
                'offset' => 0,
3182
                'limit' => 10,
3183
                'sortClauses' => array(),
3184
            )
3185
        );
3186
3187
        $searchService = $repository->getSearchService();
3188
        $result = $searchService->findContent($query);
3189
3190
        $this->assertEquals(1, $result->totalCount);
3191
        $this->assertEquals(
3192
            $polarBear->id,
3193
            $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...
3194
        );
3195
    }
3196
3197
    /**
3198
     * Test for the findContent() method.
3199
     *
3200
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3201
     * @group maplocation
3202
     */
3203 View Code Duplication
    public function testMapLocationDistanceSortAscending()
3204
    {
3205
        $contentType = $this->createTestPlaceContentType();
3206
3207
        // Create a draft to account for behaviour with ContentType in different states
3208
        $repository = $this->getRepository();
3209
        $contentTypeService = $repository->getContentTypeService();
3210
        $contentService = $repository->getContentService();
3211
        $contentTypeService->createContentTypeDraft($contentType);
3212
3213
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3214
        $createStruct->alwaysAvailable = false;
3215
        $createStruct->mainLanguageCode = 'eng-GB';
3216
        $createStruct->setField(
3217
            'maplocation',
3218
            array(
3219
                'latitude' => 45.894877,
3220
                'longitude' => 15.972699,
3221
                'address' => 'Here be wild boars',
3222
            ),
3223
            'eng-GB'
3224
        );
3225
3226
        $draft = $contentService->createContent($createStruct);
3227
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
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.927334,
3236
                'longitude' => 15.934847,
3237
                'address' => 'A lone tree',
3238
            ),
3239
            'eng-GB'
3240
        );
3241
3242
        $draft = $contentService->createContent($createStruct);
3243
        $tree = $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.903777,
3252
                'longitude' => 15.958788,
3253
                'address' => 'Meadow with mushrooms',
3254
            ),
3255
            'eng-GB'
3256
        );
3257
3258
        $draft = $contentService->createContent($createStruct);
3259
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3260
3261
        $this->refreshSearch($repository);
3262
3263
        $wellInVodice = array(
3264
            'latitude' => 43.756825,
3265
            'longitude' => 15.775074,
3266
        );
3267
3268
        $query = new Query(
3269
            array(
3270
                'filter' => new Criterion\LogicalAnd(
3271
                    array(
3272
                        new Criterion\ContentTypeId($contentType->id),
3273
                        new Criterion\MapLocationDistance(
3274
                            'maplocation',
3275
                            Criterion\Operator::GTE,
3276
                            235,
3277
                            $wellInVodice['latitude'],
3278
                            $wellInVodice['longitude']
3279
                        ),
3280
                    )
3281
                ),
3282
                'offset' => 0,
3283
                'limit' => 10,
3284
                'sortClauses' => array(
3285
                    new SortClause\MapLocationDistance(
3286
                        'testtype',
3287
                        'maplocation',
3288
                        $wellInVodice['latitude'],
3289
                        $wellInVodice['longitude'],
3290
                        Query::SORT_ASC
3291
                    ),
3292
                ),
3293
            )
3294
        );
3295
3296
        $searchService = $repository->getSearchService();
3297
        $result = $searchService->findContent($query);
3298
3299
        $this->assertEquals(3, $result->totalCount);
3300
        $this->assertEquals(
3301
            $wildBoars->id,
3302
            $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...
3303
        );
3304
        $this->assertEquals(
3305
            $mushrooms->id,
3306
            $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...
3307
        );
3308
        $this->assertEquals(
3309
            $tree->id,
3310
            $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...
3311
        );
3312
    }
3313
3314
    /**
3315
     * Test for the findContent() method.
3316
     *
3317
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3318
     * @group maplocation
3319
     */
3320 View Code Duplication
    public function testMapLocationDistanceSortDescending()
3321
    {
3322
        $contentType = $this->createTestPlaceContentType();
3323
3324
        // Create a draft to account for behaviour with ContentType in different states
3325
        $repository = $this->getRepository();
3326
        $contentTypeService = $repository->getContentTypeService();
3327
        $contentService = $repository->getContentService();
3328
        $contentTypeService->createContentTypeDraft($contentType);
3329
3330
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3331
        $createStruct->alwaysAvailable = false;
3332
        $createStruct->mainLanguageCode = 'eng-GB';
3333
        $createStruct->setField(
3334
            'maplocation',
3335
            array(
3336
                'latitude' => 45.894877,
3337
                'longitude' => 15.972699,
3338
                'address' => 'Here be wild boars',
3339
            ),
3340
            'eng-GB'
3341
        );
3342
3343
        $draft = $contentService->createContent($createStruct);
3344
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
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.927334,
3353
                'longitude' => 15.934847,
3354
                'address' => 'A lone tree',
3355
            ),
3356
            'eng-GB'
3357
        );
3358
3359
        $draft = $contentService->createContent($createStruct);
3360
        $tree = $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.903777,
3369
                'longitude' => 15.958788,
3370
                'address' => 'Meadow with mushrooms',
3371
            ),
3372
            'eng-GB'
3373
        );
3374
3375
        $draft = $contentService->createContent($createStruct);
3376
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3377
3378
        $this->refreshSearch($repository);
3379
3380
        $well = array(
3381
            'latitude' => 43.756825,
3382
            'longitude' => 15.775074,
3383
        );
3384
3385
        $query = new Query(
3386
            array(
3387
                'filter' => new Criterion\LogicalAnd(
3388
                    array(
3389
                        new Criterion\ContentTypeId($contentType->id),
3390
                        new Criterion\MapLocationDistance(
3391
                            'maplocation',
3392
                            Criterion\Operator::GTE,
3393
                            235,
3394
                            $well['latitude'],
3395
                            $well['longitude']
3396
                        ),
3397
                    )
3398
                ),
3399
                'offset' => 0,
3400
                'limit' => 10,
3401
                'sortClauses' => array(
3402
                    new SortClause\MapLocationDistance(
3403
                        'testtype',
3404
                        'maplocation',
3405
                        $well['latitude'],
3406
                        $well['longitude'],
3407
                        Query::SORT_DESC
3408
                    ),
3409
                ),
3410
            )
3411
        );
3412
3413
        $searchService = $repository->getSearchService();
3414
        $result = $searchService->findContent($query);
3415
3416
        $this->assertEquals(3, $result->totalCount);
3417
        $this->assertEquals(
3418
            $wildBoars->id,
3419
            $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...
3420
        );
3421
        $this->assertEquals(
3422
            $mushrooms->id,
3423
            $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...
3424
        );
3425
        $this->assertEquals(
3426
            $tree->id,
3427
            $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...
3428
        );
3429
    }
3430
3431
    /**
3432
     * Test for the findContent() method.
3433
     *
3434
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3435
     * @group maplocation
3436
     */
3437
    public function testMapLocationDistanceWithCustomField()
3438
    {
3439
        $setupFactory = $this->getSetupFactory();
3440
        if ($setupFactory instanceof LegacyElasticsearch) {
3441
            $this->markTestIncomplete("TODO: Some issues with 'copy_to' and 'geo_point'");
3442
        }
3443
3444
        $contentType = $this->createTestPlaceContentType();
3445
3446
        // Create a draft to account for behaviour with ContentType in different states
3447
        $repository = $this->getRepository();
3448
        $contentTypeService = $repository->getContentTypeService();
3449
        $contentService = $repository->getContentService();
3450
        $contentTypeService->createContentTypeDraft($contentType);
3451
3452
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3453
        $createStruct->alwaysAvailable = false;
3454
        $createStruct->mainLanguageCode = 'eng-GB';
3455
        $createStruct->setField(
3456
            'maplocation',
3457
            array(
3458
                'latitude' => 45.894877,
3459
                'longitude' => 15.972699,
3460
                'address' => 'Here be wild boars',
3461
            ),
3462
            'eng-GB'
3463
        );
3464
3465
        $draft = $contentService->createContent($createStruct);
3466
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
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.927334,
3475
                'longitude' => 15.934847,
3476
                'address' => 'A lone tree',
3477
            ),
3478
            'eng-GB'
3479
        );
3480
3481
        $draft = $contentService->createContent($createStruct);
3482
        $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...
3483
3484
        $this->refreshSearch($repository);
3485
3486
        $distanceCriterion = new Criterion\MapLocationDistance(
3487
            'maplocation',
3488
            Criterion\Operator::LTE,
3489
            240,
3490
            43.756825,
3491
            15.775074
3492
        );
3493
        $distanceCriterion->setCustomField('testtype', 'maplocation', 'custom_geolocation_field');
3494
3495
        $query = new Query(
3496
            array(
3497
                'filter' => new Criterion\LogicalAnd(
3498
                    array(
3499
                        new Criterion\ContentTypeId($contentType->id),
3500
                        $distanceCriterion,
3501
                    )
3502
                ),
3503
                'offset' => 0,
3504
                'limit' => 10,
3505
                'sortClauses' => array(),
3506
            )
3507
        );
3508
3509
        $searchService = $repository->getSearchService();
3510
        $result = $searchService->findContent($query);
3511
3512
        $this->assertEquals(1, $result->totalCount);
3513
        $this->assertEquals(
3514
            $wildBoars->id,
3515
            $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...
3516
        );
3517
    }
3518
3519
    /**
3520
     * Test for the findContent() method.
3521
     *
3522
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3523
     * @group maplocation
3524
     */
3525
    public function testMapLocationDistanceWithCustomFieldSort()
3526
    {
3527
        $setupFactory = $this->getSetupFactory();
3528
        if ($setupFactory instanceof LegacyElasticsearch) {
3529
            $this->markTestIncomplete("TODO: Some issues with 'copy_to' and 'geo_point'");
3530
        }
3531
3532
        $contentType = $this->createTestPlaceContentType();
3533
3534
        // Create a draft to account for behaviour with ContentType in different states
3535
        $repository = $this->getRepository();
3536
        $contentTypeService = $repository->getContentTypeService();
3537
        $contentService = $repository->getContentService();
3538
        $contentTypeService->createContentTypeDraft($contentType);
3539
3540
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3541
        $createStruct->alwaysAvailable = false;
3542
        $createStruct->mainLanguageCode = 'eng-GB';
3543
        $createStruct->setField(
3544
            'maplocation',
3545
            array(
3546
                'latitude' => 45.894877,
3547
                'longitude' => 15.972699,
3548
                'address' => 'Here be wild boars',
3549
            ),
3550
            'eng-GB'
3551
        );
3552
3553
        $draft = $contentService->createContent($createStruct);
3554
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
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.927334,
3563
                'longitude' => 15.934847,
3564
                'address' => 'A lone tree',
3565
            ),
3566
            'eng-GB'
3567
        );
3568
3569
        $draft = $contentService->createContent($createStruct);
3570
        $tree = $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.903777,
3579
                'longitude' => 15.958788,
3580
                'address' => 'Meadow with mushrooms',
3581
            ),
3582
            'eng-GB'
3583
        );
3584
3585
        $draft = $contentService->createContent($createStruct);
3586
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3587
3588
        $this->refreshSearch($repository);
3589
3590
        $well = array(
3591
            'latitude' => 43.756825,
3592
            'longitude' => 15.775074,
3593
        );
3594
3595
        $sortClause = new SortClause\MapLocationDistance(
3596
            'testtype',
3597
            'maplocation',
3598
            $well['latitude'],
3599
            $well['longitude'],
3600
            Query::SORT_DESC
3601
        );
3602
        $sortClause->setCustomField('testtype', 'maplocation', 'custom_geolocation_field');
3603
3604
        $query = new Query(
3605
            array(
3606
                'filter' => new Criterion\LogicalAnd(
3607
                    array(
3608
                        new Criterion\ContentTypeId($contentType->id),
3609
                        new Criterion\MapLocationDistance(
3610
                            'maplocation',
3611
                            Criterion\Operator::GTE,
3612
                            235,
3613
                            $well['latitude'],
3614
                            $well['longitude']
3615
                        ),
3616
                    )
3617
                ),
3618
                'offset' => 0,
3619
                'limit' => 10,
3620
                'sortClauses' => array(
3621
                    $sortClause,
3622
                ),
3623
            )
3624
        );
3625
3626
        $searchService = $repository->getSearchService();
3627
        $result = $searchService->findContent($query);
3628
3629
        $this->assertEquals(3, $result->totalCount);
3630
        $this->assertEquals(
3631
            $wildBoars->id,
3632
            $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...
3633
        );
3634
        $this->assertEquals(
3635
            $mushrooms->id,
3636
            $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...
3637
        );
3638
        $this->assertEquals(
3639
            $tree->id,
3640
            $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...
3641
        );
3642
    }
3643
3644
    /**
3645
     * Test for the findLocations() method.
3646
     *
3647
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3648
     */
3649 View Code Duplication
    public function testFindMainLocation()
3650
    {
3651
        $plainSiteLocationId = 56;
3652
        $designLocationId = 58;
3653
        $partnersContentId = 59;
3654
        $repository = $this->getRepository();
3655
        $locationService = $repository->getLocationService();
3656
        $contentService = $repository->getContentService();
3657
3658
        // Add secondary Location for "Partners" user group, under "Design" page
3659
        $locationService->createLocation(
3660
            $contentService->loadContentInfo($partnersContentId),
3661
            $locationService->newLocationCreateStruct($designLocationId)
3662
        );
3663
3664
        $this->refreshSearch($repository);
3665
3666
        $query = new LocationQuery(
3667
            array(
3668
                'filter' => new Criterion\LogicalAnd(
3669
                    array(
3670
                        new Criterion\ParentLocationId($designLocationId),
3671
                        new Criterion\Location\IsMainLocation(
3672
                            Criterion\Location\IsMainLocation::MAIN
3673
                        ),
3674
                    )
3675
                ),
3676
                'offset' => 0,
3677
                'limit' => 10,
3678
                'sortClauses' => array(),
3679
            )
3680
        );
3681
3682
        $searchService = $repository->getSearchService();
3683
        $result = $searchService->findLocations($query);
3684
3685
        $this->assertEquals(1, $result->totalCount);
3686
        $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...
3687
    }
3688
3689
    /**
3690
     * Test for the findLocations() method.
3691
     *
3692
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3693
     */
3694 View Code Duplication
    public function testFindNonMainLocation()
3695
    {
3696
        $designLocationId = 58;
3697
        $partnersContentId = 59;
3698
        $repository = $this->getRepository();
3699
        $locationService = $repository->getLocationService();
3700
        $contentService = $repository->getContentService();
3701
3702
        // Add secondary Location for "Partners" user group, under "Design" page
3703
        $newLocation = $locationService->createLocation(
3704
            $contentService->loadContentInfo($partnersContentId),
3705
            $locationService->newLocationCreateStruct($designLocationId)
3706
        );
3707
3708
        $this->refreshSearch($repository);
3709
3710
        $query = new LocationQuery(
3711
            array(
3712
                'filter' => new Criterion\LogicalAnd(
3713
                    array(
3714
                        new Criterion\ParentLocationId($designLocationId),
3715
                        new Criterion\Location\IsMainLocation(
3716
                            Criterion\Location\IsMainLocation::NOT_MAIN
3717
                        ),
3718
                    )
3719
                ),
3720
                'offset' => 0,
3721
                'limit' => 10,
3722
                'sortClauses' => array(),
3723
            )
3724
        );
3725
3726
        $searchService = $repository->getSearchService();
3727
        $result = $searchService->findLocations($query);
3728
3729
        $this->assertEquals(1, $result->totalCount);
3730
        $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...
3731
    }
3732
3733
    /**
3734
     * Test for the findLocations() method.
3735
     *
3736
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3737
     */
3738 View Code Duplication
    public function testSortMainLocationAscending()
3739
    {
3740
        $plainSiteLocationId = 56;
3741
        $designLocationId = 58;
3742
        $partnersContentId = 59;
3743
        $repository = $this->getRepository();
3744
        $locationService = $repository->getLocationService();
3745
        $contentService = $repository->getContentService();
3746
3747
        // Add secondary Location for "Partners" user group, under "Design" page
3748
        $newLocation = $locationService->createLocation(
3749
            $contentService->loadContentInfo($partnersContentId),
3750
            $locationService->newLocationCreateStruct($designLocationId)
3751
        );
3752
3753
        $this->refreshSearch($repository);
3754
3755
        $query = new LocationQuery(
3756
            array(
3757
                'filter' => new Criterion\ParentLocationId($designLocationId),
3758
                'offset' => 0,
3759
                'limit' => 10,
3760
                'sortClauses' => array(
3761
                    new SortClause\Location\IsMainLocation(
3762
                        LocationQuery::SORT_ASC
3763
                    ),
3764
                ),
3765
            )
3766
        );
3767
3768
        $searchService = $repository->getSearchService();
3769
        $result = $searchService->findLocations($query);
3770
3771
        $this->assertEquals(2, $result->totalCount);
3772
        $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...
3773
        $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...
3774
    }
3775
3776
    /**
3777
     * Test for the findLocations() method.
3778
     *
3779
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3780
     */
3781 View Code Duplication
    public function testSortMainLocationDescending()
3782
    {
3783
        $plainSiteLocationId = 56;
3784
        $designLocationId = 58;
3785
        $partnersContentId = 59;
3786
        $repository = $this->getRepository();
3787
        $locationService = $repository->getLocationService();
3788
        $contentService = $repository->getContentService();
3789
3790
        // Add secondary Location for "Partners" user group, under "Design" page
3791
        $newLocation = $locationService->createLocation(
3792
            $contentService->loadContentInfo($partnersContentId),
3793
            $locationService->newLocationCreateStruct($designLocationId)
3794
        );
3795
3796
        $this->refreshSearch($repository);
3797
3798
        $query = new LocationQuery(
3799
            array(
3800
                'filter' => new Criterion\ParentLocationId($designLocationId),
3801
                'offset' => 0,
3802
                'limit' => 10,
3803
                'sortClauses' => array(
3804
                    new SortClause\Location\IsMainLocation(
3805
                        LocationQuery::SORT_DESC
3806
                    ),
3807
                ),
3808
            )
3809
        );
3810
3811
        $searchService = $repository->getSearchService();
3812
        $result = $searchService->findLocations($query);
3813
3814
        $this->assertEquals(2, $result->totalCount);
3815
        $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...
3816
        $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...
3817
    }
3818
3819
    /**
3820
     * Test for the findLocations() method.
3821
     *
3822
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3823
     */
3824
    public function testContentWithMultipleLocations()
3825
    {
3826
        $repository = $this->getRepository();
3827
        $contentService = $repository->getContentService();
3828
        $contentTypeService = $repository->getContentTypeService();
3829
        $locationService = $repository->getLocationService();
3830
3831
        $forumType = $contentTypeService->loadContentTypeByIdentifier('forum');
3832
3833
        $createStruct = $contentService->newContentCreateStruct($forumType, 'eng-GB');
3834
        $createStruct->alwaysAvailable = false;
3835
        $createStruct->setField('name', 'An awesome duplicate forum');
3836
3837
        $draft = $contentService->createContent($createStruct);
3838
        $content = $contentService->publishVersion($draft->getVersionInfo());
3839
3840
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
3841
        $location1 = $locationService->createLocation($content->contentInfo, $locationCreateStruct);
3842
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(5);
3843
        $location2 = $locationService->createLocation($content->contentInfo, $locationCreateStruct);
3844
3845
        $this->refreshSearch($repository);
3846
3847
        $query = new LocationQuery(
3848
            array(
3849
                'filter' => new Criterion\ContentId($content->id),
3850
                'sortClauses' => array(
3851
                    new SortClause\Location\Id(LocationQuery::SORT_ASC),
3852
                ),
3853
            )
3854
        );
3855
3856
        $searchService = $repository->getSearchService();
3857
        $result = $searchService->findLocations($query);
3858
3859
        $this->assertEquals(2, $result->totalCount);
3860
        $this->assertEquals(
3861
            $location1->id,
3862
            $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...
3863
        );
3864
        $this->assertEquals(
3865
            $location2->id,
3866
            $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...
3867
        );
3868
    }
3869
3870
    protected function createContentForTestUserMetadataGroupHorizontal()
3871
    {
3872
        $repository = $this->getRepository();
3873
        $contentService = $repository->getContentService();
3874
        $contentTypeService = $repository->getContentTypeService();
3875
        $locationService = $repository->getLocationService();
3876
        $userService = $repository->getUserService();
3877
        $administratorUser = $repository->getCurrentUser();
3878
        // ID of the "Administrators" user group in an eZ Publish demo installation
3879
        $administratorsUserGroupId = 12;
3880
        // ID of the "Editors" user group in an eZ Publish demo installation
3881
        $editorsUserGroupId = 13;
3882
3883
        $administratorsUserGroup = $userService->loadUserGroup($administratorsUserGroupId);
3884
        $editorsUserGroup = $userService->loadUserGroup($editorsUserGroupId);
3885
3886
        // Add additional Location for Administrators UserGroup under Editors UserGroup Location
3887
        $locationCreateStruct = $locationService->newLocationCreateStruct(
3888
            $editorsUserGroup->contentInfo->mainLocationId
3889
        );
3890
        $newAdministratorsUserGroupLocation = $locationService->createLocation(
3891
            $administratorsUserGroup->contentInfo,
3892
            $locationCreateStruct
3893
        );
3894
3895
        // Add additional Location for administrator user under newly created UserGroup Location
3896
        $locationCreateStruct = $locationService->newLocationCreateStruct(
3897
            $newAdministratorsUserGroupLocation->id
3898
        );
3899
        $locationService->createLocation(
3900
            $administratorUser->contentInfo,
3901
            $locationCreateStruct
3902
        );
3903
3904
        // Create a Content to be found through Editors UserGroup id.
3905
        // This ensures data is indexed, it could also be done by updating metadata of
3906
        // an existing Content, but slot would need to reindex Content and that should
3907
        // be tested elsewhere (dedicated indexing integration tests, missing ATM).
3908
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
3909
3910
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3911
        $createStruct->setField('name', 'test');
3912
3913
        $locationCreateStruct = $locationService->newLocationCreateStruct(2);
3914
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
3915
        $content = $contentService->publishVersion($draft->getVersionInfo());
3916
        $contentTypeService->createContentTypeDraft($contentType);
3917
3918
        $this->refreshSearch($repository);
3919
3920
        return $content;
3921
    }
3922
3923
    /**
3924
     * Test for the findContent() method.
3925
     *
3926
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3927
     */
3928
    public function testUserMetadataGroupHorizontalFilterContent($queryType = null)
3929
    {
3930
        if ($queryType === null) {
3931
            $queryType = 'filter';
3932
        }
3933
3934
        $repository = $this->getRepository();
3935
        $searchService = $repository->getSearchService();
3936
        $editorsUserGroupId = 13;
3937
3938
        $content = $this->createContentForTestUserMetadataGroupHorizontal();
3939
3940
        $criteria = array();
3941
        $setupFactory = $this->getSetupFactory();
3942
3943
        // Do not limit for LSE, as it does not not require reindexing.
3944
        // See explanation below.
3945
        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...
3946
            $criteria[] = new Criterion\ContentTypeIdentifier('folder');
3947
        }
3948
3949
        $criteria[] = new Criterion\UserMetadata(
3950
            Criterion\UserMetadata::GROUP,
3951
            Criterion\Operator::EQ,
3952
            $editorsUserGroupId
3953
        );
3954
3955
        $query = new Query(
3956
            array(
3957
                $queryType => new Criterion\LogicalAnd($criteria),
3958
                'sortClauses' => array(
3959
                    new SortClause\ContentId(),
3960
                ),
3961
                'limit' => 50,
3962
            )
3963
        );
3964
3965
        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...
3966
            $result = $searchService->findContent($query);
3967
3968
            // Administrator User is owned by itself, when additional Locations are added
3969
            // it should be reindexed and its UserGroups will updated, which means it should
3970
            // also be found as a Content of Editors UserGroup. However we do not handle this
3971
            // in slots yet, and also miss SPI methods to do it without using Search (also
3972
            // needed to decouple services), because as indexing is asynchronous Search
3973
            // should not eat its own dog food for reindexing.
3974
            $this->assertEquals(1, $result->totalCount);
3975
3976
            $this->assertEquals(
3977
                $content->id,
3978
                $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...
3979
            );
3980
        } else {
3981
            // This is how it should eventually work for all search engines,
3982
            // with required reindexing slots properly implemented.
3983
3984
            $result = $searchService->findContent($query);
3985
3986
            // Assert last hit manually, as id will change because it is created in test
3987
            // and not present it base fixture.
3988
            $foundContent1 = array_pop($result->searchHits);
3989
            $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...
3990
            $this->assertEquals($content->id, $foundContent1->valueObject->id);
3991
3992
            $this->simplifySearchResult($result);
3993
            $this->assertEquals(
3994
                include $this->getFixtureDir() . '/UserMetadata.php',
3995
                $result,
3996
                'Search results do not match.',
3997
                .1 // Be quite generous regarding delay -- most important for scores
3998
            );
3999
        }
4000
    }
4001
4002
    /**
4003
     * Test for the findContent() method.
4004
     *
4005
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4006
     */
4007
    public function testUserMetadataGroupHorizontalQueryContent()
4008
    {
4009
        $this->testUserMetadataGroupHorizontalFilterContent('query');
4010
    }
4011
4012
    /**
4013
     * Test for the findLocations() method.
4014
     *
4015
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
4016
     */
4017
    public function testUserMetadataGroupHorizontalFilterLocation($queryType = null)
4018
    {
4019
        if ($queryType === null) {
4020
            $queryType = 'filter';
4021
        }
4022
4023
        $repository = $this->getRepository();
4024
        $searchService = $repository->getSearchService();
4025
        $editorsUserGroupId = 13;
4026
4027
        $content = $this->createContentForTestUserMetadataGroupHorizontal();
4028
4029
        $criteria = array();
4030
        $setupFactory = $this->getSetupFactory();
4031
4032
        // Do not limit for LSE, as it does not not require reindexing.
4033
        // See explanation below.
4034
        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...
4035
            $criteria[] = new Criterion\ContentTypeIdentifier('folder');
4036
        }
4037
4038
        $criteria[] = new Criterion\UserMetadata(
4039
            Criterion\UserMetadata::GROUP,
4040
            Criterion\Operator::EQ,
4041
            $editorsUserGroupId
4042
        );
4043
4044
        $query = new LocationQuery(
4045
            array(
4046
                $queryType => new Criterion\LogicalAnd($criteria),
4047
                'sortClauses' => array(
4048
                    new SortClause\Location\Id(),
4049
                ),
4050
                'limit' => 50,
4051
            )
4052
        );
4053
4054
        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...
4055
            $result = $searchService->findLocations($query);
4056
4057
            // Administrator User is owned by itself, when additional Locations are added
4058
            // it should be reindexed and its UserGroups will updated, which means it should
4059
            // also be found as a Content of Editors UserGroup. However we do not handle this
4060
            // in slots yet, and also miss SPI methods to do it without using Search (also
4061
            // needed to decouple services), because as indexing is asynchronous Search
4062
            // should not eat its own dog food for reindexing.
4063
            $this->assertEquals(1, $result->totalCount);
4064
4065
            $this->assertEquals(
4066
                $content->contentInfo->mainLocationId,
4067
                $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...
4068
            );
4069
        } else {
4070
            // This is how it should eventually work for all search engines,
4071
            // with required reindexing slots properly implemented.
4072
4073
            $result = $searchService->findLocations($query);
4074
4075
            // Assert last two hits manually, as ids will change because they are created
4076
            // in test and not present in base fixture.
4077
            $foundLocation1 = array_pop($result->searchHits);
4078
            $foundLocation2 = array_pop($result->searchHits);
4079
            // Remove additional Administrators UserGroup Location
4080
            array_pop($result->searchHits);
4081
            $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...
4082
            $this->assertEquals(
4083
                $content->versionInfo->contentInfo->mainLocationId,
4084
                $foundLocation1->valueObject->id
4085
            );
4086
            $this->assertEquals(
4087
                $repository->getCurrentUser()->id,
4088
                $foundLocation2->valueObject->contentId
4089
            );
4090
4091
            $this->simplifySearchResult($result);
4092
            $this->assertEquals(
4093
                include $this->getFixtureDir() . '/UserMetadataLocation.php',
4094
                $result,
4095
                'Search results do not match.',
4096
                .1 // Be quite generous regarding delay -- most important for scores
4097
            );
4098
        }
4099
    }
4100
4101
    /**
4102
     * Test for the findLocations() method.
4103
     *
4104
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
4105
     */
4106
    public function testUserMetadataGroupHorizontalQueryLocation()
4107
    {
4108
        $this->testUserMetadataGroupHorizontalFilterLocation('query');
4109
    }
4110
4111
    /**
4112
     * Test for the findContent() method.
4113
     *
4114
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4115
     */
4116
    public function testLanguageAnalysisSeparateContent()
4117
    {
4118
        $setupFactory = $this->getSetupFactory();
4119
        if (!$setupFactory instanceof LegacyElasticsearch) {
4120
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4121
        }
4122
4123
        $repository = $this->getRepository();
4124
        $contentService = $repository->getContentService();
4125
        $contentTypeService = $repository->getContentTypeService();
4126
        $locationService = $repository->getLocationService();
4127
        $searchService = $repository->getSearchService();
4128
        $languageService = $repository->getContentLanguageService();
4129
4130
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4131
        $languageCreateStruct->languageCode = 'rus-RU';
4132
        $languageCreateStruct->name = 'Russian';
4133
4134
        $languageService->createLanguage($languageCreateStruct);
4135
4136
        $contentCreateStruct = $contentService->newContentCreateStruct(
4137
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4138
            'eng-GB'
4139
        );
4140
4141
        $contentCreateStruct->setField('name', 'foxes');
4142
4143
        $englishContent = $contentService->publishVersion(
4144
            $contentService->createContent(
4145
                $contentCreateStruct,
4146
                array($locationService->newLocationCreateStruct(2))
4147
            )->versionInfo
4148
        );
4149
4150
        $contentCreateStruct = $contentService->newContentCreateStruct(
4151
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4152
            'rus-RU'
4153
        );
4154
4155
        $contentCreateStruct->setField('name', 'foxes');
4156
4157
        $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...
4158
            $contentService->createContent(
4159
                $contentCreateStruct,
4160
                array($locationService->newLocationCreateStruct(2))
4161
            )->versionInfo
4162
        );
4163
4164
        // Only Content in English should be found, because Content in Russian
4165
        // will not be correctly stemmed
4166
        $query = new Query(
4167
            array(
4168
                'query' => new Criterion\FullText('foxing'),
4169
            )
4170
        );
4171
4172
        $searchResult = $searchService->findContent($query);
4173
4174
        $this->assertEquals(1, $searchResult->totalCount);
4175
        $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...
4176
    }
4177
4178
    /**
4179
     * Test for the findContent() method.
4180
     *
4181
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4182
     */
4183
    public function testLanguageAnalysisSameContent()
4184
    {
4185
        $setupFactory = $this->getSetupFactory();
4186
        if (!$setupFactory instanceof LegacyElasticsearch) {
4187
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4188
        }
4189
4190
        $repository = $this->getRepository();
4191
        $contentService = $repository->getContentService();
4192
        $contentTypeService = $repository->getContentTypeService();
4193
        $locationService = $repository->getLocationService();
4194
        $searchService = $repository->getSearchService();
4195
        $languageService = $repository->getContentLanguageService();
4196
4197
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4198
        $languageCreateStruct->languageCode = 'rus-RU';
4199
        $languageCreateStruct->name = 'Russian';
4200
4201
        $languageService->createLanguage($languageCreateStruct);
4202
4203
        $contentCreateStruct = $contentService->newContentCreateStruct(
4204
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4205
            'eng-GB'
4206
        );
4207
4208
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'eng-GB');
4209
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'rus-RU');
4210
4211
        $mixedContent = $contentService->publishVersion(
4212
            $contentService->createContent(
4213
                $contentCreateStruct,
4214
                array($locationService->newLocationCreateStruct(2))
4215
            )->versionInfo
4216
        );
4217
4218
        // Content will be found because translation in Russian will be correctly stemmed
4219
        $query = new Query(
4220
            array(
4221
                'query' => new Criterion\FullText('важнее'),
4222
            )
4223
        );
4224
4225
        $searchResult = $searchService->findContent($query);
4226
4227
        $this->assertEquals(1, $searchResult->totalCount);
4228
        $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...
4229
    }
4230
4231
    /**
4232
     * Test for the findContent() method.
4233
     *
4234
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4235
     */
4236
    public function testLanguageAnalysisSameContentNotFound()
4237
    {
4238
        $setupFactory = $this->getSetupFactory();
4239
        if (!$setupFactory instanceof LegacyElasticsearch) {
4240
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4241
        }
4242
4243
        $repository = $this->getRepository();
4244
        $contentService = $repository->getContentService();
4245
        $contentTypeService = $repository->getContentTypeService();
4246
        $locationService = $repository->getLocationService();
4247
        $searchService = $repository->getSearchService();
4248
        $languageService = $repository->getContentLanguageService();
4249
4250
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4251
        $languageCreateStruct->languageCode = 'rus-RU';
4252
        $languageCreateStruct->name = 'Russian';
4253
4254
        $languageService->createLanguage($languageCreateStruct);
4255
4256
        $contentCreateStruct = $contentService->newContentCreateStruct(
4257
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4258
            'eng-GB'
4259
        );
4260
4261
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'eng-GB');
4262
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'rus-RU');
4263
4264
        $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...
4265
            $contentService->createContent(
4266
                $contentCreateStruct,
4267
                array($locationService->newLocationCreateStruct(2))
4268
            )->versionInfo
4269
        );
4270
4271
        // Content should be found because translation in Russian will be correctly stemmed
4272
        $query = new Query(
4273
            array(
4274
                'query' => new Criterion\FullText('важнее'),
4275
            )
4276
        );
4277
4278
        // Filtering fields for only English will cause no match because the term will
4279
        // not be correctly stemmed
4280
        $searchResult = $searchService->findContent($query, array('languages' => array('eng-GB')));
4281
4282
        $this->assertEquals(0, $searchResult->totalCount);
4283
    }
4284
4285
    /**
4286
     * Assert that query result matches the given fixture.
4287
     *
4288
     * @param Query $query
4289
     * @param string $fixture
4290
     * @param null|callable $closure
4291
     * @param bool $info
4292
     * @param bool $id
4293
     */
4294
    protected function assertQueryFixture(Query $query, $fixture, $closure = null, $ignoreScore = true, $info = false, $id = true)
4295
    {
4296
        $repository = $this->getRepository();
4297
        $searchService = $repository->getSearchService();
4298
4299
        try {
4300
            if ($query instanceof LocationQuery) {
4301
                $setupFactory = $this->getSetupFactory();
4302
                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...
4303
                    // @todo When we want to test score again by default we will need fixtures for Solr
4304
                }
4305
4306
                if ($setupFactory instanceof LegacyElasticsearch) {
4307
                    $position = strrpos($fixture, '/');
4308
                    $fixture = substr_replace($fixture, '/Location', $position, 0);
4309
                }
4310
4311
                $result = $searchService->findLocations($query);
4312
            } elseif ($query instanceof Query) {
4313
                if ($info) {
4314
                    $result = $searchService->findContentInfo($query);
4315
                } else {
4316
                    $result = $searchService->findContent($query);
4317
                }
4318
            } else {
4319
                $this->fail('Expected instance of LocationQuery or Query, got: ' . gettype($query));
4320
            }
4321
            $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...
4322
        } catch (NotImplementedException $e) {
4323
            $this->markTestSkipped(
4324
                'This feature is not supported by the current search backend: ' . $e->getMessage()
4325
            );
4326
        }
4327
4328 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...
4329
            if (isset($_ENV['ez_tests_record'])) {
4330
                file_put_contents(
4331
                    $record = $fixture . '.recording',
4332
                    "<?php\n\nreturn " . var_export($result, true) . ";\n\n"
4333
                );
4334
                $this->markTestIncomplete("No fixture available. Result recorded at $record. Result: \n" . $this->printResult($result));
4335
            } else {
4336
                $this->markTestIncomplete("No fixture available. Set \$_ENV['ez_tests_record'] to generate it.");
4337
            }
4338
        }
4339
4340
        $fixture = include $fixture;
4341
4342
        if ($closure !== null) {
4343
            $closure($fixture);
4344
            $closure($result);
4345
        }
4346
4347 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...
4348
            foreach (array($fixture, $result) as $set) {
4349
                $property = new \ReflectionProperty(get_class($set), 'maxScore');
4350
                $property->setAccessible(true);
4351
                $property->setValue($set, 0.0);
4352
4353
                foreach ($set->searchHits as $hit) {
4354
                    $property = new \ReflectionProperty(get_class($hit), 'score');
4355
                    $property->setAccessible(true);
4356
                    $property->setValue($hit, 0.0);
4357
                }
4358
            }
4359
        }
4360
4361
        foreach (array($fixture, $result) as $set) {
4362
            foreach ($set->searchHits as $hit) {
4363
                $property = new \ReflectionProperty(get_class($hit), 'index');
4364
                $property->setAccessible(true);
4365
                $property->setValue($hit, null);
4366
4367
                $property = new \ReflectionProperty(get_class($hit), 'matchedTranslation');
4368
                $property->setAccessible(true);
4369
                $property->setValue($hit, null);
4370
4371
                if (!$id) {
4372
                    $hit->valueObject['id'] = null;
4373
                }
4374
            }
4375
        }
4376
4377
        $this->assertEquals(
4378
            $fixture,
4379
            $result,
4380
            'Search results do not match.',
4381
            .99 // Be quite generous regarding delay -- most important for scores
4382
        );
4383
    }
4384
4385
    /**
4386
     * Show a simplified view of the search result for manual introspection.
4387
     *
4388
     * @param SearchResult $result
4389
     *
4390
     * @return string
4391
     */
4392 View Code Duplication
    protected function printResult(SearchResult $result)
4393
    {
4394
        $printed = '';
4395
        foreach ($result->searchHits as $hit) {
4396
            $printed .= sprintf(" - %s (%s)\n", $hit->valueObject['title'], $hit->valueObject['id']);
4397
        }
4398
4399
        return $printed;
4400
    }
4401
4402
    /**
4403
     * Simplify search result.
4404
     *
4405
     * This leads to saner comparisons of results, since we do not get the full
4406
     * content objects every time.
4407
     *
4408
     * @param SearchResult $result
4409
     */
4410
    protected function simplifySearchResult(SearchResult $result)
4411
    {
4412
        $result->time = 1;
4413
4414
        foreach ($result->searchHits as $hit) {
4415
            switch (true) {
4416
                case $hit->valueObject instanceof Content:
4417 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...
4418
                    $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...
4419
                        'id' => $hit->valueObject->contentInfo->id,
4420
                        'title' => $hit->valueObject->contentInfo->name,
4421
                    );
4422
                    break;
4423
4424
                case $hit->valueObject instanceof ContentInfo:
4425
                    $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...
4426
                        'id' => $hit->valueObject->id,
4427
                        'title' => $hit->valueObject->name,
4428
                    );
4429
                    break;
4430
4431
                default:
4432
                    throw new \RuntimeException('Unknown search result hit type: ' . get_class($hit->valueObject));
4433
            }
4434
        }
4435
    }
4436
4437
    /**
4438
     * Get fixture directory.
4439
     *
4440
     * @return string
4441
     */
4442
    protected function getFixtureDir()
4443
    {
4444
        return __DIR__ . '/_fixtures/' . getenv('fixtureDir') . '/';
4445
    }
4446
4447
    /**
4448
     * For findContentInfo tests, to reuse fixtures for findContent tests.
4449
     *
4450
     * @param null|callable $closure
4451
     *
4452
     * @return callable
4453
     */
4454
    private function getContentInfoFixtureClosure($closure = null)
4455
    {
4456
        /** @var $data \eZ\Publish\API\Repository\Values\Content\Search\SearchResult */
4457
        return function (&$data) use ($closure) {
4458
            foreach ($data->searchHits as $searchHit) {
4459
                if ($searchHit->valueObject instanceof Content) {
4460
                    $searchHit->valueObject = $searchHit->valueObject->getVersionInfo()->getContentInfo();
4461
                }
4462
            }
4463
4464
            if (isset($closure)) {
4465
                $closure($data);
4466
            }
4467
        };
4468
    }
4469
}
4470