Completed
Push — test-fieldrelation-location-se... ( 97dac5...55c1a3 )
by
unknown
19:47 queued 08:05
created

SearchServiceTest::testQueryCustomField()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

Loading history...
3947
        // ID of the "Administrators" user group in an eZ Publish demo installation
3948
        $administratorsUserGroupId = 12;
3949
        // ID of the "Editors" user group in an eZ Publish demo installation
3950
        $editorsUserGroupId = 13;
3951
3952
        $administratorsUserGroup = $userService->loadUserGroup($administratorsUserGroupId);
3953
        $editorsUserGroup = $userService->loadUserGroup($editorsUserGroupId);
3954
3955
        // Add additional Location for Administrators UserGroup under Editors UserGroup Location
3956
        $locationCreateStruct = $locationService->newLocationCreateStruct(
3957
            $editorsUserGroup->contentInfo->mainLocationId
3958
        );
3959
        $newAdministratorsUserGroupLocation = $locationService->createLocation(
3960
            $administratorsUserGroup->contentInfo,
3961
            $locationCreateStruct
3962
        );
3963
3964
        // Add additional Location for administrator user under newly created UserGroup Location
3965
        $locationCreateStruct = $locationService->newLocationCreateStruct(
3966
            $newAdministratorsUserGroupLocation->id
3967
        );
3968
        $locationService->createLocation(
3969
            $administratorUser->contentInfo,
3970
            $locationCreateStruct
3971
        );
3972
3973
        // Create a Content to be found through Editors UserGroup id.
3974
        // This ensures data is indexed, it could also be done by updating metadata of
3975
        // an existing Content, but slot would need to reindex Content and that should
3976
        // be tested elsewhere (dedicated indexing integration tests, missing ATM).
3977
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
3978
3979
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3980
        $createStruct->setField('name', 'test');
3981
3982
        $locationCreateStruct = $locationService->newLocationCreateStruct(2);
3983
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
3984
        $content = $contentService->publishVersion($draft->getVersionInfo());
3985
        $contentTypeService->createContentTypeDraft($contentType);
3986
3987
        $this->refreshSearch($repository);
3988
3989
        return $content;
3990
    }
3991
3992
    /**
3993
     * Test for the findContent() method.
3994
     *
3995
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3996
     */
3997
    public function testUserMetadataGroupHorizontalFilterContent($queryType = null)
3998
    {
3999
        if ($queryType === null) {
4000
            $queryType = 'filter';
4001
        }
4002
4003
        $repository = $this->getRepository();
4004
        $searchService = $repository->getSearchService();
4005
        $editorsUserGroupId = 13;
4006
4007
        $content = $this->createContentForTestUserMetadataGroupHorizontal();
4008
4009
        $criteria = array();
4010
        $setupFactory = $this->getSetupFactory();
4011
4012
        // Do not limit for LSE, as it does not not require reindexing.
4013
        // See explanation below.
4014
        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...
4015
            $criteria[] = new Criterion\ContentTypeIdentifier('folder');
4016
        }
4017
4018
        $criteria[] = new Criterion\UserMetadata(
4019
            Criterion\UserMetadata::GROUP,
4020
            Criterion\Operator::EQ,
4021
            $editorsUserGroupId
4022
        );
4023
4024
        $query = new Query(
4025
            array(
4026
                $queryType => new Criterion\LogicalAnd($criteria),
4027
                'sortClauses' => array(
4028
                    new SortClause\ContentId(),
4029
                ),
4030
                'limit' => 50,
4031
            )
4032
        );
4033
4034
        if ($setupFactory instanceof LegacySolrSetupFactory || $setupFactory instanceof LegacyElasticsearch) {
0 ignored issues
show
Bug introduced by
The class EzSystems\EzPlatformSolr...tory\LegacySetupFactory does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

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

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

2. Missing use statement

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

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

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

Loading history...
4035
            $result = $searchService->findContent($query);
4036
4037
            // Administrator User is owned by itself, when additional Locations are added
4038
            // it should be reindexed and its UserGroups will updated, which means it should
4039
            // also be found as a Content of Editors UserGroup. However we do not handle this
4040
            // in slots yet, and also miss SPI methods to do it without using Search (also
4041
            // needed to decouple services), because as indexing is asynchronous Search
4042
            // should not eat its own dog food for reindexing.
4043
            $this->assertEquals(1, $result->totalCount);
4044
4045
            $this->assertEquals(
4046
                $content->id,
4047
                $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...
4048
            );
4049
        } else {
4050
            // This is how it should eventually work for all search engines,
4051
            // with required reindexing slots properly implemented.
4052
4053
            $result = $searchService->findContent($query);
4054
4055
            // Assert last hit manually, as id will change because it is created in test
4056
            // and not present it base fixture.
4057
            $foundContent1 = array_pop($result->searchHits);
4058
            $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...
4059
            $this->assertEquals($content->id, $foundContent1->valueObject->id);
4060
4061
            $this->simplifySearchResult($result);
4062
            $this->assertEquals(
4063
                include $this->getFixtureDir() . '/UserMetadata.php',
4064
                $result,
4065
                'Search results do not match.',
4066
                .1 // Be quite generous regarding delay -- most important for scores
4067
            );
4068
        }
