Completed
Push — master ( 153208...2bf973 )
by André
38:13 queued 14:43
created

SearchServiceTest::getSortedLocationSearches()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 72
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 72
rs 9.102
cc 2
eloc 49
nc 1
nop 0

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

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

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
553
                            '/1/5/44/',
554
                            '/1/5/44/45/',
555
                        )
556
                    ),
557
                    'sortClauses' => array(
558
                        new SortClause\ContentId(),
559
                    ),
560
                    'limit' => 50,
561
                ),
562
                $fixtureDir . 'AncestorContent.php',
563
            ),
564
        );
565
    }
566
567
    public function getContentQuerySearches()
568
    {
569
        $fixtureDir = $this->getFixtureDir();
570
571
        return array(
572
            array(
573
                array(
574
                    'filter' => new Criterion\ContentId(
575
                        array(58, 10)
576
                    ),
577
                    'query' => new Criterion\FullText('contact'),
578
                    'sortClauses' => array(new SortClause\ContentId()),
579
                ),
580
                $fixtureDir . 'FullTextFiltered.php',
581
            ),
582
            array(
583
                array(
584
                    'query' => new Criterion\FullText(
585
                        'contact',
586
                        array(
587
                            'boost' => array(
588
                                'title' => 2,
589
                            ),
590
                            'fuzziness' => .5,
591
                        )
592
                    ),
593
                    'sortClauses' => array(new SortClause\ContentId()),
594
                ),
595
                $fixtureDir . 'FullText.php',
596
            ),
597
            array(
598
                array(
599
                    'query' => new Criterion\FullText(
600
                        'Contact*'
601
                    ),
602
                    'sortClauses' => array(new SortClause\ContentId()),
603
                ),
604
                $fixtureDir . 'FullTextWildcard.php',
605
            ),
606
            array(
607
                array(
608
                    'query' => new Criterion\LanguageCode('eng-GB', false),
609
                    'sortClauses' => array(new SortClause\ContentId()),
610
                ),
611
                $fixtureDir . 'LanguageCode.php',
612
            ),
613
            array(
614
                array(
615
                    'query' => new Criterion\LanguageCode(array('eng-US', 'eng-GB')),
616
                    'offset' => 10,
617
                    'sortClauses' => array(new SortClause\ContentId()),
618
                ),
619
                $fixtureDir . 'LanguageCodeIn.php',
620
            ),
621
            array(
622
                array(
623
                    'query' => new Criterion\LanguageCode('eng-GB'),
624
                    'offset' => 10,
625
                    'sortClauses' => array(new SortClause\ContentId()),
626
                ),
627
                $fixtureDir . 'LanguageCodeAlwaysAvailable.php',
628
            ),
629
            array(
630
                array(
631
                    'query' => new Criterion\Visibility(
632
                        Criterion\Visibility::VISIBLE
633
                    ),
634
                    'sortClauses' => array(new SortClause\ContentId()),
635
                    'limit' => 50,
636
                ),
637
                $fixtureDir . 'Visibility.php',
638
            ),
639
        );
640
    }
641
642
    public function getLocationQuerySearches()
643
    {
644
        $fixtureDir = $this->getFixtureDir();
645
646
        return array(
647
            array(
648
                array(
649
                    'query' => new Criterion\Location\Depth(Criterion\Operator::EQ, 1),
650
                    'sortClauses' => array(new SortClause\ContentId()),
651
                ),
652
                $fixtureDir . 'Depth.php',
653
            ),
654
            array(
655
                array(
656
                    'query' => new Criterion\Location\Depth(Criterion\Operator::IN, array(1, 3)),
657
                    'sortClauses' => array(new SortClause\ContentId()),
658
                ),
659
                $fixtureDir . 'DepthIn.php',
660
            ),
661
            array(
662
                array(
663
                    'query' => new Criterion\Location\Depth(Criterion\Operator::GT, 2),
664
                    'sortClauses' => array(new SortClause\ContentId()),
665
                ),
666
                $fixtureDir . 'DepthGt.php',
667
            ),
668
            array(
669
                array(
670
                    'query' => new Criterion\Location\Depth(Criterion\Operator::GTE, 2),
671
                    'sortClauses' => array(new SortClause\ContentId()),
672
                    'limit' => 50,
673
                ),
674
                $fixtureDir . 'DepthGte.php',
675
            ),
676
            array(
677
                array(
678
                    'query' => new Criterion\Location\Depth(Criterion\Operator::LT, 2),
679
                    'sortClauses' => array(new SortClause\ContentId()),
680
                ),
681
                $fixtureDir . 'Depth.php',
682
            ),
683
            array(
684
                array(
685
                    'query' => new Criterion\Location\Depth(Criterion\Operator::LTE, 2),
686
                    'sortClauses' => array(new SortClause\ContentId()),
687
                    'limit' => 50,
688
                ),
689
                $fixtureDir . 'DepthLte.php',
690
            ),
691
            array(
692
                array(
693
                    'query' => new Criterion\Location\Depth(Criterion\Operator::BETWEEN, array(1, 2)),
694
                    'sortClauses' => array(new SortClause\ContentId()),
695
                    'limit' => 50,
696
                ),
697
                $fixtureDir . 'DepthLte.php',
698
            ),
699
            array(
700
                array(
701
                    'filter' => new Criterion\Ancestor('/1/5/44/45/'),
702
                    'sortClauses' => array(
703
                        new SortClause\Location\Depth(),
704
                    ),
705
                    'limit' => 50,
706
                ),
707
                $fixtureDir . 'AncestorLocation.php',
708
            ),
709
        );
710
    }
711
712
    /**
713
     * Test for the findContent() method.
714
     *
715
     * @dataProvider getFilterContentSearches
716
     *
717
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
718
     */
719
    public function testFindContentFiltered($queryData, $fixture, $closure = null)
720
    {
721
        $query = new Query($queryData);
722
        $this->assertQueryFixture($query, $fixture, $closure);
723
    }
724
725
    /**
726
     * Test for the findContentInfo() method.
727
     *
728
     * @dataProvider getFilterContentSearches
729
     * @see \eZ\Publish\API\Repository\SearchService::findContentInfo()
730
     */
731
    public function testFindContentInfoFiltered($queryData, $fixture, $closure = null)
732
    {
733
        $query = new Query($queryData);
734
        $this->assertQueryFixture($query, $fixture, $this->getContentInfoFixtureClosure($closure), true);
735
    }
736
737
    /**
738
     * Test for the findLocations() method.
739
     *
740
     * @dataProvider getFilterContentSearches
741
     *
742
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
743
     */
744
    public function testFindLocationsContentFiltered($queryData, $fixture, $closure = null)
745
    {
746
        $query = new LocationQuery($queryData);
747
        $this->assertQueryFixture($query, $fixture, $closure);
748
    }
749
750
    /**
751
     * Test for deprecated $criterion property on query object.
752
     *
753
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
754
     * @deprecated
755
     */
756
    public function testDeprecatedCriteriaProperty()
757
    {
758
        $this->assertQueryFixture(
759
            new Query(
760
                array(
761
                    'query' => new Criterion\ContentId(
762
                        array(1, 4, 10)
763
                    ),
764
                    'sortClauses' => array(new SortClause\ContentId()),
765
                )
766
            ),
767
            $this->getFixtureDir() . 'DeprecatedContentIdQuery.php'
768
        );
769
    }
770
771
    /**
772
     * Test for the findContent() method.
773
     *
774
     * @dataProvider getContentQuerySearches
775
     *
776
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
777
     */
778
    public function testQueryContent($queryData, $fixture, $closure = null)
779
    {
780
        $query = new Query($queryData);
781
        $this->assertQueryFixture($query, $fixture, $closure);
782
    }
783
784
    /**
785
     * Test for the findContentInfo() method.
786
     *
787
     * @dataProvider getContentQuerySearches
788
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
789
     */
790
    public function testQueryContentInfo($queryData, $fixture, $closure = null)
791
    {
792
        $query = new Query($queryData);
793
        $this->assertQueryFixture($query, $fixture, $this->getContentInfoFixtureClosure($closure), true);
794
    }
795
796
    /**
797
     * Test for the findLocations() method.
798
     *
799
     * @dataProvider getContentQuerySearches
800
     *
801
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
802
     */
803
    public function testQueryContentLocations($queryData, $fixture, $closure = null)
804
    {
805
        $query = new LocationQuery($queryData);
806
        $this->assertQueryFixture($query, $fixture, $closure);
807
    }
808
809
    /**
810
     * Test for the findLocations() method.
811
     *
812
     * @dataProvider getLocationQuerySearches
813
     *
814
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
815
     */
816
    public function testQueryLocations($queryData, $fixture, $closure = null)
817
    {
818
        $query = new LocationQuery($queryData);
819
        $this->assertQueryFixture($query, $fixture, $closure);
820
    }
821
822
    public function getCaseInsensitiveSearches()
823
    {
824
        return array(
825
            array(
826
                array(
827
                    'filter' => new Criterion\Field(
828
                        'name',
829
                        Criterion\Operator::EQ,
830
                        'Members'
831
                    ),
832
                    'sortClauses' => array(new SortClause\ContentId()),
833
                ),
834
            ),
835
            array(
836
                array(
837
                    'filter' => new Criterion\Field(
838
                        'name',
839
                        Criterion\Operator::EQ,
840
                        'members'
841
                    ),
842
                    'sortClauses' => array(new SortClause\ContentId()),
843
                ),
844
            ),
845
            array(
846
                array(
847
                    'filter' => new Criterion\Field(
848
                        'name',
849
                        Criterion\Operator::EQ,
850
                        'MEMBERS'
851
                    ),
852
                    'sortClauses' => array(new SortClause\ContentId()),
853
                ),
854
            ),
855
        );
856
    }
857
858
    /**
859
     * Test for the findContent() method.
860
     *
861
     * @dataProvider getCaseInsensitiveSearches
862
     *
863
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
864
     */
865
    public function testFindContentFieldFiltersCaseSensitivity($queryData)
866
    {
867
        $query = new Query($queryData);
868
        $this->assertQueryFixture(
869
            $query,
870
            $this->getFixtureDir() . 'Field.php'
871
        );
872
    }
873
874
    /**
875
     * Test for the findLocations() method.
876
     *
877
     * @dataProvider getCaseInsensitiveSearches
878
     *
879
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
880
     */
881
    public function testFindLocationsFieldFiltersCaseSensitivity($queryData)
882
    {
883
        $query = new LocationQuery($queryData);
884
        $this->assertQueryFixture(
885
            $query,
886
            $this->getFixtureDir() . 'Field.php'
887
        );
888
    }
889
890 View Code Duplication
    public function testFindSingle()
891
    {
892
        $repository = $this->getRepository();
893
        $searchService = $repository->getSearchService();
894
895
        $content = $searchService->findSingle(
896
            new Criterion\ContentId(
897
                array(4)
898
            )
899
        );
900
901
        $this->assertEquals(
902
            4,
903
            $content->id
904
        );
905
    }
906
907 View Code Duplication
    public function testFindNoPerformCount()
908
    {
909
        $repository = $this->getRepository();
910
        $searchService = $repository->getSearchService();
911
912
        $query = new Query();
913
        $query->performCount = false;
914
        $query->query = new Criterion\ContentTypeId(
915
            array(4)
916
        );
917
918
        $searchHit = $searchService->findContent($query);
919
920
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
921
            $this->assertEquals(
922
                null,
923
                $searchHit->totalCount
924
            );
925
        } else {
926
            $this->assertEquals(
927
                2,
928
                $searchHit->totalCount
929
            );
930
        }
931
    }
932
933
    /**
934
     * @expectedException \RuntimeException
935
     */
936 View Code Duplication
    public function testFindNoPerformCountException()
937
    {
938
        if (ltrim(get_class($this->getSetupFactory()), '\\') !== 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
939
            $this->markTestSkipped('Only applicable to Legacy/DB based search');
940
        }
941
942
        $repository = $this->getRepository();
943
        $searchService = $repository->getSearchService();
944
945
        $query = new Query();
946
        $query->performCount = false;
947
        $query->limit = 0;
948
        $query->query = new Criterion\ContentTypeId(
949
            array(4)
950
        );
951
952
        $searchService->findContent($query);
953
    }
954
955 View Code Duplication
    public function testFindLocationsNoPerformCount()
956
    {
957
        $repository = $this->getRepository();
958
        $searchService = $repository->getSearchService();
959
960
        $query = new LocationQuery();
961
        $query->performCount = false;
962
        $query->query = new Criterion\ContentTypeId(
963
            array(4)
964
        );
965
966
        $searchHit = $searchService->findLocations($query);
967
968
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
969
            $this->assertEquals(
970
                null,
971
                $searchHit->totalCount
972
            );
973
        } else {
974
            $this->assertEquals(
975
                2,
976
                $searchHit->totalCount
977
            );
978
        }
979
    }
980
981
    /**
982
     * @expectedException \RuntimeException
983
     */
984 View Code Duplication
    public function testFindLocationsNoPerformCountException()
985
    {
986
        if (ltrim(get_class($this->getSetupFactory()), '\\') !== 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
987
            $this->markTestSkipped('Only applicable to Legacy/DB based search');
988
        }
989
990
        $repository = $this->getRepository();
991
        $searchService = $repository->getSearchService();
992
993
        $query = new LocationQuery();
994
        $query->performCount = false;
995
        $query->limit = 0;
996
        $query->query = new Criterion\ContentTypeId(
997
            array(4)
998
        );
999
1000
        $searchService->findLocations($query);
1001
    }
1002
1003
    /**
1004
     * Create test Content with ezcountry field having multiple countries selected.
1005
     *
1006
     * @return Content
1007
     */
1008
    protected function createMultipleCountriesContent()
1009
    {
1010
        $repository = $this->getRepository();
1011
        $contentTypeService = $repository->getContentTypeService();
1012
        $contentService = $repository->getContentService();
1013
1014
        $createStruct = $contentTypeService->newContentTypeCreateStruct('countries-multiple');
1015
        $createStruct->mainLanguageCode = 'eng-GB';
1016
        $createStruct->remoteId = 'countries-multiple-123';
1017
        $createStruct->names = array('eng-GB' => 'Multiple countries');
1018
        $createStruct->creatorId = 14;
1019
        $createStruct->creationDate = new \DateTime();
1020
1021
        $fieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('countries', 'ezcountry');
1022
        $fieldCreate->names = array('eng-GB' => 'Countries');
1023
        $fieldCreate->fieldGroup = 'main';
1024
        $fieldCreate->position = 1;
1025
        $fieldCreate->isTranslatable = false;
1026
        $fieldCreate->isSearchable = true;
1027
        $fieldCreate->fieldSettings = array('isMultiple' => true);
1028
1029
        $createStruct->addFieldDefinition($fieldCreate);
1030
1031
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
1032
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, array($contentGroup));
1033
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
1034
        $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...
1035
1036
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
1037
        $createStruct->remoteId = 'countries-multiple-456';
1038
        $createStruct->alwaysAvailable = false;
1039
        $createStruct->setField(
1040
            'countries',
1041
            array('BE', 'DE', 'FR', 'HR', 'NO', 'PT', 'RU')
1042
        );
1043
1044
        $draft = $contentService->createContent($createStruct);
1045
        $content = $contentService->publishVersion($draft->getVersionInfo());
1046
1047
        $this->refreshSearch($repository);
1048
1049
        return $content;
1050
    }
1051
1052
    /**
1053
     * Test for the findContent() method.
1054
     *
1055
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
1056
     */
1057 View Code Duplication
    public function testFieldCollectionContains()
