Completed
Push — facets-EZP-26465 ( 4eac8e...b3ca9c )
by André
14:49
created

SearchServiceTest::testFindFacetedContentInfo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

Loading history...
3661
        // ID of the "Administrators" user group in an eZ Publish demo installation
3662
        $administratorsUserGroupId = 12;
3663
        // ID of the "Editors" user group in an eZ Publish demo installation
3664
        $editorsUserGroupId = 13;
3665
3666
        $administratorsUserGroup = $userService->loadUserGroup($administratorsUserGroupId);
3667
        $editorsUserGroup = $userService->loadUserGroup($editorsUserGroupId);
3668
3669
        // Add additional Location for Administrators UserGroup under Editors UserGroup Location
3670
        $locationCreateStruct = $locationService->newLocationCreateStruct(
3671
            $editorsUserGroup->contentInfo->mainLocationId
3672
        );
3673
        $newAdministratorsUserGroupLocation = $locationService->createLocation(
3674
            $administratorsUserGroup->contentInfo,
3675
            $locationCreateStruct
3676
        );
3677
3678
        // Add additional Location for administrator user under newly created UserGroup Location
3679
        $locationCreateStruct = $locationService->newLocationCreateStruct(
3680
            $newAdministratorsUserGroupLocation->id
3681
        );
3682
        $locationService->createLocation(
3683
            $administratorUser->contentInfo,
3684
            $locationCreateStruct
3685
        );
3686
3687
        // Create a Content to be found through Editors UserGroup id.
3688
        // This ensures data is indexed, it could also be done by updating metadata of
3689
        // an existing Content, but slot would need to reindex Content and that should
3690
        // be tested elsewhere (dedicated indexing integration tests, missing ATM).
3691
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
3692
3693
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3694
        $createStruct->setField('name', 'test');
3695
3696
        $locationCreateStruct = $locationService->newLocationCreateStruct(2);
3697
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
3698
        $content = $contentService->publishVersion($draft->getVersionInfo());
3699
        $contentTypeService->createContentTypeDraft($contentType);
3700
3701
        $this->refreshSearch($repository);
3702
3703
        return $content;
3704
    }
3705
3706
    /**
3707
     * Test for the findContent() method.
3708
     *
3709
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3710
     */
3711
    public function testUserMetadataGroupHorizontalFilterContent($queryType = null)
3712
    {
3713
        if ($queryType === null) {
3714
            $queryType = 'filter';
3715
        }
3716
3717
        $repository = $this->getRepository();
3718
        $searchService = $repository->getSearchService();
3719
        $editorsUserGroupId = 13;
3720
3721
        $content = $this->createContentForTestUserMetadataGroupHorizontal();
3722
3723
        $criteria = array();
3724
        $setupFactory = $this->getSetupFactory();
3725
3726
        // Do not limit for LSE, as it does not not require reindexing.
3727
        // See explanation below.
3728
        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...
3729
            $criteria[] = new Criterion\ContentTypeIdentifier('folder');
3730
        }
3731
3732
        $criteria[] = new Criterion\UserMetadata(
3733
            Criterion\UserMetadata::GROUP,
3734
            Criterion\Operator::EQ,
3735
            $editorsUserGroupId
3736
        );
3737
3738
        $query = new Query(
3739
            array(
3740
                $queryType => new Criterion\LogicalAnd($criteria),
3741
                'sortClauses' => array(
3742
                    new SortClause\ContentId(),
3743
                ),
3744
                'limit' => 50,
3745
            )
3746
        );
3747
3748
        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...
3749
            $result = $searchService->findContent($query);
3750
3751
            // Administrator User is owned by itself, when additional Locations are added
3752
            // it should be reindexed and its UserGroups will updated, which means it should
3753
            // also be found as a Content of Editors UserGroup. However we do not handle this
3754
            // in slots yet, and also miss SPI methods to do it without using Search (also
3755
            // needed to decouple services), because as indexing is asynchronous Search
3756
            // should not eat its own dog food for reindexing.
3757
            $this->assertEquals(1, $result->totalCount);
3758
3759
            $this->assertEquals(
3760
                $content->id,
3761
                $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...
3762
            );
