Completed
Push — location_swap_spi_bug ( de9e5f...0d5b4c )
by André
13:56
created

testMapLocationDistanceWithCustomField()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 81
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 56
nc 2
nop 0
dl 0
loc 81
rs 8.8076
c 0
b 0
f 0

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * File containing the SearchServiceTest class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\API\Repository\Tests;
10
11
use eZ\Publish\API\Repository\Tests\SetupFactory\LegacyElasticsearch;
12
use EzSystems\EzPlatformSolrSearchEngine\Tests\SetupFactory\LegacySetupFactory as LegacySolrSetupFactory;
13
use eZ\Publish\API\Repository\Values\Content\Content;
14
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
15
use eZ\Publish\API\Repository\Values\Content\Query;
16
use eZ\Publish\API\Repository\Values\Content\Location;
17
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
18
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
19
use eZ\Publish\API\Repository\Values\Content\Query\SortClause;
20
use eZ\Publish\API\Repository\Values\Content\Query\FacetBuilder;
21
use eZ\Publish\API\Repository\Values\Content\Search\SearchResult;
22
use eZ\Publish\API\Repository\Values\Content\Search\SearchHit;
23
use eZ\Publish\API\Repository\Exceptions\NotImplementedException;
24
25
/**
26
 * Test case for operations in the SearchService using in memory storage.
27
 *
28
 * @see eZ\Publish\API\Repository\SearchService
29
 * @group integration
30
 * @group search
31
 */