1058
    {
1059
        $testContent = $this->createMultipleCountriesContent();
1060
1061
        $query = new Query(
1062
            array(
1063
                'query' => new Criterion\Field(
1064
                    'countries',
1065
                    Criterion\Operator::CONTAINS,
1066
                    'Belgium'
1067
                ),
1068
            )
1069
        );
1070
1071
        $repository = $this->getRepository();
1072
        $searchService = $repository->getSearchService();
1073
        $result = $searchService->findContent($query);
1074
1075
        $this->assertEquals(1, $result->totalCount);
1076
        $this->assertEquals(
1077
            $testContent->id,
1078
            $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...
1079
        );
1080
    }
1081
1082
    /**
1083
     * Test for the findContent() method.
1084
     *
1085
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
1086
     * @depends eZ\Publish\API\Repository\Tests\SearchServiceTest::testFieldCollectionContains
1087
     */
1088 View Code Duplication
    public function testFieldCollectionContainsNoMatch()
1089
    {
1090
        $this->createMultipleCountriesContent();
1091
        $query = new Query(
1092
            array(
1093
                'query' => new Criterion\Field(
1094
                    'countries',
1095
                    Criterion\Operator::CONTAINS,
1096
                    'Netherlands Antilles'
1097
                ),
1098
            )
1099
        );
1100
1101
        $repository = $this->getRepository();
1102
        $searchService = $repository->getSearchService();
1103
        $result = $searchService->findContent($query);
1104
1105
        $this->assertEquals(0, $result->totalCount);
1106
    }
1107
1108
    /**
1109
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1110
     * @expectedExceptionMessage Argument '$criterion->target' is invalid: No searchable fields found for the given criterion target 'some_hopefully_unknown_field'
1111
     */
1112 View Code Duplication
    public function testInvalidFieldIdentifierRange()
1113
    {
1114
        $repository = $this->getRepository();
1115
        $searchService = $repository->getSearchService();
1116
1117
        $searchService->findContent(
1118
            new Query(
1119
                array(
1120
                    'filter' => new Criterion\Field(
1121
                        'some_hopefully_unknown_field',
1122
                        Criterion\Operator::BETWEEN,
1123
                        array(10, 1000)
1124
                    ),
1125
                    'sortClauses' => array(new SortClause\ContentId()),
1126
                )
1127
            )
1128
        );
1129
    }
1130
1131
    /**
1132
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1133
     * @expectedExceptionMessage Argument '$criterion->target' is invalid: No searchable fields found for the given criterion target 'some_hopefully_unknown_field'
1134
     */
1135 View Code Duplication
    public function testInvalidFieldIdentifierIn()
1136
    {
1137
        $repository = $this->getRepository();
1138
        $searchService = $repository->getSearchService();
1139
1140
        $searchService->findContent(
1141
            new Query(
1142
                array(
1143
                    'filter' => new Criterion\Field(
1144
                        'some_hopefully_unknown_field',
1145
                        Criterion\Operator::EQ,
1146
                        1000
1147
                    ),
1148
                    'sortClauses' => array(new SortClause\ContentId()),
1149
                )
1150
            )
1151
        );
1152
    }
1153
1154
    /**
1155
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1156
     * @expectedExceptionMessage Argument '$criterion->target' is invalid: No searchable fields found for the given criterion target 'tag_cloud_url'
1157
     */
1158 View Code Duplication
    public function testFindContentWithNonSearchableField()
1159
    {
1160
        $repository = $this->getRepository();
1161
        $searchService = $repository->getSearchService();
1162
1163
        $searchService->findContent(
1164
            new Query(
1165
                array(
1166
                    'filter' => new Criterion\Field(
1167
                        'tag_cloud_url',
1168
                        Criterion\Operator::EQ,
1169
                        'http://nimbus.com'
1170
                    ),
1171
                    'sortClauses' => array(new SortClause\ContentId()),
1172
                )
1173
            )
1174
        );
1175
    }
1176
1177
    /**
1178
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1179
     * @expectedExceptionMessage Argument '$sortClause->targetData' is invalid: No searchable fields found for the given sort clause target 'title' on 'template_look'
1180
     */
1181 View Code Duplication
    public function testSortFieldWithNonSearchableField()
1182
    {
1183
        $repository = $this->getRepository();
1184
        $searchService = $repository->getSearchService();
1185
1186
        $searchService->findContent(
1187
            new Query(
1188
                array(
1189
                    'sortClauses' => array(new SortClause\Field('template_look', 'title')),
1190
                )
1191
            )
1192
        );
1193
    }
1194
1195
    /**
1196
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1197
     * @expectedExceptionMessage Argument '$sortClause->targetData' is invalid: No searchable fields found for the given sort clause target 'title' on 'template_look'
1198
     */
1199 View Code Duplication
    public function testSortMapLocationDistanceWithNonSearchableField()
1200
    {
1201
        $repository = $this->getRepository();
1202
        $searchService = $repository->getSearchService();
1203
1204
        $searchService->findContent(
1205
            new Query(
1206
                array(
1207
                    'sortClauses' => array(
1208
                        new SortClause\MapLocationDistance(
1209
                            'template_look',
1210
                            'title',
1211
                            1,
1212
                            2
1213
                        ),
1214
                    ),
1215
                )
1216
            )
1217
        );
1218
    }
1219
1220
    /**
1221
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1222
     */
1223 View Code Duplication
    public function testFindSingleFailMultiple()
1224
    {
1225
        $repository = $this->getRepository();
1226
        $searchService = $repository->getSearchService();
1227
1228
        $searchService->findSingle(
1229
            new Criterion\ContentId(
1230
                array(4, 10)
1231
            )
1232
        );
1233
    }
1234
1235
    /**
1236
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1237
     */
1238
    public function testFindSingleWithNonSearchableField()
1239
    {
1240
        $repository = $this->getRepository();
1241
        $searchService = $repository->getSearchService();
1242
1243
        $searchService->findSingle(
1244
            new Criterion\Field(
1245
                'tag_cloud_url',
1246
                Criterion\Operator::EQ,
1247
                'http://nimbus.com'
1248
            )
1249
        );
1250
    }
1251
1252
    public function getSortedContentSearches()
1253
    {
1254
        $fixtureDir = $this->getFixtureDir();
1255
1256
        return array(
1257
            0 => array(
1258
                array(
1259
                    'filter' => new Criterion\SectionId(array(2)),
1260
                    'offset' => 0,
1261
                    'limit' => 10,
1262
                    'sortClauses' => array(),
1263
                ),
1264
                $fixtureDir . 'SortNone.php',
1265
                // Result having the same sort level should be sorted between them to be system independent
1266
                function (&$data) {
1267
                    usort(
1268
                        $data->searchHits,
1269
                        function ($a, $b) {
1270
                            return ($a->valueObject['id'] < $b->valueObject['id']) ? -1 : 1;
1271
                        }
1272
                    );
1273
                },
1274
            ),
1275
            1 => array(
1276
                array(
1277
                    'filter' => new Criterion\SectionId(array(2)),
1278
                    'offset' => 0,
1279
                    'limit' => 10,
1280
                    'sortClauses' => array(
1281
                        new SortClause\DatePublished(),
1282
                        new SortClause\ContentId(),
1283
                    ),
1284
                ),
1285
                $fixtureDir . 'SortDatePublished.php',
1286
            ),
1287
            2 => array(
1288
                array(
1289
                    'filter' => new Criterion\SectionId(array(2)),
1290
                    'offset' => 0,
1291
                    'limit' => 50,
1292
                    'sortClauses' => array(
1293
                        new SortClause\DateModified(),
1294
                        new SortClause\ContentId(),
1295
                    ),
1296
                ),
1297
                $fixtureDir . 'SortDateModified.php',
1298
            ),
1299
            3 => array(
1300
                array(
1301
                    'filter' => new Criterion\SectionId(array(4, 2, 6, 3)),
1302
                    'offset' => 0,
1303
                    'limit' => 50,
1304
                    'sortClauses' => array(
1305
                        new SortClause\SectionIdentifier(),
1306
                        new SortClause\ContentId(),
1307
                    ),
1308
                ),
1309
                $fixtureDir . 'SortSectionIdentifier.php',
1310
            ),
1311
            4 => array(
1312
                array(
1313
                    'filter' => new Criterion\SectionId(array(4, 2, 6, 3)),
1314
                    'offset' => 0,
1315
                    'limit' => 50,
1316
                    'sortClauses' => array(
1317
                        new SortClause\SectionName(),
1318
                        new SortClause\ContentId(),
1319
                    ),
1320
                ),
1321
                $fixtureDir . 'SortSectionName.php',
1322
            ),
1323
            5 => array(
1324
                array(
1325
                    'filter' => new Criterion\SectionId(array(2, 3)),
1326
                    'offset' => 0,
1327
                    'limit' => 50,
1328
                    'sortClauses' => array(
1329
                        new SortClause\ContentName(),
1330
                        new SortClause\ContentId(),
1331
                    ),
1332
                ),
1333
                $fixtureDir . 'SortContentName.php',
1334
            ),
1335
            6 => array(
1336
                array(
1337
                    'filter' => new Criterion\ContentTypeId(1),
1338
                    'offset' => 0,
1339
                    'limit' => 50,
1340
                    'sortClauses' => array(
1341
                        new SortClause\Field('folder', 'name', Query::SORT_ASC),
1342
                        new SortClause\ContentId(),
1343
                    ),
1344
                ),
1345
                $fixtureDir . 'SortFolderName.php',
1346
            ),
1347
            7 => array(
1348
                array(
1349
                    'filter' => new Criterion\ContentTypeId(array(1, 3)),
1350
                    'offset' => 0,
1351
                    'limit' => 50,
1352
                    'sortClauses' => array(
1353
                        new SortClause\Field('folder', 'name', Query::SORT_ASC),
1354
                        new SortClause\ContentId(),
1355
                    ),
1356
                ),
1357
                $fixtureDir . 'SortFieldMultipleTypes.php',
1358
            ),
1359
            8 => array(
1360
                array(
1361
                    'filter' => new Criterion\ContentTypeId(array(1, 3)),
1362
                    'offset' => 0,
1363
                    'limit' => 50,
1364
                    'sortClauses' => array(
1365
                        new SortClause\Field('folder', 'name', Query::SORT_DESC),
1366
                        new SortClause\ContentId(),
1367
                    ),
1368
                ),
1369
                $fixtureDir . 'SortFieldMultipleTypesReverse.php',
1370
            ),
1371
            9 => array(
1372
                array(
1373
                    'filter' => new Criterion\ContentTypeId(array(1, 3)),
1374
                    'offset' => 3,
1375
                    'limit' => 5,
1376
                    'sortClauses' => array(
1377
                        new SortClause\Field('folder', 'name', Query::SORT_ASC),
1378
                        new SortClause\Field('user', 'first_name', Query::SORT_ASC),
1379
                        new SortClause\ContentId(),
1380
                    ),
1381
                ),
1382
                $fixtureDir . 'SortFieldMultipleTypesSlice.php',
1383
            ),
1384
            10 => array(
1385
                array(
1386
                    'filter' => new Criterion\ContentTypeId(array(1, 3)),
1387
                    'offset' => 3,
1388
                    'limit' => 5,
1389
                    'sortClauses' => array(
1390
                        new SortClause\Field('folder', 'name', Query::SORT_DESC),
1391
                        new SortClause\Field('user', 'first_name', Query::SORT_ASC),
1392
                        new SortClause\ContentId(),
1393
                    ),
1394
                ),
1395
                $fixtureDir . 'SortFieldMultipleTypesSliceReverse.php',
1396
            ),
1397
        );
1398
    }
1399
1400
    public function getSortedLocationSearches()
1401
    {
1402
        $fixtureDir = $this->getFixtureDir();
1403
1404
        return array(
1405
            array(
1406
                array(
1407
                    'filter' => new Criterion\SectionId(array(2)),
1408
                    'offset' => 0,
1409
                    'limit' => 10,
1410
                    'sortClauses' => array(new SortClause\Location\Path(Query::SORT_DESC)),
1411
                ),
1412
                $fixtureDir . 'SortPathString.php',
1413
            ),
1414
            array(
1415
                array(
1416
                    'filter' => new Criterion\SectionId(array(2)),
1417
                    'offset' => 0,
1418
                    'limit' => 10,
1419
                    'sortClauses' => array(new SortClause\Location\Depth(Query::SORT_ASC)),
1420
                ),
1421
                $fixtureDir . 'SortLocationDepth.php',
1422
                // Result having the same sort level should be sorted between them to be system independent
1423
                function (&$data) {
1424
                    // Result with ids:
1425
                    //     4 has depth = 1
1426
                    //     11, 12, 13, 42, 59 have depth = 2
1427
                    //     10, 14 have depth = 3
1428
                    $map = array(
1429
                        4 => 0,
1430
                        11 => 1,
1431
                        12 => 2,
1432
                        13 => 3,
1433
                        42 => 4,
1434
                        59 => 5,
1435
                        10 => 6,
1436
                        14 => 7,
1437
                    );
1438
                    usort(
1439
                        $data->searchHits,
1440
                        function ($a, $b) use ($map) {
1441
                            return ($map[$a->valueObject['id']] < $map[$b->valueObject['id']]) ? -1 : 1;
1442
                        }
1443
                    );
1444
                },
1445
            ),
1446
            array(
1447
                array(
1448
                    'filter' => new Criterion\SectionId(array(3)),
1449
                    'offset' => 0,
1450
                    'limit' => 10,
1451
                    'sortClauses' => array(
1452
                        new SortClause\Location\Path(Query::SORT_DESC),
1453
                        new SortClause\ContentName(Query::SORT_ASC),
1454
                    ),
1455
                ),
1456
                $fixtureDir . 'SortMultiple.php',
1457
            ),
1458
            array(
1459
                array(
1460
                    'filter' => new Criterion\SectionId(array(2)),
1461
                    'offset' => 0,
1462
                    'limit' => 10,
1463
                    'sortClauses' => array(
1464
                        new SortClause\Location\Priority(Query::SORT_DESC),
1465
                        new SortClause\ContentId(),
1466
                    ),
1467
                ),
1468
                $fixtureDir . 'SortDesc.php',
1469
            ),
1470
        );
1471
    }
1472
1473
    /**
1474
     * @return \eZ\Publish\API\Repository\Values\ContentType\ContentType
1475
     */
1476 View Code Duplication
    protected function createTestContentType()
1477
    {
1478
        $repository = $this->getRepository();
1479
        $contentTypeService = $repository->getContentTypeService();
1480
1481
        $createStruct = $contentTypeService->newContentTypeCreateStruct('test-type');
1482
        $createStruct->mainLanguageCode = 'eng-GB';
1483
        $createStruct->names = array('eng-GB' => 'Test type');
1484
        $createStruct->creatorId = 14;
1485
        $createStruct->creationDate = new \DateTime();
1486
1487
        $translatableFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('integer', 'ezinteger');
1488
        $translatableFieldCreate->names = array('eng-GB' => 'Simple translatable integer field');
1489
        $translatableFieldCreate->fieldGroup = 'main';
1490
        $translatableFieldCreate->position = 1;
1491
        $translatableFieldCreate->isTranslatable = true;
1492
        $translatableFieldCreate->isSearchable = true;
1493
1494
        $createStruct->addFieldDefinition($translatableFieldCreate);
1495
1496
        $nonTranslatableFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('integer2', 'ezinteger');
1497
        $nonTranslatableFieldCreate->names = array('eng-GB' => 'Simple non-translatable integer field');
1498
        $nonTranslatableFieldCreate->fieldGroup = 'main';
1499
        $nonTranslatableFieldCreate->position = 2;
1500
        $nonTranslatableFieldCreate->isTranslatable = false;
1501
        $nonTranslatableFieldCreate->isSearchable = true;
1502
1503
        $createStruct->addFieldDefinition($nonTranslatableFieldCreate);
1504
1505
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
1506
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, array($contentGroup));
1507
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
1508
        $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...
1509
1510
        return $contentType;
1511
    }