4069
    }
4070
4071
    /**
4072
     * Test for the findContent() method.
4073
     *
4074
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4075
     */
4076
    public function testUserMetadataGroupHorizontalQueryContent()
4077
    {
4078
        $this->testUserMetadataGroupHorizontalFilterContent('query');
4079
    }
4080
4081
    /**
4082
     * Test for the findLocations() method.
4083
     *
4084
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
4085
     */
4086
    public function testUserMetadataGroupHorizontalFilterLocation($queryType = null)
4087
    {
4088
        if ($queryType === null) {
4089
            $queryType = 'filter';
4090
        }
4091
4092
        $repository = $this->getRepository();
4093
        $searchService = $repository->getSearchService();
4094
        $editorsUserGroupId = 13;
4095
4096
        $content = $this->createContentForTestUserMetadataGroupHorizontal();
4097
4098
        $criteria = array();
4099
        $setupFactory = $this->getSetupFactory();
4100
4101
        // Do not limit for LSE, as it does not not require reindexing.
4102
        // See explanation below.
4103
        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...
4104
            $criteria[] = new Criterion\ContentTypeIdentifier('folder');
4105
        }
4106
4107
        $criteria[] = new Criterion\UserMetadata(
4108
            Criterion\UserMetadata::GROUP,
4109
            Criterion\Operator::EQ,
4110
            $editorsUserGroupId
4111
        );
4112
4113
        $query = new LocationQuery(
4114
            array(
4115
                $queryType => new Criterion\LogicalAnd($criteria),
4116
                'sortClauses' => array(
4117
                    new SortClause\Location\Id(),
4118
                ),
4119
                'limit' => 50,
4120
            )
4121
        );
4122
4123
        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...
4124
            $result = $searchService->findLocations($query);
4125
4126
            // Administrator User is owned by itself, when additional Locations are added
4127
            // it should be reindexed and its UserGroups will updated, which means it should
4128
            // also be found as a Content of Editors UserGroup. However we do not handle this
4129
            // in slots yet, and also miss SPI methods to do it without using Search (also
4130
            // needed to decouple services), because as indexing is asynchronous Search
4131
            // should not eat its own dog food for reindexing.
4132
            $this->assertEquals(1, $result->totalCount);
4133
4134
            $this->assertEquals(
4135
                $content->contentInfo->mainLocationId,
4136
                $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...
4137
            );
4138
        } else {
4139
            // This is how it should eventually work for all search engines,
4140
            // with required reindexing slots properly implemented.
4141
4142
            $result = $searchService->findLocations($query);
4143
4144
            // Assert last two hits manually, as ids will change because they are created
4145
            // in test and not present in base fixture.
4146
            $foundLocation1 = array_pop($result->searchHits);
4147
            $foundLocation2 = array_pop($result->searchHits);
4148
            // Remove additional Administrators UserGroup Location
4149
            array_pop($result->searchHits);
4150
            $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...
4151
            $this->assertEquals(
4152
                $content->versionInfo->contentInfo->mainLocationId,
4153
                $foundLocation1->valueObject->id
4154
            );
4155
            $this->assertEquals(
4156
                $repository->getCurrentUser()->id,
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...itory::getCurrentUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::getCurrentUserReference() instead. Get current user. Loads the full user object if not already loaded, if you only need to know user id use {@see getCurrentUserReference()}

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

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

Loading history...
4157
                $foundLocation2->valueObject->contentId
4158
            );
4159
4160
            $this->simplifySearchResult($result);
4161
            $this->assertEquals(
4162
                include $this->getFixtureDir() . '/UserMetadataLocation.php',
4163
                $result,
4164
                'Search results do not match.',
4165
                .1 // Be quite generous regarding delay -- most important for scores
4166
            );
4167
        }