3763
        } else {
3764
            // This is how it should eventually work for all search engines,
3765
            // with required reindexing slots properly implemented.
3766
3767
            $result = $searchService->findContent($query);
3768
3769
            // Assert last hit manually, as id will change because it is created in test
3770
            // and not present it base fixture.
3771
            $foundContent1 = array_pop($result->searchHits);
3772
            $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...
3773
            $this->assertEquals($content->id, $foundContent1->valueObject->id);
3774
3775
            $this->simplifySearchResult($result);
3776
            $this->assertEquals(
3777
                include $this->getFixtureDir() . '/UserMetadata.php',
3778
                $result,
3779
                'Search results do not match.',
3780
                .1 // Be quite generous regarding delay -- most important for scores
3781
            );
3782
        }
3783
    }
3784
3785
    /**
3786
     * Test for the findContent() method.
3787
     *
3788
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3789
     */
3790
    public function testUserMetadataGroupHorizontalQueryContent()
3791
    {
3792
        $this->testUserMetadataGroupHorizontalFilterContent('query');
3793
    }
3794
3795
    /**
3796
     * Test for the findLocations() method.
3797
     *
3798
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3799
     */
3800
    public function testUserMetadataGroupHorizontalFilterLocation($queryType = null)
3801
    {
3802
        if ($queryType === null) {
3803
            $queryType = 'filter';
3804
        }
3805
3806
        $repository = $this->getRepository();
3807
        $searchService = $repository->getSearchService();
3808
        $editorsUserGroupId = 13;
3809
3810
        $content = $this->createContentForTestUserMetadataGroupHorizontal();
3811
3812
        $criteria = array();
3813
        $setupFactory = $this->getSetupFactory();
3814
3815
        // Do not limit for LSE, as it does not not require reindexing.
3816
        // See explanation below.
3817
        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...
3818
            $criteria[] = new Criterion\ContentTypeIdentifier('folder');
3819
        }
3820
3821
        $criteria[] = new Criterion\UserMetadata(
3822
            Criterion\UserMetadata::GROUP,
3823
            Criterion\Operator::EQ,
3824
            $editorsUserGroupId
3825
        );
3826
3827
        $query = new LocationQuery(
3828
            array(
3829
                $queryType => new Criterion\LogicalAnd($criteria),
3830
                'sortClauses' => array(
3831
                    new SortClause\Location\Id(),
3832
                ),
3833
                'limit' => 50,
3834
            )
3835
        );
3836
3837
        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...
3838
            $result = $searchService->findLocations($query);
3839
3840
            // Administrator User is owned by itself, when additional Locations are added
3841
            // it should be reindexed and its UserGroups will updated, which means it should
3842
            // also be found as a Content of Editors UserGroup. However we do not handle this
3843
            // in slots yet, and also miss SPI methods to do it without using Search (also
3844
            // needed to decouple services), because as indexing is asynchronous Search
3845
            // should not eat its own dog food for reindexing.
3846
            $this->assertEquals(1, $result->totalCount);
3847
3848
            $this->assertEquals(
3849
                $content->contentInfo->mainLocationId,
3850
                $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...
3851
            );
3852
        } else {
3853
            // This is how it should eventually work for all search engines,
3854
            // with required reindexing slots properly implemented.
3855
3856
            $result = $searchService->findLocations($query);
3857
3858
            // Assert last two hits manually, as ids will change because they are created
3859
            // in test and not present in base fixture.
3860
            $foundLocation1 = array_pop($result->searchHits);
3861
            $foundLocation2 = array_pop($result->searchHits);
3862
            // Remove additional Administrators UserGroup Location
3863
            array_pop($result->searchHits);
3864
            $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...
3865
            $this->assertEquals(
3866
                $content->versionInfo->contentInfo->mainLocationId,
3867
                $foundLocation1->valueObject->id
3868
            );
3869
            $this->assertEquals(
3870
                $repository->getCurrentUser()->id,
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...itory::getCurrentUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::getCurrentUserReference() instead. Get current user. Loads the full user object if not already loaded, if you only need to know user id use {@see getCurrentUserReference()}

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

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

Loading history...
3871
                $foundLocation2->valueObject->contentId
3872
            );
3873
3874
            $this->simplifySearchResult($result);
3875
            $this->assertEquals(
3876
                include $this->getFixtureDir() . '/UserMetadataLocation.php',
3877
                $result,
3878
                'Search results do not match.',
3879
                .1 // Be quite generous regarding delay -- most important for scores
3880
            );
3881
        }
3882
    }
3883
3884
    /**
3885
     * Test for the findLocations() method.
3886
     *
3887
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3888
     */