32
class SearchServiceTest extends BaseTest
33
{
34
    public function getFilterContentSearches()
35
    {
36
        $fixtureDir = $this->getFixtureDir();
37
38
        return array(
39
            0 => array(
40
                array(
41
                    'filter' => new Criterion\ContentId(
42
                        array(1, 4, 10)
43
                    ),
44
                    'sortClauses' => array(new SortClause\ContentId()),
45
                ),
46
                $fixtureDir . 'ContentId.php',
47
            ),
48
            1 => array(
49
                array(
50
                    'filter' => new Criterion\LogicalAnd(
51
                        array(
52
                            new Criterion\ContentId(
53
                                array(1, 4, 10)
54
                            ),
55
                            new Criterion\ContentId(
56
                                array(4, 12)
57
                            ),
58
                        )
59
                    ),
60
                    'sortClauses' => array(new SortClause\ContentId()),
61
                ),
62
                $fixtureDir . 'LogicalAnd.php',
63
            ),
64
            2 => array(
65
                array(
66
                    'filter' => new Criterion\LogicalOr(
67
                        array(
68
                            new Criterion\ContentId(
69
                                array(1, 4, 10)
70
                            ),
71
                            new Criterion\ContentId(
72
                                array(4, 12)
73
                            ),
74
                        )
75
                    ),
76
                    'sortClauses' => array(new SortClause\ContentId()),
77
                ),
78
                $fixtureDir . 'LogicalOr.php',
79
            ),
80
            3 => array(
81
                array(
82
                    'filter' => new Criterion\LogicalAnd(
83
                        array(
84
                            new Criterion\ContentId(
85
                                array(1, 4, 10)
86
                            ),
87
                            new Criterion\LogicalNot(
88
                                new Criterion\ContentId(
89
                                    array(10, 12)
90
                                )
91
                            ),
92
                        )
93
                    ),
94
                    'sortClauses' => array(new SortClause\ContentId()),
95
                ),
96
                $fixtureDir . 'LogicalNot.php',
97
            ),
98
            4 => array(
99
                array(
100
                    'filter' => new Criterion\LogicalAnd(
101
                        array(
102
                            new Criterion\ContentId(
103
                                array(1, 4, 10)
104
                            ),
105
                            new Criterion\LogicalAnd(
106
                                array(
107
                                    new Criterion\LogicalNot(
108
                                        new Criterion\ContentId(
109
                                            array(10, 12)
110
                                        )
111
                                    ),
112
                                )
113
                            ),
114
                        )
115
                    ),
116
                    'sortClauses' => array(new SortClause\ContentId()),
117
                ),
118
                $fixtureDir . 'LogicalNot.php',
119
            ),
120
            5 => array(
121
                array(
122
                    'filter' => new Criterion\ContentTypeId(
123
                        4
124
                    ),
125
                    'sortClauses' => array(new SortClause\ContentId()),
126
                ),
127
                $fixtureDir . 'ContentTypeId.php',
128
            ),
129
            6 => array(
130
                array(
131
                    'filter' => new Criterion\ContentTypeIdentifier(
132
                        'user'
133
                    ),
134
                    'sortClauses' => array(new SortClause\ContentId()),
135
                ),
136
                $fixtureDir . 'ContentTypeId.php',
137
            ),
138
            7 => array(
139
                array(
140
                    'filter' => new Criterion\MatchNone(),
141
                    'sortClauses' => array(new SortClause\ContentId()),
142
                ),
143
                $fixtureDir . 'MatchNone.php',
144
            ),
145
            8 => array(
146
                array(
147
                    'filter' => new Criterion\ContentTypeGroupId(
148
                        2
149
                    ),
150
                    'sortClauses' => array(new SortClause\ContentId()),
151
                ),
152
                $fixtureDir . 'ContentTypeGroupId.php',
153
            ),
154
            9 => array(
155
                array(
156
                    'filter' => new Criterion\DateMetadata(
157
                        Criterion\DateMetadata::MODIFIED,
158
                        Criterion\Operator::GT,
159
                        1343140540
160
                    ),
161
                    'sortClauses' => array(new SortClause\ContentId()),
162
                ),
163
                $fixtureDir . 'DateMetadataGt.php',
164
            ),
165
            10 => array(
166
                array(
167
                    'filter' => new Criterion\DateMetadata(
168
                        Criterion\DateMetadata::MODIFIED,
169
                        Criterion\Operator::GTE,
170
                        1311154215
171
                    ),
172
                    'sortClauses' => array(new SortClause\ContentId()),
173
                ),
174
                $fixtureDir . 'DateMetadataGte.php',
175
            ),
176
            11 => array(
177
                array(
178
                    'filter' => new Criterion\DateMetadata(
179
                        Criterion\DateMetadata::MODIFIED,
180
                        Criterion\Operator::LTE,
181
                        1311154215
182
                    ),
183
                    'limit' => 10,
184
                    'sortClauses' => array(new SortClause\ContentId()),
185
                ),
186
                $fixtureDir . 'DateMetadataLte.php',
187
            ),
188
            12 => array(
189
                array(
190
                    'filter' => new Criterion\DateMetadata(
191
                        Criterion\DateMetadata::MODIFIED,
192
                        Criterion\Operator::IN,
193
                        array(1033920794, 1060695457, 1343140540)
194
                    ),
195
                    'sortClauses' => array(new SortClause\ContentId()),
196
                ),
197
                $fixtureDir . 'DateMetadataIn.php',
198
            ),
199
            13 => array(
200
                array(
201
                    'filter' => new Criterion\DateMetadata(
202
                        Criterion\DateMetadata::MODIFIED,
203
                        Criterion\Operator::BETWEEN,
204
                        array(1033920776, 1072180276)
205
                    ),
206
                    'sortClauses' => array(new SortClause\ContentId()),
207
                ),
208
                $fixtureDir . 'DateMetadataBetween.php',
209
            ),
210
            14 => array(
211
                array(
212
                    'filter' => new Criterion\DateMetadata(
213
                        Criterion\DateMetadata::CREATED,
214
                        Criterion\Operator::BETWEEN,
215
                        array(1033920776, 1072180278)
216
                    ),
217
                    'sortClauses' => array(new SortClause\ContentId()),
218
                ),
219
                $fixtureDir . 'DateMetadataCreated.php',
220
            ),
221
            15 => array(
222
                array(
223
                    'filter' => new Criterion\CustomField(
224
                        'user_group_name_value_s',
225
                        Criterion\Operator::EQ,
226
                        'Members'
227
                    ),
228
                    'sortClauses' => array(new SortClause\ContentId()),
229
                ),
230
                $fixtureDir . 'Field.php',
231
            ),
232
            16 => array(
233
                array(
234
                    'filter' => new Criterion\CustomField(
235
                        'user_group_name_value_s',
236
                        Criterion\Operator::CONTAINS,
237
                        'Members'
238
                    ),
239
                    'sortClauses' => array(new SortClause\ContentId()),
240
                ),
241
                $fixtureDir . 'Field.php',
242
            ),
243
            17 => array(
244
                array(
245
                    'filter' => new Criterion\CustomField(
246
                        'user_group_name_value_s',
247
                        Criterion\Operator::LT,
248
                        'Members'
249
                    ),
250
                    'sortClauses' => array(new SortClause\ContentId()),
251
                ),
252
                $fixtureDir . 'CustomFieldLt.php',
253
            ),
254
            18 => array(
255
                array(
256
                    'filter' => new Criterion\CustomField(
257
                        'user_group_name_value_s',
258
                        Criterion\Operator::LTE,
259
                        'Members'
260
                    ),
261
                    'sortClauses' => array(new SortClause\ContentId()),
262
                ),
263
                $fixtureDir . 'CustomFieldLte.php',
264
            ),
265
            19 => array(
266
                array(
267
                    'filter' => new Criterion\CustomField(
268
                        'user_group_name_value_s',
269
                        Criterion\Operator::GT,
270
                        'Members'
271
                    ),
272
                    'sortClauses' => array(new SortClause\ContentId()),
273
                ),
274
                $fixtureDir . 'CustomFieldGt.php',
275
            ),
276
            20 => array(
277
                array(
278
                    'filter' => new Criterion\CustomField(
279
                        'user_group_name_value_s',
280
                        Criterion\Operator::GTE,
281
                        'Members'
282
                    ),
283
                    'sortClauses' => array(new SortClause\ContentId()),
284
                ),
285
                $fixtureDir . 'CustomFieldGte.php',
286
            ),
287
            21 => array(
288
                array(
289
                    'filter' => new Criterion\CustomField(
290
                        'user_group_name_value_s',
291
                        Criterion\Operator::BETWEEN,
292
                        array('Administrator users', 'Members')
293
                    ),
294
                    'sortClauses' => array(new SortClause\ContentId()),
295
                ),
296
                $fixtureDir . 'CustomFieldBetween.php',
297
            ),
298
            22 => array(
299
                array(
300
                    'filter' => new Criterion\RemoteId(
301
                        array('f5c88a2209584891056f987fd965b0ba', 'faaeb9be3bd98ed09f606fc16d144eca')
302
                    ),
303
                    'sortClauses' => array(new SortClause\ContentId()),
304
                ),
305
                $fixtureDir . 'RemoteId.php',
306
            ),
307
            23 => array(
308
                array(
309
                    'filter' => new Criterion\SectionId(
310
                        array(2)
311
                    ),
312
                    'sortClauses' => array(new SortClause\ContentId()),
313
                ),
314
                $fixtureDir . 'SectionId.php',
315
            ),
316
            24 => array(
317
                array(
318
                    'filter' => new Criterion\Field(
319
                        'name',
320
                        Criterion\Operator::EQ,
321
                        'Members'
322
                    ),
323
                    'sortClauses' => array(new SortClause\ContentId()),
324
                ),
325
                $fixtureDir . 'Field.php',
326
            ),
327
            25 => array(
328
                array(
329
                    'filter' => new Criterion\Field(
330
                        'name',
331
                        Criterion\Operator::IN,
332
                        array('Members', 'Anonymous Users')
333
                    ),
334
                    'sortClauses' => array(new SortClause\ContentId()),
335
                ),
336
                $fixtureDir . 'FieldIn.php',
337
            ),
338
            26 => array(
339
                array(
340
                    'filter' => new Criterion\DateMetadata(
341
                        Criterion\DateMetadata::MODIFIED,
342
                        Criterion\Operator::BETWEEN,
343
                        array(1033920275, 1033920794)
344
                    ),
345
                    'sortClauses' => array(new SortClause\ContentId()),
346
                ),
347
                $fixtureDir . 'FieldBetween.php',
348
            ),
349
            27 => array(
350
                array(
351
                    'filter' => new Criterion\LogicalOr(
352
                        array(
353
                            new Criterion\Field(
354
                                'name',
355
                                Criterion\Operator::EQ,
356
                                'Members'
357
                            ),
358
                            new Criterion\DateMetadata(
359
                                Criterion\DateMetadata::MODIFIED,
360
                                Criterion\Operator::BETWEEN,
361
                                array(1033920275, 1033920794)
362
                            ),
363
                        )
364
                    ),
365
                    'sortClauses' => array(new SortClause\ContentId()),
366
                ),
367
                $fixtureDir . 'FieldOr.php',
368
            ),
369
            28 => array(
370
                array(
371
                    'filter' => new Criterion\Subtree(
372
                        '/1/5/'
373
                    ),
374
                    'sortClauses' => array(new SortClause\ContentId()),
375
                ),
376
                $fixtureDir . 'Subtree.php',
377
            ),
378
            29 => array(
379
                array(
380
                    'filter' => new Criterion\LocationId(
381
                        array(1, 2, 5)
382
                    ),
383
                    'sortClauses' => array(new SortClause\ContentId()),
384
                ),
385
                $fixtureDir . 'LocationId.php',
386
            ),
387
            30 => array(
388
                array(
389
                    'filter' => new Criterion\ParentLocationId(
390
                        array(1)
391
                    ),
392
                    'sortClauses' => array(new SortClause\ContentId()),
393
                ),
394
                $fixtureDir . 'ParentLocationId.php',
395
            ),
396
            31 => array(
397
                array(
398
                    'filter' => new Criterion\LocationRemoteId(
399
                        array('3f6d92f8044aed134f32153517850f5a', 'f3e90596361e31d496d4026eb624c983')
400
                    ),
401
                    'sortClauses' => array(new SortClause\ContentId()),
402
                ),
403
                $fixtureDir . 'LocationRemoteId.php',
404
            ),
405
            32 => array(
406
                array(
407
                    // There is no Status Criterion anymore, this should match all published as well
408
                    'filter' => new Criterion\Subtree(
409
                        '/1/'
410
                    ),
411
                    'sortClauses' => array(new SortClause\ContentId()),
412
                    'limit' => 50,
413
                ),
414
                $fixtureDir . 'Status.php',
415
                // Result having the same sort level should be sorted between them to be system independent
416
                function (&$data) {
417
                    usort(
418
                        $data->searchHits,
419
                        function ($a, $b) {
420
                            if ($a->score == $b->score) {
421
                                if ($a->valueObject['id'] == $b->valueObject['id']) {
422
                                    return 0;
423
                                }
424
425
                                // Order by ascending ID
426
                                return ($a->valueObject['id'] < $b->valueObject['id']) ? -1 : 1;
427
                            }
428
429
                            // Order by descending score
430
                            return ($a->score > $b->score) ? -1 : 1;
431
                        }
432
                    );
433
                },
434
            ),
435
            33 => array(
436
                array(
437
                    'filter' => new Criterion\UserMetadata(
438
                        Criterion\UserMetadata::MODIFIER,
439
                        Criterion\Operator::EQ,
440
                        14
441
                    ),
442
                    'sortClauses' => array(
443
                        new SortClause\ContentId(),
444
                    ),
445
                    'limit' => 50,
446
                ),
447
                $fixtureDir . 'UserMetadata.php',
448
            ),
449
            34 => array(
450
                array(
451
                    'filter' => new Criterion\UserMetadata(
452
                        Criterion\UserMetadata::MODIFIER,
453
                        Criterion\Operator::IN,
454
                        array(14)
455
                    ),
456
                    'sortClauses' => array(
457
                        new SortClause\ContentId(),
458
                    ),
459
                    'limit' => 50,
460
                ),
461
                $fixtureDir . 'UserMetadata.php',
462
            ),
463
            35 => array(
464
                array(
465
                    'filter' => new Criterion\UserMetadata(
466
                        Criterion\UserMetadata::OWNER,
467
                        Criterion\Operator::EQ,
468
                        14
469
                    ),
470
                    'sortClauses' => array(
471
                        new SortClause\ContentId(),
472
                    ),
473
                    'limit' => 50,
474
                ),
475
                $fixtureDir . 'UserMetadata.php',
476
            ),
477
            36 => array(
478
                array(
479
                    'filter' => new Criterion\UserMetadata(
480
                        Criterion\UserMetadata::OWNER,
481
                        Criterion\Operator::IN,
482
                        array(14)
483
                    ),
484
                    'sortClauses' => array(
485
                        new SortClause\ContentId(),
486
                    ),
487
                    'limit' => 50,
488
                ),
489
                $fixtureDir . 'UserMetadata.php',
490
            ),
491
            37 => array(
492
                array(
493
                    'filter' => new Criterion\UserMetadata(
494
                        Criterion\UserMetadata::GROUP,
495
                        Criterion\Operator::EQ,
496
                        12
497
                    ),
498
                    'sortClauses' => array(
499
                        new SortClause\ContentId(),
500
                    ),
501
                    'limit' => 50,
502
                ),
503
                $fixtureDir . 'UserMetadata.php',
504
            ),
505
            38 => array(
506
                array(
507
                    'filter' => new Criterion\UserMetadata(
508
                        Criterion\UserMetadata::GROUP,
509
                        Criterion\Operator::IN,
510
                        array(12)
511
                    ),
512
                    'sortClauses' => array(
513
                        new SortClause\ContentId(),
514
                    ),
515
                    'limit' => 50,
516
                ),
517
                $fixtureDir . 'UserMetadata.php',
518
            ),
519
            39 => array(
520
                array(
521
                    'filter' => new Criterion\UserMetadata(
522
                        Criterion\UserMetadata::GROUP,
523
                        Criterion\Operator::EQ,
524
                        4
525
                    ),
526
                    'sortClauses' => array(
527
                        new SortClause\ContentId(),
528
                    ),
529
                    'limit' => 50,
530
                ),
531
                $fixtureDir . 'UserMetadata.php',
532
            ),
533
            40 => array(
534
                array(
535
                    'filter' => new Criterion\UserMetadata(
536
                        Criterion\UserMetadata::GROUP,
537
                        Criterion\Operator::IN,
538
                        array(4)
539
                    ),
540
                    'sortClauses' => array(
541
                        new SortClause\ContentId(),
542
                    ),
543
                    'limit' => 50,
544
                ),
545
                $fixtureDir . 'UserMetadata.php',
546
            ),
547
            41 => array(
548
                array(
549
                    'filter' => new Criterion\Ancestor(
550
                        array(
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
            ),
2513
            array(
2514
                new Query(
2515
                    array(
2516
                        'filter' => new Criterion\SectionId(array(1)),
2517
                        'offset' => 0,
2518
                        'limit' => 10,
2519
                        'facetBuilders' => array(
2520
                            new FacetBuilder\ContentTypeFacetBuilder(
2521
                                array(
2522
                                    'name' => 'type',
2523
                                    'minCount' => 3,
2524
                                )
2525
                            ),
2526
                        ),
2527
                        'sortClauses' => array(new SortClause\ContentId()),
2528
                    )
2529
                ),
2530
                $fixtureDir . '/FacetContentTypeMinCount.php',
2531
            ),
2532
            array(
2533
                new Query(
2534
                    array(
2535
                        'filter' => new Criterion\SectionId(array(1)),
2536
                        'offset' => 0,
2537
                        'limit' => 10,
2538
                        'facetBuilders' => array(
2539
                            new FacetBuilder\ContentTypeFacetBuilder(
2540
                                array(
2541
                                    'name' => 'type',
2542
                                    'limit' => 5,
2543
                                )
2544
                            ),
2545
                        ),
2546
                        'sortClauses' => array(new SortClause\ContentId()),
2547
                    )
2548
                ),
2549
                $fixtureDir . '/FacetContentTypeMinLimit.php',
2550
            ),
2551
            array(
2552
                new Query(
2553
                    array(
2554
                        'filter' => new Criterion\SectionId(array(1)),
2555
                        'offset' => 0,
2556
                        'limit' => 10,
2557
                        'facetBuilders' => array(
2558
                            new FacetBuilder\SectionFacetBuilder(
2559
                                array(
2560
                                    'name' => 'section',
2561
                                )
2562
                            ),
2563
                        ),
2564
                        'sortClauses' => array(new SortClause\ContentId()),
2565
                    )
2566
                ),
2567
                $fixtureDir . '/FacetSection.php',
2568
            ),
2569
            array(
2570
                new Query(
2571
                    array(
2572
                        'filter' => new Criterion\SectionId(array(1)),
2573
                        'offset' => 0,
2574
                        'limit' => 10,
2575
                        'facetBuilders' => array(
2576
                            new FacetBuilder\UserFacetBuilder(
2577
                                array(
2578
                                    'name' => 'creator',
2579
                                )
2580
                            ),
2581
                        ),
2582
                        'sortClauses' => array(new SortClause\ContentId()),
2583
                    )
2584
                ),
2585
                $fixtureDir . '/FacetUser.php',
2586
            ),
2587
            array(
2588
                new Query(
2589
                    array(
2590
                        'filter' => new Criterion\SectionId(array(1)),
2591
                        'offset' => 0,
2592
                        'limit' => 10,
2593
                        'facetBuilders' => array(
2594
                            new FacetBuilder\TermFacetBuilder(),
2595
                        ),
2596
                        'sortClauses' => array(new SortClause\ContentId()),
2597
                    )
2598
                ),
2599
                $fixtureDir . '/FacetTerm.php',
2600
            ),
2601
            /* @todo: It needs to be defined how this one is supposed to work.
2602
            array(
2603
                new Query(
2604
                    array(
2605
                        'filter'      => new Criterion\SectionId( array( 1 ) ),
2606
                        'offset'      => 0,
2607
                        'limit'       => 10,
2608
                        'facetBuilders' => array(
2609
                            new FacetBuilder\CriterionFacetBuilder()
2610
                        ),
2611
                        'sortClauses' => array( new SortClause\ContentId() )
2612
                    )
2613
                ),
2614
                $fixtureDir . '/FacetCriterion.php',
2615
            ), // */
2616
            /* @todo: Add sane ranges here:
2617
            array(
2618
                new Query(
2619
                    array(
2620
                        'filter'      => new Criterion\SectionId( array( 1 ) ),
2621
                        'offset'      => 0,
2622
                        'limit'       => 10,
2623
                        'facetBuilders' => array(
2624
                            new FacetBuilder\DateRangeFacetBuilder( array() )
2625
                        ),
2626
                        'sortClauses' => array( new SortClause\ContentId() )
2627
                    )
2628
                ),
2629
                $fixtureDir . '/FacetDateRange.php',
2630
            ), // */
2631
            array(
2632
                new Query(
2633
                    array(
2634
                        'filter' => new Criterion\SectionId(array(1)),
2635
                        'offset' => 0,
2636
                        'limit' => 10,
2637
                        'facetBuilders' => array(
2638
                            new FacetBuilder\FieldFacetBuilder(
2639
                                array(
2640
                                    'fieldPaths' => array('article/title'),
2641
                                )
2642
                            ),
2643
                        ),
2644
                        'sortClauses' => array(new SortClause\ContentId()),
2645
                    )
2646
                ),
2647
                $fixtureDir . '/FacetFieldSimple.php',
2648
            ),
2649
            array(
2650
                new Query(
2651
                    array(
2652
                        'filter' => new Criterion\SectionId(array(1)),
2653
                        'offset' => 0,
2654
                        'limit' => 10,
2655
                        'facetBuilders' => array(
2656
                            new FacetBuilder\FieldFacetBuilder(
2657
                                array(
2658
                                    'fieldPaths' => array('article/title'),
2659
                                    'regex' => '(a|b|c)',
2660
                                )
2661
                            ),
2662
                        ),
2663
                        'sortClauses' => array(new SortClause\ContentId()),
2664
                    )
2665
                ),
2666
                $fixtureDir . '/FacetFieldRegexp.php',
2667
            ),
2668
            array(
2669
                new Query(
2670
                    array(
2671
                        'filter' => new Criterion\SectionId(array(1)),
2672
                        'offset' => 0,
2673
                        'limit' => 10,
2674
                        'facetBuilders' => array(
2675
                            new FacetBuilder\FieldFacetBuilder(
2676
                                array(
2677
                                    'fieldPaths' => array('article/title'),
2678
                                    'regex' => '(a|b|c)',
2679
                                    'sort' => FacetBuilder\FieldFacetBuilder::TERM_DESC,
2680
                                )
2681
                            ),
2682
                        ),
2683
                        'sortClauses' => array(new SortClause\ContentId()),
2684
                    )
2685
                ),
2686
                $fixtureDir . '/FacetFieldRegexpSortTerm.php',
2687
            ),
2688
            array(
2689
                new Query(
2690
                    array(
2691
                        'filter' => new Criterion\SectionId(array(1)),
2692
                        'offset' => 0,
2693
                        'limit' => 10,
2694
                        'facetBuilders' => array(
2695
                            new FacetBuilder\FieldFacetBuilder(
2696
                                array(
2697
                                    'fieldPaths' => array('article/title'),
2698
                                    'regex' => '(a|b|c)',
2699
                                    'sort' => FacetBuilder\FieldFacetBuilder::COUNT_DESC,
2700
                                )
2701
                            ),
2702
                        ),
2703
                        'sortClauses' => array(new SortClause\ContentId()),
2704
                    )
2705
                ),
2706
                $fixtureDir . '/FacetFieldRegexpSortCount.php',
2707
            ),
2708
            /* @todo: Add sane ranges here:
2709
            array(
2710
                new Query(
2711
                    array(
2712
                        'filter'      => new Criterion\SectionId( array( 1 ) ),
2713
                        'offset'      => 0,
2714
                        'limit'       => 10,
2715
                        'facetBuilders' => array(
2716
                            new FacetBuilder\FieldRangeFacetBuilder( array(
2717
                                'fieldPath' => 'product/price',
2718
                            ) )
2719
                        ),
2720
                        'sortClauses' => array( new SortClause\ContentId() )
2721
                    )
2722
                ),
2723
                $fixtureDir . '/FacetFieldRegexpSortCount.php',
2724
            ), // */
2725
        );
2726
    }
2727
2728
    /**
2729
     * Test for the findContent() method.
2730
     *
2731
     * @dataProvider getFacettedSearches
2732
     *
2733
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2734
     */
2735
    public function testFindFacettedContent(Query $query, $fixture)
2736
    {
2737
        $this->assertQueryFixture($query, $fixture);
2738
    }
2739
2740
    /**
2741
     * Test for the findContentInfo() method.
2742
     *
2743
     * @dataProvider getFacettedSearches
2744
     * @see \eZ\Publish\API\Repository\SearchService::findContentInfo()
2745
     */
2746
    public function testFindFacettedContentInfo(Query $query, $fixture)
2747
    {
2748
        $this->assertQueryFixture($query, $fixture, $this->getContentInfoFixtureClosure(), true);
2749
    }
2750
2751
    /**
2752
     * Test for the findContent() method.
2753
     *
2754
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2755
     */
2756 View Code Duplication
    public function testQueryCustomField()
2757
    {
2758
        $query = new Query(
2759
            array(
2760
                'query' => new Criterion\CustomField(
2761
                    'custom_field',
2762
                    Criterion\Operator::EQ,
2763
                    'AdMiNiStRaToR'
2764
                ),
2765
                'offset' => 0,
2766
                'limit' => 10,
2767
                'sortClauses' => array(new SortClause\ContentId()),
2768
            )
2769
        );
2770
        $this->assertQueryFixture(
2771
            $query,
2772
            $this->getFixtureDir() . '/QueryCustomField.php'
2773
        );
2774
    }
2775
2776
    /**
2777
     * Test for the findContent() method.
2778
     *
2779
     * This tests explicitely queries the first_name while user is contained in
2780
     * the last_name of admin and anonymous. This is done to show the custom
2781
     * copy field working.
2782
     *
2783
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2784
     */
2785 View Code Duplication
    public function testQueryModifiedField()
2786
    {
2787
        // Check using get_class since the others extend SetupFactory\Legacy
2788
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
2789
            $this->markTestIncomplete(
2790
                'Custom fields not supported by LegacySE ' .
2791
                '(@todo: Legacy should fallback to just querying normal field so this should be tested here)'
2792
            );
2793
        }
2794
2795
        $query = new Query(
2796
            array(
2797
                'query' => new Criterion\Field(
2798
                    'first_name',
2799
                    Criterion\Operator::EQ,
2800
                    'User'
2801
                ),
2802
                'offset' => 0,
2803
                'limit' => 10,
2804
                'sortClauses' => array(new SortClause\ContentId()),
2805
            )
2806
        );
2807
        $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...
2808
2809
        $this->assertQueryFixture(
2810
            $query,
2811
            $this->getFixtureDir() . '/QueryModifiedField.php'
2812
        );
2813
    }
2814
2815
    /**
2816
     * Test for the findContent() method.
2817
     *
2818
     * This tests first explicitly creates sort clause on the 'short_name' which is empty
2819
     * for all Content instances of 'folder' ContentType. Custom sort field is then set
2820
     * to the index storage name of folder's 'name' field, in order to show the custom
2821
     * sort field working.
2822
     *
2823
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2824
     */
2825
    public function testSortModifiedField()
2826
    {
2827
        // Check using get_class since the others extend SetupFactory\Legacy
2828
        if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
2829
            $this->markTestIncomplete(
2830
                'Custom field sort not supported by LegacySE ' .
2831
                '(@todo: Legacy should fallback to just querying normal field so this should be tested here)'
2832
            );
2833
        }
2834
2835
        $sortClause = new SortClause\Field('folder', 'short_name', Query::SORT_ASC);
2836
        $sortClause->setCustomField('folder', 'short_name', 'folder_name_value_s');
2837
2838
        $query = new Query(
2839
            array(
2840
                'filter' => new Criterion\ContentTypeId(1),
2841
                'offset' => 0,
2842
                'limit' => 10,
2843
                'sortClauses' => array(
2844
                    $sortClause,
2845
                    new SortClause\ContentId(),
2846
                ),
2847
            )
2848
        );
2849
2850
        $this->assertQueryFixture(
2851
            $query,
2852
            $this->getFixtureDir() . '/SortFolderName.php'
2853
        );
2854
    }
2855
2856
    /**
2857
     * @return \eZ\Publish\API\Repository\Values\ContentType\ContentType
2858
     */
2859 View Code Duplication
    protected function createTestPlaceContentType()
2860
    {
2861
        $repository = $this->getRepository();
2862
        $contentTypeService = $repository->getContentTypeService();
2863
2864
        $createStruct = $contentTypeService->newContentTypeCreateStruct('testtype');
2865
        $createStruct->mainLanguageCode = 'eng-GB';
2866
        $createStruct->names = array('eng-GB' => 'Test type');
2867
        $createStruct->creatorId = 14;
2868
        $createStruct->creationDate = new \DateTime();
2869
2870
        $translatableFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('maplocation', 'ezgmaplocation');
2871
        $translatableFieldCreate->names = array('eng-GB' => 'Map location field');
2872
        $translatableFieldCreate->fieldGroup = 'main';
2873
        $translatableFieldCreate->position = 1;
2874
        $translatableFieldCreate->isTranslatable = false;
2875
        $translatableFieldCreate->isSearchable = true;
2876
2877
        $createStruct->addFieldDefinition($translatableFieldCreate);
2878
2879
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
2880
        $contentTypeDraft = $contentTypeService->createContentType($createStruct, array($contentGroup));
2881
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
2882
        $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...
2883
2884
        return $contentType;
2885
    }
2886
2887
    /**
2888
     * Test for the findContent() method.
2889
     *
2890
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2891
     * @group maplocation
2892
     */
2893 View Code Duplication
    public function testMapLocationDistanceLessThanOrEqual()
2894
    {
2895
        $contentType = $this->createTestPlaceContentType();
2896
2897
        // Create a draft to account for behaviour with ContentType in different states
2898
        $repository = $this->getRepository();
2899
        $contentTypeService = $repository->getContentTypeService();
2900
        $contentService = $repository->getContentService();
2901
        $contentTypeService->createContentTypeDraft($contentType);
2902
2903
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2904
        $createStruct->alwaysAvailable = false;
2905
        $createStruct->mainLanguageCode = 'eng-GB';
2906
        $createStruct->setField(
2907
            'maplocation',
2908
            array(
2909
                'latitude' => 45.894877,
2910
                'longitude' => 15.972699,
2911
                'address' => 'Here be wild boars',
2912
            ),
2913
            'eng-GB'
2914
        );
2915
2916
        $draft = $contentService->createContent($createStruct);
2917
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
2918
2919
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2920
        $createStruct->alwaysAvailable = false;
2921
        $createStruct->mainLanguageCode = 'eng-GB';
2922
        $createStruct->setField(
2923
            'maplocation',
2924
            array(
2925
                'latitude' => 45.927334,
2926
                'longitude' => 15.934847,
2927
                'address' => 'A lone tree',
2928
            ),
2929
            'eng-GB'
2930
        );
2931
2932
        $draft = $contentService->createContent($createStruct);
2933
        $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...
2934
2935
        $this->refreshSearch($repository);
2936
2937
        $query = new Query(
2938
            array(
2939
                'filter' => new Criterion\LogicalAnd(
2940
                    array(
2941
                        new Criterion\ContentTypeId($contentType->id),
2942
                        new Criterion\MapLocationDistance(
2943
                            'maplocation',
2944
                            Criterion\Operator::LTE,
2945
                            240,
2946
                            43.756825,
2947
                            15.775074
2948
                        ),
2949
                    )
2950
                ),
2951
                'offset' => 0,
2952
                'limit' => 10,
2953
                'sortClauses' => array(),
2954
            )
2955
        );
2956
2957
        $searchService = $repository->getSearchService();
2958
        $result = $searchService->findContent($query);
2959
2960
        $this->assertEquals(1, $result->totalCount);
2961
        $this->assertEquals(
2962
            $wildBoars->id,
2963
            $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...
2964
        );
2965
    }
2966
2967
    /**
2968
     * Test for the findContent() method.
2969
     *
2970
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
2971
     * @group maplocation
2972
     */
2973 View Code Duplication
    public function testMapLocationDistanceGreaterThanOrEqual()
2974
    {
2975
        $contentType = $this->createTestPlaceContentType();
2976
2977
        // Create a draft to account for behaviour with ContentType in different states
2978
        $repository = $this->getRepository();
2979
        $contentTypeService = $repository->getContentTypeService();
2980
        $contentService = $repository->getContentService();
2981
        $contentTypeService->createContentTypeDraft($contentType);
2982
2983
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
2984
        $createStruct->alwaysAvailable = false;
2985
        $createStruct->mainLanguageCode = 'eng-GB';
2986
        $createStruct->setField(
2987
            'maplocation',
2988
            array(
2989
                'latitude' => 45.894877,
2990
                'longitude' => 15.972699,
2991
                'address' => 'Here be wild boars',
2992
            ),
2993
            'eng-GB'
2994
        );
2995
2996
        $draft = $contentService->createContent($createStruct);
2997
        $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...
2998
2999
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3000
        $createStruct->alwaysAvailable = false;
3001
        $createStruct->mainLanguageCode = 'eng-GB';
3002
        $createStruct->setField(
3003
            'maplocation',
3004
            array(
3005
                'latitude' => 45.927334,
3006
                'longitude' => 15.934847,
3007
                'address' => 'A lone tree',
3008
            ),
3009
            'eng-GB'
3010
        );
3011
3012
        $draft = $contentService->createContent($createStruct);
3013
        $tree = $contentService->publishVersion($draft->getVersionInfo());
3014
3015
        $this->refreshSearch($repository);
3016
3017
        $query = new Query(
3018
            array(
3019
                'filter' => new Criterion\LogicalAnd(
3020
                    array(
3021
                        new Criterion\ContentTypeId($contentType->id),
3022
                        new Criterion\MapLocationDistance(
3023
                            'maplocation',
3024
                            Criterion\Operator::GTE,
3025
                            240,
3026
                            43.756825,
3027
                            15.775074
3028
                        ),
3029
                    )
3030
                ),
3031
                'offset' => 0,
3032
                'limit' => 10,
3033
                'sortClauses' => array(),
3034
            )
3035
        );
3036
3037
        $searchService = $repository->getSearchService();
3038
        $result = $searchService->findContent($query);
3039
3040
        $this->assertEquals(1, $result->totalCount);
3041
        $this->assertEquals(
3042
            $tree->id,
3043
            $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...
3044
        );
3045
    }
3046
3047
    /**
3048
     * Test for the findContent() method.
3049
     *
3050
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3051
     * @group maplocation
3052
     */
3053
    public function testMapLocationDistanceBetween()
3054
    {
3055
        $contentType = $this->createTestPlaceContentType();
3056
3057
        // Create a draft to account for behaviour with ContentType in different states
3058
        $repository = $this->getRepository();
3059
        $contentTypeService = $repository->getContentTypeService();
3060
        $contentService = $repository->getContentService();
3061
        $contentTypeService->createContentTypeDraft($contentType);
3062
3063
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3064
        $createStruct->alwaysAvailable = false;
3065
        $createStruct->mainLanguageCode = 'eng-GB';
3066
        $createStruct->setField(
3067
            'maplocation',
3068
            array(
3069
                'latitude' => 45.894877,
3070
                'longitude' => 15.972699,
3071
                'address' => 'Here be wild boars',
3072
            ),
3073
            'eng-GB'
3074
        );
3075
3076
        $draft = $contentService->createContent($createStruct);
3077
        $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...
3078
3079
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3080
        $createStruct->alwaysAvailable = false;
3081
        $createStruct->mainLanguageCode = 'eng-GB';
3082
        $createStruct->setField(
3083
            'maplocation',
3084
            array(
3085
                'latitude' => 45.927334,
3086
                'longitude' => 15.934847,
3087
                'address' => 'A lone tree',
3088
            ),
3089
            'eng-GB'
3090
        );
3091
3092
        $draft = $contentService->createContent($createStruct);
3093
        $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...
3094
3095
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3096
        $createStruct->alwaysAvailable = false;
3097
        $createStruct->mainLanguageCode = 'eng-GB';
3098
        $createStruct->setField(
3099
            'maplocation',
3100
            array(
3101
                'latitude' => 45.903777,
3102
                'longitude' => 15.958788,
3103
                'address' => 'Meadow with mushrooms',
3104
            ),
3105
            'eng-GB'
3106
        );
3107
3108
        $draft = $contentService->createContent($createStruct);
3109
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3110
3111
        $this->refreshSearch($repository);
3112
3113
        $query = new Query(
3114
            array(
3115
                'filter' => new Criterion\LogicalAnd(
3116
                    array(
3117
                        new Criterion\ContentTypeId($contentType->id),
3118
                        new Criterion\MapLocationDistance(
3119
                            'maplocation',
3120
                            Criterion\Operator::BETWEEN,
3121
                            array(239, 241),
3122
                            43.756825,
3123
                            15.775074
3124
                        ),
3125
                    )
3126
                ),
3127
                'offset' => 0,
3128
                'limit' => 10,
3129
                'sortClauses' => array(),
3130
            )
3131
        );
3132
3133
        $searchService = $repository->getSearchService();
3134
        $result = $searchService->findContent($query);
3135
3136
        $this->assertEquals(1, $result->totalCount);
3137
        $this->assertEquals(
3138
            $mushrooms->id,
3139
            $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...
3140
        );
3141
    }
3142
3143
    /**
3144
     * Test for the findContent() method.
3145
     *
3146
     * This tests the distance over the pole. The tests intentionally uses large range,
3147
     * as the flat Earth model used in Legacy Storage Search is not precise for the use case.
3148
     * What is tested here is that outer bounding box is correctly calculated, so that
3149
     * location is not excluded.
3150
     *
3151
     * Range between 222km and 350km shows the magnitude of error between great-circle
3152
     * (always very precise) and flat Earth (very imprecise for this use case) models.
3153
     *
3154
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3155
     * @group maplocation
3156
     */
3157
    public function testMapLocationDistanceBetweenPolar()
3158
    {
3159
        $contentType = $this->createTestPlaceContentType();
3160
3161
        // Create a draft to account for behaviour with ContentType in different states
3162
        $repository = $this->getRepository();
3163
        $contentTypeService = $repository->getContentTypeService();
3164
        $contentService = $repository->getContentService();
3165
        $contentTypeService->createContentTypeDraft($contentType);
3166
3167
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3168
        $createStruct->alwaysAvailable = false;
3169
        $createStruct->mainLanguageCode = 'eng-GB';
3170
        $createStruct->setField(
3171
            'maplocation',
3172
            array(
3173
                'latitude' => 89,
3174
                'longitude' => -164,
3175
                'address' => 'Polar bear media tower',
3176
            ),
3177
            'eng-GB'
3178
        );
3179
3180
        $draft = $contentService->createContent($createStruct);
3181
        $polarBear = $contentService->publishVersion($draft->getVersionInfo());
3182
3183
        $this->refreshSearch($repository);
3184
3185
        $query = new Query(
3186
            array(
3187
                'filter' => new Criterion\LogicalAnd(
3188
                    array(
3189
                        new Criterion\ContentTypeId($contentType->id),
3190
                        new Criterion\MapLocationDistance(
3191
                            'maplocation',
3192
                            Criterion\Operator::BETWEEN,
3193
                            array(221, 350),
3194
                            89,
3195
                            16
3196
                        ),
3197
                    )
3198
                ),
3199
                'offset' => 0,
3200
                'limit' => 10,
3201
                'sortClauses' => array(),
3202
            )
3203
        );
3204
3205
        $searchService = $repository->getSearchService();
3206
        $result = $searchService->findContent($query);
3207
3208
        $this->assertEquals(1, $result->totalCount);
3209
        $this->assertEquals(
3210
            $polarBear->id,
3211
            $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...
3212
        );
3213
    }
3214
3215
    /**
3216
     * Test for the findContent() method.
3217
     *
3218
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3219
     * @group maplocation
3220
     */
3221 View Code Duplication
    public function testMapLocationDistanceSortAscending()
3222
    {
3223
        $contentType = $this->createTestPlaceContentType();
3224
3225
        // Create a draft to account for behaviour with ContentType in different states
3226
        $repository = $this->getRepository();
3227
        $contentTypeService = $repository->getContentTypeService();
3228
        $contentService = $repository->getContentService();
3229
        $contentTypeService->createContentTypeDraft($contentType);
3230
3231
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3232
        $createStruct->alwaysAvailable = false;
3233
        $createStruct->mainLanguageCode = 'eng-GB';
3234
        $createStruct->setField(
3235
            'maplocation',
3236
            array(
3237
                'latitude' => 45.894877,
3238
                'longitude' => 15.972699,
3239
                'address' => 'Here be wild boars',
3240
            ),
3241
            'eng-GB'
3242
        );
3243
3244
        $draft = $contentService->createContent($createStruct);
3245
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3246
3247
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3248
        $createStruct->alwaysAvailable = false;
3249
        $createStruct->mainLanguageCode = 'eng-GB';
3250
        $createStruct->setField(
3251
            'maplocation',
3252
            array(
3253
                'latitude' => 45.927334,
3254
                'longitude' => 15.934847,
3255
                'address' => 'A lone tree',
3256
            ),
3257
            'eng-GB'
3258
        );
3259
3260
        $draft = $contentService->createContent($createStruct);
3261
        $tree = $contentService->publishVersion($draft->getVersionInfo());
3262
3263
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3264
        $createStruct->alwaysAvailable = false;
3265
        $createStruct->mainLanguageCode = 'eng-GB';
3266
        $createStruct->setField(
3267
            'maplocation',
3268
            array(
3269
                'latitude' => 45.903777,
3270
                'longitude' => 15.958788,
3271
                'address' => 'Meadow with mushrooms',
3272
            ),
3273
            'eng-GB'
3274
        );
3275
3276
        $draft = $contentService->createContent($createStruct);
3277
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3278
3279
        $this->refreshSearch($repository);
3280
3281
        $wellInVodice = array(
3282
            'latitude' => 43.756825,
3283
            'longitude' => 15.775074,
3284
        );
3285
3286
        $query = new Query(
3287
            array(
3288
                'filter' => new Criterion\LogicalAnd(
3289
                    array(
3290
                        new Criterion\ContentTypeId($contentType->id),
3291
                        new Criterion\MapLocationDistance(
3292
                            'maplocation',
3293
                            Criterion\Operator::GTE,
3294
                            235,
3295
                            $wellInVodice['latitude'],
3296
                            $wellInVodice['longitude']
3297
                        ),
3298
                    )
3299
                ),
3300
                'offset' => 0,
3301
                'limit' => 10,
3302
                'sortClauses' => array(
3303
                    new SortClause\MapLocationDistance(
3304
                        'testtype',
3305
                        'maplocation',
3306
                        $wellInVodice['latitude'],
3307
                        $wellInVodice['longitude'],
3308
                        Query::SORT_ASC
3309
                    ),
3310
                ),
3311
            )
3312
        );
3313
3314
        $searchService = $repository->getSearchService();
3315
        $result = $searchService->findContent($query);
3316
3317
        $this->assertEquals(3, $result->totalCount);
3318
        $this->assertEquals(
3319
            $wildBoars->id,
3320
            $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...
3321
        );
3322
        $this->assertEquals(
3323
            $mushrooms->id,
3324
            $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...
3325
        );
3326
        $this->assertEquals(
3327
            $tree->id,
3328
            $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...
3329
        );
3330
    }
3331
3332
    /**
3333
     * Test for the findContent() method.
3334
     *
3335
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3336
     * @group maplocation
3337
     */
3338 View Code Duplication
    public function testMapLocationDistanceSortDescending()
3339
    {
3340
        $contentType = $this->createTestPlaceContentType();
3341
3342
        // Create a draft to account for behaviour with ContentType in different states
3343
        $repository = $this->getRepository();
3344
        $contentTypeService = $repository->getContentTypeService();
3345
        $contentService = $repository->getContentService();
3346
        $contentTypeService->createContentTypeDraft($contentType);
3347
3348
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3349
        $createStruct->alwaysAvailable = false;
3350
        $createStruct->mainLanguageCode = 'eng-GB';
3351
        $createStruct->setField(
3352
            'maplocation',
3353
            array(
3354
                'latitude' => 45.894877,
3355
                'longitude' => 15.972699,
3356
                'address' => 'Here be wild boars',
3357
            ),
3358
            'eng-GB'
3359
        );
3360
3361
        $draft = $contentService->createContent($createStruct);
3362
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3363
3364
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3365
        $createStruct->alwaysAvailable = false;
3366
        $createStruct->mainLanguageCode = 'eng-GB';
3367
        $createStruct->setField(
3368
            'maplocation',
3369
            array(
3370
                'latitude' => 45.927334,
3371
                'longitude' => 15.934847,
3372
                'address' => 'A lone tree',
3373
            ),
3374
            'eng-GB'
3375
        );
3376
3377
        $draft = $contentService->createContent($createStruct);
3378
        $tree = $contentService->publishVersion($draft->getVersionInfo());
3379
3380
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3381
        $createStruct->alwaysAvailable = false;
3382
        $createStruct->mainLanguageCode = 'eng-GB';
3383
        $createStruct->setField(
3384
            'maplocation',
3385
            array(
3386
                'latitude' => 45.903777,
3387
                'longitude' => 15.958788,
3388
                'address' => 'Meadow with mushrooms',
3389
            ),
3390
            'eng-GB'
3391
        );
3392
3393
        $draft = $contentService->createContent($createStruct);
3394
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3395
3396
        $this->refreshSearch($repository);
3397
3398
        $well = array(
3399
            'latitude' => 43.756825,
3400
            'longitude' => 15.775074,
3401
        );
3402
3403
        $query = new Query(
3404
            array(
3405
                'filter' => new Criterion\LogicalAnd(
3406
                    array(
3407
                        new Criterion\ContentTypeId($contentType->id),
3408
                        new Criterion\MapLocationDistance(
3409
                            'maplocation',
3410
                            Criterion\Operator::GTE,
3411
                            235,
3412
                            $well['latitude'],
3413
                            $well['longitude']
3414
                        ),
3415
                    )
3416
                ),
3417
                'offset' => 0,
3418
                'limit' => 10,
3419
                'sortClauses' => array(
3420
                    new SortClause\MapLocationDistance(
3421
                        'testtype',
3422
                        'maplocation',
3423
                        $well['latitude'],
3424
                        $well['longitude'],
3425
                        Query::SORT_DESC
3426
                    ),
3427
                ),
3428
            )
3429
        );
3430
3431
        $searchService = $repository->getSearchService();
3432
        $result = $searchService->findContent($query);
3433
3434
        $this->assertEquals(3, $result->totalCount);
3435
        $this->assertEquals(
3436
            $wildBoars->id,
3437
            $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...
3438
        );
3439
        $this->assertEquals(
3440
            $mushrooms->id,
3441
            $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...
3442
        );
3443
        $this->assertEquals(
3444
            $tree->id,
3445
            $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...
3446
        );
3447
    }
3448
3449
    /**
3450
     * Test for the findContent() method.
3451
     *
3452
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3453
     * @group maplocation
3454
     */
3455
    public function testMapLocationDistanceWithCustomField()
3456
    {
3457
        $setupFactory = $this->getSetupFactory();
3458
        if ($setupFactory instanceof LegacyElasticsearch) {
3459
            $this->markTestIncomplete("TODO: Some issues with 'copy_to' and 'geo_point'");
3460
        }
3461
3462
        $contentType = $this->createTestPlaceContentType();
3463
3464
        // Create a draft to account for behaviour with ContentType in different states
3465
        $repository = $this->getRepository();
3466
        $contentTypeService = $repository->getContentTypeService();
3467
        $contentService = $repository->getContentService();
3468
        $contentTypeService->createContentTypeDraft($contentType);
3469
3470
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3471
        $createStruct->alwaysAvailable = false;
3472
        $createStruct->mainLanguageCode = 'eng-GB';
3473
        $createStruct->setField(
3474
            'maplocation',
3475
            array(
3476
                'latitude' => 45.894877,
3477
                'longitude' => 15.972699,
3478
                'address' => 'Here be wild boars',
3479
            ),
3480
            'eng-GB'
3481
        );
3482
3483
        $draft = $contentService->createContent($createStruct);
3484
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3485
3486
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3487
        $createStruct->alwaysAvailable = false;
3488
        $createStruct->mainLanguageCode = 'eng-GB';
3489
        $createStruct->setField(
3490
            'maplocation',
3491
            array(
3492
                'latitude' => 45.927334,
3493
                'longitude' => 15.934847,
3494
                'address' => 'A lone tree',
3495
            ),
3496
            'eng-GB'
3497
        );
3498
3499
        $draft = $contentService->createContent($createStruct);
3500
        $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...
3501
3502
        $this->refreshSearch($repository);
3503
3504
        $distanceCriterion = new Criterion\MapLocationDistance(
3505
            'maplocation',
3506
            Criterion\Operator::LTE,
3507
            240,
3508
            43.756825,
3509
            15.775074
3510
        );
3511
        $distanceCriterion->setCustomField('testtype', 'maplocation', 'custom_geolocation_field');
3512
3513
        $query = new Query(
3514
            array(
3515
                'filter' => new Criterion\LogicalAnd(
3516
                    array(
3517
                        new Criterion\ContentTypeId($contentType->id),
3518
                        $distanceCriterion,
3519
                    )
3520
                ),
3521
                'offset' => 0,
3522
                'limit' => 10,
3523
                'sortClauses' => array(),
3524
            )
3525
        );
3526
3527
        $searchService = $repository->getSearchService();
3528
        $result = $searchService->findContent($query);
3529
3530
        $this->assertEquals(1, $result->totalCount);
3531
        $this->assertEquals(
3532
            $wildBoars->id,
3533
            $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...
3534
        );
3535
    }
3536
3537
    /**
3538
     * Test for the findContent() method.
3539
     *
3540
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3541
     * @group maplocation
3542
     */
3543
    public function testMapLocationDistanceWithCustomFieldSort()
3544
    {
3545
        $setupFactory = $this->getSetupFactory();
3546
        if ($setupFactory instanceof LegacyElasticsearch) {
3547
            $this->markTestIncomplete("TODO: Some issues with 'copy_to' and 'geo_point'");
3548
        }
3549
3550
        $contentType = $this->createTestPlaceContentType();
3551
3552
        // Create a draft to account for behaviour with ContentType in different states
3553
        $repository = $this->getRepository();
3554
        $contentTypeService = $repository->getContentTypeService();
3555
        $contentService = $repository->getContentService();
3556
        $contentTypeService->createContentTypeDraft($contentType);
3557
3558
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3559
        $createStruct->alwaysAvailable = false;
3560
        $createStruct->mainLanguageCode = 'eng-GB';
3561
        $createStruct->setField(
3562
            'maplocation',
3563
            array(
3564
                'latitude' => 45.894877,
3565
                'longitude' => 15.972699,
3566
                'address' => 'Here be wild boars',
3567
            ),
3568
            'eng-GB'
3569
        );
3570
3571
        $draft = $contentService->createContent($createStruct);
3572
        $wildBoars = $contentService->publishVersion($draft->getVersionInfo());
3573
3574
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3575
        $createStruct->alwaysAvailable = false;
3576
        $createStruct->mainLanguageCode = 'eng-GB';
3577
        $createStruct->setField(
3578
            'maplocation',
3579
            array(
3580
                'latitude' => 45.927334,
3581
                'longitude' => 15.934847,
3582
                'address' => 'A lone tree',
3583
            ),
3584
            'eng-GB'
3585
        );
3586
3587
        $draft = $contentService->createContent($createStruct);
3588
        $tree = $contentService->publishVersion($draft->getVersionInfo());
3589
3590
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3591
        $createStruct->alwaysAvailable = false;
3592
        $createStruct->mainLanguageCode = 'eng-GB';
3593
        $createStruct->setField(
3594
            'maplocation',
3595
            array(
3596
                'latitude' => 45.903777,
3597
                'longitude' => 15.958788,
3598
                'address' => 'Meadow with mushrooms',
3599
            ),
3600
            'eng-GB'
3601
        );
3602
3603
        $draft = $contentService->createContent($createStruct);
3604
        $mushrooms = $contentService->publishVersion($draft->getVersionInfo());
3605
3606
        $this->refreshSearch($repository);
3607
3608
        $well = array(
3609
            'latitude' => 43.756825,
3610
            'longitude' => 15.775074,
3611
        );
3612
3613
        $sortClause = new SortClause\MapLocationDistance(
3614
            'testtype',
3615
            'maplocation',
3616
            $well['latitude'],
3617
            $well['longitude'],
3618
            Query::SORT_DESC
3619
        );
3620
        $sortClause->setCustomField('testtype', 'maplocation', 'custom_geolocation_field');
3621
3622
        $query = new Query(
3623
            array(
3624
                'filter' => new Criterion\LogicalAnd(
3625
                    array(
3626
                        new Criterion\ContentTypeId($contentType->id),
3627
                        new Criterion\MapLocationDistance(
3628
                            'maplocation',
3629
                            Criterion\Operator::GTE,
3630
                            235,
3631
                            $well['latitude'],
3632
                            $well['longitude']
3633
                        ),
3634
                    )
3635
                ),
3636
                'offset' => 0,
3637
                'limit' => 10,
3638
                'sortClauses' => array(
3639
                    $sortClause,
3640
                ),
3641
            )
3642
        );
3643
3644
        $searchService = $repository->getSearchService();
3645
        $result = $searchService->findContent($query);
3646
3647
        $this->assertEquals(3, $result->totalCount);
3648
        $this->assertEquals(
3649
            $wildBoars->id,
3650
            $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...
3651
        );
3652
        $this->assertEquals(
3653
            $mushrooms->id,
3654
            $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...
3655
        );
3656
        $this->assertEquals(
3657
            $tree->id,
3658
            $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...
3659
        );
3660
    }
3661
3662
    /**
3663
     * Test for the findLocations() method.
3664
     *
3665
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3666
     */
3667 View Code Duplication
    public function testFindMainLocation()
3668
    {
3669
        $plainSiteLocationId = 56;
3670
        $designLocationId = 58;
3671
        $partnersContentId = 59;
3672
        $repository = $this->getRepository();
3673
        $locationService = $repository->getLocationService();
3674
        $contentService = $repository->getContentService();
3675
3676
        // Add secondary Location for "Partners" user group, under "Design" page
3677
        $locationService->createLocation(
3678
            $contentService->loadContentInfo($partnersContentId),
3679
            $locationService->newLocationCreateStruct($designLocationId)
3680
        );
3681
3682
        $this->refreshSearch($repository);
3683
3684
        $query = new LocationQuery(
3685
            array(
3686
                'filter' => new Criterion\LogicalAnd(
3687
                    array(
3688
                        new Criterion\ParentLocationId($designLocationId),
3689
                        new Criterion\Location\IsMainLocation(
3690
                            Criterion\Location\IsMainLocation::MAIN
3691
                        ),
3692
                    )
3693
                ),
3694
                'offset' => 0,
3695
                'limit' => 10,
3696
                'sortClauses' => array(),
3697
            )
3698
        );
3699
3700
        $searchService = $repository->getSearchService();
3701
        $result = $searchService->findLocations($query);
3702
3703
        $this->assertEquals(1, $result->totalCount);
3704
        $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...
3705
    }
3706
3707
    /**
3708
     * Test for the findLocations() method.
3709
     *
3710
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3711
     */
3712 View Code Duplication
    public function testFindNonMainLocation()
3713
    {
3714
        $designLocationId = 58;
3715
        $partnersContentId = 59;
3716
        $repository = $this->getRepository();
3717
        $locationService = $repository->getLocationService();
3718
        $contentService = $repository->getContentService();
3719
3720
        // Add secondary Location for "Partners" user group, under "Design" page
3721
        $newLocation = $locationService->createLocation(
3722
            $contentService->loadContentInfo($partnersContentId),
3723
            $locationService->newLocationCreateStruct($designLocationId)
3724
        );
3725
3726
        $this->refreshSearch($repository);
3727
3728
        $query = new LocationQuery(
3729
            array(
3730
                'filter' => new Criterion\LogicalAnd(
3731
                    array(
3732
                        new Criterion\ParentLocationId($designLocationId),
3733
                        new Criterion\Location\IsMainLocation(
3734
                            Criterion\Location\IsMainLocation::NOT_MAIN
3735
                        ),
3736
                    )
3737
                ),
3738
                'offset' => 0,
3739
                'limit' => 10,
3740
                'sortClauses' => array(),
3741
            )
3742
        );
3743
3744
        $searchService = $repository->getSearchService();
3745
        $result = $searchService->findLocations($query);
3746
3747
        $this->assertEquals(1, $result->totalCount);
3748
        $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...
3749
    }
3750
3751
    /**
3752
     * Test for the findLocations() method.
3753
     *
3754
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3755
     */
3756 View Code Duplication
    public function testSortMainLocationAscending()
3757
    {
3758
        $plainSiteLocationId = 56;
3759
        $designLocationId = 58;
3760
        $partnersContentId = 59;
3761
        $repository = $this->getRepository();
3762
        $locationService = $repository->getLocationService();
3763
        $contentService = $repository->getContentService();
3764
3765
        // Add secondary Location for "Partners" user group, under "Design" page
3766
        $newLocation = $locationService->createLocation(
3767
            $contentService->loadContentInfo($partnersContentId),
3768
            $locationService->newLocationCreateStruct($designLocationId)
3769
        );
3770
3771
        $this->refreshSearch($repository);
3772
3773
        $query = new LocationQuery(
3774
            array(
3775
                'filter' => new Criterion\ParentLocationId($designLocationId),
3776
                'offset' => 0,
3777
                'limit' => 10,
3778
                'sortClauses' => array(
3779
                    new SortClause\Location\IsMainLocation(
3780
                        LocationQuery::SORT_ASC
3781
                    ),
3782
                ),
3783
            )
3784
        );
3785
3786
        $searchService = $repository->getSearchService();
3787
        $result = $searchService->findLocations($query);
3788
3789
        $this->assertEquals(2, $result->totalCount);
3790
        $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...
3791
        $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...
3792
    }
3793
3794
    /**
3795
     * Test for the findLocations() method.
3796
     *
3797
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3798
     */
3799 View Code Duplication
    public function testSortMainLocationDescending()
3800
    {
3801
        $plainSiteLocationId = 56;
3802
        $designLocationId = 58;
3803
        $partnersContentId = 59;
3804
        $repository = $this->getRepository();
3805
        $locationService = $repository->getLocationService();
3806
        $contentService = $repository->getContentService();
3807
3808
        // Add secondary Location for "Partners" user group, under "Design" page
3809
        $newLocation = $locationService->createLocation(
3810
            $contentService->loadContentInfo($partnersContentId),
3811
            $locationService->newLocationCreateStruct($designLocationId)
3812
        );
3813
3814
        $this->refreshSearch($repository);
3815
3816
        $query = new LocationQuery(
3817
            array(
3818
                'filter' => new Criterion\ParentLocationId($designLocationId),
3819
                'offset' => 0,
3820
                'limit' => 10,
3821
                'sortClauses' => array(
3822
                    new SortClause\Location\IsMainLocation(
3823
                        LocationQuery::SORT_DESC
3824
                    ),
3825
                ),
3826
            )
3827
        );
3828
3829
        $searchService = $repository->getSearchService();
3830
        $result = $searchService->findLocations($query);
3831
3832
        $this->assertEquals(2, $result->totalCount);
3833
        $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...
3834
        $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...
3835
    }
3836
3837
    /**
3838
     * Test for the findLocations() method.
3839
     *
3840
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
3841
     */
3842
    public function testContentWithMultipleLocations()
3843
    {
3844
        $repository = $this->getRepository();
3845
        $contentService = $repository->getContentService();
3846
        $contentTypeService = $repository->getContentTypeService();
3847
        $locationService = $repository->getLocationService();
3848
3849
        $forumType = $contentTypeService->loadContentTypeByIdentifier('forum');
3850
3851
        $createStruct = $contentService->newContentCreateStruct($forumType, 'eng-GB');
3852
        $createStruct->alwaysAvailable = false;
3853
        $createStruct->setField('name', 'An awesome duplicate forum');
3854
3855
        $draft = $contentService->createContent($createStruct);
3856
        $content = $contentService->publishVersion($draft->getVersionInfo());
3857
3858
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(2);
3859
        $location1 = $locationService->createLocation($content->contentInfo, $locationCreateStruct);
3860
        $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(5);
3861
        $location2 = $locationService->createLocation($content->contentInfo, $locationCreateStruct);
3862
3863
        $this->refreshSearch($repository);
3864
3865
        $query = new LocationQuery(
3866
            array(
3867
                'filter' => new Criterion\ContentId($content->id),
3868
                'sortClauses' => array(
3869
                    new SortClause\Location\Id(LocationQuery::SORT_ASC),
3870
                ),
3871
            )
3872
        );
3873
3874
        $searchService = $repository->getSearchService();
3875
        $result = $searchService->findLocations($query);
3876
3877
        $this->assertEquals(2, $result->totalCount);
3878
        $this->assertEquals(
3879
            $location1->id,
3880
            $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...
3881
        );
3882
        $this->assertEquals(
3883
            $location2->id,
3884
            $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...
3885
        );
3886
    }
3887
3888
    protected function createContentForTestUserMetadataGroupHorizontal()
3889
    {
3890
        $repository = $this->getRepository();
3891
        $contentService = $repository->getContentService();
3892
        $contentTypeService = $repository->getContentTypeService();
3893
        $locationService = $repository->getLocationService();
3894
        $userService = $repository->getUserService();
3895
        $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...
3896
        // ID of the "Administrators" user group in an eZ Publish demo installation
3897
        $administratorsUserGroupId = 12;
3898
        // ID of the "Editors" user group in an eZ Publish demo installation
3899
        $editorsUserGroupId = 13;
3900
3901
        $administratorsUserGroup = $userService->loadUserGroup($administratorsUserGroupId);
3902
        $editorsUserGroup = $userService->loadUserGroup($editorsUserGroupId);
3903
3904
        // Add additional Location for Administrators UserGroup under Editors UserGroup Location
3905
        $locationCreateStruct = $locationService->newLocationCreateStruct(
3906
            $editorsUserGroup->contentInfo->mainLocationId
3907
        );
3908
        $newAdministratorsUserGroupLocation = $locationService->createLocation(
3909
            $administratorsUserGroup->contentInfo,
3910
            $locationCreateStruct
3911
        );
3912
3913
        // Add additional Location for administrator user under newly created UserGroup Location
3914
        $locationCreateStruct = $locationService->newLocationCreateStruct(
3915
            $newAdministratorsUserGroupLocation->id
3916
        );
3917
        $locationService->createLocation(
3918
            $administratorUser->contentInfo,
3919
            $locationCreateStruct
3920
        );
3921
3922
        // Create a Content to be found through Editors UserGroup id.
3923
        // This ensures data is indexed, it could also be done by updating metadata of
3924
        // an existing Content, but slot would need to reindex Content and that should
3925
        // be tested elsewhere (dedicated indexing integration tests, missing ATM).
3926
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
3927
3928
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
3929
        $createStruct->setField('name', 'test');
3930
3931
        $locationCreateStruct = $locationService->newLocationCreateStruct(2);
3932
        $draft = $contentService->createContent($createStruct, array($locationCreateStruct));
3933
        $content = $contentService->publishVersion($draft->getVersionInfo());
3934
        $contentTypeService->createContentTypeDraft($contentType);
3935
3936
        $this->refreshSearch($repository);
3937
3938
        return $content;
3939
    }
3940
3941
    /**
3942
     * Test for the findContent() method.
3943
     *
3944
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
3945
     */
3946
    public function testUserMetadataGroupHorizontalFilterContent($queryType = null)
3947
    {
3948
        if ($queryType === null) {
3949
            $queryType = 'filter';
3950
        }
3951
3952
        $repository = $this->getRepository();
3953
        $searchService = $repository->getSearchService();
3954
        $editorsUserGroupId = 13;
3955
3956
        $content = $this->createContentForTestUserMetadataGroupHorizontal();
3957
3958
        $criteria = array();
3959
        $setupFactory = $this->getSetupFactory();
3960
3961
        // Do not limit for LSE, as it does not not require reindexing.
3962
        // See explanation below.
3963
        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...
3964
            $criteria[] = new Criterion\ContentTypeIdentifier('folder');
3965
        }
3966
3967
        $criteria[] = new Criterion\UserMetadata(
3968
            Criterion\UserMetadata::GROUP,
3969
            Criterion\Operator::EQ,
3970
            $editorsUserGroupId
3971
        );
3972
3973
        $query = new Query(
3974
            array(
3975
                $queryType => new Criterion\LogicalAnd($criteria),
3976
                'sortClauses' => array(
3977
                    new SortClause\ContentId(),
3978
                ),
3979
                'limit' => 50,
3980
            )
3981
        );
3982
3983
        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...
3984
            $result = $searchService->findContent($query);
3985
3986
            // Administrator User is owned by itself, when additional Locations are added
3987
            // it should be reindexed and its UserGroups will updated, which means it should
3988
            // also be found as a Content of Editors UserGroup. However we do not handle this
3989
            // in slots yet, and also miss SPI methods to do it without using Search (also
3990
            // needed to decouple services), because as indexing is asynchronous Search
3991
            // should not eat its own dog food for reindexing.
3992
            $this->assertEquals(1, $result->totalCount);
3993
3994
            $this->assertEquals(
3995
                $content->id,
3996
                $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...
3997
            );
3998
        } else {
3999
            // This is how it should eventually work for all search engines,
4000
            // with required reindexing slots properly implemented.
4001
4002
            $result = $searchService->findContent($query);
4003
4004
            // Assert last hit manually, as id will change because it is created in test
4005
            // and not present it base fixture.
4006
            $foundContent1 = array_pop($result->searchHits);
4007
            $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...
4008
            $this->assertEquals($content->id, $foundContent1->valueObject->id);
4009
4010
            $this->simplifySearchResult($result);
4011
            $this->assertEquals(
4012
                include $this->getFixtureDir() . '/UserMetadata.php',
4013
                $result,
4014
                'Search results do not match.',
4015
                .1 // Be quite generous regarding delay -- most important for scores
4016
            );
4017
        }
4018
    }