4168
    }
4169
4170
    /**
4171
     * Test for the findLocations() method.
4172
     *
4173
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
4174
     */
4175
    public function testUserMetadataGroupHorizontalQueryLocation()
4176
    {
4177
        $this->testUserMetadataGroupHorizontalFilterLocation('query');
4178
    }
4179
4180
    /**
4181
     * Test for FullText on the findContent() method.
4182
     *
4183
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4184
     */
4185
    public function testFullTextOnNewContent()
4186
    {
4187
        $repository = $this->getRepository();
4188
        $contentService = $repository->getContentService();
4189
        $contentTypeService = $repository->getContentTypeService();
4190
        $locationService = $repository->getLocationService();
4191
        $searchService = $repository->getSearchService();
4192
4193
        $contentCreateStruct = $contentService->newContentCreateStruct(
4194
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4195
            'eng-GB'
4196
        );
4197
4198
        $contentCreateStruct->setField('name', 'foxes');
4199
4200
        $englishContent = $contentService->publishVersion(
4201
            $contentService->createContent(
4202
                $contentCreateStruct,
4203
                array($locationService->newLocationCreateStruct(2))
4204
            )->versionInfo
4205
        );
4206
4207
        $this->refreshSearch($repository);
4208
4209
        $query = new Query(
4210
            array(
4211
                'query' => new Criterion\FullText('foxes'),
4212
            )
4213
        );
4214
4215
        $searchResult = $searchService->findContentInfo($query);
4216
4217
        $this->assertEquals(1, $searchResult->totalCount);
4218
        $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...
4219
    }
4220
4221
    /**
4222
     * Test for the findContent() method.
4223
     *
4224
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4225
     */
4226
    public function testLanguageAnalysisSeparateContent()
4227
    {
4228
        $setupFactory = $this->getSetupFactory();
4229
        if (!$setupFactory instanceof LegacyElasticsearch) {
4230
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4231
        }
4232
4233
        $repository = $this->getRepository();
4234
        $contentService = $repository->getContentService();
4235
        $contentTypeService = $repository->getContentTypeService();
4236
        $locationService = $repository->getLocationService();
4237
        $searchService = $repository->getSearchService();
4238
        $languageService = $repository->getContentLanguageService();
4239
4240
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4241
        $languageCreateStruct->languageCode = 'rus-RU';
4242
        $languageCreateStruct->name = 'Russian';
4243
4244
        $languageService->createLanguage($languageCreateStruct);
4245
4246
        $contentCreateStruct = $contentService->newContentCreateStruct(
4247
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4248
            'eng-GB'
4249
        );
4250
4251
        $contentCreateStruct->setField('name', 'foxes');
4252
4253
        $englishContent = $contentService->publishVersion(
4254
            $contentService->createContent(
4255
                $contentCreateStruct,
4256
                array($locationService->newLocationCreateStruct(2))
4257
            )->versionInfo
4258
        );
4259
4260
        $contentCreateStruct = $contentService->newContentCreateStruct(
4261
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4262
            'rus-RU'
4263
        );
4264
4265
        $contentCreateStruct->setField('name', 'foxes');
4266
4267
        $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...
4268
            $contentService->createContent(
4269
                $contentCreateStruct,
4270
                array($locationService->newLocationCreateStruct(2))
4271
            )->versionInfo
4272
        );
4273
4274
        // Only Content in English should be found, because Content in Russian
4275
        // will not be correctly stemmed
4276
        $query = new Query(
4277
            array(
4278
                'query' => new Criterion\FullText('foxing'),
4279
            )
4280
        );
4281
4282
        $searchResult = $searchService->findContent($query);
4283
4284
        $this->assertEquals(1, $searchResult->totalCount);
4285
        $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...
4286
    }
4287
4288
    /**
4289
     * Test for the findContent() method.
4290
     *
4291
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4292
     */
4293
    public function testLanguageAnalysisSameContent()