1512
1513
    /**
1514
     * @param \eZ\Publish\API\Repository\Values\ContentType\ContentType $contentType
1515
     * @param int $fieldValue11 Value for translatable field in first language
1516
     * @param int $fieldValue12 Value for translatable field in second language
1517
     * @param int $fieldValue2 Value for non translatable field
1518
     * @param string $mainLanguageCode
1519
     * @param bool $alwaysAvailable
1520
     *
1521
     * @return Content
1522
     */
1523
    protected function createMultilingualContent(
1524
        $contentType,
1525
        $fieldValue11 = null,
1526
        $fieldValue12 = null,
1527
        $fieldValue2 = null,
1528
        $mainLanguageCode = 'eng-GB',
1529
        $alwaysAvailable = false
1530
    ) {
1531
        $repository = $this->getRepository();
1532
        $contentService = $repository->getContentService();
1533
1534
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
1535
        $createStruct->alwaysAvailable = $alwaysAvailable;
1536
        $createStruct->mainLanguageCode = $mainLanguageCode;
1537
        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...
1538
            $createStruct->setField('integer', $fieldValue11, 'eng-GB');
1539
        }
1540
        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...
1541
            $createStruct->setField('integer', $fieldValue12, 'ger-DE');
1542
        }
1543
        $createStruct->setField('integer2', $fieldValue2, $mainLanguageCode);
1544
1545
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
1546
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
1547
        $content = $contentService->publishVersion($draft->getVersionInfo());
1548
1549
        $this->refreshSearch($repository);
1550
1551
        return $content;
1552
    }
1553
1554
    protected function checkPrioritizedLanguagesSupport()
1555
    {
1556
        $setupFactory = $this->getSetupFactory();
1557
        if ($setupFactory instanceof LegacyElasticsearch) {
1558
            $this->markTestIncomplete('Prioritized languages are not supported with Elasticsearch engine');
1559
        }
1560
    }
1561
1562
    public function providerForTestMultilingualFieldSort()
1563
    {
1564
        return array(
1565
            0 => array(
1566
                array(
1567
                    1 => array(1, 2, 1),
1568
                    2 => array(2, 1, 2),
1569
                    3 => array(2, 1, 3),
1570
                    4 => array(1, 2, 4),
1571
                ),
1572
                array(
1573
                    'languages' => array(
1574
                        'eng-GB',
1575
                        'ger-DE',
1576
                    ),
1577
                ),
1578
                array(
1579
                    new SortClause\Field('test-type', 'integer', Query::SORT_ASC),
1580
                    new SortClause\Field('test-type', 'integer2', Query::SORT_DESC),
1581
                ),
1582
                /**
1583
                 * Expected order, Value eng-GB, Value ger-DE.
1584
                 *
1585
                 * Content 4, 1, 2, 4
1586
                 * Content 1, 1, 2, 1
1587
                 * Content 3, 2, 1, 3
1588
                 * Content 2, 2, 1, 2
1589
                 */
1590
                array(4, 1, 3, 2),
1591
            ),
1592
            1 => array(
1593
                array(
1594
                    1 => array(1, 2, 1),
1595
                    2 => array(2, 1, 2),
1596
                    3 => array(2, 1, 3),
1597
                    4 => array(1, 2, 4),
1598
                ),
1599
                array(
1600
                    'languages' => array(
1601
                        'ger-DE',
1602
                        'eng-GB',
1603
                    ),
1604
                ),
1605
                array(
1606
                    new SortClause\Field('test-type', 'integer', Query::SORT_ASC),
1607
                    new SortClause\Field('test-type', 'integer2', Query::SORT_DESC),
1608
                ),
1609
                /**
1610
                 * Expected order, Value eng-GB, Value ger-DE.
1611
                 *
1612
                 * Content 3, 2, 1, 3
1613
                 * Content 2, 2, 1, 2
1614
                 * Content 4, 1, 2, 4
1615
                 * Content 1, 1, 2, 1
1616
                 */
1617
                array(3, 2, 4, 1),
1618
            ),
1619
            2 => array(
1620
                array(
1621
                    1 => array(null, 2, null, 'ger-DE'),
1622
                    2 => array(3, null, null, 'eng-GB'),
1623
                    3 => array(4, null, null, 'eng-GB'),
1624
                    4 => array(null, 1, null, 'ger-DE'),
1625
                ),
1626
                array(
1627
                    'languages' => array(
1628
                        'eng-GB',
1629
                    ),
1630
                ),
1631
                array(
1632
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1633
                ),
1634
                /**
1635
                 * Expected order, Value eng-GB, Value ger-DE.
1636
                 *
1637
                 * Content 3, 4, -
1638
                 * Content 2, 3, -
1639
                 */
1640
                array(3, 2),
1641
            ),
1642
            3 => array(
1643
                array(
1644
                    1 => array(null, 2, null, 'ger-DE'),
1645
                    2 => array(3, null, null, 'eng-GB'),
1646
                    3 => array(4, null, null, 'eng-GB'),
1647
                    4 => array(null, 1, null, 'ger-DE'),
1648
                ),
1649
                array(
1650
                    'languages' => array(
1651
                        'ger-DE',
1652
                    ),
1653
                ),
1654
                array(
1655
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1656
                ),
1657
                /**
1658
                 * Expected order, Value eng-GB, Value ger-DE.
1659
                 *
1660
                 * Content 1, -, 2
1661
                 * Content 4, -, 1
1662
                 */
1663
                array(1, 4),
1664
            ),
1665
            4 => array(
1666
                array(
1667
                    1 => array(null, 2, null, 'ger-DE'),
1668
                    2 => array(3, null, null, 'eng-GB'),
1669
                    3 => array(4, null, null, 'eng-GB'),
1670
                    4 => array(null, 1, null, 'ger-DE'),
1671
                ),
1672
                array(
1673
                    'languages' => array(
1674
                        'eng-GB',
1675
                        'ger-DE',
1676
                    ),
1677
                ),
1678
                array(
1679
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1680
                ),
1681
                /**
1682
                 * Expected order, Value eng-GB, Value ger-DE.
1683
                 *
1684
                 * Content 3, 4, -
1685
                 * Content 2, 3, -
1686
                 * Content 1, -, 2
1687
                 * Content 4, -, 1
1688
                 */
1689
                array(3, 2, 1, 4),
1690
            ),
1691
            5 => array(
1692
                array(
1693
                    1 => array(null, 2, null, 'ger-DE'),
1694
                    2 => array(3, null, null, 'eng-GB'),
1695
                    3 => array(4, null, null, 'eng-GB'),
1696
                    4 => array(null, 1, null, 'ger-DE'),
1697
                ),
1698
                array(
1699
                    'languages' => array(
1700
                        'ger-DE',
1701
                        'eng-GB',
1702
                    ),
1703
                ),
1704
                array(
1705
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1706
                ),
1707
                /**
1708
                 * Expected order, Value eng-GB, Value ger-DE.
1709
                 *
1710
                 * Content 3, 4, -
1711
                 * Content 2, 3, -
1712
                 * Content 1, -, 2
1713
                 * Content 4, -, 1
1714
                 */
1715
                array(3, 2, 1, 4),
1716
            ),
1717
            6 => array(
1718
                array(
1719
                    1 => array(null, 2, null, 'ger-DE'),
1720
                    2 => array(3, 4, null, 'eng-GB'),
1721
                    3 => array(4, 3, null, 'eng-GB'),
1722
                    4 => array(null, 1, null, 'ger-DE'),
1723
                ),
1724
                array(
1725
                    'languages' => array(
1726
                        'eng-GB',
1727
                        'ger-DE',
1728
                    ),
1729
                ),
1730
                array(
1731
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1732
                ),
1733
                /**
1734
                 * Expected order, Value eng-GB, Value ger-DE.
1735
                 *
1736
                 * Content 3, 4, 3
1737
                 * Content 2, 3, 4
1738
                 * Content 1, -, 2
1739
                 * Content 4, -, 1
1740
                 */
1741
                array(3, 2, 1, 4),
1742
            ),
1743
            7 => array(
1744
                array(
1745
                    1 => array(null, 2, null, 'ger-DE'),
1746
                    2 => array(3, 4, null, 'eng-GB'),
1747
                    3 => array(4, 3, null, 'eng-GB'),
1748
                    4 => array(null, 1, null, 'ger-DE'),
1749
                ),
1750
                array(
1751
                    'languages' => array(
1752
                        'ger-DE',
1753
                        'eng-GB',
1754
                    ),
1755
                ),
1756
                array(
1757
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1758
                ),
1759
                /**
1760
                 * Expected order, Value eng-GB, Value ger-DE.
1761
                 *
1762
                 * Content 2, 3, 4
1763
                 * Content 3, 4, 3
1764
                 * Content 1, -, 2
1765
                 * Content 4, -, 1
1766
                 */
1767
                array(2, 3, 1, 4),
1768
            ),
1769
            8 => array(
1770
                array(
1771
                    1 => array(null, 1, null, 'ger-DE', true),
1772
                    2 => array(4, null, null, 'eng-GB', true),
1773
                    3 => array(3, null, null, 'eng-GB', false),
1774
                    4 => array(null, 2, null, 'ger-DE', false),
1775
                ),
1776
                array(
1777
                    'languages' => array(
1778
                        'eng-GB',
1779
                    ),
1780
                ),
1781
                array(
1782
                    new SortClause\Field('test-type', 'integer', Query::SORT_ASC),
1783
                ),
1784
                /**
1785
                 * Expected order, Value eng-GB, Value ger-DE.
1786
                 *
1787
                 * Content 1, -, 1
1788
                 * Content 3, 3, -
1789
                 * Content 2, 4, -
1790
                 */
1791
                array(1, 3, 2),
1792
            ),
1793
            9 => array(
1794
                array(
1795
                    1 => array(null, 1, null, 'ger-DE', true),
1796
                    2 => array(4, null, null, 'eng-GB', true),
1797
                    3 => array(3, null, null, 'eng-GB', false),
1798
                    4 => array(null, 2, null, 'ger-DE', false),
1799
                ),
1800
                array(
1801
                    'languages' => array(
1802
                        'ger-DE',
1803
                    ),
1804
                ),
1805
                array(
1806
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1807
                ),
1808
                /**
1809
                 * Expected order, Value eng-GB, Value ger-DE.
1810
                 *
1811
                 * Content 2, 4, -
1812
                 * Content 4, -, 2
1813
                 * Content 1, -, 1
1814
                 */
1815
                array(2, 4, 1),
1816
            ),
1817
            10 => array(
1818
                array(
1819
                    1 => array(null, 1, null, 'ger-DE', true),
1820
                    2 => array(4, null, null, 'eng-GB', true),
1821
                    3 => array(3, null, null, 'eng-GB', false),
1822
                    4 => array(null, 2, null, 'ger-DE', false),
1823
                ),
1824
                array(
1825
                    'languages' => array(
1826
                        'eng-GB',
1827
                    ),
1828
                    'useAlwaysAvailable' => false,
1829
                ),
1830
                array(
1831
                    new SortClause\Field('test-type', 'integer', Query::SORT_ASC),
1832
                ),
1833
                /**
1834
                 * Expected order, Value eng-GB, Value ger-DE.
1835
                 *
1836
                 * Content 3, 3, -
1837
                 * Content 2, 4, -
1838
                 */
1839
                array(3, 2),
1840
            ),
1841
            11 => array(
1842
                array(
1843
                    1 => array(null, 1, null, 'ger-DE', true),
1844
                    2 => array(4, null, null, 'eng-GB', true),
1845
                    3 => array(3, null, null, 'eng-GB', false),
1846
                    4 => array(null, 2, null, 'ger-DE', false),
1847
                ),
1848
                array(
1849
                    'languages' => array(
1850
                        'ger-DE',
1851
                    ),
1852
                    'useAlwaysAvailable' => false,
1853
                ),
1854
                array(
1855
                    new SortClause\Field('test-type', 'integer', Query::SORT_DESC),
1856
                ),
1857
                /**
1858
                 * Expected order, Value eng-GB, Value ger-DE.
1859
                 *
1860
                 * Content 4, -, 2
1861
                 * Content 1, -, 1
1862
                 */
1863
                array(4, 1),
1864
            ),
1865
        );
1866
    }
1867
1868
    /**
1869
     * Test for the findContent() method.
1870
     *
1871
     * @group rrr
1872
     * @dataProvider providerForTestMultilingualFieldSort
1873
     *
1874
     * @param array $contentDataList
1875
     * @param array $languageSettings
1876
     * @param \eZ\Publish\API\Repository\Values\Content\Query\SortClause[] $sortClauses
1877
     * @param array $expected
1878
     */
1879
    public function testMultilingualFieldSortContent(
1880
        array $contentDataList,
1881
        $languageSettings,
1882
        array $sortClauses,
1883
        $expected
1884
    ) {
1885
        $this->assertMultilingualFieldSort(
1886
            $contentDataList,
1887
            $languageSettings,
1888
            $sortClauses,
1889
            $expected
1890
        );
1891
    }
1892
1893
    /**
1894
     * Test for the findLocations() method.
1895
     *
1896
     * @group rrr
1897
     * @dataProvider providerForTestMultilingualFieldSort
1898
     *
1899
     * @param array $contentDataList
1900
     * @param array $languageSettings
1901
     * @param \eZ\Publish\API\Repository\Values\Content\Query\SortClause[] $sortClauses
1902
     * @param array $expected
1903
     */
1904
    public function testMultilingualFieldSortLocation(
1905
        array $contentDataList,
1906
        $languageSettings,
1907
        array $sortClauses,
1908
        $expected
1909
    ) {
1910
        $this->assertMultilingualFieldSort(
1911
            $contentDataList,
1912
            $languageSettings,
1913
            $sortClauses,
1914
            $expected,
1915
            false
1916
        );
1917
    }
1918
1919
    /**
1920
     * @param array $contentDataList
1921
     * @param array $languageSettings
1922
     * @param \eZ\Publish\API\Repository\Values\Content\Query\SortClause[] $sortClauses
1923
     * @param array $expected
1924
     * @param bool $contentSearch
1925
     */
1926
    protected function assertMultilingualFieldSort(
1927
        array $contentDataList,
1928
        $languageSettings,
1929
        array $sortClauses,
1930
        $expected,
1931
        $contentSearch = true
1932
    ) {
1933
        $this->checkPrioritizedLanguagesSupport();
1934
        $contentType = $this->createTestContentType();
1935
1936
        // Create a draft to account for behaviour with ContentType in different states
1937
        $repository = $this->getRepository();
1938
        $contentTypeService = $repository->getContentTypeService();
1939
        $contentTypeService->createContentTypeDraft($contentType);
1940
1941
        $defaults = array(null, null, null, 'eng-GB', false);
1942
        $contentIdList = array();
1943 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...
1944
            $contentData = $contentData + $defaults;
1945
            list(
1946
                $fieldValue11,
1947
                $fieldValue12,
1948
                $fieldValue2,
1949
                $mainLanguageCode,
1950
                $alwaysAvailable
1951
            ) = $contentData;
1952
1953
            $contentIdList[$key] = $this->createMultilingualContent(
1954
                $contentType,
1955
                $fieldValue11,
1956
                $fieldValue12,
1957
                $fieldValue2,
1958
                $mainLanguageCode,
1959
                $alwaysAvailable
1960
            )->id;
1961
        }
1962
1963
        // "article" type Content is not matched, this ensures that non-matched
1964
        // field does not affect sort
1965
        $dummySortClause = new SortClause\Field('article', 'title', Query::SORT_ASC);
1966
        array_unshift($sortClauses, $dummySortClause);
1967
        array_push($sortClauses, $dummySortClause);
1968
1969
        $searchService = $repository->getSearchService();