4019
4020
    /**
4021
     * Test for the findContent() method.
4022
     *
4023
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4024
     */
4025
    public function testUserMetadataGroupHorizontalQueryContent()
4026
    {
4027
        $this->testUserMetadataGroupHorizontalFilterContent('query');
4028
    }
4029
4030
    /**
4031
     * Test for the findLocations() method.
4032
     *
4033
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
4034
     */
4035
    public function testUserMetadataGroupHorizontalFilterLocation($queryType = null)
4036
    {
4037
        if ($queryType === null) {
4038
            $queryType = 'filter';
4039
        }
4040
4041
        $repository = $this->getRepository();
4042
        $searchService = $repository->getSearchService();
4043
        $editorsUserGroupId = 13;
4044
4045
        $content = $this->createContentForTestUserMetadataGroupHorizontal();
4046
4047
        $criteria = array();
4048
        $setupFactory = $this->getSetupFactory();
4049
4050
        // Do not limit for LSE, as it does not not require reindexing.
4051
        // See explanation below.
4052
        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...
4053
            $criteria[] = new Criterion\ContentTypeIdentifier('folder');
4054
        }
4055
4056
        $criteria[] = new Criterion\UserMetadata(
4057
            Criterion\UserMetadata::GROUP,
4058
            Criterion\Operator::EQ,
4059
            $editorsUserGroupId
4060
        );