4294
    {
4295
        $setupFactory = $this->getSetupFactory();
4296
        if (!$setupFactory instanceof LegacyElasticsearch) {
4297
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4298
        }
4299
4300
        $repository = $this->getRepository();
4301
        $contentService = $repository->getContentService();
4302
        $contentTypeService = $repository->getContentTypeService();
4303
        $locationService = $repository->getLocationService();
4304
        $searchService = $repository->getSearchService();
4305
        $languageService = $repository->getContentLanguageService();
4306
4307
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4308
        $languageCreateStruct->languageCode = 'rus-RU';
4309
        $languageCreateStruct->name = 'Russian';
4310
4311
        $languageService->createLanguage($languageCreateStruct);
4312
4313
        $contentCreateStruct = $contentService->newContentCreateStruct(
4314
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4315
            'eng-GB'
4316
        );
4317
4318
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'eng-GB');
4319
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'rus-RU');
4320
4321
        $mixedContent = $contentService->publishVersion(
4322
            $contentService->createContent(
4323
                $contentCreateStruct,
4324
                array($locationService->newLocationCreateStruct(2))
4325
            )->versionInfo
4326
        );
4327
4328
        // Content will be found because translation in Russian will be correctly stemmed
4329
        $query = new Query(
4330
            array(
4331
                'query' => new Criterion\FullText('важнее'),
4332
            )
4333
        );
4334
4335
        $searchResult = $searchService->findContent($query);
4336
4337
        $this->assertEquals(1, $searchResult->totalCount);
4338
        $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...
4339
    }
4340
4341
    /**
4342
     * Test for the findContent() method.
4343
     *
4344
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4345
     */
4346
    public function testLanguageAnalysisSameContentNotFound()
4347
    {
4348
        $setupFactory = $this->getSetupFactory();
4349
        if (!$setupFactory instanceof LegacyElasticsearch) {
4350
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4351
        }
4352
4353
        $repository = $this->getRepository();
4354
        $contentService = $repository->getContentService();
4355
        $contentTypeService = $repository->getContentTypeService();
4356
        $locationService = $repository->getLocationService();
4357
        $searchService = $repository->getSearchService();
4358
        $languageService = $repository->getContentLanguageService();
4359
4360
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4361
        $languageCreateStruct->languageCode = 'rus-RU';
4362
        $languageCreateStruct->name = 'Russian';
4363
4364
        $languageService->createLanguage($languageCreateStruct);
4365
4366
        $contentCreateStruct = $contentService->newContentCreateStruct(
4367
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4368
            'eng-GB'
4369
        );
4370
4371
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'eng-GB');
4372
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'rus-RU');
4373
4374
        $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...
4375
            $contentService->createContent(
4376
                $contentCreateStruct,
4377
                array($locationService->newLocationCreateStruct(2))
4378
            )->versionInfo
4379
        );
4380
4381
        // Content should be found because translation in Russian will be correctly stemmed
4382
        $query = new Query(
4383
            array(
4384
                'query' => new Criterion\FullText('важнее'),
4385
            )
4386
        );
4387
4388
        // Filtering fields for only English will cause no match because the term will
4389
        // not be correctly stemmed
4390
        $searchResult = $searchService->findContent($query, array('languages' => array('eng-GB')));
4391
4392
        $this->assertEquals(0, $searchResult->totalCount);
4393
    }
4394
4395
    /**
4396
     * Test for the findContent() method.
4397
     *
4398
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4399
     */
4400
    public function testFulltextComplex()