3889
    public function testUserMetadataGroupHorizontalQueryLocation()
3890
    {
3891
        $this->testUserMetadataGroupHorizontalFilterLocation('query');
3892
    }
3893
3894
    /**
3895
     * Test for FullText on the findContent() method.
3896
     *
3897
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3898
     */
3899
    public function testFullTextOnNewContent()
3900
    {
3901
        $repository = $this->getRepository();
3902
        $contentService = $repository->getContentService();
3903
        $contentTypeService = $repository->getContentTypeService();
3904
        $locationService = $repository->getLocationService();
3905
        $searchService = $repository->getSearchService();
3906
3907
        $contentCreateStruct = $contentService->newContentCreateStruct(
3908
            $contentTypeService->loadContentTypeByIdentifier('folder'),
3909
            'eng-GB'
3910
        );
3911
3912
        $contentCreateStruct->setField('name', 'foxes');
3913
3914
        $englishContent = $contentService->publishVersion(
3915
            $contentService->createContent(
3916
                $contentCreateStruct,
3917
                array($locationService->newLocationCreateStruct(2))
3918
            )->versionInfo
3919
        );
3920
3921
        $this->refreshSearch($repository);
3922
3923
        $query = new Query(
3924
            array(
3925
                'query' => new Criterion\FullText('foxes'),
3926
            )
3927
        );
3928
3929
        $searchResult = $searchService->findContentInfo($query);
3930
3931
        $this->assertEquals(1, $searchResult->totalCount);
3932
        $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...
3933
    }
3934
3935
    /**
3936
     * Test for the findContent() method.
3937
     *
3938
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3939
     */
3940
    public function testLanguageAnalysisSeparateContent()
3941
    {
3942
        $setupFactory = $this->getSetupFactory();
3943
        if (!$setupFactory instanceof LegacyElasticsearch) {
3944
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
3945
        }
3946
3947
        $repository = $this->getRepository();
3948
        $contentService = $repository->getContentService();
3949
        $contentTypeService = $repository->getContentTypeService();
3950
        $locationService = $repository->getLocationService();
3951
        $searchService = $repository->getSearchService();
3952
        $languageService = $repository->getContentLanguageService();
3953
3954
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
3955
        $languageCreateStruct->languageCode = 'rus-RU';
3956
        $languageCreateStruct->name = 'Russian';
3957
3958
        $languageService->createLanguage($languageCreateStruct);
3959
3960
        $contentCreateStruct = $contentService->newContentCreateStruct(
3961
            $contentTypeService->loadContentTypeByIdentifier('folder'),
3962
            'eng-GB'
3963
        );
3964
3965
        $contentCreateStruct->setField('name', 'foxes');
3966
3967
        $englishContent = $contentService->publishVersion(
3968
            $contentService->createContent(
3969
                $contentCreateStruct,
3970
                array($locationService->newLocationCreateStruct(2))
3971
            )->versionInfo
3972
        );
3973
3974
        $contentCreateStruct = $contentService->newContentCreateStruct(
3975
            $contentTypeService->loadContentTypeByIdentifier('folder'),
3976
            'rus-RU'
3977
        );
3978
3979
        $contentCreateStruct->setField('name', 'foxes');
3980
3981
        $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...
3982
            $contentService->createContent(
3983
                $contentCreateStruct,
3984
                array($locationService->newLocationCreateStruct(2))
3985
            )->versionInfo
3986
        );
3987
3988
        // Only Content in English should be found, because Content in Russian
3989
        // will not be correctly stemmed
3990
        $query = new Query(
3991
            array(
3992
                'query' => new Criterion\FullText('foxing'),
3993
            )
3994
        );
3995
3996
        $searchResult = $searchService->findContent($query);
3997
3998
        $this->assertEquals(1, $searchResult->totalCount);
3999
        $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...
4000
    }
4001
4002
    /**
4003
     * Test for the findContent() method.
4004
     *
4005
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4006
     */
4007
    public function testLanguageAnalysisSameContent()