4061
4062
        $query = new LocationQuery(
4063
            array(
4064
                $queryType => new Criterion\LogicalAnd($criteria),
4065
                'sortClauses' => array(
4066
                    new SortClause\Location\Id(),
4067
                ),
4068
                'limit' => 50,
4069
            )
4070
        );
4071
4072
        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...
4073
            $result = $searchService->findLocations($query);
4074
4075
            // Administrator User is owned by itself, when additional Locations are added
4076
            // it should be reindexed and its UserGroups will updated, which means it should
4077
            // also be found as a Content of Editors UserGroup. However we do not handle this
4078
            // in slots yet, and also miss SPI methods to do it without using Search (also
4079
            // needed to decouple services), because as indexing is asynchronous Search
4080
            // should not eat its own dog food for reindexing.
4081
            $this->assertEquals(1, $result->totalCount);
4082
4083
            $this->assertEquals(
4084
                $content->contentInfo->mainLocationId,
4085
                $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...
4086
            );
4087
        } else {
4088
            // This is how it should eventually work for all search engines,
4089
            // with required reindexing slots properly implemented.
4090
4091
            $result = $searchService->findLocations($query);
4092
4093
            // Assert last two hits manually, as ids will change because they are created
4094
            // in test and not present in base fixture.
4095
            $foundLocation1 = array_pop($result->searchHits);
4096
            $foundLocation2 = array_pop($result->searchHits);
4097
            // Remove additional Administrators UserGroup Location
4098
            array_pop($result->searchHits);
4099
            $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...
4100
            $this->assertEquals(
4101
                $content->versionInfo->contentInfo->mainLocationId,
4102
                $foundLocation1->valueObject->id
4103
            );
4104
            $this->assertEquals(
4105
                $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...
4106
                $foundLocation2->valueObject->contentId
4107
            );
4108
4109
            $this->simplifySearchResult($result);
4110
            $this->assertEquals(
4111
                include $this->getFixtureDir() . '/UserMetadataLocation.php',
4112
                $result,
4113
                'Search results do not match.',
4114
                .1 // Be quite generous regarding delay -- most important for scores
4115
            );
4116
        }