4401
    {
4402
        $repository = $this->getRepository();
4403
        $contentService = $repository->getContentService();
4404
        $contentTypeService = $repository->getContentTypeService();
4405
        $locationService = $repository->getLocationService();
4406
        $searchService = $repository->getSearchService();
4407
4408
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
4409
        $contentCreateStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
4410
4411
        $contentCreateStruct->setField('name', 'red');
4412
        $contentCreateStruct->setField('short_name', 'red apple');
4413
        $content1 = $contentService->publishVersion(
4414
            $contentService->createContent(
4415
                $contentCreateStruct,
4416
                [$locationService->newLocationCreateStruct(2)]
4417
            )->versionInfo
4418
        );
4419
4420
        $contentCreateStruct->setField('name', 'apple');
4421
        $contentCreateStruct->setField('short_name', 'two');
4422
        $content2 = $contentService->publishVersion(
4423
            $contentService->createContent(
4424
                $contentCreateStruct,
4425
                [$locationService->newLocationCreateStruct(2)]
4426
            )->versionInfo
4427
        );
4428
4429
        $contentCreateStruct->setField('name', 'red apple');
4430
        $contentCreateStruct->setField('short_name', 'three');
4431
        $content3 = $contentService->publishVersion(
4432
            $contentService->createContent(
4433
                $contentCreateStruct,
4434
                [$locationService->newLocationCreateStruct(2)]
4435
            )->versionInfo
4436
        );
4437
4438
        $this->refreshSearch($repository);
4439
4440
        $query = new Query(
4441
            [
4442
                'query' => new Criterion\FullText(
4443
                    'red apple',
4444
                    [
4445
                        'boost' => [
4446
                            'short_name' => 2,
4447
                        ],
4448
                        'fuzziness' => .1,
4449
                    ]
4450
                ),
4451
            ]
4452
        );
4453
4454
        $searchResult = $searchService->findContent($query, ['languages' => ['eng-GB']]);
4455
4456
        $this->assertEquals(3, $searchResult->totalCount);
4457
4458
        // Legacy search engine does have scoring, sorting the results by ID in that case
4459
        $setupFactory = $this->getSetupFactory();
4460
        if (get_class($setupFactory) === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
4461
            usort(
4462
                $searchResult->searchHits,
4463
                function ($a, $b) {
4464
                    return ($a->valueObject->id < $b->valueObject->id) ? -1 : 1;
4465
                }
4466
            );
4467
4468
            $this->assertEquals($content1->id, $searchResult->searchHits[0]->valueObject->id);
4469
            $this->assertEquals($content2->id, $searchResult->searchHits[1]->valueObject->id);
4470
            $this->assertEquals($content3->id, $searchResult->searchHits[2]->valueObject->id);
4471
4472
            return;
4473
        }
4474
4475
        $this->assertEquals($content1->id, $searchResult->searchHits[0]->valueObject->id);
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

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

<?php

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

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

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

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

}

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

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

See also the PhpDoc documentation for @property.

Loading history...
4476
        $this->assertEquals($content3->id, $searchResult->searchHits[1]->valueObject->id);
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

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

<?php

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

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

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

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

}

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

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

See also the PhpDoc documentation for @property.

Loading history...
4477
        $this->assertEquals($content2->id, $searchResult->searchHits[2]->valueObject->id);
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

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

<?php

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

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

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

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

}

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

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

See also the PhpDoc documentation for @property.

Loading history...
4478
    }
4479
4480
    /**
4481
     * Assert that query result matches the given fixture.
4482
     *
4483
     * @param Query $query
4484
     * @param string $fixture
4485
     * @param null|callable $closure
4486
     * @param bool $info
4487
     * @param bool $id
4488
     */
4489
    protected function assertQueryFixture(
4490
        Query $query,
4491
        $fixture,
4492
        $closure = null,
4493
        $ignoreScore = true,
4494
        $info = false,
4495
        $id = true,
4496
        $skipNotImplemented = false
4497
    ) {
4498
        $repository = $this->getRepository();
4499
        $searchService = $repository->getSearchService();
4500
4501
        try {
4502
            if ($query instanceof LocationQuery) {
4503
                $setupFactory = $this->getSetupFactory();
4504
                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...
4505
                    // @todo When we want to test score again by default we will need fixtures for Solr
4506
                }
4507
4508
                if ($setupFactory instanceof LegacyElasticsearch) {
4509
                    $position = strrpos($fixture, '/');
4510
                    $fixture = substr_replace($fixture, '/Location', $position, 0);
4511
                }
4512
4513
                $result = $searchService->findLocations($query);
4514
            } elseif ($query instanceof Query) {
4515
                if ($info) {
4516
                    $result = $searchService->findContentInfo($query);
4517
                } else {
4518
                    $result = $searchService->findContent($query);
4519
                }
4520
            } else {
4521
                $this->fail('Expected instance of LocationQuery or Query, got: ' . gettype($query));
4522
            }
4523
            $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...
4524
        } catch (NotImplementedException $e) {
4525
            if (!$skipNotImplemented) {
4526
                throw $e;
4527
            }
4528
4529
            $this->markTestSkipped(
4530
                'This feature is not supported by the current search backend: ' . $e->getMessage()
4531
            );
4532
        }
4533
4534 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...
4535
            if (isset($_ENV['ez_tests_record'])) {
4536
                file_put_contents(
4537
                    $record = $fixture . '.recording',
4538
                    "<?php\n\nreturn " . var_export($result, true) . ";\n\n"
4539
                );
4540
                $this->markTestIncomplete("No fixture available. Result recorded at $record. Result: \n" . $this->printResult($result));
4541
            } else {
4542
                $this->markTestIncomplete("No fixture available. Set \$_ENV['ez_tests_record'] to generate it.");
4543
            }