4008
    {
4009
        $setupFactory = $this->getSetupFactory();
4010
        if (!$setupFactory instanceof LegacyElasticsearch) {
4011
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4012
        }
4013
4014
        $repository = $this->getRepository();
4015
        $contentService = $repository->getContentService();
4016
        $contentTypeService = $repository->getContentTypeService();
4017
        $locationService = $repository->getLocationService();
4018
        $searchService = $repository->getSearchService();
4019
        $languageService = $repository->getContentLanguageService();
4020
4021
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4022
        $languageCreateStruct->languageCode = 'rus-RU';
4023
        $languageCreateStruct->name = 'Russian';
4024
4025
        $languageService->createLanguage($languageCreateStruct);
4026
4027
        $contentCreateStruct = $contentService->newContentCreateStruct(
4028
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4029
            'eng-GB'
4030
        );
4031
4032
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'eng-GB');
4033
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'rus-RU');
4034
4035
        $mixedContent = $contentService->publishVersion(
4036
            $contentService->createContent(
4037
                $contentCreateStruct,
4038
                array($locationService->newLocationCreateStruct(2))
4039
            )->versionInfo
4040
        );
4041
4042
        // Content will be found because translation in Russian will be correctly stemmed
4043
        $query = new Query(
4044
            array(
4045
                'query' => new Criterion\FullText('важнее'),
4046
            )
4047
        );
4048
4049
        $searchResult = $searchService->findContent($query);
4050
4051
        $this->assertEquals(1, $searchResult->totalCount);
4052
        $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...
4053
    }
4054
4055
    /**
4056
     * Test for the findContent() method.
4057
     *
4058
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4059
     */
4060
    public function testLanguageAnalysisSameContentNotFound()
4061
    {
4062
        $setupFactory = $this->getSetupFactory();
4063
        if (!$setupFactory instanceof LegacyElasticsearch) {
4064
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4065
        }
4066
4067
        $repository = $this->getRepository();
4068
        $contentService = $repository->getContentService();
4069
        $contentTypeService = $repository->getContentTypeService();
4070
        $locationService = $repository->getLocationService();
4071
        $searchService = $repository->getSearchService();
4072
        $languageService = $repository->getContentLanguageService();
4073
4074
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4075
        $languageCreateStruct->languageCode = 'rus-RU';
4076
        $languageCreateStruct->name = 'Russian';
4077
4078
        $languageService->createLanguage($languageCreateStruct);
4079
4080
        $contentCreateStruct = $contentService->newContentCreateStruct(
4081
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4082
            'eng-GB'
4083
        );
4084
4085
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'eng-GB');
4086
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'rus-RU');
4087
4088
        $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...
4089
            $contentService->createContent(
4090
                $contentCreateStruct,
4091
                array($locationService->newLocationCreateStruct(2))
4092
            )->versionInfo
4093
        );
4094
4095
        // Content should be found because translation in Russian will be correctly stemmed
4096
        $query = new Query(
4097
            array(
4098
                'query' => new Criterion\FullText('важнее'),
4099
            )
4100
        );
4101
4102
        // Filtering fields for only English will cause no match because the term will
4103
        // not be correctly stemmed
4104
        $searchResult = $searchService->findContent($query, array('languages' => array('eng-GB')));
4105
4106
        $this->assertEquals(0, $searchResult->totalCount);
4107
    }
4108
4109
    /**
4110
     * Test for the findContent() method searching for content filtered by languages.
4111
     *
4112
     * @covers \eZ\Publish\Core\Repository\SearchService::findContent
4113
     */
4114
    public function testFindContentWithLanguageFilter()
4115
    {
4116
        $repository = $this->getRepository();
4117
        $searchService = $repository->getSearchService();
4118
4119
        $query = new Query(
4120
            [
4121
                'filter' => new Criterion\ContentId([4]),
4122
                'offset' => 0,
4123
            ]
4124
        );
4125
        $searchResult = $searchService->findContent(
4126
            $query,
4127
            ['languages' => ['eng-US']],
4128
            false
4129
        );
4130
        /* END: Use Case */
4131
4132
        $this->assertInstanceOf(
4133
            SearchResult::class,
4134
            $searchResult
4135
        );
4136
4137
        $this->assertEquals(1, $searchResult->totalCount);
4138
        $this->assertCount($searchResult->totalCount, $searchResult->searchHits);
4139
        foreach ($searchResult->searchHits as $searchHit) {
4140
            $this->assertInstanceOf(
4141
                SearchHit::class,
4142
                $searchHit
4143
            );
4144
        }
4145
    }
4146
4147
    /**
4148
     * This test prepares data for other tests.
4149
     *
4150
     * @see testFulltextContentSearchComplex
4151
     * @see testFulltextLocationSearchComplex
4152
     *
4153
     * @return array
4154
     */