1970
        if ($contentSearch) {
1971
            $query = new Query(
1972
                array(
1973
                    'query' => new Criterion\ContentTypeId($contentType->id),
1974
                    'sortClauses' => $sortClauses,
1975
                )
1976
            );
1977
            $result = $searchService->findContent($query, $languageSettings);
1978
        } else {
1979
            $query = new LocationQuery(
1980
                array(
1981
                    'query' => new Criterion\ContentTypeId($contentType->id),
1982
                    'sortClauses' => $sortClauses,
1983
                )
1984
            );
1985
            $result = $searchService->findLocations($query, $languageSettings);
1986
        }
1987
1988
        $this->assertEquals(count($expected), $result->totalCount);
1989
1990
        $expectedIdList = array();
1991
        foreach ($expected as $contentNumber) {
1992
            $expectedIdList[] = $contentIdList[$contentNumber];
1993
        }
1994
1995
        $this->assertEquals($expectedIdList, $this->mapResultContentIds($result));
1996
    }
1997
1998
    public function providerForTestMultilingualFieldFilter()
1999
    {
2000
        return array(
2001
            0 => array(
2002
                $fixture = array(
2003
                    1 => array(null, 1, null, 'ger-DE', true),
2004
                    2 => array(4, null, null, 'eng-GB', true),
2005
                    3 => array(3, null, null, 'eng-GB', false),
2006
                    4 => array(null, 2, null, 'ger-DE', false),
2007
                    5 => array(5, null, null, 'eng-GB', true),
2008
                ),
2009
                $languageSettings = array(
2010
                    'languages' => array(
2011
                        'ger-DE',
2012
                    ),
2013
                ),
2014
                new Criterion\Field('integer', Criterion\Operator::LT, 5),
2015
                /**
2016
                 * Expected order, Value eng-GB, Value ger-DE.
2017
                 *
2018
                 * Content 2, 4, -
2019
                 * Content 4, -, 2
2020
                 * Content 1, -, 1
2021
                 */
2022
                array(2, 4, 1),
2023
            ),
2024
            1 => array(
2025
                $fixture,
2026
                array(
2027
                    'languages' => array(
2028
                        'ger-DE',
2029
                    ),
2030
                    'useAlwaysAvailable' => false,
2031
                ),
2032
                new Criterion\Field('integer', Criterion\Operator::LT, 2),
2033
                /**
2034
                 * Expected order, Value eng-GB, Value ger-DE.
2035
                 *
2036
                 * Content 1, -, 1
2037
                 */
2038
                array(1),
2039
            ),
2040
            2 => array(
2041
                $fixture,
2042
                array(
2043
                    'languages' => array(
2044
                        'eng-GB',
2045
                    ),
2046
                ),
2047
                new Criterion\Field('integer', Criterion\Operator::LTE, 4),
2048
                /**
2049
                 * Expected order, Value eng-GB, Value ger-DE.
2050
                 *
2051
                 * Content 5, 5, -
2052
                 * Content 2, 4, -
2053
                 * Content 3, 3, -
2054
                 * Content 1, -, 1
2055
                 */
2056
                array(2, 3, 1),
2057
            ),
2058
            3 => array(
2059
                $fixture,
2060
                array(
2061
                    'languages' => array(
2062
                        'eng-GB',
2063
                    ),
2064
                    'useAlwaysAvailable' => false,
2065
                ),
2066
                new Criterion\Field('integer', Criterion\Operator::LTE, 4),
2067
                /**
2068
                 * Expected order, Value eng-GB, Value ger-DE.
2069
                 *
2070
                 * Content 2, 4, -
2071
                 * Content 3, 3, -
2072
                 */
2073
                array(2, 3),
2074
            ),
2075
            4 => array(
2076
                $fixture,
2077
                $languageSettings,
2078
                new Criterion\Field('integer', Criterion\Operator::LTE, 4),
2079
                /**
2080
                 * Expected order, Value eng-GB, Value ger-DE.
2081
                 *
2082
                 * Content 2, 4, -
2083
                 * Content 4, -, 2
2084
                 * Content 1, -, 1
2085
                 */
2086
                array(2, 4, 1),
2087
            ),
2088
            5 => array(
2089
                $fixture,
2090
                $languageSettings,
2091
                new Criterion\Field('integer', Criterion\Operator::GT, 1),
2092
                /**
2093
                 * Expected order, Value eng-GB, Value ger-DE.
2094
                 *
2095
                 * Content 5, 5, -
2096
                 * Content 2, 4, -
2097
                 * Content 4, -, 2
2098
                 */
2099
                array(5, 2, 4),
2100
            ),
2101
            6 => array(
2102
                $fixture,
2103
                $languageSettings,
2104
                new Criterion\Field('integer', Criterion\Operator::GTE, 2),
2105
                /**
2106
                 * Expected order, Value eng-GB, Value ger-DE.
2107
                 *
2108
                 * Content 5, 5, -
2109
                 * Content 2, 4, -
2110
                 * Content 4, -, 2
2111
                 */
2112
                array(5, 2, 4),
2113
            ),
2114
            7 => array(
2115
                $fixture,
2116
                $languageSettings,
2117
                new Criterion\Field('integer', Criterion\Operator::BETWEEN, array(2, 4)),
2118
                /**
2119
                 * Expected order, Value eng-GB, Value ger-DE.
2120
                 *
2121
                 * Content 2, 4, -
2122
                 * Content 4, -, 2
2123
                 */
2124
                array(2, 4),
2125
            ),
2126
            8 => array(
2127
                $fixture,
2128
                $languageSettings,
2129
                new Criterion\Field('integer', Criterion\Operator::BETWEEN, array(4, 2)),
2130
                array(),
2131
            ),
2132
            9 => array(
2133
                $fixture,
2134
                $languageSettings,
2135
                new Criterion\Field('integer', Criterion\Operator::EQ, 4),
2136
                /**
2137
                 * Expected order, Value eng-GB, Value ger-DE.
2138
                 *
2139
                 * Content 4, -, 2
2140
                 */
2141
                array(2),
2142
            ),
2143
            10 => array(
2144
                $fixture,
2145
                $languageSettings,
2146
                new Criterion\Field('integer', Criterion\Operator::EQ, 2),
2147
                /**
2148
                 * Expected order, Value eng-GB, Value ger-DE.
2149
                 *
2150
                 * Content 2, 4, -
2151
                 */
2152
                array(4),
2153
            ),
2154
        );
2155
    }
2156
2157
    /**
2158
     * Test for the findContent() method.
2159
     *
2160
     * @group ttt
2161
     * @dataProvider providerForTestMultilingualFieldFilter
2162
     *
2163
     * @param array $contentDataList
2164
     * @param array $languageSettings
2165
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
2166
     * @param array $expected
2167
     */
2168
    public function testMultilingualFieldFilterContent(
2169
        array $contentDataList,
2170
        $languageSettings,
2171
        Criterion $criterion,
2172
        $expected
2173
    ) {
2174
        $this->assertMultilingualFieldFilter(
2175
            $contentDataList,
2176
            $languageSettings,
2177
            $criterion,
2178
            $expected
2179
        );
2180
    }
2181
2182
    /**
2183
     * Test for the findLocations() method.
2184
     *
2185
     * @group ttt
2186
     * @dataProvider providerForTestMultilingualFieldFilter
2187
     *
2188
     * @param array $contentDataList
2189
     * @param array $languageSettings
2190
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
2191
     * @param array $expected
2192
     */
2193
    public function testMultilingualFieldFilterLocation(
2194
        array $contentDataList,
2195
        $languageSettings,
2196
        Criterion $criterion,
2197
        $expected
2198
    ) {
2199
        $this->assertMultilingualFieldFilter(
2200
            $contentDataList,
2201
            $languageSettings,
2202
            $criterion,
2203
            $expected,
2204
            false
2205
        );
2206
    }
2207
2208
    /**
2209
     * @param array $contentDataList
2210
     * @param array $languageSettings
2211
     * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
2212
     * @param array $expected
2213
     * @param bool $contentSearch
2214
     */
2215
    protected function assertMultilingualFieldFilter(
2216
        array $contentDataList,
2217
        $languageSettings,
2218
        Criterion $criterion,
2219
        $expected,
2220
        $contentSearch = true
2221
    ) {
2222
        $this->checkPrioritizedLanguagesSupport();
2223
        $contentType = $this->createTestContentType();
2224
2225
        // Create a draft to account for behaviour with ContentType in different states
2226
        $repository = $this->getRepository();
2227
        $contentTypeService = $repository->getContentTypeService();
2228
        $contentTypeService->createContentTypeDraft($contentType);
2229
2230
        $defaults = array(null, null, null, 'eng-GB', false);
2231
        $contentIdList = array();
2232 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...
2233
            $contentData = $contentData + $defaults;
2234
            list(
2235
                $fieldValue11,
2236
                $fieldValue12,
2237
                $fieldValue2,
2238
                $mainLanguageCode,
2239
                $alwaysAvailable
2240
            ) = $contentData;
2241
2242
            $contentIdList[$key] = $this->createMultilingualContent(
2243
                $contentType,
2244
                $fieldValue11,
2245
                $fieldValue12,
2246
                $fieldValue2,
2247
                $mainLanguageCode,
2248
                $alwaysAvailable
2249
            )->id;
2250
        }
2251
2252
        $sortClause = new SortClause\Field('test-type', 'integer', Query::SORT_DESC);
2253
        $searchService = $repository->getSearchService();
2254
        if ($contentSearch) {
2255
            $query = new Query(
2256
                array(
2257
                    'query' => new Criterion\LogicalAnd(
2258
                        array(
2259
                            new Criterion\ContentTypeId($contentType->id),
2260
                            $criterion,
2261
                        )
2262
                    ),
2263
                    'sortClauses' => array($sortClause),
2264
                )
2265
            );
2266
            $result = $searchService->findContent($query, $languageSettings);
2267
        } else {
2268
            $query = new LocationQuery(
2269
                array(
2270
                    'query' => new Criterion\LogicalAnd(
2271
                        array(
2272
                            new Criterion\ContentTypeId($contentType->id),
2273
                            $criterion,
2274
                        )
2275
                    ),
2276
                    'sortClauses' => array($sortClause),
2277
                )
2278
            );
2279
            $result = $searchService->findLocations($query, $languageSettings);
2280
        }
2281
2282
        $this->assertEquals(count($expected), $result->totalCount);
2283
2284
        $expectedIdList = array();
2285
        foreach ($expected as $contentNumber) {
2286
            $expectedIdList[] = $contentIdList[$contentNumber];
2287
        }
2288
2289
        $this->assertEquals($expectedIdList, $this->mapResultContentIds($result));
2290
    }
2291
2292
    /**
2293
     * @param \eZ\Publish\API\Repository\Values\Content\Search\SearchResult $result
2294
     *
2295
     * @return array
2296
     */
2297
    protected function mapResultContentIds(SearchResult $result)
2298
    {
2299
        return array_map(
2300
            function (SearchHit $searchHit) {
2301
                if ($searchHit->valueObject instanceof Location) {
2302
                    return $searchHit->valueObject->contentInfo->id;
2303
                }
2304
2305
                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...
2306
            },
2307
            $result->searchHits
2308
        );
2309
    }
2310
2311
    /**
2312
     * Test for the findContent() method.
2313
     *
2314
     * @dataProvider getSortedContentSearches
2315
     *
2316
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2317
     */
2318
    public function testFindAndSortContent($queryData, $fixture, $closure = null)
2319
    {
2320
        $query = new Query($queryData);
2321
        $this->assertQueryFixture($query, $fixture, $closure);
2322
    }
2323
2324
    /**
2325
     * Test for the findContentInfo() method.
2326
     *
2327
     * @dataProvider getSortedContentSearches
2328
     * @see \eZ\Publish\API\Repository\SearchService::findContentInfo()
2329
     */
2330
    public function testFindAndSortContentInfo($queryData, $fixture, $closure = null)
2331
    {
2332
        $query = new Query($queryData);
2333
        $this->assertQueryFixture($query, $fixture, $this->getContentInfoFixtureClosure($closure), true);
2334
    }
2335
2336
    /**
2337
     * Test for the findLocations() method.
2338
     *
2339
     * @dataProvider getSortedContentSearches
2340
     *
2341
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
2342
     */
2343
    public function testFindAndSortContentLocations($queryData, $fixture, $closure = null)
2344
    {
2345
        $query = new LocationQuery($queryData);
2346
        $this->assertQueryFixture($query, $fixture, $closure);
2347
    }
2348
2349
    /**
2350
     * Test for the findLocations() method.
2351
     *
2352
     * @dataProvider getSortedLocationSearches
2353
     *
2354
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
2355
     */
2356
    public function testFindAndSortLocations($queryData, $fixture, $closure = null)
2357
    {
2358
        $query = new LocationQuery($queryData);
2359
        $this->assertQueryFixture($query, $fixture, $closure);
2360
    }
2361
2362
    public function getFacettedSearches()