4117
    }
4118
4119
    /**
4120
     * Test for the findLocations() method.
4121
     *
4122
     * @see \eZ\Publish\API\Repository\SearchService::findLocations()
4123
     */
4124
    public function testUserMetadataGroupHorizontalQueryLocation()
4125
    {
4126
        $this->testUserMetadataGroupHorizontalFilterLocation('query');
4127
    }
4128
4129
    /**
4130
     * Test for FullText on the findContent() method.
4131
     *
4132
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4133
     */
4134
    public function testFullTextOnNewContent()
4135
    {
4136
        $repository = $this->getRepository();
4137
        $contentService = $repository->getContentService();
4138
        $contentTypeService = $repository->getContentTypeService();
4139
        $locationService = $repository->getLocationService();
4140
        $searchService = $repository->getSearchService();
4141
4142
        $contentCreateStruct = $contentService->newContentCreateStruct(
4143
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4144
            'eng-GB'
4145
        );
4146
4147
        $contentCreateStruct->setField('name', 'foxes');
4148
4149
        $englishContent = $contentService->publishVersion(
4150
            $contentService->createContent(
4151
                $contentCreateStruct,
4152
                array($locationService->newLocationCreateStruct(2))
4153
            )->versionInfo
4154
        );
4155
4156
        $this->refreshSearch($repository);
4157
4158
        $query = new Query(
4159
            array(
4160
                'query' => new Criterion\FullText('foxes'),
4161
            )
4162
        );
4163
4164
        $searchResult = $searchService->findContentInfo($query);
4165
4166
        $this->assertEquals(1, $searchResult->totalCount);
4167
        $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...
4168
    }