4155
    public function testFulltextComplex()
4156
    {
4157
        $repository = $this->getRepository();
4158
        $contentService = $repository->getContentService();
4159
        $contentTypeService = $repository->getContentTypeService();
4160
        $locationService = $repository->getLocationService();
4161
4162
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
4163
        $contentCreateStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
4164
4165
        $contentCreateStruct->setField('name', 'red');
4166
        $contentCreateStruct->setField('short_name', 'red apple');
4167
        $content1 = $contentService->publishVersion(
4168
            $contentService->createContent(
4169
                $contentCreateStruct,
4170
                [$locationService->newLocationCreateStruct(2)]
4171
            )->versionInfo
4172
        );
4173
4174
        $contentCreateStruct->setField('name', 'apple');
4175
        $contentCreateStruct->setField('short_name', 'two');
4176
        $content2 = $contentService->publishVersion(
4177
            $contentService->createContent(
4178
                $contentCreateStruct,
4179
                [$locationService->newLocationCreateStruct(2)]
4180
            )->versionInfo
4181
        );
4182
4183
        $contentCreateStruct->setField('name', 'red apple');
4184
        $contentCreateStruct->setField('short_name', 'three');
4185
        $content3 = $contentService->publishVersion(
4186
            $contentService->createContent(
4187
                $contentCreateStruct,
4188
                [$locationService->newLocationCreateStruct(2)]
4189
            )->versionInfo
4190
        );
4191
4192
        $this->refreshSearch($repository);
4193
4194
        $criterion = new Criterion\FullText(
4195
            'red apple',
4196
            [
4197
                'boost' => [
4198
                    'short_name' => 2,
4199
                ],
4200
                'fuzziness' => .1,
4201
            ]
4202
        );
4203
4204
        return [$criterion, $content1, $content2, $content3];
4205
    }
4206
4207
    /**
4208
     * Test for the findContent() method.
4209
     *
4210
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4211
     * @depends testFulltextComplex
4212
     *
4213
     * @param array $data
4214
     */
4215
    public function testFulltextContentSearchComplex(array $data)