2363
    {
2364
        $fixtureDir = $this->getFixtureDir();
2365
2366
        return array(
2367
            array(
2368
                new Query(
2369
                    array(
2370
                        'filter' => new Criterion\SectionId(array(1)),
2371
                        'offset' => 0,
2372
                        'limit' => 10,
2373
                        'facetBuilders' => array(
2374
                            new FacetBuilder\ContentTypeFacetBuilder(
2375
                                array(
2376
                                    'name' => 'type',
2377
                                )
2378
                            ),
2379
                        ),
2380
                        'sortClauses' => array(new SortClause\ContentId()),
2381
                    )
2382
                ),
2383
                $fixtureDir . '/FacetContentType.php',
2384
            ),
2385
            array(
2386
                new Query(
2387
                    array(
2388
                        'filter' => new Criterion\SectionId(array(1)),
2389
                        'offset' => 0,
2390
                        'limit' => 10,
2391
                        'facetBuilders' => array(
2392
                            new FacetBuilder\ContentTypeFacetBuilder(
2393
                                array(
2394
                                    'name' => 'type',
2395
                                    'minCount' => 3,
2396
                                )
2397
                            ),
2398
                        ),
2399
                        'sortClauses' => array(new SortClause\ContentId()),
2400
                    )
2401
                ),
2402
                $fixtureDir . '/FacetContentTypeMinCount.php',
2403
            ),
2404
            array(
2405
                new Query(
2406
                    array(
2407
                        'filter' => new Criterion\SectionId(array(1)),
2408
                        'offset' => 0,
2409
                        'limit' => 10,
2410
                        'facetBuilders' => array(
2411
                            new FacetBuilder\ContentTypeFacetBuilder(
2412
                                array(
2413
                                    'name' => 'type',
2414
                                    'limit' => 5,
2415
                                )
2416
                            ),
2417
                        ),
2418
                        'sortClauses' => array(new SortClause\ContentId()),
2419
                    )
2420
                ),
2421
                $fixtureDir . '/FacetContentTypeMinLimit.php',
2422
            ),
2423
            array(
2424
                new Query(
2425
                    array(
2426
                        'filter' => new Criterion\SectionId(array(1)),
2427
                        'offset' => 0,
2428
                        'limit' => 10,
2429
                        'facetBuilders' => array(
2430
                            new FacetBuilder\SectionFacetBuilder(
2431
                                array(
2432
                                    'name' => 'section',
2433
                                )
2434
                            ),
2435
                        ),
2436
                        'sortClauses' => array(new SortClause\ContentId()),
2437
                    )
2438
                ),
2439
                $fixtureDir . '/FacetSection.php',
2440
            ),
2441
            array(
2442
                new Query(
2443
                    array(
2444
                        'filter' => new Criterion\SectionId(array(1)),
2445
                        'offset' => 0,
2446
                        'limit' => 10,
2447
                        'facetBuilders' => array(
2448
                            new FacetBuilder\UserFacetBuilder(
2449
                                array(
2450
                                    'name' => 'creator',
2451
                                )
2452
                            ),
2453
                        ),
2454
                        'sortClauses' => array(new SortClause\ContentId()),
2455
                    )
2456
                ),
2457
                $fixtureDir . '/FacetUser.php',
2458
            ),
2459
            array(
2460
                new Query(
2461
                    array(
2462
                        'filter' => new Criterion\SectionId(array(1)),
2463
                        'offset' => 0,
2464
                        'limit' => 10,
2465
                        'facetBuilders' => array(
2466
                            new FacetBuilder\TermFacetBuilder(),
2467
                        ),
2468
                        'sortClauses' => array(new SortClause\ContentId()),
2469
                    )
2470
                ),
2471
                $fixtureDir . '/FacetTerm.php',
2472
            ),
2473
            /* @todo: It needs to be defined how this one is supposed to work.
2474
            array(
2475
                new Query(
2476
                    array(
2477
                        'filter'      => new Criterion\SectionId( array( 1 ) ),
2478
                        'offset'      => 0,
2479
                        'limit'       => 10,
2480
                        'facetBuilders' => array(
2481
                            new FacetBuilder\CriterionFacetBuilder()
2482
                        ),
2483
                        'sortClauses' => array( new SortClause\ContentId() )
2484
                    )
2485
                ),
2486
                $fixtureDir . '/FacetCriterion.php',
2487
            ), // */
2488
            /* @todo: Add sane ranges here:
2489
            array(
2490
                new Query(
2491
                    array(
2492
                        'filter'      => new Criterion\SectionId( array( 1 ) ),
2493
                        'offset'      => 0,
2494
                        'limit'       => 10,
2495
                        'facetBuilders' => array(
2496
                            new FacetBuilder\DateRangeFacetBuilder( array() )
2497
                        ),
2498
                        'sortClauses' => array( new SortClause\ContentId() )
2499
                    )
2500
                ),
2501
                $fixtureDir . '/FacetDateRange.php',
2502
            ), // */
2503
            array(
2504
                new Query(
2505
                    array(
2506
                        'filter' => new Criterion\SectionId(array(1)),
2507
                        'offset' => 0,
2508
                        'limit' => 10,
2509
                        'facetBuilders' => array(
2510
                            new FacetBuilder\FieldFacetBuilder(
2511
                                array(
2512
                                    'fieldPaths' => array('article/title'),
2513
                                )
2514
                            ),
2515
                        ),
2516
                        'sortClauses' => array(new SortClause\ContentId()),
2517
                    )
2518
                ),
2519
                $fixtureDir . '/FacetFieldSimple.php',
2520
            ),
2521
            array(
2522
                new Query(
2523
                    array(
2524
                        'filter' => new Criterion\SectionId(array(1)),
2525
                        'offset' => 0,
2526
                        'limit' => 10,
2527
                        'facetBuilders' => array(
2528
                            new FacetBuilder\FieldFacetBuilder(
2529
                                array(
2530
                                    'fieldPaths' => array('article/title'),
2531
                                    'regex' => '(a|b|c)',
2532
                                )
2533
                            ),
2534
                        ),
2535
                        'sortClauses' => array(new SortClause\ContentId()),
2536
                    )
2537
                ),
2538
                $fixtureDir . '/FacetFieldRegexp.php',
2539
            ),
2540
            array(
2541
                new Query(
2542
                    array(
2543
                        'filter' => new Criterion\SectionId(array(1)),
2544
                        'offset' => 0,
2545
                        'limit' => 10,
2546
                        'facetBuilders' => array(
2547
                            new FacetBuilder\FieldFacetBuilder(
2548
                                array(
2549
                                    'fieldPaths' => array('article/title'),
2550
                                    'regex' => '(a|b|c)',
2551
                                    'sort' => FacetBuilder\FieldFacetBuilder::TERM_DESC,
2552
                                )
2553
                            ),
2554
                        ),
2555
                        'sortClauses' => array(new SortClause\ContentId()),
2556
                    )
2557
                ),
2558
                $fixtureDir . '/FacetFieldRegexpSortTerm.php',
2559
            ),
2560
            array(
2561
                new Query(
2562
                    array(
2563
                        'filter' => new Criterion\SectionId(array(1)),
2564
                        'offset' => 0,
2565
                        'limit' => 10,
2566
                        'facetBuilders' => array(
2567
                            new FacetBuilder\FieldFacetBuilder(
2568
                                array(
2569
                                    'fieldPaths' => array('article/title'),
2570
                                    'regex' => '(a|b|c)',
2571
                                    'sort' => FacetBuilder\FieldFacetBuilder::COUNT_DESC,
2572
                                )
2573
                            ),
2574
                        ),
2575
                        'sortClauses' => array(new SortClause\ContentId()),
2576
                    )
2577
                ),
2578
                $fixtureDir . '/FacetFieldRegexpSortCount.php',
2579
            ),
2580
            /* @todo: Add sane ranges here:
2581
            array(
2582
                new Query(
2583
                    array(
2584
                        'filter'      => new Criterion\SectionId( array( 1 ) ),
2585
                        'offset'      => 0,
2586
                        'limit'       => 10,
2587
                        'facetBuilders' => array(
2588
                            new FacetBuilder\FieldRangeFacetBuilder( array(
2589
                                'fieldPath' => 'product/price',
2590
                            ) )
2591
                        ),
2592
                        'sortClauses' => array( new SortClause\ContentId() )
2593
                    )
2594
                ),
2595
                $fixtureDir . '/FacetFieldRegexpSortCount.php',
2596
            ), // */
2597
        );
2598
    }
2599
2600
    /**
2601
     * Test for the findContent() method.
2602
     *
2603
     * @dataProvider getFacettedSearches
2604
     *
2605
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2606
     */
2607
    public function testFindFacettedContent(Query $query, $fixture)
2608
    {
2609
        $this->assertQueryFixture($query, $fixture);
2610
    }
2611
2612
    /**
2613
     * Test for the findContentInfo() method.
2614
     *
2615
     * @dataProvider getFacettedSearches
2616
     * @see \eZ\Publish\API\Repository\SearchService::findContentInfo()
2617
     */
2618
    public function testFindFacettedContentInfo(Query $query, $fixture)
2619
    {
2620
        $this->assertQueryFixture($query, $fixture, $this->getContentInfoFixtureClosure(), true);
2621
    }
2622
2623
    /**
2624
     * Test for the findContent() method.
2625
     *
2626
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2627
     */
2628 View Code Duplication
    public function testQueryCustomField()
2629
    {
2630
        $query = new Query(
2631
            array(
2632
                'query' => new Criterion\CustomField(
2633
                    'custom_field',
2634
                    Criterion\Operator::EQ,
2635
                    'AdMiNiStRaToR'
2636
                ),
2637
                'offset' => 0,
2638
                'limit' => 10,
2639
                'sortClauses' => array(new SortClause\ContentId()),
2640
            )
2641
        );
2642
        $this->assertQueryFixture(
2643
            $query,
2644
            $this->getFixtureDir() . '/QueryCustomField.php'
2645
        );
2646
    }
2647
2648
    /**
2649
     * Test for the findContent() method.
2650
     *
2651
     * This tests explicitely queries the first_name while user is contained in
2652
     * the last_name of admin and anonymous. This is done to show the custom
2653
     * copy field working.
2654
     *
2655
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2656
     */
2657 View Code Duplication
    public function testQueryModifiedField()
2658
    {
2659
        // Check using get_class since the others extend SetupFactory\Legacy
2660
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
2661
            $this->markTestIncomplete(
2662
                'Custom fields not supported by LegacySE ' .
2663
                '(@todo: Legacy should fallback to just querying normal field so this should be tested here)'
2664
            );
2665
        }
2666
2667
        $query = new Query(
2668
            array(
2669
                'query' => new Criterion\Field(
2670
                    'first_name',
2671
                    Criterion\Operator::EQ,
2672
                    'User'
2673
                ),
2674
                'offset' => 0,
2675
                'limit' => 10,
2676
                'sortClauses' => array(new SortClause\ContentId()),
2677
            )
2678
        );
2679
        $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...
2680
2681
        $this->assertQueryFixture(
2682
            $query,
2683
            $this->getFixtureDir() . '/QueryModifiedField.php'
2684
        );
2685
    }
2686
2687
    /**
2688
     * Test for the findContent() method.
2689
     *
2690
     * This tests first explicitly creates sort clause on the 'short_name' which is empty
2691
     * for all Content instances of 'folder' ContentType. Custom sort field is then set
2692
     * to the index storage name of folder's 'name' field, in order to show the custom
2693
     * sort field working.
2694
     *
2695
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2696
     * @depends eZ\Publish\API\Repository\Tests\RepositoryTest::testGetSearchService
2697
     */
2698
    public function testSortModifiedField()
2699
    {
2700
        // Check using get_class since the others extend SetupFactory\Legacy
2701
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
2702
            $this->markTestIncomplete(
2703
                'Custom field sort not supported by LegacySE ' .
2704
                '(@todo: Legacy should fallback to just querying normal field so this should be tested here)'
2705
            );
2706
        }
2707
2708
        $sortClause = new SortClause\Field('folder', 'short_name', Query::SORT_ASC);
2709
        $sortClause->setCustomField('folder', 'short_name', 'folder_name_value_s');
2710
2711
        $query = new Query(
2712
            array(
2713
                'filter' => new Criterion\ContentTypeId(1),
2714
                'offset' => 0,
2715
                'limit' => 10,
2716
                'sortClauses' => array(
2717
                    $sortClause,
2718
                    new SortClause\ContentId(),
2719
                ),
2720
            )
2721
        );
2722
2723
        $this->assertQueryFixture(
2724
            $query,
2725
            $this->getFixtureDir() . '/SortFolderName.php'
2726
        );
2727
    }
2728
2729
    /**
2730
     * @return \eZ\Publish\API\Repository\Values\ContentType\ContentType
2731
     */
2732 View Code Duplication
    protected function createTestPlaceContentType()
2733
    {
2734
        $repository = $this->getRepository();
2735
        $contentTypeService = $repository->getContentTypeService();
2736
2737
        $createStruct = $contentTypeService->newContentTypeCreateStruct('testtype');
2738
        $createStruct->mainLanguageCode = 'eng-GB';
2739
        $createStruct->names = array('eng-GB' => 'Test type');
2740
        $createStruct->creatorId = 14;
2741
        $createStruct->creationDate = new \DateTime();
2742
2743
        $translatableFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('maplocation', 'ezgmaplocation');
2744
        $translatableFieldCreate->names = array('eng-GB' => 'Map location field');
2745
        $translatableFieldCreate->fieldGroup = 'main';
2746
        $translatableFieldCreate->position = 1;
2747
        $translatableFieldCreate->isTranslatable = false;
2748
        $translatableFieldCreate->isSearchable = true;
2749
2750
        $createStruct->addFieldDefinition($translatableFieldCreate);
2751
2752
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
2753
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, array($contentGroup));
2754
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
2755
        $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...
2756
2757
        return $contentType;
2758
    }
2759
2760
    /**
2761
     * Test for the findContent() method.
2762
     *
2763
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2764
     * @group maplocation
2765
     */
2766 View Code Duplication
    public function testMapLocationDistanceLessThanOrEqual()
2767
    {
2768
        $contentType = $this->createTestPlaceContentType();
2769
2770
        // Create a draft to account for behaviour with ContentType in different states
2771
        $repository = $this->getRepository();
2772
        $contentTypeService = $repository->getContentTypeService();
2773
        $contentService = $repository->getContentService();
2774
        $contentTypeService->createContentTypeDraft($contentType);
2775
2776
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2777
        $createStruct->alwaysAvailable = false;
2778
        $createStruct->mainLanguageCode = 'eng-GB';
2779
        $createStruct->setField(
2780
            'maplocation',
2781
            array(
2782
                'latitude' => 45.894877,
2783
                'longitude' => 15.972699,
2784
                'address' => 'Here be wild boars',
2785
            ),
2786
            'eng-GB'
2787
        );
2788
2789
        $draft = $contentService->createContent($createStruct);
2790
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
2791
2792
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2793
        $createStruct->alwaysAvailable = false;
2794
        $createStruct->mainLanguageCode = 'eng-GB';
2795
        $createStruct->setField(
2796
            'maplocation',
2797
            array(
2798
                'latitude' => 45.927334,
2799
                'longitude' => 15.934847,
2800
                'address' => 'A lone tree',
2801
            ),
2802
            'eng-GB'
2803
        );
2804
2805
        $draft = $contentService->createContent($createStruct);
2806
        $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...
2807
2808
        $this->refreshSearch($repository);
2809
2810
        $query = new Query(
2811
            array(
2812
                'filter' => new Criterion\LogicalAnd(
2813
                    array(
2814
                        new Criterion\ContentTypeId($contentType->id),
2815
                        new Criterion\MapLocationDistance(
2816
                            'maplocation',
2817
                            Criterion\Operator::LTE,
2818
                            240,
2819
                            43.756825,
2820
                            15.775074
2821
                        ),
2822
                    )
2823
                ),
2824
                'offset' => 0,
2825
                'limit' => 10,
2826
                'sortClauses' => array(),
2827
            )
2828
        );
2829
2830
        $searchService = $repository->getSearchService();
2831
        $result = $searchService->findContent($query);
2832
2833
        $this->assertEquals(1, $result->totalCount);
2834
        $this->assertEquals(
2835
            $wildBoars->id,
2836
            $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...
2837
        );
2838
    }
2839
2840
    /**
2841
     * Test for the findContent() method.
2842
     *
2843
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2844
     * @group maplocation
2845
     */
2846 View Code Duplication
    public function testMapLocationDistanceGreaterThanOrEqual()
2847
    {
2848
        $contentType = $this->createTestPlaceContentType();
2849
2850
        // Create a draft to account for behaviour with ContentType in different states
2851
        $repository = $this->getRepository();
2852
        $contentTypeService = $repository->getContentTypeService();
2853
        $contentService = $repository->getContentService();
2854
        $contentTypeService->createContentTypeDraft($contentType);
2855
2856
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2857
        $createStruct->alwaysAvailable = false;
2858
        $createStruct->mainLanguageCode = 'eng-GB';
2859
        $createStruct->setField(
2860
            'maplocation',
2861
            array(
2862
                'latitude' => 45.894877,
2863
                'longitude' => 15.972699,
2864
                'address' => 'Here be wild boars',
2865
            ),
2866
            'eng-GB'
2867
        );
2868
2869
        $draft = $contentService->createContent($createStruct);
2870
        $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...
2871
2872
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2873
        $createStruct->alwaysAvailable = false;
2874
        $createStruct->mainLanguageCode = 'eng-GB';
2875
        $createStruct->setField(
2876
            'maplocation',
2877
            array(
2878
                'latitude' => 45.927334,
2879
                'longitude' => 15.934847,
2880
                'address' => 'A lone tree',
2881
            ),
2882
            'eng-GB'
2883
        );
2884
2885
        $draft = $contentService->createContent($createStruct);
2886
        $tree = $contentService->publishVersion($draft->getVersionInfo());
2887
2888
        $this->refreshSearch($repository);
2889
2890
        $query = new Query(
2891
            array(
2892
                'filter' => new Criterion\LogicalAnd(
2893
                    array(
2894
                        new Criterion\ContentTypeId($contentType->id),
2895
                        new Criterion\MapLocationDistance(
2896
                            'maplocation',
2897
                            Criterion\Operator::GTE,
2898
                            240,
2899
                            43.756825,
2900
                            15.775074
2901
                        ),
2902
                    )
2903
                ),
2904
                'offset' => 0,
2905
                'limit' => 10,
2906
                'sortClauses' => array(),
2907
            )
2908
        );
2909
2910
        $searchService = $repository->getSearchService();
2911
        $result = $searchService->findContent($query);
2912
2913
        $this->assertEquals(1, $result->totalCount);
2914
        $this->assertEquals(
2915
            $tree->id,
2916
            $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...
2917
        );
2918
    }
2919
2920
    /**
2921
     * Test for the findContent() method.
2922
     *
2923
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2924
     * @group maplocation
2925
     */
2926
    public function testMapLocationDistanceBetween()
