Completed
Push — master ( 0a7dac...746db8 )
by
unknown
14:53
created

SearchTest::getDomainMapperMock()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File contains: eZ\Publish\Core\Repository\Tests\Service\Mock\SearchTest 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\Core\Repository\Tests\Service\Mock;
10
11
use eZ\Publish\Core\Repository\ContentService;
12
use eZ\Publish\Core\Repository\Tests\Service\Mock\Base as BaseServiceMockTest;
13
use eZ\Publish\Core\Repository\SearchService;
14
use eZ\Publish\Core\Repository\Permission\PermissionCriterionResolver;
15
use eZ\Publish\API\Repository\Values\Content\Content;
16
use eZ\Publish\API\Repository\Values\Content\Location;
17
use eZ\Publish\API\Repository\Values\Content\Query;
18
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
19
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
20
use eZ\Publish\API\Repository\Values\Content\Query\SortClause;
21
use eZ\Publish\API\Repository\Values\Content\Search\SearchResult;
22
use eZ\Publish\API\Repository\Values\Content\Search\SearchHit;
23
use eZ\Publish\Core\Search\Common\BackgroundIndexer;
24
use eZ\Publish\Core\Search\Common\BackgroundIndexer\NullIndexer;
25
use eZ\Publish\SPI\Persistence\Content\ContentInfo as SPIContentInfo;
26
use eZ\Publish\SPI\Persistence\Content\Location as SPILocation;
27
use eZ\Publish\API\Repository\Exceptions\InvalidArgumentException;
28
use Exception;
29
30
/**
31
 * Mock test case for Search service.
32
 */