4216
    {
4217
        // Do not initialize from scratch
4218
        $repository = $this->getRepository(false);
4219
        $searchService = $repository->getSearchService();
4220
        list($criterion, $content1, $content2, $content3) = $data;
4221
4222
        $searchResult = $searchService->findContent(
4223
            new Query(['query' => $criterion]),
4224
            ['languages' => ['eng-GB']]
4225
        );
4226
        $searchHits = $searchResult->searchHits;
4227
4228
        $this->assertEquals(3, $searchResult->totalCount);
4229
4230
        // Legacy search engine does have scoring, sorting the results by ID in that case
4231
        $setupFactory = $this->getSetupFactory();
4232 View Code Duplication
        if (get_class($setupFactory) === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
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...
4233
            usort(
4234
                $searchHits,
4235
                function ($a, $b) {
4236
                    return ($a->valueObject->id < $b->valueObject->id) ? -1 : 1;
4237
                }
4238
            );
4239
4240
            $this->assertEquals($content1->id, $searchHits[0]->valueObject->id);
4241
            $this->assertEquals($content2->id, $searchHits[1]->valueObject->id);
4242
            $this->assertEquals($content3->id, $searchHits[2]->valueObject->id);
4243
4244
            return;
4245
        }
4246
4247
        // Assert scores are descending
4248
        $this->assertGreaterThan($searchHits[1]->score, $searchHits[0]->score);
4249
        $this->assertGreaterThan($searchHits[2]->score, $searchHits[1]->score);
4250
4251
        // Assert order
4252
        $this->assertEquals($content1->id, $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...
4253
        $this->assertEquals($content3->id, $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...
4254
        $this->assertEquals($content2->id, $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...
4255
    }
4256
4257
    /**
4258
     * Test for the findLocations() method.
4259
     *
4260
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
4261
     * @depends testFulltextComplex
4262
     *
4263
     * @param array $data
4264
     */
4265
    public function testFulltextLocationSearchComplex(array $data)
4266
    {
4267
        $setupFactory = $this->getSetupFactory();
4268
        if ($setupFactory instanceof LegacyElasticsearch) {
4269
            $this->markTestIncomplete(
4270
                'Fulltext criterion is not supported with Location search in Elasticsearch engine'
4271
            );
4272
        }
4273
4274
        if ($setupFactory instanceof LegacySolrSetupFactory && getenv('SOLR_VERSION') === '4.10.4') {
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...
4275
            $this->markTestSkipped('Skipping location search score test on Solr 4.10, you need Solr 6 for this!');
4276
        }
4277
4278
        // Do not initialize from scratch
4279
        $repository = $this->getRepository(false);
4280
        list($criterion, $content1, $content2, $content3) = $data;
4281
        $searchService = $repository->getSearchService();
4282
4283
        $searchResult = $searchService->findLocations(
4284
            new LocationQuery(['query' => $criterion]),
4285
            ['languages' => ['eng-GB']]
4286
        );
4287
        $searchHits = $searchResult->searchHits;
4288
4289
        $this->assertEquals(3, $searchResult->totalCount);
4290
4291
        // Legacy search engine does have scoring, sorting the results by ID in that case
4292
        $setupFactory = $this->getSetupFactory();
4293 View Code Duplication
        if (get_class($setupFactory) === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
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...
4294
            usort(
4295
                $searchHits,
4296
                function ($a, $b) {
4297
                    return ($a->valueObject->id < $b->valueObject->id) ? -1 : 1;
4298
                }
4299
            );
4300
4301
            $this->assertEquals($content1->id, $searchHits[0]->valueObject->contentId);
4302
            $this->assertEquals($content2->id, $searchHits[1]->valueObject->contentId);
4303
            $this->assertEquals($content3->id, $searchHits[2]->valueObject->contentId);
4304
4305
            return;
4306
        }
4307
4308
        // Assert scores are descending
4309
        $this->assertGreaterThan($searchHits[1]->score, $searchHits[0]->score);
4310
        $this->assertGreaterThan($searchHits[2]->score, $searchHits[1]->score);
4311
4312
        // Assert order
4313
        $this->assertEquals($content1->id, $searchHits[0]->valueObject->contentId);
0 ignored issues
show
Documentation introduced by
The property contentId 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...
4314
        $this->assertEquals($content3->id, $searchHits[1]->valueObject->contentId);
0 ignored issues
show
Documentation introduced by
The property contentId 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...
4315
        $this->assertEquals($content2->id, $searchHits[2]->valueObject->contentId);
0 ignored issues
show
Documentation introduced by
The property contentId 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...
4316
    }
4317
4318
    /**
4319
     * Assert that query result matches the given fixture.
4320
     *
4321
     * @param Query $query
4322
     * @param string $fixture
4323
     * @param null|callable $closure
4324
     * @param bool $info
4325
     * @param bool $id
4326
     */
4327
    protected function assertQueryFixture(Query $query, $fixture, $closure = null, $ignoreScore = true, $info = false, $id = true)
4328
    {
4329
        $repository = $this->getRepository();
4330
        $searchService = $repository->getSearchService();
4331
4332
        try {
4333
            if ($query instanceof LocationQuery) {
4334
                $setupFactory = $this->getSetupFactory();
4335
                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...
4336
                    // @todo When we want to test score again by default we will need fixtures for Solr
4337
                }
4338
4339
                if ($setupFactory instanceof LegacyElasticsearch) {
4340
                    $position = strrpos($fixture, '/');
4341
                    $fixture = substr_replace($fixture, '/Location', $position, 0);
4342
                }
4343
4344
                $result = $searchService->findLocations($query);
4345
            } elseif ($query instanceof Query) {
4346
                if ($info) {
4347
                    $result = $searchService->findContentInfo($query);
4348
                } else {
4349
                    $result = $searchService->findContent($query);
4350
                }
4351
            } else {
4352
                $this->fail('Expected instance of LocationQuery or Query, got: ' . gettype($query));
4353
            }
4354
            $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...
4355
        } catch (NotImplementedException $e) {
4356
            $this->markTestSkipped(
4357
                'This feature is not supported by the current search backend: ' . $e->getMessage()
4358
            );
4359
        }
4360
4361 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...
4362
            if (isset($_ENV['ez_tests_record'])) {
4363
                file_put_contents(
4364
                    $record = $fixture . '.recording',
4365
                    "<?php\n\nreturn " . var_export($result, true) . ";\n\n"
4366
                );
4367
                $this->markTestIncomplete("No fixture available. Result recorded at $record. Result: \n" . $this->printResult($result));
4368
            } else {
4369
                $this->markTestIncomplete("No fixture available. Set \$_ENV['ez_tests_record'] to generate:\n " . $fixture);
4370
            }
4371
        }
4372
4373
        $fixture = include $fixture;
4374
4375
        if ($closure !== null) {
4376
            $closure($fixture);
4377
            $closure($result);
4378
        }
4379
4380 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...
4381
            foreach (array($fixture, $result) as $set) {
4382
                $property = new \ReflectionProperty(get_class($set), 'maxScore');
4383
                $property->setAccessible(true);
4384
                $property->setValue($set, 0.0);
4385
4386
                foreach ($set->searchHits as $hit) {
4387
                    $property = new \ReflectionProperty(get_class($hit), 'score');
4388
                    $property->setAccessible(true);
4389
                    $property->setValue($hit, 0.0);
4390
                }
4391
            }
4392
        }
4393
4394
        foreach (array($fixture, $result) as $set) {
4395
            foreach ($set->searchHits as $hit) {
4396
                $property = new \ReflectionProperty(get_class($hit), 'index');
4397
                $property->setAccessible(true);
4398
                $property->setValue($hit, null);
4399
4400
                $property = new \ReflectionProperty(get_class($hit), 'matchedTranslation');
4401
                $property->setAccessible(true);
4402
                $property->setValue($hit, null);
4403
4404
                if (!$id) {
4405
                    $hit->valueObject['id'] = null;
4406
                }
4407
            }
4408
        }
4409
4410
        $this->assertEquals(
4411
            $fixture,
4412
            $result,
4413
            'Search results do not match.',
4414
            .99 // Be quite generous regarding delay -- most important for scores
4415
        );
4416
    }