4169
4170
    /**
4171
     * Test for the findContent() method.
4172
     *
4173
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4174
     */
4175
    public function testLanguageAnalysisSeparateContent()
4176
    {
4177
        $setupFactory = $this->getSetupFactory();
4178
        if (!$setupFactory instanceof LegacyElasticsearch) {
4179
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4180
        }
4181
4182
        $repository = $this->getRepository();
4183
        $contentService = $repository->getContentService();
4184
        $contentTypeService = $repository->getContentTypeService();
4185
        $locationService = $repository->getLocationService();
4186
        $searchService = $repository->getSearchService();
4187
        $languageService = $repository->getContentLanguageService();
4188
4189
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4190
        $languageCreateStruct->languageCode = 'rus-RU';
4191
        $languageCreateStruct->name = 'Russian';
4192
4193
        $languageService->createLanguage($languageCreateStruct);
4194
4195
        $contentCreateStruct = $contentService->newContentCreateStruct(
4196
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4197
            'eng-GB'
4198
        );
4199
4200
        $contentCreateStruct->setField('name', 'foxes');
4201
4202
        $englishContent = $contentService->publishVersion(
4203
            $contentService->createContent(
4204
                $contentCreateStruct,
4205
                array($locationService->newLocationCreateStruct(2))
4206
            )->versionInfo
4207
        );
4208
4209
        $contentCreateStruct = $contentService->newContentCreateStruct(
4210
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4211
            'rus-RU'
4212
        );
4213
4214
        $contentCreateStruct->setField('name', 'foxes');
4215
4216
        $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...
4217
            $contentService->createContent(
4218
                $contentCreateStruct,
4219
                array($locationService->newLocationCreateStruct(2))
4220
            )->versionInfo
4221
        );