2927
    {
2928
        $contentType = $this->createTestPlaceContentType();
2929
2930
        // Create a draft to account for behaviour with ContentType in different states
2931
        $repository = $this->getRepository();
2932
        $contentTypeService = $repository->getContentTypeService();
2933
        $contentService = $repository->getContentService();
2934
        $contentTypeService->createContentTypeDraft($contentType);
2935
2936
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2937
        $createStruct->alwaysAvailable = false;
2938
        $createStruct->mainLanguageCode = 'eng-GB';
2939
        $createStruct->setField(
2940
            'maplocation',
2941
            array(
2942
                'latitude' => 45.894877,
2943
                'longitude' => 15.972699,
2944
                'address' => 'Here be wild boars',
2945
            ),
2946
            'eng-GB'
2947
        );
2948
2949
        $draft = $contentService->createContent($createStruct);
2950
        $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...
2951
2952
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2953
        $createStruct->alwaysAvailable = false;
2954
        $createStruct->mainLanguageCode = 'eng-GB';
2955
        $createStruct->setField(
2956
            'maplocation',
2957
            array(
2958
                'latitude' => 45.927334,
2959
                'longitude' => 15.934847,
2960
                'address' => 'A lone tree',
2961
            ),
2962
            'eng-GB'
2963
        );
2964
2965
        $draft = $contentService->createContent($createStruct);
2966
        $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...
2967
2968
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2969
        $createStruct->alwaysAvailable = false;
2970
        $createStruct->mainLanguageCode = 'eng-GB';
2971
        $createStruct->setField(
2972
            'maplocation',
2973
            array(
2974
                'latitude' => 45.903777,
2975
                'longitude' => 15.958788,
2976
                'address' => 'Meadow with mushrooms',
2977
            ),
2978
            'eng-GB'
2979
        );
2980
2981
        $draft = $contentService->createContent($createStruct);
2982
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
2983
2984
        $this->refreshSearch($repository);
2985
2986
        $query = new Query(
2987
            array(
2988
                'filter' => new Criterion\LogicalAnd(
2989
                    array(
2990
                        new Criterion\ContentTypeId($contentType->id),
2991
                        new Criterion\MapLocationDistance(
2992
                            'maplocation',
2993
                            Criterion\Operator::BETWEEN,
2994
                            array(239, 241),
2995
                            43.756825,
2996
                            15.775074
2997
                        ),
2998
                    )
2999
                ),
3000
                'offset' => 0,
3001
                'limit' => 10,
3002
                'sortClauses' => array(),
3003
            )
3004
        );
3005
3006
        $searchService = $repository->getSearchService();
3007
        $result = $searchService->findContent($query);
3008
3009
        $this->assertEquals(1, $result->totalCount);
3010
        $this->assertEquals(
3011
            $mushrooms->id,
3012
            $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...
3013
        );
3014
    }
3015
3016
    /**
3017
     * Test for the findContent() method.
3018
     *
3019
     * This tests the distance over the pole. The tests intentionally uses large range,
3020
     * as the flat Earth model used in Legacy Storage Search is not precise for the use case.
3021
     * What is tested here is that outer bounding box is correctly calculated, so that
3022
     * location is not excluded.
3023
     *
3024
     * Range between 222km and 350km shows the magnitude of error between great-circle
3025
     * (always very precise) and flat Earth (very imprecise for this use case) models.
3026
     *
3027
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3028
     * @group maplocation
3029
     */
3030
    public function testMapLocationDistanceBetweenPolar()
3031
    {
3032
        $contentType = $this->createTestPlaceContentType();
3033
3034
        // Create a draft to account for behaviour with ContentType in different states
3035
        $repository = $this->getRepository();
3036
        $contentTypeService = $repository->getContentTypeService();
3037
        $contentService = $repository->getContentService();
3038
        $contentTypeService->createContentTypeDraft($contentType);
3039
3040
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3041
        $createStruct->alwaysAvailable = false;
3042
        $createStruct->mainLanguageCode = 'eng-GB';
3043
        $createStruct->setField(
3044
            'maplocation',
3045
            array(
3046
                'latitude' => 89,
3047
                'longitude' => -164,
3048
                'address' => 'Polar bear media tower',
3049
            ),
3050
            'eng-GB'
3051
        );
3052
3053
        $draft = $contentService->createContent($createStruct);
3054
        $polarBear = $contentService->publishVersion($draft->getVersionInfo());
3055
3056
        $this->refreshSearch($repository);
3057
3058
        $query = new Query(
3059
            array(
3060
                'filter' => new Criterion\LogicalAnd(
3061
                    array(
3062
                        new Criterion\ContentTypeId($contentType->id),
3063
                        new Criterion\MapLocationDistance(
3064
                            'maplocation',
3065
                            Criterion\Operator::BETWEEN,
3066
                            array(221, 350),
3067
                            89,
3068
                            16
3069
                        ),
3070
                    )
3071
                ),
3072
                'offset' => 0,
3073
                'limit' => 10,
3074
                'sortClauses' => array(),
3075
            )
3076
        );
3077
3078
        $searchService = $repository->getSearchService();
3079
        $result = $searchService->findContent($query);
3080
3081
        $this->assertEquals(1, $result->totalCount);
3082
        $this->assertEquals(
3083
            $polarBear->id,
3084
            $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...
3085
        );
3086
    }
3087
3088
    /**
3089
     * Test for the findContent() method.
3090
     *
3091
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3092
     * @group maplocation
3093
     */
3094 View Code Duplication
    public function testMapLocationDistanceSortAscending()
3095
    {
3096
        $contentType = $this->createTestPlaceContentType();
3097
3098
        // Create a draft to account for behaviour with ContentType in different states
3099
        $repository = $this->getRepository();
3100
        $contentTypeService = $repository->getContentTypeService();
3101
        $contentService = $repository->getContentService();
3102
        $contentTypeService->createContentTypeDraft($contentType);
3103
3104
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3105
        $createStruct->alwaysAvailable = false;
3106
        $createStruct->mainLanguageCode = 'eng-GB';
3107
        $createStruct->setField(
3108
            'maplocation',
3109
            array(
3110
                'latitude' => 45.894877,
3111
                'longitude' => 15.972699,
3112
                'address' => 'Here be wild boars',
3113
            ),
3114
            'eng-GB'
3115
        );
3116
3117
        $draft = $contentService->createContent($createStruct);
3118
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3119
3120
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3121
        $createStruct->alwaysAvailable = false;
3122
        $createStruct->mainLanguageCode = 'eng-GB';
3123
        $createStruct->setField(
3124
            'maplocation',
3125
            array(
3126
                'latitude' => 45.927334,
3127
                'longitude' => 15.934847,
3128
                'address' => 'A lone tree',
3129
            ),
3130
            'eng-GB'
3131
        );
3132
3133
        $draft = $contentService->createContent($createStruct);
3134
        $tree = $contentService->publishVersion($draft->getVersionInfo());
3135
3136
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3137
        $createStruct->alwaysAvailable = false;
3138
        $createStruct->mainLanguageCode = 'eng-GB';
3139
        $createStruct->setField(
3140
            'maplocation',
3141
            array(
3142
                'latitude' => 45.903777,
3143
                'longitude' => 15.958788,
3144
                'address' => 'Meadow with mushrooms',
3145
            ),
3146
            'eng-GB'
3147
        );
3148
3149
        $draft = $contentService->createContent($createStruct);
3150
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3151
3152
        $this->refreshSearch($repository);
3153
3154
        $wellInVodice = array(
3155
            'latitude' => 43.756825,
3156
            'longitude' => 15.775074,
3157
        );
3158
3159
        $query = new Query(
3160
            array(
3161
                'filter' => new Criterion\LogicalAnd(
3162
                    array(
3163
                        new Criterion\ContentTypeId($contentType->id),
3164
                        new Criterion\MapLocationDistance(
3165
                            'maplocation',
3166
                            Criterion\Operator::GTE,
3167
                            235,
3168
                            $wellInVodice['latitude'],
3169
                            $wellInVodice['longitude']
3170
                        ),
3171
                    )
3172
                ),
3173
                'offset' => 0,
3174
                'limit' => 10,
3175
                'sortClauses' => array(
3176
                    new SortClause\MapLocationDistance(
3177
                        'testtype',
3178
                        'maplocation',
3179
                        $wellInVodice['latitude'],
3180
                        $wellInVodice['longitude'],
3181
                        Query::SORT_ASC
3182
                    ),
3183
                ),
3184
            )
3185
        );
3186
3187
        $searchService = $repository->getSearchService();
3188
        $result = $searchService->findContent($query);
3189
3190
        $this->assertEquals(3, $result->totalCount);
3191
        $this->assertEquals(
3192
            $wildBoars->id,
3193
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

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

<?php

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

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

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

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

}

If the property has read access only, you can use the @property-read annotation instead.

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

See also the PhpDoc documentation for @property.

Loading history...
3194
        );
3195
        $this->assertEquals(
3196
            $mushrooms->id,
3197
            $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...
3198
        );
3199
        $this->assertEquals(
3200
            $tree->id,
3201
            $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...
3202
        );
3203
    }
3204
3205
    /**
3206
     * Test for the findContent() method.
3207
     *
3208
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3209
     * @group maplocation
3210
     */
3211 View Code Duplication
    public function testMapLocationDistanceSortDescending()
3212
    {
3213
        $contentType = $this->createTestPlaceContentType();
3214
3215
        // Create a draft to account for behaviour with ContentType in different states
3216
        $repository = $this->getRepository();
3217
        $contentTypeService = $repository->getContentTypeService();
3218
        $contentService = $repository->getContentService();
3219
        $contentTypeService->createContentTypeDraft($contentType);
3220
3221
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3222
        $createStruct->alwaysAvailable = false;
3223
        $createStruct->mainLanguageCode = 'eng-GB';
3224
        $createStruct->setField(
3225
            'maplocation',
3226
            array(
3227
                'latitude' => 45.894877,
3228
                'longitude' => 15.972699,
3229
                'address' => 'Here be wild boars',
3230
            ),
3231
            'eng-GB'
3232
        );
3233
3234
        $draft = $contentService->createContent($createStruct);
3235
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3236
3237
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3238
        $createStruct->alwaysAvailable = false;
3239
        $createStruct->mainLanguageCode = 'eng-GB';
3240
        $createStruct->setField(
3241
            'maplocation',
3242
            array(
3243
                'latitude' => 45.927334,
3244
                'longitude' => 15.934847,
3245
                'address' => 'A lone tree',
3246
            ),
3247
            'eng-GB'
3248
        );
3249
3250
        $draft = $contentService->createContent($createStruct);
3251
        $tree = $contentService->publishVersion($draft->getVersionInfo());
3252
3253
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3254
        $createStruct->alwaysAvailable = false;
3255
        $createStruct->mainLanguageCode = 'eng-GB';
3256
        $createStruct->setField(
3257
            'maplocation',
3258
            array(
3259
                'latitude' => 45.903777,
3260
                'longitude' => 15.958788,
3261
                'address' => 'Meadow with mushrooms',
3262
            ),
3263
            'eng-GB'
3264
        );
3265
3266
        $draft = $contentService->createContent($createStruct);
3267
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3268
3269
        $this->refreshSearch($repository);
3270
3271
        $well = array(
3272
            'latitude' => 43.756825,
3273
            'longitude' => 15.775074,
3274
        );
3275
3276
        $query = new Query(
3277
            array(
3278
                'filter' => new Criterion\LogicalAnd(
3279
                    array(
3280
                        new Criterion\ContentTypeId($contentType->id),
3281
                        new Criterion\MapLocationDistance(
3282
                            'maplocation',
3283
                            Criterion\Operator::GTE,
3284
                            235,
3285
                            $well['latitude'],
3286
                            $well['longitude']
3287
                        ),
3288
                    )
3289
                ),
3290
                'offset' => 0,
3291
                'limit' => 10,
3292
                'sortClauses' => array(
3293
                    new SortClause\MapLocationDistance(
3294
                        'testtype',
3295
                        'maplocation',
3296
                        $well['latitude'],
3297
                        $well['longitude'],
3298
                        Query::SORT_DESC
3299
                    ),
3300
                ),
3301
            )
3302
        );
3303
3304
        $searchService = $repository->getSearchService();
3305
        $result = $searchService->findContent($query);
3306
3307
        $this->assertEquals(3, $result->totalCount);
3308
        $this->assertEquals(
3309
            $wildBoars->id,
3310
            $result->searchHits[2]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

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

<?php

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

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

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

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

}

If the property has read access only, you can use the @property-read annotation instead.

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

See also the PhpDoc documentation for @property.

Loading history...
3311
        );
3312
        $this->assertEquals(
3313
            $mushrooms->id,
3314
            $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...
3315
        );
3316
        $this->assertEquals(
3317
            $tree->id,
3318
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

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

<?php

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

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

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

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

}

If the property has read access only, you can use the @property-read annotation instead.

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

See also the PhpDoc documentation for @property.

Loading history...
3319
        );
3320
    }
3321
3322
    /**
3323
     * Test for the findContent() method.
3324
     *
3325
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3326
     * @group maplocation
3327
     */
3328
    public function testMapLocationDistanceWithCustomField()
3329
    {
3330
        $setupFactory = $this->getSetupFactory();
3331
        if ($setupFactory instanceof LegacyElasticsearch) {
3332
            $this->markTestIncomplete("TODO: Some issues with 'copy_to' and 'geo_point'");
3333
        }
3334
3335
        $contentType = $this->createTestPlaceContentType();
3336
3337
        // Create a draft to account for behaviour with ContentType in different states
3338
        $repository = $this->getRepository();
3339
        $contentTypeService = $repository->getContentTypeService();
3340
        $contentService = $repository->getContentService();
3341
        $contentTypeService->createContentTypeDraft($contentType);
3342
3343
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3344
        $createStruct->alwaysAvailable = false;
3345
        $createStruct->mainLanguageCode = 'eng-GB';
3346
        $createStruct->setField(
3347
            'maplocation',
3348
            array(
3349
                'latitude' => 45.894877,
3350
                'longitude' => 15.972699,
3351
                'address' => 'Here be wild boars',
3352
            ),
3353
            'eng-GB'
3354
        );
3355
3356
        $draft = $contentService->createContent($createStruct);
3357
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3358
3359
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3360
        $createStruct->alwaysAvailable = false;
3361
        $createStruct->mainLanguageCode = 'eng-GB';
3362
        $createStruct->setField(
3363
            'maplocation',
3364
            array(
3365
                'latitude' => 45.927334,
3366
                'longitude' => 15.934847,
3367
                'address' => 'A lone tree',
3368
            ),
3369
            'eng-GB'
3370
        );
3371
3372
        $draft = $contentService->createContent($createStruct);
3373
        $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...
3374
3375
        $this->refreshSearch($repository);
3376
3377
        $distanceCriterion = new Criterion\MapLocationDistance(
3378
            'maplocation',
3379
            Criterion\Operator::LTE,
3380
            240,
3381
            43.756825,
3382
            15.775074
3383
        );
3384
        $distanceCriterion->setCustomField('testtype', 'maplocation', 'custom_geolocation_field');
3385
3386
        $query = new Query(
3387
            array(
3388
                'filter' => new Criterion\LogicalAnd(
3389
                    array(
3390
                        new Criterion\ContentTypeId($contentType->id),
3391
                        $distanceCriterion,
3392
                    )
3393
                ),
3394
                'offset' => 0,
3395
                'limit' => 10,
3396
                'sortClauses' => array(),
3397
            )
3398
        );
3399
3400
        $searchService = $repository->getSearchService();
3401
        $result = $searchService->findContent($query);
3402
3403
        $this->assertEquals(1, $result->totalCount);
3404
        $this->assertEquals(
3405
            $wildBoars->id,
3406
            $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...
3407
        );
3408
    }
3409
3410
    /**
3411
     * Test for the findContent() method.
3412
     *
3413
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3414
     * @group maplocation
3415
     */