4417
4418
    /**
4419
     * Show a simplified view of the search result for manual introspection.
4420
     *
4421
     * @param SearchResult $result
4422
     *
4423
     * @return string
4424
     */
4425 View Code Duplication
    protected function printResult(SearchResult $result)
4426
    {
4427
        $printed = '';
4428
        foreach ($result->searchHits as $hit) {
4429
            $printed .= sprintf(" - %s (%s)\n", $hit->valueObject['title'], $hit->valueObject['id']);
4430
        }
4431
4432
        return $printed;
4433
    }
4434
4435
    /**
4436
     * Simplify search result.
4437
     *
4438
     * This leads to saner comparisons of results, since we do not get the full
4439
     * content objects every time.
4440
     *
4441
     * @param SearchResult $result
4442
     */
4443
    protected function simplifySearchResult(SearchResult $result)
4444
    {
4445
        $result->time = 1;
4446
4447
        foreach ($result->searchHits as $hit) {
4448
            switch (true) {
4449
                case $hit->valueObject instanceof Content:
4450 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...
4451
                    $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...
4452
                        'id' => $hit->valueObject->contentInfo->id,
4453
                        'title' => $hit->valueObject->contentInfo->name,
4454
                    );
4455
                    break;
4456
4457
                case $hit->valueObject instanceof ContentInfo:
4458
                    $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...
4459
                        'id' => $hit->valueObject->id,
4460
                        'title' => $hit->valueObject->name,
4461
                    );
4462
                    break;
4463
4464
                default:
4465
                    throw new \RuntimeException('Unknown search result hit type: ' . get_class($hit->valueObject));
4466
            }
4467
        }
4468
    }
4469
4470
    /**
4471
     * Get fixture directory.
4472
     *
4473
     * @return string
4474
     */
4475
    protected function getFixtureDir()
4476
    {
4477
        return __DIR__ . '/_fixtures/' . getenv('fixtureDir') . '/';
4478
    }
4479
4480
    /**
4481
     * For findContentInfo tests, to reuse fixtures for findContent tests.
4482
     *
4483
     * @param null|callable $closure
4484
     *
4485
     * @return callable
4486
     */
4487
    private function getContentInfoFixtureClosure($closure = null)
4488
    {
4489
        /** @var $data \eZ\Publish\API\Repository\Values\Content\Search\SearchResult */
4490
        return function (&$data) use ($closure) {
4491
            foreach ($data->searchHits as $searchHit) {
4492
                if ($searchHit->valueObject instanceof Content) {
4493
                    $searchHit->valueObject = $searchHit->valueObject->getVersionInfo()->getContentInfo();
4494
                }
4495
            }
4496
4497
            if (isset($closure)) {
4498
                $closure($data);
4499
            }
4500
        };
4501
    }
4502
}
4503