33
class SearchTest extends BaseServiceMockTest
34
{
35
    protected $repositoryMock;
36
37
    protected $contentDomainMapperMock;
38
39
    protected $permissionsCriterionResolverMock;
40
41
    /**
42
     * Test for the __construct() method.
43
     *
44
     * @covers \eZ\Publish\Core\Repository\SearchService::__construct
45
     */
46
    public function testConstructor()
47
    {
48
        $repositoryMock = $this->getRepositoryMock();
49
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
50
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
51
        $contentDomainMapperMock = $this->getContentDomainMapperMock();
52
        $permissionsCriterionResolverMock = $this->getPermissionCriterionResolverMock();
53
        $settings = ['teh setting'];
54
55
        $service = new SearchService(
0 ignored issues
show
Unused Code introduced by
$service 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...
56
            $repositoryMock,
57
            $searchHandlerMock,
58
            $contentDomainMapperMock,
59
            $permissionsCriterionResolverMock,
0 ignored issues
show
Bug introduced by
It seems like $permissionsCriterionResolverMock defined by $this->getPermissionCriterionResolverMock() on line 52 can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
60
            new NullIndexer(),
61
            $settings
62
        );
63
    }
64
65
    public function providerForFindContentValidatesLocationCriteriaAndSortClauses()
66
    {
67
        return [
68
            [
69
                new Query(['filter' => new Criterion\Location\Depth(Criterion\Operator::LT, 2)]),
70
                "Argument '\$query' is invalid: Location Criteria cannot be used in Content search",
71
            ],
72
            [
73
                new Query(['query' => new Criterion\Location\Depth(Criterion\Operator::LT, 2)]),
74
                "Argument '\$query' is invalid: Location Criteria cannot be used in Content search",
75
            ],
76
            [
77
                new Query(
78
                    [
79
                        'query' => new Criterion\LogicalAnd(
80
                            [
81
                                new Criterion\Location\Depth(Criterion\Operator::LT, 2),
82
                            ]
83
                        ),
84
                    ]
85
                ),
86
                "Argument '\$query' is invalid: Location Criteria cannot be used in Content search",
87
            ],
88
            [
89
                new Query(['sortClauses' => [new SortClause\Location\Id()]]),
90
                "Argument '\$query' is invalid: Location Sort Clauses cannot be used in Content search",
91
            ],
92
        ];
93
    }
94
95
    /**
96
     * @dataProvider providerForFindContentValidatesLocationCriteriaAndSortClauses
97
     */
98 View Code Duplication
    public function testFindContentValidatesLocationCriteriaAndSortClauses($query, $exceptionMessage)
99
    {
100
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
101
102
        $repositoryMock = $this->getRepositoryMock();
103
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
104
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
105
        $permissionsCriterionResolverMock = $this->getPermissionCriterionResolverMock();
106
107
        $service = new SearchService(
108
            $repositoryMock,
109
            $searchHandlerMock,
110
            $this->getContentDomainMapperMock(),
111
            $permissionsCriterionResolverMock,
0 ignored issues
show
Bug introduced by
It seems like $permissionsCriterionResolverMock defined by $this->getPermissionCriterionResolverMock() on line 105 can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
112
            new NullIndexer(),
113
            []
114
        );
115
116
        try {
117
            $service->findContent($query);
118
        } catch (InvalidArgumentException $e) {
119
            $this->assertEquals($exceptionMessage, $e->getMessage());
120
            throw $e;
121
        }
122
123
        $this->fail('Expected exception was not thrown');
124
    }
125
126
    public function providerForFindSingleValidatesLocationCriteria()
127
    {
128
        return [
129
            [
130
                new Criterion\Location\Depth(Criterion\Operator::LT, 2),
131
                "Argument '\$filter' is invalid: Location Criteria cannot be used in Content search",
132
            ],
133
            [
134
                new Criterion\LogicalAnd(
135
                    [
136
                        new Criterion\Location\Depth(Criterion\Operator::LT, 2),
137
                    ]
138
                ),
139
                "Argument '\$filter' is invalid: Location Criteria cannot be used in Content search",
140
            ],
141
        ];
142
    }
143
144
    /**
145
     * @dataProvider providerForFindSingleValidatesLocationCriteria
146
     */
147 View Code Duplication
    public function testFindSingleValidatesLocationCriteria($criterion, $exceptionMessage)
148
    {
149
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
150
151
        $repositoryMock = $this->getRepositoryMock();
152
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
153
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
154
        $permissionsCriterionResolverMock = $this->getPermissionCriterionResolverMock();
155
        $service = new SearchService(
156
            $repositoryMock,
157
            $searchHandlerMock,
158
            $this->getContentDomainMapperMock(),
159
            $permissionsCriterionResolverMock,
0 ignored issues
show
Bug introduced by
It seems like $permissionsCriterionResolverMock defined by $this->getPermissionCriterionResolverMock() on line 154 can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
160
            new NullIndexer(),
161
            []
162
        );
163
164
        try {
165
            $service->findSingle($criterion);
166
        } catch (InvalidArgumentException $e) {
167
            $this->assertEquals($exceptionMessage, $e->getMessage());
168
            throw $e;
169
        }
170
171
        $this->fail('Expected exception was not thrown');
172
    }
173
174
    /**
175
     * Test for the findContent() method.
176
     *
177
     * @covers \eZ\Publish\Core\Repository\SearchService::addPermissionsCriterion
178
     * @covers \eZ\Publish\Core\Repository\SearchService::findContent
179
     */
180 View Code Duplication
    public function testFindContentThrowsHandlerException()
181
    {
182
        $this->expectException(\Exception::class);
183
        $this->expectExceptionMessage('Handler threw an exception');
184
185
        $repositoryMock = $this->getRepositoryMock();
186
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
187
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
188
        $permissionsCriterionResolverMock = $this->getPermissionCriterionResolverMock();
189
190
        $service = new SearchService(
191
            $repositoryMock,
192
            $searchHandlerMock,
193
            $this->getContentDomainMapperMock(),
194
            $permissionsCriterionResolverMock,
0 ignored issues
show
Bug introduced by
It seems like $permissionsCriterionResolverMock defined by $this->getPermissionCriterionResolverMock() on line 188 can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
195
            new NullIndexer(),
196
            []
197
        );
198
199
        /** @var \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterionMock */
200
        $criterionMock = $this
201
            ->getMockBuilder(Criterion::class)
202
            ->disableOriginalConstructor()
203
            ->getMock();
204
        $query = new Query(['filter' => $criterionMock]);
205
206
        $permissionsCriterionResolverMock->expects($this->once())
207
            ->method('getPermissionsCriterion')
208
            ->with('content', 'read')
209
            ->will($this->throwException(new Exception('Handler threw an exception')));
210
211
        $service->findContent($query, [], true);
212
    }
213
214
    /**
215
     * Test for the findContent() method when search is out of sync with persistence.
216
     *
217
     * @covers \eZ\Publish\Core\Repository\SearchService::findContent
218
     */
219
    public function testFindContentWhenDomainMapperThrowsException()
220
    {
221
        $indexer = $this->createMock(BackgroundIndexer::class);
222
        $indexer->expects($this->once())
223
            ->method('registerContent')
224
            ->with($this->isInstanceOf(SPIContentInfo::class));
225
226
        $service = $this->getMockBuilder(SearchService::class)
227
            ->setConstructorArgs([
228
                $this->getRepositoryMock(),
229
                $this->getSPIMockHandler('Search\\Handler'),
230
                $mapper = $this->getContentDomainMapperMock(),
231
                $this->getPermissionCriterionResolverMock(),
232
                $indexer,
233
            ])->setMethods(['internalFindContentInfo'])
234
            ->getMock();
235
236
        $info = new SPIContentInfo(['id' => 33]);
237
        $result = new SearchResult(['searchHits' => [new SearchHit(['valueObject' => $info])], 'totalCount' => 2]);
238
        $service->expects($this->once())
239
            ->method('internalFindContentInfo')
240
            ->with($this->isInstanceOf(Query::class))
241
            ->willReturn($result);
242
243
        $mapper->expects($this->once())
244
            ->method('buildContentDomainObjectsOnSearchResult')
245
            ->with($this->equalTo($result), $this->equalTo([]))
246
            ->willReturnCallback(function (SearchResult $spiResult) use ($info) {
247
                unset($spiResult->searchHits[0]);
248
                --$spiResult->totalCount;
249
250
                return [$info];
251
            });
252
253
        $finalResult = $service->findContent(new Query());
254
255
        $this->assertEmpty($finalResult->searchHits, 'Expected search hits to be empty');
256
        $this->assertEquals(1, $finalResult->totalCount, 'Expected total count to be 1');
257
    }
258
259
    /**
260
     * Test for the findContent() method.
261
     *
262
     * @covers \eZ\Publish\Core\Repository\SearchService::addPermissionsCriterion
263
     * @covers \eZ\Publish\Core\Repository\SearchService::findContent
264
     */
265
    public function testFindContentNoPermissionsFilter()
266
    {
267
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
268
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
269
        $repositoryMock = $this->getRepositoryMock();
270
        $service = new SearchService(
271
            $repositoryMock,
272
            $searchHandlerMock,
273
            $mapper = $this->getContentDomainMapperMock(),
274
            $permissionsCriterionResolverMock = $this->getPermissionCriterionResolverMock(),
0 ignored issues
show
Bug introduced by
It seems like $permissionsCriterionRes...CriterionResolverMock() can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
275
            new NullIndexer(),
276
            []
277
        );
278
279
        $repositoryMock->expects($this->never())->method('getPermissionResolver');
280
281
        $serviceQuery = new Query();
282
        $handlerQuery = new Query(['filter' => new Criterion\MatchAll(), 'limit' => 25]);
283
        $languageFilter = [];
284
        $spiContentInfo = new SPIContentInfo();
285
        $contentMock = $this->getMockForAbstractClass(Content::class);
286
287
        /* @var \PHPUnit\Framework\MockObject\MockObject $searchHandlerMock */
288
        $searchHandlerMock->expects($this->once())
289
            ->method('findContent')
290
            ->with($this->equalTo($handlerQuery), $this->equalTo($languageFilter))
291
            ->will(
292
                $this->returnValue(
293
                    new SearchResult(
294
                        [
295
                            'searchHits' => [new SearchHit(['valueObject' => $spiContentInfo])],
296
                            'totalCount' => 1,
297
                        ]
298
                    )
299
                )
300
            );
301
302
        $mapper->expects($this->once())
303
            ->method('buildContentDomainObjectsOnSearchResult')
304
            ->with($this->isInstanceOf(SearchResult::class), $this->equalTo([]))
305
            ->willReturnCallback(function (SearchResult $spiResult) use ($contentMock) {
306
                $spiResult->searchHits[0]->valueObject = $contentMock;
307
308
                return [];
309
            });
310
311
        $result = $service->findContent($serviceQuery, $languageFilter, false);
312
313
        $this->assertEquals(
314
            new SearchResult(
315
                [
316
                    'searchHits' => [new SearchHit(['valueObject' => $contentMock])],
317
                    'totalCount' => 1,
318
                ]
319
            ),
320
            $result
321
        );
322
    }
323
324
    /**
325
     * Test for the findContent() method.
326
     *
327
     * @covers \eZ\Publish\Core\Repository\SearchService::addPermissionsCriterion
328
     * @covers \eZ\Publish\Core\Repository\SearchService::findContent
329
     */
330
    public function testFindContentWithPermission()
331
    {
332
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
333
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
334
        $domainMapperMock = $this->getContentDomainMapperMock();
335
        $permissionsCriterionResolverMock = $this->getPermissionCriterionResolverMock();
336
        $service = new SearchService(
337
            $this->getRepositoryMock(),
338
            $searchHandlerMock,
339
            $domainMapperMock,
340
            $permissionsCriterionResolverMock,
0 ignored issues
show
Bug introduced by
It seems like $permissionsCriterionResolverMock defined by $this->getPermissionCriterionResolverMock() on line 335 can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
341
            new NullIndexer(),
342
            []
343
        );
344
345
        $criterionMock = $this
346
            ->getMockBuilder(Criterion::class)
347
            ->disableOriginalConstructor()
348
            ->getMock();
349
        $query = new Query(['filter' => $criterionMock, 'limit' => 10]);
350
        $languageFilter = [];
351
        $spiContentInfo = new SPIContentInfo();
352
        $contentMock = $this->getMockForAbstractClass(Content::class);
353
354
        $permissionsCriterionResolverMock->expects($this->once())
355
            ->method('getPermissionsCriterion')
356
            ->with('content', 'read')
357
            ->will($this->returnValue(true));
358
359
        /* @var \PHPUnit\Framework\MockObject\MockObject $searchHandlerMock */
360
        $searchHandlerMock->expects($this->once())
361
            ->method('findContent')
362
            ->with($this->equalTo($query), $this->equalTo($languageFilter))
363
            ->will(
364
                $this->returnValue(
365
                    new SearchResult(
366
                        [
367
                            'searchHits' => [new SearchHit(['valueObject' => $spiContentInfo])],
368
                            'totalCount' => 1,
369
                        ]
370
                    )
371
                )
372
            );
373
374
        $domainMapperMock
375
            ->expects($this->once())
376
            ->method('buildContentDomainObjectsOnSearchResult')
377
            ->with($this->isInstanceOf(SearchResult::class), $this->equalTo([]))
378
            ->willReturnCallback(function (SearchResult $spiResult) use ($contentMock) {
379
                $spiResult->searchHits[0]->valueObject = $contentMock;
380
381
                return [];
382
            });
383
384
        $result = $service->findContent($query, $languageFilter, true);
385
386
        $this->assertEquals(
387
            new SearchResult(
388
                [
389
                    'searchHits' => [new SearchHit(['valueObject' => $contentMock])],
390
                    'totalCount' => 1,
391
                ]
392
            ),
393
            $result
394
        );
395
    }
396
397
    /**
398
     * Test for the findContent() method.
399
     *
400
     * @covers \eZ\Publish\Core\Repository\SearchService::addPermissionsCriterion
401
     * @covers \eZ\Publish\Core\Repository\SearchService::findContent
402
     */
403
    public function testFindContentWithNoPermission()
404
    {
405
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
406
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
407
        $permissionsCriterionResolverMock = $this->getPermissionCriterionResolverMock();
408
        $service = new SearchService(
409
            $this->getRepositoryMock(),
410
            $searchHandlerMock,
411
            $mapper = $this->getContentDomainMapperMock(),
412
            $permissionsCriterionResolverMock,
0 ignored issues
show
Bug introduced by
It seems like $permissionsCriterionResolverMock defined by $this->getPermissionCriterionResolverMock() on line 407 can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
413
            new NullIndexer(),
414
            []
415
        );
416
417
        /* @var \PHPUnit\Framework\MockObject\MockObject $searchHandlerMock */
418
        $searchHandlerMock->expects($this->never())->method('findContent');
419
420
        $criterionMock = $this
421
            ->getMockBuilder(Criterion::class)
422
            ->disableOriginalConstructor()
423
            ->getMock();
424
        $query = new Query(['filter' => $criterionMock]);
425
426
        $permissionsCriterionResolverMock->expects($this->once())
427
            ->method('getPermissionsCriterion')
428
            ->with('content', 'read')
429
            ->will($this->returnValue(false));
430
431
        $mapper->expects($this->once())
432
            ->method('buildContentDomainObjectsOnSearchResult')
433
            ->with($this->isInstanceOf(SearchResult::class), $this->equalTo([]))
434
            ->willReturn([]);
435
436
        $result = $service->findContent($query, [], true);
437
438
        $this->assertEquals(
439
            new SearchResult(['time' => 0, 'totalCount' => 0]),
440
            $result
441
        );
442
    }
443
444
    /**
445
     * Test for the findContent() method.
446
     */
447
    public function testFindContentWithDefaultQueryValues()
448
    {
449
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
450
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
451
        $domainMapperMock = $this->getContentDomainMapperMock();
452
        $service = new SearchService(
453
            $this->getRepositoryMock(),
454
            $searchHandlerMock,
455
            $domainMapperMock,
456
            $this->getPermissionCriterionResolverMock(),
0 ignored issues
show
Bug introduced by
It seems like $this->getPermissionCriterionResolverMock() targeting eZ\Publish\Core\Reposito...CriterionResolverMock() can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
457
            new NullIndexer(),
458
            []
459
        );
460
461
        $languageFilter = [];
462
        $spiContentInfo = new SPIContentInfo();
463
        $contentMock = $this->getMockForAbstractClass(Content::class);
464
465
        /* @var \PHPUnit\Framework\MockObject\MockObject $searchHandlerMock */
466
        $searchHandlerMock
467
            ->expects($this->once())
468
            ->method('findContent')
469
            ->with(
470
                new Query(
471
                    [
472
                        'filter' => new Criterion\MatchAll(),
473
                        'limit' => 25,
474
                    ]
475
                ),
476
                []
477
            )
478
            ->will(
479
                $this->returnValue(
480
                    new SearchResult(
481
                        [
482
                            'searchHits' => [new SearchHit(['valueObject' => $spiContentInfo])],
483
                            'totalCount' => 1,
484
                        ]
485
                    )
486
                )
487
            );
488
489
        $domainMapperMock
490
            ->expects($this->once())
491
            ->method('buildContentDomainObjectsOnSearchResult')
492
            ->with($this->isInstanceOf(SearchResult::class), $this->equalTo([]))
493
            ->willReturnCallback(function (SearchResult $spiResult) use ($contentMock) {
494
                $spiResult->searchHits[0]->valueObject = $contentMock;
495
496
                return [];
497
            });
498
499
        $result = $service->findContent(new Query(), $languageFilter, false);
500
501
        $this->assertEquals(
502
            new SearchResult(
503
                [
504
                    'searchHits' => [new SearchHit(['valueObject' => $contentMock])],
505
                    'totalCount' => 1,
506
                ]
507
            ),
508
            $result
509
        );
510
    }
511
512
    /**
513
     * Test for the findSingle() method.
514
     *
515
     * @covers \eZ\Publish\Core\Repository\SearchService::addPermissionsCriterion
516
     * @covers \eZ\Publish\Core\Repository\SearchService::findSingle
517
     */
518
    public function testFindSingleThrowsNotFoundException()
519
    {
520
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
521
522
        $repositoryMock = $this->getRepositoryMock();
523
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
524
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
525
        $service = new SearchService(
526
            $repositoryMock,
527
            $searchHandlerMock,
528
            $this->getContentDomainMapperMock(),
529
            $permissionsCriterionResolverMock = $this->getPermissionCriterionResolverMock(),
0 ignored issues
show
Bug introduced by
It seems like $permissionsCriterionRes...CriterionResolverMock() can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
530
            new NullIndexer(),
531
            []
532
        );
533
534
        /** @var \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterionMock */
535
        $criterionMock = $this
536
            ->getMockBuilder(Criterion::class)
537
            ->disableOriginalConstructor()
538
            ->getMock();
539
540
        $permissionsCriterionResolverMock->expects($this->once())
541
            ->method('getPermissionsCriterion')
542
            ->with('content', 'read')
543
            ->willReturn(false);
544
545
        $service->findSingle($criterionMock, [], true);
546
    }
547
548
    /**
549
     * Test for the findSingle() method.
550
     *
551
     * @covers \eZ\Publish\Core\Repository\SearchService::addPermissionsCriterion
552
     * @covers \eZ\Publish\Core\Repository\SearchService::findSingle
553
     */
554
    public function testFindSingleThrowsHandlerException()
555
    {
556
        $this->expectException(\Exception::class);
557
        $this->expectExceptionMessage('Handler threw an exception');
558
559
        $repositoryMock = $this->getRepositoryMock();
560
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
561
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
562
        $permissionsCriterionResolverMock = $this->getPermissionCriterionResolverMock();
563
        $service = new SearchService(
564
            $repositoryMock,
565
            $searchHandlerMock,
566
            $this->getContentDomainMapperMock(),
567
            $permissionsCriterionResolverMock,
0 ignored issues
show
Bug introduced by
It seems like $permissionsCriterionResolverMock defined by $this->getPermissionCriterionResolverMock() on line 562 can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
568
            new NullIndexer(),
569
            []
570
        );
571
572
        /** @var \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterionMock */
573
        $criterionMock = $this
574
            ->getMockBuilder(Criterion::class)
575
            ->disableOriginalConstructor()
576
            ->getMock();
577
578
        $permissionsCriterionResolverMock->expects($this->once())
579
            ->method('getPermissionsCriterion')
580
            ->with('content', 'read')
581
            ->will($this->throwException(new Exception('Handler threw an exception')));
582
583
        $service->findSingle($criterionMock, [], true);
584
    }
585
586
    /**
587
     * Test for the findSingle() method.
588
     *
589
     * @covers \eZ\Publish\Core\Repository\SearchService::addPermissionsCriterion
590
     * @covers \eZ\Publish\Core\Repository\SearchService::findSingle
591
     */
592
    public function testFindSingle()
593
    {
594
        $repositoryMock = $this->getRepositoryMock();
595
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
596
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
597
        $domainMapperMock = $this->getContentDomainMapperMock();
598
        $permissionsCriterionResolverMock = $this->getPermissionCriterionResolverMock();
599
        $service = new SearchService(
600
            $repositoryMock,
601
            $searchHandlerMock,
602
            $domainMapperMock,
603
            $permissionsCriterionResolverMock,
0 ignored issues
show
Bug introduced by
It seems like $permissionsCriterionResolverMock defined by $this->getPermissionCriterionResolverMock() on line 598 can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
604
            new NullIndexer(),
605
            []
606
        );
607
608
        $repositoryMock
609
            ->expects($this->once())
610
            ->method('getContentService')
611
            ->will(
612
                $this->returnValue(
613
                    $contentServiceMock = $this
614
                        ->getMockBuilder(ContentService::class)
615
                        ->disableOriginalConstructor()
616
                        ->getMock()
617
                )
618
            );
619
620
        /** @var \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterionMock */
621
        $criterionMock = $this
622
            ->getMockBuilder(Criterion::class)
623
            ->disableOriginalConstructor()
624
            ->getMock();
625
626
        $permissionsCriterionResolverMock->expects($this->once())
627
            ->method('getPermissionsCriterion')
628
            ->with('content', 'read')
629
            ->will($this->returnValue(true));
630
631
        $languageFilter = [];
632
        $spiContentInfo = new SPIContentInfo();
633
        $contentMock = $this->getMockForAbstractClass(Content::class);
634
635
        /* @var \PHPUnit\Framework\MockObject\MockObject $searchHandlerMock */
636
        $searchHandlerMock->expects($this->once())
637
            ->method('findSingle')
638
            ->with($this->equalTo($criterionMock), $this->equalTo($languageFilter))
639
            ->will($this->returnValue($spiContentInfo));
640
641
        $domainMapperMock->expects($this->never())
642
            ->method($this->anything());
643
644
        $contentServiceMock
645
            ->expects($this->once())
646
            ->method('internalLoadContent')
647
            ->will($this->returnValue($contentMock));
648
649
        $result = $service->findSingle($criterionMock, $languageFilter, true);
650
651
        $this->assertEquals($contentMock, $result);
652
    }
653
654
    /**
655
     * Test for the findLocations() method.
656
     */
657
    public function testFindLocationsWithPermission()
658
    {
659
        $repositoryMock = $this->getRepositoryMock();
660
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
661
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
662
        $domainMapperMock = $this->getContentDomainMapperMock();
663
        $permissionsCriterionResolverMock = $this->getPermissionCriterionResolverMock();
664
        $service = new SearchService(
665
            $repositoryMock,
666
            $searchHandlerMock,
667
            $domainMapperMock,
668
            $permissionsCriterionResolverMock,
0 ignored issues
show
Bug introduced by
It seems like $permissionsCriterionResolverMock defined by $this->getPermissionCriterionResolverMock() on line 663 can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
669
            new NullIndexer(),
670
            []
671
        );
672
673
        $criterionMock = $this
674
            ->getMockBuilder(Criterion::class)
675
            ->disableOriginalConstructor()
676
            ->getMock();
677
        $query = new LocationQuery(['filter' => $criterionMock, 'limit' => 10]);
678
        $spiLocation = new SPILocation();
679
        $locationMock = $this->getMockForAbstractClass(Location::class);
680
681
        /* @var \PHPUnit\Framework\MockObject\MockObject $searchHandlerMock */
682
        $searchHandlerMock->expects($this->once())
683
            ->method('findLocations')
684
            ->with($this->equalTo($query))
685
            ->will(
686
                $this->returnValue(
687
                    $spiResult = new SearchResult(
688
                        [
689
                            'searchHits' => [new SearchHit(['valueObject' => $spiLocation])],
690
                            'totalCount' => 1,
691
                        ]
692
                    )
693
                )
694
            );
695
696
        $permissionsCriterionResolverMock->expects($this->once())
697
            ->method('getPermissionsCriterion')
698
            ->with('content', 'read')
699
            ->will($this->returnValue(true));
700
701
        $endResult = new SearchResult(
702
            [
703
                'searchHits' => [new SearchHit(['valueObject' => $locationMock])],
704
                'totalCount' => 1,
705
            ]
706
        );
707
708
        $domainMapperMock->expects($this->once())
709
            ->method('buildLocationDomainObjectsOnSearchResult')
710
            ->with($this->equalTo($spiResult))
711
            ->willReturnCallback(function (SearchResult $spiResult) use ($endResult) {
712
                $spiResult->searchHits[0] = $endResult->searchHits[0];
713
714
                return [];
715
            });
716
717
        $result = $service->findLocations($query, [], true);
718
719
        $this->assertEquals(
720
            $endResult,
721
            $result
722
        );
723
    }
724
725
    /**
726
     * Test for the findLocations() method.
727
     */
728
    public function testFindLocationsWithNoPermissionsFilter()
729
    {
730
        $repositoryMock = $this->getRepositoryMock();
731
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
732
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
733
        $domainMapperMock = $this->getContentDomainMapperMock();
734
        $permissionsCriterionResolverMock = $this->getPermissionCriterionResolverMock();
735
        $service = new SearchService(
736
            $repositoryMock,
737
            $searchHandlerMock,
738
            $domainMapperMock,
739
            $permissionsCriterionResolverMock,
0 ignored issues
show
Bug introduced by
It seems like $permissionsCriterionResolverMock defined by $this->getPermissionCriterionResolverMock() on line 734 can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
740
            new NullIndexer(),
741
            []
742
        );
743
744
        $repositoryMock->expects($this->never())->method('getPermissionResolver');
745
746
        $serviceQuery = new LocationQuery();
747
        $handlerQuery = new LocationQuery(['filter' => new Criterion\MatchAll(), 'limit' => 25]);
748
        $spiLocation = new SPILocation();
749
        $locationMock = $this->getMockForAbstractClass(Location::class);
750
751
        /* @var \PHPUnit\Framework\MockObject\MockObject $searchHandlerMock */
752
        $searchHandlerMock->expects($this->once())
753
            ->method('findLocations')
754
            ->with($this->equalTo($handlerQuery))
755
            ->will(
756
                $this->returnValue(
757
                    $spiResult = new SearchResult(
758
                        [
759
                            'searchHits' => [new SearchHit(['valueObject' => $spiLocation])],
760
                            'totalCount' => 1,
761
                        ]
762
                    )
763
                )
764
            );
765
766
        $permissionsCriterionResolverMock->expects($this->never())->method($this->anything());
767
768
        $endResult = new SearchResult(
769
            [
770
                'searchHits' => [new SearchHit(['valueObject' => $locationMock])],
771
                'totalCount' => 1,
772
            ]
773
        );
774
775
        $domainMapperMock->expects($this->once())
776
            ->method('buildLocationDomainObjectsOnSearchResult')
777
            ->with($this->equalTo($spiResult))
778
            ->willReturnCallback(function (SearchResult $spiResult) use ($endResult) {
779
                $spiResult->searchHits[0] = $endResult->searchHits[0];
780
781
                return [];
782
            });
783
784
        $result = $service->findLocations($serviceQuery, [], false);
785
786
        $this->assertEquals(
787
            $endResult,
788
            $result
789
        );
790
    }
791
792
    /**
793
     * Test for the findLocations() method when search is out of sync with persistence.
794
     *
795
     * @covers \eZ\Publish\Core\Repository\SearchService::findLocations
796
     */
797
    public function testFindLocationsBackgroundIndexerWhenDomainMapperThrowsException()
798
    {
799
        $indexer = $this->createMock(BackgroundIndexer::class);
800
        $indexer->expects($this->once())
801
            ->method('registerLocation')
802
            ->with($this->isInstanceOf(SPILocation::class));
803
804
        $service = $this->getMockBuilder(SearchService::class)
805
            ->setConstructorArgs([
806
                $this->getRepositoryMock(),
807
                $searchHandler = $this->getSPIMockHandler('Search\\Handler'),
808
                $mapper = $this->getContentDomainMapperMock(),
809
                $this->getPermissionCriterionResolverMock(),
810
                $indexer,
811
            ])->setMethods(['addPermissionsCriterion'])
812
            ->getMock();
813
814
        $location = new SPILocation(['id' => 44]);
815
        $service->expects($this->once())
816
            ->method('addPermissionsCriterion')
817
            ->with($this->isInstanceOf(Criterion::class))
818
            ->willReturn(true);
819
820
        $result = new SearchResult(['searchHits' => [new SearchHit(['valueObject' => $location])], 'totalCount' => 2]);
821
        $searchHandler->expects($this->once())
822
            ->method('findLocations')
823
            ->with($this->isInstanceOf(LocationQuery::class), $this->isType('array'))
824
            ->willReturn($result);
825
826
        $mapper->expects($this->once())
827
            ->method('buildLocationDomainObjectsOnSearchResult')
828
            ->with($this->equalTo($result))
829
            ->willReturnCallback(function (SearchResult $spiResult) use ($location) {
830
                unset($spiResult->searchHits[0]);
831
                --$spiResult->totalCount;
832
833
                return [$location];
834
            });
835
836
        $finalResult = $service->findLocations(new LocationQuery());
837
838
        $this->assertEmpty($finalResult->searchHits, 'Expected search hits to be empty');
839
        $this->assertEquals(1, $finalResult->totalCount, 'Expected total count to be 1');
840
    }
841
842
    /**
843
     * Test for the findLocations() method.
844
     */
845 View Code Duplication
    public function testFindLocationsThrowsHandlerException()
846
    {
847
        $this->expectException(\Exception::class);
848
        $this->expectExceptionMessage('Handler threw an exception');
849
850
        $repositoryMock = $this->getRepositoryMock();
851
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
852
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
853
        $permissionsCriterionResolverMock = $this->getPermissionCriterionResolverMock();
854
855
        $service = new SearchService(
856
            $repositoryMock,
857
            $searchHandlerMock,
858
            $this->getContentDomainMapperMock(),
859
            $permissionsCriterionResolverMock,
0 ignored issues
show
Bug introduced by
It seems like $permissionsCriterionResolverMock defined by $this->getPermissionCriterionResolverMock() on line 853 can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
860
            new NullIndexer(),
861
            []
862
        );
863
864
        /** @var \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterionMock */
865
        $criterionMock = $this
866
            ->getMockBuilder(Criterion::class)
867
            ->disableOriginalConstructor()
868
            ->getMock();
869
        $query = new LocationQuery(['filter' => $criterionMock]);
870
871
        $permissionsCriterionResolverMock->expects($this->once())
872
            ->method('getPermissionsCriterion')
873
            ->with('content', 'read')
874
            ->will($this->throwException(new Exception('Handler threw an exception')));
875
876
        $service->findLocations($query, [], true);
877
    }
878
879
    /**
880
     * Test for the findLocations() method.
881
     */
882
    public function testFindLocationsWithDefaultQueryValues()
883
    {
884
        $repositoryMock = $this->getRepositoryMock();
885
        /** @var \eZ\Publish\SPI\Search\Handler $searchHandlerMock */
886
        $searchHandlerMock = $this->getSPIMockHandler('Search\\Handler');
887
        $domainMapperMock = $this->getContentDomainMapperMock();
888
        $service = new SearchService(
889
            $repositoryMock,
890
            $searchHandlerMock,
891
            $domainMapperMock,
892
            $this->getPermissionCriterionResolverMock(),
0 ignored issues
show
Bug introduced by
It seems like $this->getPermissionCriterionResolverMock() targeting eZ\Publish\Core\Reposito...CriterionResolverMock() can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\Core\Reposito...hService::__construct() does only seem to accept object<eZ\Publish\API\Re...ssionCriterionResolver>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
893
            new NullIndexer(),
894
            []
895
        );
896
897
        $spiLocation = new SPILocation();
898
        $locationMock = $this->getMockForAbstractClass(Location::class);
899
900
        /* @var \PHPUnit\Framework\MockObject\MockObject $searchHandlerMock */
901
        $searchHandlerMock
902
            ->expects($this->once())
903
            ->method('findLocations')
904
            ->with(
905
                new LocationQuery(
906
                    [
907
                        'filter' => new Criterion\MatchAll(),
908
                        'limit' => 25,
909
                    ]
910
                )
911
            )
912
            ->will(
913
                $this->returnValue(
914
                    $spiResult = new SearchResult(
915
                        [
916
                            'searchHits' => [new SearchHit(['valueObject' => $spiLocation])],
917
                            'totalCount' => 1,
918
                        ]
919
                    )
920
                )
921
            );
922
923
        $endResult = new SearchResult(
924
            [
925
                'searchHits' => [new SearchHit(['valueObject' => $locationMock])],
926
                'totalCount' => 1,
927
            ]
928
        );
929
930
        $domainMapperMock->expects($this->once())
931
            ->method('buildLocationDomainObjectsOnSearchResult')
932
            ->with($this->equalTo($spiResult))
933
            ->willReturnCallback(function (SearchResult $spiResult) use ($endResult) {
934
                $spiResult->searchHits[0] = $endResult->searchHits[0];
935
936
                return [];
937
            });
938
939
        $result = $service->findLocations(new LocationQuery(), [], false);
940
941
        $this->assertEquals(
942
            $endResult,
943
            $result
944
        );
945
    }
946
947
    /**
948
     * @return \PHPUnit\Framework\MockObject\MockObject|\eZ\Publish\API\Repository\PermissionCriterionResolver
949
     */
950
    protected function getPermissionCriterionResolverMock()
951
    {
952
        if (!isset($this->permissionsCriterionResolverMock)) {
953
            $this->permissionsCriterionResolverMock = $this
954
                ->getMockBuilder(PermissionCriterionResolver::class)
955
                ->disableOriginalConstructor()
956
                ->getMock();
957
        }
958
959
        return $this->permissionsCriterionResolverMock;
960
    }
961
}
962