4222
4223
        // Only Content in English should be found, because Content in Russian
4224
        // will not be correctly stemmed
4225
        $query = new Query(
4226
            array(
4227
                'query' => new Criterion\FullText('foxing'),
4228
            )
4229
        );
4230
4231
        $searchResult = $searchService->findContent($query);
4232
4233
        $this->assertEquals(1, $searchResult->totalCount);
4234
        $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...
4235
    }
4236
4237
    /**
4238
     * Test for the findContent() method.
4239
     *
4240
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4241
     */
4242
    public function testLanguageAnalysisSameContent()
4243
    {
4244
        $setupFactory = $this->getSetupFactory();
4245
        if (!$setupFactory instanceof LegacyElasticsearch) {
4246
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4247
        }
4248
4249
        $repository = $this->getRepository();
4250
        $contentService = $repository->getContentService();
4251
        $contentTypeService = $repository->getContentTypeService();
4252
        $locationService = $repository->getLocationService();
4253
        $searchService = $repository->getSearchService();
4254
        $languageService = $repository->getContentLanguageService();
4255
4256
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4257
        $languageCreateStruct->languageCode = 'rus-RU';
4258
        $languageCreateStruct->name = 'Russian';
4259
4260
        $languageService->createLanguage($languageCreateStruct);
4261
4262
        $contentCreateStruct = $contentService->newContentCreateStruct(
4263
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4264
            'eng-GB'
4265
        );
4266
4267
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'eng-GB');
4268
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'rus-RU');
4269
4270
        $mixedContent = $contentService->publishVersion(
4271
            $contentService->createContent(
4272
                $contentCreateStruct,
4273
                array($locationService->newLocationCreateStruct(2))
4274
            )->versionInfo
4275
        );
4276
4277
        // Content will be found because translation in Russian will be correctly stemmed
4278
        $query = new Query(
4279
            array(
4280
                'query' => new Criterion\FullText('важнее'),
4281
            )
4282
        );
4283
4284
        $searchResult = $searchService->findContent($query);
4285
4286
        $this->assertEquals(1, $searchResult->totalCount);
4287
        $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...
4288
    }
4289
4290
    /**
4291
     * Test for the findContent() method.
4292
     *
4293
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4294
     */
4295
    public function testLanguageAnalysisSameContentNotFound()