3416
    public function testMapLocationDistanceWithCustomFieldSort()
3417
    {
3418
        $setupFactory = $this->getSetupFactory();
3419
        if ($setupFactory instanceof LegacyElasticsearch) {
3420
            $this->markTestIncomplete("TODO: Some issues with 'copy_to' and 'geo_point'");
3421
        }
3422
3423
        $contentType = $this->createTestPlaceContentType();
3424
3425
        // Create a draft to account for behaviour with ContentType in different states
3426
        $repository = $this->getRepository();
3427
        $contentTypeService = $repository->getContentTypeService();
3428
        $contentService = $repository->getContentService();
3429
        $contentTypeService->createContentTypeDraft($contentType);
3430
3431
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3432
        $createStruct->alwaysAvailable = false;
3433
        $createStruct->mainLanguageCode = 'eng-GB';
3434
        $createStruct->setField(
3435
            'maplocation',
3436
            array(
3437
                'latitude' => 45.894877,
3438
                'longitude' => 15.972699,
3439
                'address' => 'Here be wild boars',
3440
            ),
3441
            'eng-GB'
3442
        );
3443
3444
        $draft = $contentService->createContent($createStruct);
3445
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3446
3447
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3448
        $createStruct->alwaysAvailable = false;
3449
        $createStruct->mainLanguageCode = 'eng-GB';
3450
        $createStruct->setField(
3451
            'maplocation',
3452
            array(
3453
                'latitude' => 45.927334,
3454
                'longitude' => 15.934847,
3455
                'address' => 'A lone tree',
3456
            ),
3457
            'eng-GB'
3458
        );
3459
3460
        $draft = $contentService->createContent($createStruct);
3461
        $tree = $contentService->publishVersion($draft->getVersionInfo());
3462
3463
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3464
        $createStruct->alwaysAvailable = false;
3465
        $createStruct->mainLanguageCode = 'eng-GB';
3466
        $createStruct->setField(
3467
            'maplocation',
3468
            array(
3469
                'latitude' => 45.903777,
3470
                'longitude' => 15.958788,
3471
                'address' => 'Meadow with mushrooms',
3472
            ),
3473
            'eng-GB'
3474
        );
3475
3476
        $draft = $contentService->createContent($createStruct);
3477
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3478
3479
        $this->refreshSearch($repository);
3480
3481
        $well = array(
3482
            'latitude' => 43.756825,
3483
            'longitude' => 15.775074,
3484
        );
3485
3486
        $sortClause = new SortClause\MapLocationDistance(
3487
            'testtype',
3488
            'maplocation',
3489
            $well['latitude'],
3490
            $well['longitude'],
3491
            Query::SORT_DESC
3492
        );
3493
        $sortClause->setCustomField('testtype', 'maplocation', 'custom_geolocation_field');
3494
3495
        $query = new Query(
3496
            array(
3497
                'filter' => new Criterion\LogicalAnd(
3498
                    array(
3499
                        new Criterion\ContentTypeId($contentType->id),
3500
                        new Criterion\MapLocationDistance(
3501
                            'maplocation',
3502
                            Criterion\Operator::GTE,
3503
                            235,
3504
                            $well['latitude'],
3505
                            $well['longitude']
3506
                        ),
3507
                    )
3508
                ),
3509
                'offset' => 0,
3510
                'limit' => 10,
3511
                'sortClauses' => array(
3512
                    $sortClause,
3513
                ),
3514
            )
3515
        );
3516
3517
        $searchService = $repository->getSearchService();
3518
        $result = $searchService->findContent($query);
3519
3520
        $this->assertEquals(3, $result->totalCount);
3521
        $this->assertEquals(
3522
            $wildBoars->id,
3523
            $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...
3524
        );
3525
        $this->assertEquals(
3526
            $mushrooms->id,
3527
            $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...
3528
        );
3529
        $this->assertEquals(
3530
            $tree->id,
3531
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

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

<?php

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

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

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

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

}

If the property has read access only, you can use the @property-read annotation instead.

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

See also the PhpDoc documentation for @property.

Loading history...
3532
        );
3533
    }
3534
3535
    /**
3536
     * Test for the findLocations() method.
3537
     *
3538
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3539
     */
3540 View Code Duplication
    public function testFindMainLocation()
3541
    {
3542
        $plainSiteLocationId = 56;
3543
        $designLocationId = 58;
3544
        $partnersContentId = 59;
3545
        $repository = $this->getRepository();
3546
        $locationService = $repository->getLocationService();
3547
        $contentService = $repository->getContentService();
3548
3549
        // Add secondary Location for "Partners" user group, under "Design" page
3550
        $locationService->createLocation(
3551
            $contentService->loadContentInfo($partnersContentId),
3552
            $locationService->newLocationCreateStruct($designLocationId)
3553
        );
3554
3555
        $this->refreshSearch($repository);
3556
3557
        $query = new LocationQuery(
3558
            array(
3559
                'filter' => new Criterion\LogicalAnd(
3560
                    array(
3561
                        new Criterion\ParentLocationId($designLocationId),
3562
                        new Criterion\Location\IsMainLocation(
3563
                            Criterion\Location\IsMainLocation::MAIN
3564
                        ),
3565
                    )
3566
                ),
3567
                'offset' => 0,
3568
                'limit' => 10,
3569
                'sortClauses' => array(),
3570
            )
3571
        );
3572
3573
        $searchService = $repository->getSearchService();
3574
        $result = $searchService->findLocations($query);
3575
3576
        $this->assertEquals(1, $result->totalCount);
3577
        $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...
3578
    }
3579
3580
    /**
3581
     * Test for the findLocations() method.
3582
     *
3583
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3584
     */
3585 View Code Duplication
    public function testFindNonMainLocation()
3586
    {
3587
        $designLocationId = 58;
3588
        $partnersContentId = 59;
3589
        $repository = $this->getRepository();
3590
        $locationService = $repository->getLocationService();
3591
        $contentService = $repository->getContentService();
3592
3593
        // Add secondary Location for "Partners" user group, under "Design" page
3594
        $newLocation = $locationService->createLocation(
3595
            $contentService->loadContentInfo($partnersContentId),
3596
            $locationService->newLocationCreateStruct($designLocationId)
3597
        );
3598
3599
        $this->refreshSearch($repository);
3600
3601
        $query = new LocationQuery(
3602
            array(
3603
                'filter' => new Criterion\LogicalAnd(
3604
                    array(
3605
                        new Criterion\ParentLocationId($designLocationId),
3606
                        new Criterion\Location\IsMainLocation(
3607
                            Criterion\Location\IsMainLocation::NOT_MAIN
3608
                        ),
3609
                    )
3610
                ),
3611
                'offset' => 0,
3612
                'limit' => 10,
3613
                'sortClauses' => array(),
3614
            )
3615
        );
3616
3617
        $searchService = $repository->getSearchService();
3618
        $result = $searchService->findLocations($query);
3619
3620
        $this->assertEquals(1, $result->totalCount);
3621
        $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...
3622
    }
3623
3624
    /**
3625
     * Test for the findLocations() method.
3626
     *
3627
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3628
     */
3629 View Code Duplication
    public function testSortMainLocationAscending()
3630
    {
3631
        $plainSiteLocationId = 56;
3632
        $designLocationId = 58;
3633
        $partnersContentId = 59;
3634
        $repository = $this->getRepository();
3635
        $locationService = $repository->getLocationService();
3636
        $contentService = $repository->getContentService();
3637
3638
        // Add secondary Location for "Partners" user group, under "Design" page
3639
        $newLocation = $locationService->createLocation(
3640
            $contentService->loadContentInfo($partnersContentId),
3641
            $locationService->newLocationCreateStruct($designLocationId)
3642
        );
3643
3644
        $this->refreshSearch($repository);
3645
3646
        $query = new LocationQuery(
3647
            array(
3648
                'filter' => new Criterion\ParentLocationId($designLocationId),
3649
                'offset' => 0,
3650
                'limit' => 10,
3651
                'sortClauses' => array(
3652
                    new SortClause\Location\IsMainLocation(
3653
                        LocationQuery::SORT_ASC
3654
                    ),
3655
                ),
3656
            )
3657
        );
3658
3659
        $searchService = $repository->getSearchService();
3660
        $result = $searchService->findLocations($query);
3661
3662
        $this->assertEquals(2, $result->totalCount);
3663
        $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...
3664
        $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...
3665
    }
3666
3667
    /**
3668
     * Test for the findLocations() method.
3669
     *
3670
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3671
     */
3672 View Code Duplication
    public function testSortMainLocationDescending()
3673
    {
3674
        $plainSiteLocationId = 56;
3675
        $designLocationId = 58;
3676
        $partnersContentId = 59;
3677
        $repository = $this->getRepository();
3678
        $locationService = $repository->getLocationService();
3679
        $contentService = $repository->getContentService();
3680
3681
        // Add secondary Location for "Partners" user group, under "Design" page
3682
        $newLocation = $locationService->createLocation(
3683
            $contentService->loadContentInfo($partnersContentId),
3684
            $locationService->newLocationCreateStruct($designLocationId)
3685
        );
3686
3687
        $this->refreshSearch($repository);
3688
3689
        $query = new LocationQuery(
3690
            array(
3691
                'filter' => new Criterion\ParentLocationId($designLocationId),
3692
                'offset' => 0,
3693
                'limit' => 10,
3694
                'sortClauses' => array(
3695
                    new SortClause\Location\IsMainLocation(
3696
                        LocationQuery::SORT_DESC
3697
                    ),
3698
                ),
3699
            )
3700
        );
3701
3702
        $searchService = $repository->getSearchService();
3703
        $result = $searchService->findLocations($query);
3704
3705
        $this->assertEquals(2, $result->totalCount);
3706
        $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...
3707
        $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...
3708
    }
3709
3710
    /**
3711
     * Test for the findLocations() method.
3712
     *
3713
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3714
     */
3715
    public function testContentWithMultipleLocations()
3716
    {
3717
        $repository = $this->getRepository();
3718
        $contentService = $repository->getContentService();
3719
        $contentTypeService = $repository->getContentTypeService();
3720
        $locationService = $repository->getLocationService();
3721
3722
        $forumType = $contentTypeService->loadContentTypeByIdentifier('forum');
3723
3724
        $createStruct = $contentService->newContentCreateStruct($forumType, 'eng-GB');
3725
        $createStruct->alwaysAvailable = false;
3726
        $createStruct->setField('name', 'An awesome duplicate forum');
3727
3728
        $draft = $contentService->createContent($createStruct);
3729
        $content = $contentService->publishVersion($draft->getVersionInfo());
3730
3731
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
3732
        $location1 = $locationService->createLocation($content->contentInfo, $locationCreateStruct);
3733
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(5);
3734
        $location2 = $locationService->createLocation($content->contentInfo, $locationCreateStruct);
3735
3736
        $this->refreshSearch($repository);
3737
3738
        $query = new LocationQuery(
3739
            array(
3740
                'filter' => new Criterion\ContentId($content->id),
3741
                'sortClauses' => array(
3742
                    new SortClause\Location\Id(LocationQuery::SORT_ASC),
3743
                ),
3744
            )
3745
        );
3746
3747
        $searchService = $repository->getSearchService();
3748
        $result = $searchService->findLocations($query);
3749
3750
        $this->assertEquals(2, $result->totalCount);
3751
        $this->assertEquals(
3752
            $location1->id,
3753
            $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...
3754
        );
3755
        $this->assertEquals(
3756
            $location2->id,
3757
            $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...
3758
        );
3759
    }
3760
3761
    protected function createContentForTestUserMetadataGroupHorizontal()
3762
    {
3763
        $repository = $this->getRepository();
3764
        $contentService = $repository->getContentService();
3765
        $contentTypeService = $repository->getContentTypeService();
3766
        $locationService = $repository->getLocationService();
3767
        $userService = $repository->getUserService();
3768
        $administratorUser = $repository->getCurrentUser();
3769
        // ID of the "Administrators" user group in an eZ Publish demo installation
3770
        $administratorsUserGroupId = 12;
3771
        // ID of the "Editors" user group in an eZ Publish demo installation
3772
        $editorsUserGroupId = 13;
3773
3774
        $administratorsUserGroup = $userService->loadUserGroup($administratorsUserGroupId);
3775
        $editorsUserGroup = $userService->loadUserGroup($editorsUserGroupId);
3776
3777
        // Add additional Location for Administrators UserGroup under Editors UserGroup Location
3778
        $locationCreateStruct = $locationService->newLocationCreateStruct(
3779
            $editorsUserGroup->contentInfo->mainLocationId
3780
        );
3781
        $newAdministratorsUserGroupLocation = $locationService->createLocation(
3782
            $administratorsUserGroup->contentInfo,
3783
            $locationCreateStruct
3784
        );
3785
3786
        // Add additional Location for administrator user under newly created UserGroup Location
3787
        $locationCreateStruct = $locationService->newLocationCreateStruct(
3788
            $newAdministratorsUserGroupLocation->id
3789
        );
3790
        $locationService->createLocation(
3791
            $administratorUser->contentInfo,
3792
            $locationCreateStruct
3793
        );
3794
3795
        // Create a Content to be found through Editors UserGroup id.
3796
        // This ensures data is indexed, it could also be done by updating metadata of
3797
        // an existing Content, but slot would need to reindex Content and that should
3798
        // be tested elsewhere (dedicated indexing integration tests, missing ATM).
3799
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
3800
3801
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3802
        $createStruct->setField('name', 'test');
3803
3804
        $locationCreateStruct = $locationService->newLocationCreateStruct(2);
3805
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
3806
        $content = $contentService->publishVersion($draft->getVersionInfo());
3807
        $contentTypeService->createContentTypeDraft($contentType);
3808
3809
        $this->refreshSearch($repository);
3810
3811
        return $content;
3812
    }
3813
3814
    /**
3815
     * Test for the findContent() method.
3816
     *
3817
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3818
     */
3819
    public function testUserMetadataGroupHorizontalFilterContent($queryType = null)
3820
    {
3821
        if ($queryType === null) {
3822
            $queryType = 'filter';
3823
        }
3824
3825
        $repository = $this->getRepository();
3826
        $searchService = $repository->getSearchService();
3827
        $editorsUserGroupId = 13;
3828
3829
        $content = $this->createContentForTestUserMetadataGroupHorizontal();
3830
3831
        $criteria = array();
3832
        $setupFactory = $this->getSetupFactory();
3833
3834
        // Do not limit for LSE, as it does not not require reindexing.
3835
        // See explanation below.
3836
        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...
3837
            $criteria[] = new Criterion\ContentTypeIdentifier('folder');
3838
        }
3839
3840
        $criteria[] = new Criterion\UserMetadata(
3841
            Criterion\UserMetadata::GROUP,
3842
            Criterion\Operator::EQ,
3843
            $editorsUserGroupId
3844
        );
3845
3846
        $query = new Query(
3847
            array(
3848
                $queryType => new Criterion\LogicalAnd($criteria),
3849
                'sortClauses' => array(
3850
                    new SortClause\ContentId(),
3851
                ),
3852
                'limit' => 50,
3853
            )
3854
        );
3855
3856
        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...
3857
            $result = $searchService->findContent($query);
3858
3859
            // Administrator User is owned by itself, when additional Locations are added
3860
            // it should be reindexed and its UserGroups will updated, which means it should
3861
            // also be found as a Content of Editors UserGroup. However we do not handle this
3862
            // in slots yet, and also miss SPI methods to do it without using Search (also
3863
            // needed to decouple services), because as indexing is asynchronous Search
3864
            // should not eat its own dog food for reindexing.
3865
            $this->assertEquals(1, $result->totalCount);
3866
3867
            $this->assertEquals(
3868
                $content->id,
3869
                $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...
3870
            );