4544
        }
4545
4546
        $fixture = include $fixture;
4547
4548
        if ($closure !== null) {
4549
            $closure($fixture);
4550
            $closure($result);
4551
        }
4552
4553 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...
4554
            foreach (array($fixture, $result) as $set) {
4555
                $property = new \ReflectionProperty(get_class($set), 'maxScore');
4556
                $property->setAccessible(true);
4557
                $property->setValue($set, 0.0);
4558
4559
                foreach ($set->searchHits as $hit) {
4560
                    $property = new \ReflectionProperty(get_class($hit), 'score');
4561
                    $property->setAccessible(true);
4562
                    $property->setValue($hit, 0.0);
4563
                }
4564
            }
4565
        }
4566
4567
        foreach (array($fixture, $result) as $set) {
4568
            foreach ($set->searchHits as $hit) {
4569
                $property = new \ReflectionProperty(get_class($hit), 'index');
4570
                $property->setAccessible(true);
4571
                $property->setValue($hit, null);
4572
4573
                $property = new \ReflectionProperty(get_class($hit), 'matchedTranslation');
4574
                $property->setAccessible(true);
4575
                $property->setValue($hit, null);
4576
4577
                if (!$id) {
4578
                    $hit->valueObject['id'] = null;
4579
                }
4580
            }
4581
        }
4582
4583
        $this->assertEquals(
4584
            $fixture,
4585
            $result,
4586
            'Search results do not match.',
4587
            .99 // Be quite generous regarding delay -- most important for scores
4588
        );
4589
    }
4590
4591
    /**
4592
     * Show a simplified view of the search result for manual introspection.
4593
     *
4594
     * @param SearchResult $result
4595
     *
4596
     * @return string
4597
     */
4598 View Code Duplication
    protected function printResult(SearchResult $result)
4599
    {
4600
        $printed = '';
4601
        foreach ($result->searchHits as $hit) {
4602
            $printed .= sprintf(" - %s (%s)\n", $hit->valueObject['title'], $hit->valueObject['id']);
4603
        }
4604
4605
        return $printed;
4606
    }
4607
4608
    /**
4609
     * Simplify search result.
4610
     *
4611
     * This leads to saner comparisons of results, since we do not get the full
4612
     * content objects every time.
4613
     *
4614
     * @param SearchResult $result
4615
     */
4616
    protected function simplifySearchResult(SearchResult $result)
4617
    {
4618
        $result->time = 1;
4619
4620
        foreach ($result->searchHits as $hit) {
4621
            switch (true) {
4622
                case $hit->valueObject instanceof Content:
4623 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...
4624
                    $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...
4625
                        'id' => $hit->valueObject->contentInfo->id,
4626
                        'title' => $hit->valueObject->contentInfo->name,
4627
                    );
4628
                    break;
4629
4630
                case $hit->valueObject instanceof ContentInfo:
4631
                    $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...
4632
                        'id' => $hit->valueObject->id,
4633
                        'title' => $hit->valueObject->name,
4634
                    );
4635
                    break;
4636
4637
                default:
4638
                    throw new \RuntimeException('Unknown search result hit type: ' . get_class($hit->valueObject));
4639
            }
4640
        }
4641
    }
4642
4643
    /**
4644
     * Get fixture directory.
4645
     *
4646
     * @return string
4647
     */
4648
    protected function getFixtureDir()
4649
    {
4650
        return __DIR__ . '/_fixtures/' . getenv('fixtureDir') . '/';
4651
    }
4652
4653
    /**
4654
     * For findContentInfo tests, to reuse fixtures for findContent tests.
4655
     *
4656
     * @param null|callable $closure
4657
     *
4658
     * @return callable
4659
     */
4660
    private function getContentInfoFixtureClosure($closure = null)
4661
    {
4662
        /** @var $data \eZ\Publish\API\Repository\Values\Content\Search\SearchResult */
4663
        return function (&$data) use ($closure) {
4664
            foreach ($data->searchHits as $searchHit) {
4665
                if ($searchHit->valueObject instanceof Content) {
4666
                    $searchHit->valueObject = $searchHit->valueObject->getVersionInfo()->getContentInfo();
4667
                }
4668
            }
4669
4670
            if (isset($closure)) {
4671
                $closure($data);
4672
            }
4673
        };
4674
    }
4675
}
4676