4296
    {
4297
        $setupFactory = $this->getSetupFactory();
4298
        if (!$setupFactory instanceof LegacyElasticsearch) {
4299
            $this->markTestSkipped('Language analysis is implemented only for Elasticsearch storage');
4300
        }
4301
4302
        $repository = $this->getRepository();
4303
        $contentService = $repository->getContentService();
4304
        $contentTypeService = $repository->getContentTypeService();
4305
        $locationService = $repository->getLocationService();
4306
        $searchService = $repository->getSearchService();
4307
        $languageService = $repository->getContentLanguageService();
4308
4309
        $languageCreateStruct = $languageService->newLanguageCreateStruct();
4310
        $languageCreateStruct->languageCode = 'rus-RU';
4311
        $languageCreateStruct->name = 'Russian';
4312
4313
        $languageService->createLanguage($languageCreateStruct);
4314
4315
        $contentCreateStruct = $contentService->newContentCreateStruct(
4316
            $contentTypeService->loadContentTypeByIdentifier('folder'),
4317
            'eng-GB'
4318
        );
4319
4320
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'eng-GB');
4321
        $contentCreateStruct->setField('name', 'foxes важнейшими', 'rus-RU');
4322
4323
        $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...
4324
            $contentService->createContent(
4325
                $contentCreateStruct,
4326
                array($locationService->newLocationCreateStruct(2))
4327
            )->versionInfo
4328
        );
4329
4330
        // Content should be found because translation in Russian will be correctly stemmed
4331
        $query = new Query(
4332
            array(
4333
                'query' => new Criterion\FullText('важнее'),
4334
            )
4335
        );
4336
4337
        // Filtering fields for only English will cause no match because the term will
4338
        // not be correctly stemmed
4339
        $searchResult = $searchService->findContent($query, array('languages' => array('eng-GB')));
4340
4341
        $this->assertEquals(0, $searchResult->totalCount);
4342
    }
4343
4344
    /**
4345
     * Test for the findContent() method.
4346
     *
4347
     * @see \eZ\Publish\API\Repository\SearchService::findContent()
4348
     */
4349
    public function testFulltextComplex()
4350
    {
4351
        $repository = $this->getRepository();
4352
        $contentService = $repository->getContentService();
4353
        $contentTypeService = $repository->getContentTypeService();
4354
        $locationService = $repository->getLocationService();
4355
        $searchService = $repository->getSearchService();
4356
4357
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
4358
        $contentCreateStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
4359
4360
        $contentCreateStruct->setField('name', 'red');
4361
        $contentCreateStruct->setField('short_name', 'red apple');
4362
        $content1 = $contentService->publishVersion(
4363
            $contentService->createContent(
4364
                $contentCreateStruct,
4365
                [$locationService->newLocationCreateStruct(2)]
4366
            )->versionInfo
4367
        );
4368
4369
        $contentCreateStruct->setField('name', 'apple');
4370
        $contentCreateStruct->setField('short_name', 'two');
4371
        $content2 = $contentService->publishVersion(
4372
            $contentService->createContent(
4373
                $contentCreateStruct,
4374
                [$locationService->newLocationCreateStruct(2)]
4375
            )->versionInfo
4376
        );
4377
4378
        $contentCreateStruct->setField('name', 'red apple');
4379
        $contentCreateStruct->setField('short_name', 'three');
4380
        $content3 = $contentService->publishVersion(
4381
            $contentService->createContent(
4382
                $contentCreateStruct,
4383
                [$locationService->newLocationCreateStruct(2)]
4384
            )->versionInfo
4385
        );
4386
4387
        $this->refreshSearch($repository);
4388
4389
        $query = new Query(
4390
            [
4391
                'query' => new Criterion\FullText(
4392
                    'red apple',
4393
                    [
4394
                        'boost' => [
4395
                            'short_name' => 2,
4396
                        ],
4397
                        'fuzziness' => .1,
4398
                    ]
4399
                ),
4400
            ]
4401
        );
4402
4403
        $searchResult = $searchService->findContent($query, ['languages' => ['eng-GB']]);
4404
4405
        $this->assertEquals(3, $searchResult->totalCount);
4406
4407
        // Legacy search engine does have scoring, sorting the results by ID in that case
4408
        $setupFactory = $this->getSetupFactory();
4409
        if (get_class($setupFactory) === 'eZ\Publish\API\Repository\Tests\SetupFactory\Legacy') {
4410
            usort(
4411
                $searchResult->searchHits,
4412
                function ($a, $b) {
4413
                    return ($a->valueObject->id < $b->valueObject->id) ? -1 : 1;
4414
                }
4415
            );
4416
4417
            $this->assertEquals($content1->id, $searchResult->searchHits[0]->valueObject->id);
4418
            $this->assertEquals($content2->id, $searchResult->searchHits[1]->valueObject->id);
4419
            $this->assertEquals($content3->id, $searchResult->searchHits[2]->valueObject->id);
4420
4421
            return;
4422
        }
4423
4424
        $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...
4425
        $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...
4426
        $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...
4427
    }
4428
4429
    /**
4430
     * Assert that query result matches the given fixture.
4431
     *
4432
     * @param Query $query
4433
     * @param string $fixture
4434
     * @param null|callable $closure
4435
     * @param bool $info
4436
     * @param bool $id
4437
     */
4438
    protected function assertQueryFixture(Query $query, $fixture, $closure = null, $ignoreScore = true, $info = false, $id = true)
4439
    {
4440
        $repository = $this->getRepository();
4441
        $searchService = $repository->getSearchService();
4442
4443
        try {
4444
            if ($query instanceof LocationQuery) {
4445
                $setupFactory = $this->getSetupFactory();
4446
                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...
4447
                    // @todo When we want to test score again by default we will need fixtures for Solr
4448
                }
4449
4450
                if ($setupFactory instanceof LegacyElasticsearch) {
4451
                    $position = strrpos($fixture, '/');
4452
                    $fixture = substr_replace($fixture, '/Location', $position, 0);
4453
                }
4454
4455
                $result = $searchService->findLocations($query);
4456
            } elseif ($query instanceof Query) {
4457
                if ($info) {
4458
                    $result = $searchService->findContentInfo($query);
4459
                } else {
4460
                    $result = $searchService->findContent($query);
4461
                }
4462
            } else {
4463
                $this->fail('Expected instance of LocationQuery or Query, got: ' . gettype($query));
4464
            }
4465
            $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...
4466
        } catch (NotImplementedException $e) {
4467
            $this->markTestSkipped(
4468
                'This feature is not supported by the current search backend: ' . $e->getMessage()
4469
            );
4470
        }
4471
4472 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...
4473
            if (isset($_ENV['ez_tests_record'])) {
4474
                file_put_contents(
4475
                    $record = $fixture . '.recording',
4476
                    "<?php\n\nreturn " . var_export($result, true) . ";\n\n"
4477
                );
4478
                $this->markTestIncomplete("No fixture available. Result recorded at $record. Result: \n" . $this->printResult($result));
4479
            } else {
4480
                $this->markTestIncomplete("No fixture available. Set \$_ENV['ez_tests_record'] to generate it.");
4481
            }
4482
        }
4483
4484
        $fixture = include $fixture;
4485
4486
        if ($closure !== null) {
4487
            $closure($fixture);
4488
            $closure($result);
4489
        }
4490
4491 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...
4492
            foreach (array($fixture, $result) as $set) {
4493
                $property = new \ReflectionProperty(get_class($set), 'maxScore');
4494
                $property->setAccessible(true);
4495
                $property->setValue($set, 0.0);
4496
4497
                foreach ($set->searchHits as $hit) {
4498
                    $property = new \ReflectionProperty(get_class($hit), 'score');
4499
                    $property->setAccessible(true);
4500
                    $property->setValue($hit, 0.0);
4501
                }
4502
            }
4503
        }
4504
4505
        foreach (array($fixture, $result) as $set) {
4506
            foreach ($set->searchHits as $hit) {
4507
                $property = new \ReflectionProperty(get_class($hit), 'index');
4508
                $property->setAccessible(true);
4509
                $property->setValue($hit, null);
4510
4511
                $property = new \ReflectionProperty(get_class($hit), 'matchedTranslation');
4512
                $property->setAccessible(true);
4513
                $property->setValue($hit, null);
4514
4515
                if (!$id) {
4516
                    $hit->valueObject['id'] = null;
4517
                }
4518
            }
4519
        }
4520
4521
        $this->assertEquals(
4522
            $fixture,
4523
            $result,
4524
            'Search results do not match.',
4525
            .99 // Be quite generous regarding delay -- most important for scores
4526
        );
4527
    }
4528
4529
    /**
4530
     * Show a simplified view of the search result for manual introspection.
4531
     *
4532
     * @param SearchResult $result
4533
     *
4534
     * @return string
4535
     */
4536 View Code Duplication
    protected function printResult(SearchResult $result)
4537
    {
4538
        $printed = '';
4539
        foreach ($result->searchHits as $hit) {
4540
            $printed .= sprintf(" - %s (%s)\n", $hit->valueObject['title'], $hit->valueObject['id']);
4541
        }
4542
4543
        return $printed;
4544
    }
4545
4546
    /**
4547
     * Simplify search result.
4548
     *
4549
     * This leads to saner comparisons of results, since we do not get the full
4550
     * content objects every time.
4551
     *
4552
     * @param SearchResult $result
4553
     */
4554
    protected function simplifySearchResult(SearchResult $result)
4555
    {
4556
        $result->time = 1;
4557
4558
        foreach ($result->searchHits as $hit) {
4559
            switch (true) {
4560
                case $hit->valueObject instanceof Content:
4561 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...
4562
                    $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...
4563
                        'id' => $hit->valueObject->contentInfo->id,
4564
                        'title' => $hit->valueObject->contentInfo->name,
4565
                    );
4566
                    break;
4567
4568
                case $hit->valueObject instanceof ContentInfo:
4569
                    $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...
4570
                        'id' => $hit->valueObject->id,
4571
                        'title' => $hit->valueObject->name,
4572
                    );
4573
                    break;
4574
4575
                default:
4576
                    throw new \RuntimeException('Unknown search result hit type: ' . get_class($hit->valueObject));
4577
            }
4578
        }
4579
    }
4580
4581
    /**
4582
     * Get fixture directory.
4583
     *
4584
     * @return string
4585
     */
4586
    protected function getFixtureDir()
4587
    {
4588
        return __DIR__ . '/_fixtures/' . getenv('fixtureDir') . '/';
4589
    }
4590
4591
    /**
4592
     * For findContentInfo tests, to reuse fixtures for findContent tests.
4593
     *
4594
     * @param null|callable $closure
4595
     *
4596
     * @return callable
4597
     */
4598
    private function getContentInfoFixtureClosure($closure = null)
4599
    {
4600
        /** @var $data \eZ\Publish\API\Repository\Values\Content\Search\SearchResult */
4601
        return function (&$data) use ($closure) {
4602
            foreach ($data->searchHits as $searchHit) {
4603
                if ($searchHit->valueObject instanceof Content) {
4604
                    $searchHit->valueObject = $searchHit->valueObject->getVersionInfo()->getContentInfo();
4605
                }
4606
            }
4607
4608
            if (isset($closure)) {
4609
                $closure($data);
4610
            }
4611
        };
4612
    }
4613
}
4614