3871
        } else {
3872
            // This is how it should eventually work for all search engines,
3873
            // with required reindexing slots properly implemented.
3874
3875
            $result = $searchService->findContent($query);
3876
3877
            // Assert last hit manually, as id will change because it is created in test
3878
            // and not present it base fixture.
3879
            $foundContent1 = array_pop($result->searchHits);
3880
            $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...
3881
            $this->assertEquals($content->id, $foundContent1->valueObject->id);
3882
3883
            $this->simplifySearchResult($result);
3884
            $this->assertEquals(
3885
                include $this->getFixtureDir() . '/UserMetadata.php',
3886
                $result,
3887
                'Search results do not match.',
3888
                .1 // Be quite generous regarding delay -- most important for scores
3889
            );
3890
        }
3891
    }
3892
3893
    /**
3894
     * Test for the findContent() method.
3895
     *
3896
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3897
     */
3898
    public function testUserMetadataGroupHorizontalQueryContent()
3899
    {
3900
        $this->testUserMetadataGroupHorizontalFilterContent('query');
3901
    }
3902
3903
    /**
3904
     * Test for the findLocations() method.
3905
     *
3906
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3907
     */
3908
    public function testUserMetadataGroupHorizontalFilterLocation($queryType = null)
3909
    {
3910
        if ($queryType === null) {
3911
            $queryType = 'filter';
3912
        }
3913
3914
        $repository = $this->getRepository();
3915
        $searchService = $repository->getSearchService();
3916
        $editorsUserGroupId = 13;
3917
3918
        $content = $this->createContentForTestUserMetadataGroupHorizontal();
3919
3920
        $criteria = array();
3921
        $setupFactory = $this->getSetupFactory();
3922
3923
        // Do not limit for LSE, as it does not not require reindexing.
3924
        // See explanation below.
3925
        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...
3926
            $criteria[] = new Criterion\ContentTypeIdentifier('folder');
3927
        }
3928
3929
        $criteria[] = new Criterion\UserMetadata(
3930
            Criterion\UserMetadata::GROUP,
3931
            Criterion\Operator::EQ,
3932
            $editorsUserGroupId
3933
        );
3934
3935
        $query = new LocationQuery(
3936
            array(
3937
                $queryType => new Criterion\LogicalAnd($criteria),
3938
                'sortClauses' => array(
3939
                    new SortClause\Location\Id(),
3940
                ),
3941
                'limit' => 50,
3942
            )
3943
        );
3944
3945
        if ($setupFactory instanceof LegacySolrSetupFactory || $setupFactory instanceof LegacyElasticsearch) {
0 ignored issues
show
Bug introduced by
The class EzSystems\EzPlatformSolr...tory\LegacySetupFactory does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
3946
            $result = $searchService->findLocations($query);
3947
3948
            // Administrator User is owned by itself, when additional Locations are added
3949
            // it should be reindexed and its UserGroups will updated, which means it should
3950
            // also be found as a Content of Editors UserGroup. However we do not handle this
3951
            // in slots yet, and also miss SPI methods to do it without using Search (also
3952
            // needed to decouple services), because as indexing is asynchronous Search
3953
            // should not eat its own dog food for reindexing.
3954
            $this->assertEquals(1, $result->totalCount);
3955
3956
            $this->assertEquals(
3957
                $content->contentInfo->mainLocationId,
3958
                $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...
3959
            );
3960
        } else {
3961
            // This is how it should eventually work for all search engines,
3962
            // with required reindexing slots properly implemented.
3963
3964
            $result = $searchService->findLocations($query);
3965
3966
            // Assert last two hits manually, as ids will change because they are created
3967
            // in test and not present in base fixture.
3968
            $foundLocation1 = array_pop($result->searchHits);
3969
            $foundLocation2 = array_pop($result->searchHits);
3970
            // Remove additional Administrators UserGroup Location
3971
            array_pop($result->searchHits);
3972
            $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...
3973
            $this->assertEquals(
3974
                $content->versionInfo->contentInfo->mainLocationId,
3975
                $foundLocation1->valueObject->id
3976
            );
3977
            $this->assertEquals(
3978
                $repository->getCurrentUser()->id,
3979
                $foundLocation2->valueObject->contentId
3980
            );
3981
3982
            $this->simplifySearchResult($result);
3983
            $this->assertEquals(
3984
                include $this->getFixtureDir() . '/UserMetadataLocation.php',
3985
                $result,
3986
                'Search results do not match.',
3987
                .1 // Be quite generous regarding delay -- most important for scores
3988
            );
3989
        }
3990
    }
3991
3992
    /**
3993
     * Test for the findLocations() method.
3994
     *
3995
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3996
     */
3997
    public function testUserMetadataGroupHorizontalQueryLocation()
3998
    {
3999
        $this->testUserMetadataGroupHorizontalFilterLocation('query');
4000
    }
4001
4002
    /**
4003
     * Test for the findContent() method.
4004
     *
4005
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4006
     */
4007
    public function testLanguageAnalysisSeparateContent()
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');
4033
4034
        $englishContent = $contentService->publishVersion(
4035
            $contentService->createContent(
4036
                $contentCreateStruct,
4037
                array($locationService->newLocationCreateStruct(2))
4038
            )->versionInfo
4039
        );
4040
4041
        $contentCreateStruct = $contentService->newContentCreateStruct(
4042
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4043
            'rus-RU'
4044
        );
4045
4046
        $contentCreateStruct->setField('name', 'foxes');
4047
4048
        $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...
4049
            $contentService->createContent(
4050
                $contentCreateStruct,
4051
                array($locationService->newLocationCreateStruct(2))
4052
            )->versionInfo
4053
        );
4054
4055
        // Only Content in English should be found, because Content in Russian
4056
        // will not be correctly stemmed
4057
        $query = new Query(
4058
            array(
4059
                'query' => new Criterion\FullText('foxing'),
4060
            )
4061
        );
4062
4063
        $searchResult = $searchService->findContent($query);
4064
4065
        $this->assertEquals(1, $searchResult->totalCount);
4066
        $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...
4067
    }
4068
4069
    /**
4070
     * Test for the findContent() method.
4071
     *
4072
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4073
     */
4074
    public function testLanguageAnalysisSameContent()
4075
    {
4076
        $setupFactory = $this->getSetupFactory();
4077
        if (!$setupFactory instanceof LegacyElasticsearch) {
4078
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4079
        }
4080
4081
        $repository = $this->getRepository();
4082
        $contentService = $repository->getContentService();
4083
        $contentTypeService = $repository->getContentTypeService();
4084
        $locationService = $repository->getLocationService();
4085
        $searchService = $repository->getSearchService();
4086
        $languageService = $repository->getContentLanguageService();
4087
4088
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4089
        $languageCreateStruct->languageCode = 'rus-RU';
4090
        $languageCreateStruct->name = 'Russian';
4091
4092
        $languageService->createLanguage($languageCreateStruct);
4093
4094
        $contentCreateStruct = $contentService->newContentCreateStruct(
4095
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4096
            'eng-GB'
4097
        );
4098
4099
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'eng-GB');
4100
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'rus-RU');
4101
4102
        $mixedContent = $contentService->publishVersion(
4103
            $contentService->createContent(
4104
                $contentCreateStruct,
4105
                array($locationService->newLocationCreateStruct(2))
4106
            )->versionInfo
4107
        );
4108
4109
        // Content will be found because translation in Russian will be correctly stemmed
4110
        $query = new Query(
4111
            array(
4112
                'query' => new Criterion\FullText('важнее'),
4113
            )
4114
        );
4115
4116
        $searchResult = $searchService->findContent($query);
4117
4118
        $this->assertEquals(1, $searchResult->totalCount);
4119
        $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...
4120
    }
4121
4122
    /**
4123
     * Test for the findContent() method.
4124
     *
4125
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4126
     */
4127
    public function testLanguageAnalysisSameContentNotFound()
4128
    {
4129
        $setupFactory = $this->getSetupFactory();
4130
        if (!$setupFactory instanceof LegacyElasticsearch) {
4131
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4132
        }
4133
4134
        $repository = $this->getRepository();
4135
        $contentService = $repository->getContentService();
4136
        $contentTypeService = $repository->getContentTypeService();
4137
        $locationService = $repository->getLocationService();
4138
        $searchService = $repository->getSearchService();
4139
        $languageService = $repository->getContentLanguageService();
4140
4141
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4142
        $languageCreateStruct->languageCode = 'rus-RU';
4143
        $languageCreateStruct->name = 'Russian';
4144
4145
        $languageService->createLanguage($languageCreateStruct);
4146
4147
        $contentCreateStruct = $contentService->newContentCreateStruct(
4148
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4149
            'eng-GB'
4150
        );
4151
4152
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'eng-GB');
4153
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'rus-RU');
4154
4155
        $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...
4156
            $contentService->createContent(
4157
                $contentCreateStruct,
4158
                array($locationService->newLocationCreateStruct(2))
4159
            )->versionInfo
4160
        );
4161
4162
        // Content should be found because translation in Russian will be correctly stemmed
4163
        $query = new Query(
4164
            array(
4165
                'query' => new Criterion\FullText('важнее'),
4166
            )
4167
        );
4168
4169
        // Filtering fields for only English will cause no match because the term will
4170
        // not be correctly stemmed
4171
        $searchResult = $searchService->findContent($query, array('languages' => array('eng-GB')));
4172
4173
        $this->assertEquals(0, $searchResult->totalCount);
4174
    }
4175
4176
    /**
4177
     * Assert that query result matches the given fixture.
4178
     *
4179
     * @param Query $query
4180
     * @param string $fixture
4181
     * @param null|callable $closure
4182
     * @param bool $info
4183
     */
4184
    protected function assertQueryFixture(Query $query, $fixture, $closure = null, $ignoreScore = true, $info = false)
4185
    {
4186
        $repository = $this->getRepository();
4187
        $searchService = $repository->getSearchService();
4188
4189
        try {
4190
            if ($query instanceof LocationQuery) {
4191
                $setupFactory = $this->getSetupFactory();
4192
                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...
4193
                    // @todo When we want to test score again by default we will need fixtures for Solr
4194
                }
4195
4196
                if ($setupFactory instanceof LegacyElasticsearch) {
4197
                    $position = strrpos($fixture, '/');
4198
                    $fixture = substr_replace($fixture, '/Location', $position, 0);
4199
                }
4200
4201
                $result = $searchService->findLocations($query);
4202
            } elseif ($query instanceof Query) {
4203
                if ($info) {
4204
                    $result = $searchService->findContentInfo($query);
4205
                } else {
4206
                    $result = $searchService->findContent($query);
4207
                }
4208
            } else {
4209
                $this->fail('Expected instance of LocationQuery or Query, got: ' . gettype($query));
4210
            }
4211
            $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...
4212
        } catch (NotImplementedException $e) {
4213
            $this->markTestSkipped(
4214
                'This feature is not supported by the current search backend: ' . $e->getMessage()
4215
            );
4216
        }
4217
4218 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...
4219
            if (isset($_ENV['ez_tests_record'])) {
4220
                file_put_contents(
4221
                    $record = $fixture . '.recording',
4222
                    "<?php\n\nreturn " . var_export($result, true) . ";\n\n"
4223
                );
4224
                $this->markTestIncomplete("No fixture available. Result recorded at $record. Result: \n" . $this->printResult($result));
4225
            } else {
4226
                $this->markTestIncomplete("No fixture available. Set \$_ENV['ez_tests_record'] to generate it.");
4227
            }
4228
        }
4229
4230
        $fixture = include $fixture;
4231
4232
        if ($closure !== null) {
4233
            $closure($fixture);
4234
            $closure($result);
4235
        }
4236
4237 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...
4238
            foreach (array($fixture, $result) as $result) {
4239
                $property = new \ReflectionProperty(get_class($result), 'maxScore');
4240
                $property->setAccessible(true);
4241
                $property->setValue($result, 0.0);
4242
4243
                foreach ($result->searchHits as $hit) {
4244
                    $property = new \ReflectionProperty(get_class($hit), 'score');
4245
                    $property->setAccessible(true);
4246
                    $property->setValue($hit, 0.0);
4247
                }
4248
            }
4249
        }
4250
4251 View Code Duplication
        foreach ($result->searchHits as $hit) {
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...
4252
            $property = new \ReflectionProperty(get_class($hit), 'index');
4253
            $property->setAccessible(true);
4254
            $property->setValue($hit, null);
4255
4256
            $property = new \ReflectionProperty(get_class($hit), 'matchedTranslation');
4257
            $property->setAccessible(true);
4258
            $property->setValue($hit, null);
4259
        }
4260
4261 View Code Duplication
        foreach ($fixture->searchHits as $hit) {
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...
4262
            $property = new \ReflectionProperty(get_class($hit), 'index');
4263
            $property->setAccessible(true);
4264
            $property->setValue($hit, null);
4265
4266
            $property = new \ReflectionProperty(get_class($hit), 'matchedTranslation');
4267
            $property->setAccessible(true);
4268
            $property->setValue($hit, null);
4269
        }
4270
4271
        $this->assertEquals(
4272
            $fixture,
4273
            $result,
4274
            'Search results do not match.',
4275
            .99 // Be quite generous regarding delay -- most important for scores
4276
        );
4277
    }
4278
4279
    /**
4280
     * Show a simplified view of the search result for manual introspection.
4281
     *
4282
     * @param SearchResult $result
4283
     *
4284
     * @return string
4285
     */
4286 View Code Duplication
    protected function printResult(SearchResult $result)
4287
    {
4288
        $printed = '';
4289
        foreach ($result->searchHits as $hit) {
4290
            $printed .= sprintf(" - %s (%s)\n", $hit->valueObject['title'], $hit->valueObject['id']);
4291
        }
4292
4293
        return $printed;
4294
    }
4295
4296
    /**
4297
     * Simplify search result.
4298
     *
4299
     * This leads to saner comparisons of results, since we do not get the full
4300
     * content objects every time.
4301
     *
4302
     * @param SearchResult $result
4303
     */
4304
    protected function simplifySearchResult(SearchResult $result)
4305
    {
4306
        $result->time = 1;
4307
4308
        foreach ($result->searchHits as $hit) {
4309
            switch (true) {
4310
                case $hit->valueObject instanceof Content:
4311 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...
4312
                    $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...
4313
                        'id' => $hit->valueObject->contentInfo->id,
4314
                        'title' => $hit->valueObject->contentInfo->name,
4315
                    );
4316
                    break;
4317
4318
                case $hit->valueObject instanceof ContentInfo:
4319
                    $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...
4320
                        'id' => $hit->valueObject->id,
4321
                        'title' => $hit->valueObject->name,
4322
                    );
4323
                    break;
4324
4325
                default:
4326
                    throw new \RuntimeException('Unknown search result hit type: ' . get_class($hit->valueObject));
4327
            }
4328
        }
4329
    }
4330
4331
    /**
4332
     * Get fixture directory.
4333
     *
4334
     * @return string
4335
     */
4336
    protected function getFixtureDir()
4337
    {
4338
        return __DIR__ . '/_fixtures/' . getenv('fixtureDir') . '/';
4339
    }
4340
4341
    /**
4342
     * For findContentInfo tests, to reuse fixtures for findContent tests.
4343
     *
4344
     * @param null|callable $closure
4345
     *
4346
     * @return callable
4347
     */
4348
    private function getContentInfoFixtureClosure($closure = null)
4349
    {
4350
        /** @var $data \eZ\Publish\API\Repository\Values\Content\Search\SearchResult */
4351
        return function (&$data) use ($closure) {
4352
            foreach ($data->searchHits as $searchHit) {
4353
                if ($searchHit->valueObject instanceof Content) {
4354
                    $searchHit->valueObject = $searchHit->valueObject->getVersionInfo()->getContentInfo();
4355
                }
4356
            }
4357
4358
            if (isset($closure)) {
4359
                $closure($data);
4360
            }
4361
        };
4362
    }
4363
}
4364