Completed
Push — signal_search_issues ( 907e1e...5556b2 )
by André
26:47
created

HandlerContentSortTest::getContentSearchHandler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 47
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 35
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 47
rs 9.0303
1
<?php
2
3
/**
4
 * This file is part of the eZ Publish Kernel package.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 *
9
 * @version //autogentag//
10
 */
11
namespace eZ\Publish\Core\Search\Legacy\Tests\Content;
12
13
use eZ\Publish\Core\Persistence\Legacy\Tests\Content\LanguageAwareTestCase;
14
use eZ\Publish\Core\Search\Legacy\Content;
15
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
16
use eZ\Publish\API\Repository\Values\Content\Query\SortClause;
17
use eZ\Publish\SPI\Persistence\Content\ContentInfo;
18
use eZ\Publish\API\Repository\Values\Content\Query;
19
use eZ\Publish\Core\Persistence\Legacy\Content\FieldValue\Converter;
20
use eZ\Publish\Core\Persistence\Legacy\Content\FieldValue\ConverterRegistry;
21
use eZ\Publish\Core\Persistence\Legacy\Content\Type\Gateway\DoctrineDatabase as ContentTypeGateway;
22
use eZ\Publish\Core\Persistence\Legacy\Content\Type\Handler as ContentTypeHandler;
23
use eZ\Publish\Core\Persistence\Legacy\Content\Type\Mapper as ContentTypeMapper;
24
25
/**
26
 * Content Search test case for ContentSearchHandler.
27
 */
28
class HandlerContentSortTest extends LanguageAwareTestCase
29
{
30
    protected static $setUp = false;
31
32
    /**
33
     * Field registry mock.
34
     *
35
     * @var \eZ\Publish\Core\Persistence\Legacy\Content\FieldValue\ConverterRegistry
36
     */
37
    protected $fieldRegistry;
38
39
    /**
40
     * Only set up once for these read only tests on a large fixture.
41
     *
42
     * Skipping the reset-up, since setting up for these tests takes quite some
43
     * time, which is not required to spent, since we are only reading from the
44
     * database anyways.
45
     */
46 View Code Duplication
    public function setUp()
47
    {
48
        if (!self::$setUp) {
49
            parent::setUp();
50
            $this->insertDatabaseFixture(__DIR__ . '/../_fixtures/full_dump.php');
51
            self::$setUp = $this->handler;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->handler of type object<eZ\Publish\Core\P...tabase\DatabaseHandler> is incompatible with the declared type boolean of property $setUp.

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...
52
        } else {
53
            $this->handler = self::$setUp;
0 ignored issues
show
Documentation Bug introduced by
It seems like self::$setUp of type boolean is incompatible with the declared type object<eZ\Publish\Core\P...tabase\DatabaseHandler> of property $handler.

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...
54
        }
55
    }
56
57
    /**
58
     * Returns the content search handler to test.
59
     *
60
     * This method returns a fully functional search handler to perform tests
61
     * on.
62
     *
63
     * @param array $fullTextSearchConfiguration
64
     *
65
     * @return \eZ\Publish\Core\Search\Legacy\Content\Handler
66
     */
67
    protected function getContentSearchHandler(array $fullTextSearchConfiguration = array())
0 ignored issues
show
Unused Code introduced by
The parameter $fullTextSearchConfiguration is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
68
    {
69
        $db = $this->getDatabaseHandler();
70
71
        return new Content\Handler(
72
            new Content\Gateway\DoctrineDatabase(
73
                $this->getDatabaseHandler(),
74
                new Content\Common\Gateway\CriteriaConverter(
75
                    array(
76
                        new Content\Common\Gateway\CriterionHandler\MatchAll($db),
77
                        new Content\Common\Gateway\CriterionHandler\LogicalAnd($db),
78
                        new Content\Common\Gateway\CriterionHandler\SectionId($db),
79
                        new Content\Common\Gateway\CriterionHandler\ContentTypeIdentifier(
80
                            $db,
81
                            $this->getContentTypeHandler()
82
                        ),
83
                    )
84
                ),
85
                new Content\Common\Gateway\SortClauseConverter(
86
                    array(
87
                        new Content\Common\Gateway\SortClauseHandler\DateModified($db),
88
                        new Content\Common\Gateway\SortClauseHandler\DatePublished($db),
89
                        new Content\Common\Gateway\SortClauseHandler\SectionIdentifier($db),
90
                        new Content\Common\Gateway\SortClauseHandler\SectionName($db),
91
                        new Content\Common\Gateway\SortClauseHandler\ContentName($db),
92
                        new Content\Common\Gateway\SortClauseHandler\Field(
93
                            $db,
94
                            $this->getLanguageHandler(),
95
                            $this->getContentTypeHandler()
96
                        ),
97
                    )
98
                ),
99
                $this->getLanguageHandler()
100
            ),
101
            $this->getMock('eZ\\Publish\\Core\\Search\\Legacy\\Content\\Location\\Gateway'),
102
            new Content\WordIndexer\Gateway\DoctrineDatabase(
103
                $this->getDatabaseHandler(),
104
                $this->getContentTypeHandler(),
105
                $this->getDefinitionBasedTransformationProcessor(),
106
                new Content\WordIndexer\Repository\SearchIndex($this->getDatabaseHandler())
107
            ),
108
            $this->getContentMapperMock(),
109
            $this->getMock('eZ\\Publish\\Core\\Persistence\\Legacy\\Content\\Location\\Mapper'),
110
            $this->getLanguageHandler(),
111
            $this->getFullTextMapper($this->getContentTypeHandler())
112
        );
113
    }
114
115
    protected $contentTypeHandler;
116
117
    protected function getContentTypeHandler()
118
    {
119
        if (!isset($this->contentTypeHandler)) {
120
            $this->contentTypeHandler = new ContentTypeHandler(
121
                new ContentTypeGateway(
122
                    $this->getDatabaseHandler(),
123
                    $this->getLanguageMaskGenerator()
124
                ),
125
                new ContentTypeMapper(
126
                    new ConverterRegistry(
127
                        array(
128
                            'ezdatetime' => new Converter\DateAndTimeConverter(),
129
                            'ezinteger' => new Converter\IntegerConverter(),
130
                            'ezstring' => new Converter\TextLineConverter(),
131
                            'ezprice' => new Converter\IntegerConverter(),
132
                            'ezurl' => new Converter\UrlConverter(),
133
                            'ezrichtext' => new Converter\RichTextConverter(),
134
                            'ezboolean' => new Converter\CheckboxConverter(),
135
                            'ezkeyword' => new Converter\KeywordConverter(),
136
                            'ezauthor' => new Converter\AuthorConverter(),
137
                            'ezimage' => new Converter\NullConverter(),
138
                            'ezsrrating' => new Converter\NullConverter(),
139
                            'ezmultioption' => new Converter\NullConverter(),
140
                        )
141
                    )
142
                ),
143
                $this->getMock('eZ\\Publish\\Core\\Persistence\\Legacy\\Content\\Type\\Update\\Handler')
144
            );
145
        }
146
147
        return $this->contentTypeHandler;
148
    }
149
150
    /**
151
     * Returns a content mapper mock.
152
     *
153
     * @return \eZ\Publish\Core\Persistence\Legacy\Content\Mapper
154
     */
155 View Code Duplication
    protected function getContentMapperMock()
156
    {
157
        $mapperMock = $this->getMock(
158
            'eZ\\Publish\\Core\\Persistence\\Legacy\\Content\\Mapper',
159
            array('extractContentInfoFromRows'),
160
            array(
161
                $this->getFieldRegistry(),
162
                $this->getLanguageHandler(),
163
            )
164
        );
165
        $mapperMock->expects($this->any())
166
            ->method('extractContentInfoFromRows')
167
            ->with($this->isType('array'))
168
            ->will(
169
                $this->returnCallback(
170
                    function ($rows) {
171
                        $contentInfoObjs = array();
172
                        foreach ($rows as $row) {
173
                            $contentId = (int)$row['id'];
174
                            if (!isset($contentInfoObjs[$contentId])) {
175
                                $contentInfoObjs[$contentId] = new ContentInfo();
176
                                $contentInfoObjs[$contentId]->id = $contentId;
177
                            }
178
                        }
179
180
                        return array_values($contentInfoObjs);
181
                    }
182
                )
183
            );
184
185
        return $mapperMock;
186
    }
187
188
    /**
189
     * Returns a field registry mock object.
190
     *
191
     * @return \eZ\Publish\Core\Persistence\Legacy\Content\FieldValue\ConverterRegistry
192
     */
193
    protected function getFieldRegistry()
194
    {
195
        if (!isset($this->fieldRegistry)) {
196
            $this->fieldRegistry = $this->getMock(
197
                '\\eZ\\Publish\\Core\\Persistence\\Legacy\\Content\\FieldValue\\ConverterRegistry',
198
                array(),
199
                array(array())
200
            );
201
        }
202
203
        return $this->fieldRegistry;
204
    }
205
206
    /**
207
     * Returns a content field handler mock.
208
     *
209
     * @return \eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler
210
     */
211
    protected function getContentFieldHandlerMock()
212
    {
213
        return $this->getMock(
214
            'eZ\\Publish\\Core\\Persistence\\Legacy\\Content\\FieldHandler',
215
            array('loadExternalFieldData'),
216
            array(),
217
            '',
218
            false
219
        );
220
    }
221
222
    public function testNoSorting()
223
    {
224
        $locator = $this->getContentSearchHandler();
225
226
        $result = $locator->findContent(
227
            new Query(
228
                array(
229
                    'filter' => new Criterion\SectionId(array(2)),
230
                    'offset' => 0,
231
                    'limit' => 10,
232
                    'sortClauses' => array(),
233
                )
234
            )
235
        );
236
237
        $ids = array_map(
238
            function ($hit) {
239
                return $hit->valueObject->id;
240
            },
241
            $result->searchHits
242
        );
243
        sort($ids);
244
        $this->assertEquals(
245
            array(4, 10, 11, 12, 13, 14, 42, 226),
246
            $ids
247
        );
248
    }
249
250 View Code Duplication
    public function testSortDateModified()
251
    {
252
        $locator = $this->getContentSearchHandler();
253
254
        $result = $locator->findContent(
255
            new Query(
256
                array(
257
                    'filter' => new Criterion\SectionId(array(2)),
258
                    'offset' => 0,
259
                    'limit' => 10,
260
                    'sortClauses' => array(
261
                        new SortClause\DateModified(),
262
                    ),
263
                )
264
            )
265
        );
266
267
        $this->assertEquals(
268
            array(4, 12, 13, 42, 10, 14, 11, 226),
269
            array_map(
270
                function ($hit) {
271
                    return $hit->valueObject->id;
272
                },
273
                $result->searchHits
274
            )
275
        );
276
    }
277
278 View Code Duplication
    public function testSortDatePublished()
279
    {
280
        $locator = $this->getContentSearchHandler();
281
282
        $result = $locator->findContent(
283
            new Query(
284
                array(
285
                    'filter' => new Criterion\SectionId(array(2)),
286
                    'offset' => 0,
287
                    'limit' => 10,
288
                    'sortClauses' => array(
289
                        new SortClause\DatePublished(),
290
                    ),
291
                )
292
            )
293
        );
294
295
        $this->assertEquals(
296
            array(4, 10, 11, 12, 13, 14, 226, 42),
297
            array_map(
298
                function ($hit) {
299
                    return $hit->valueObject->id;
300
                },
301
                $result->searchHits
302
            )
303
        );
304
    }
305
306
    public function testSortSectionIdentifier()
307
    {
308
        $locator = $this->getContentSearchHandler();
309
310
        $result = $locator->findContent(
311
            new Query(
312
                array(
313
                    'filter' => new Criterion\SectionId(array(4, 2, 6, 3)),
314
                    'offset' => 0,
315
                    'limit' => null,
316
                    'sortClauses' => array(
317
                        new SortClause\SectionIdentifier(),
318
                    ),
319
                )
320
            )
321
        );
322
323
        // First, results of section 2 should appear, then the ones of 3, 4 and 6
324
        // From inside a specific section, no particular order should be defined
325
        // the logic is then to have a set of sorted id's to compare with
326
        // the comparison being done slice by slice.
327
        $idMapSet = array(
328
            2 => array(4, 10, 11, 12, 13, 14, 42, 226),
329
            3 => array(41, 49, 50, 51, 57, 58, 59, 60, 61, 62, 63, 64, 66, 200, 201),
330
            4 => array(45, 52),
331
            6 => array(154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164),
332
        );
333
        $contentIds = array_map(
334
            function ($hit) {
335
                return $hit->valueObject->id;
336
            },
337
            $result->searchHits
338
        );
339
        $index = 0;
340
341
        foreach ($idMapSet as $idSet) {
342
            $contentIdsSubset = array_slice($contentIds, $index, $count = count($idSet));
343
            $index += $count;
344
            sort($contentIdsSubset);
345
            $this->assertEquals(
346
                $idSet,
347
                $contentIdsSubset
348
            );
349
        }
350
    }
351
352 View Code Duplication
    public function testSortSectionName()
353
    {
354
        $locator = $this->getContentSearchHandler();
355
356
        $result = $locator->findContent(
357
            new Query(
358
                array(
359
                    'filter' => new Criterion\SectionId(array(4, 2, 6, 3)),
360
                    'offset' => 0,
361
                    'limit' => null,
362
                    'sortClauses' => array(
363
                        new SortClause\SectionName(),
364
                    ),
365
                )
366
            )
367
        );
368
369
        // First, results of section "Media" should appear, then the ones of "Protected",
370
        // "Setup" and "Users"
371
        // From inside a specific section, no particular order should be defined
372
        // the logic is then to have a set of sorted id's to compare with
373
        // the comparison being done slice by slice.
374
        $idMapSet = array(
375
            'media' => array(41, 49, 50, 51, 57, 58, 59, 60, 61, 62, 63, 64, 66, 200, 201),
376
            'protected' => array(154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164),
377
            'setup' => array(45, 52),
378
            'users' => array(4, 10, 11, 12, 13, 14, 42, 226),
379
        );
380
        $contentIds = array_map(
381
            function ($hit) {
382
                return $hit->valueObject->id;
383
            },
384
            $result->searchHits
385
        );
386
387
        $expectedCount = 0;
388
        foreach ($idMapSet as $set) {
389
            $expectedCount += count($set);
390
        }
391
392
        $this->assertEquals($expectedCount, $result->totalCount);
393
394
        $index = 0;
395
        foreach ($idMapSet as $idSet) {
396
            $contentIdsSubset = array_slice($contentIds, $index, $count = count($idSet));
397
            $index += $count;
398
            sort($contentIdsSubset);
399
            $this->assertEquals(
400
                $idSet,
401
                $contentIdsSubset
402
            );
403
        }
404
    }
405
406
    public function testSortContentName()
407
    {
408
        $locator = $this->getContentSearchHandler();
409
410
        $result = $locator->findContent(
411
            new Query(
412
                array(
413
                    'filter' => new Criterion\SectionId(array(2, 3)),
414
                    'offset' => 0,
415
                    'limit' => null,
416
                    'sortClauses' => array(
417
                        new SortClause\ContentName(),
418
                    ),
419
                )
420
            )
421
        );
422
423
        $this->assertEquals(
424
            array(226, 14, 12, 10, 42, 57, 13, 50, 49, 41, 11, 51, 62, 4, 58, 59, 61, 60, 64, 63, 200, 66, 201),
425
            array_map(
426
                function ($hit) {
427
                    return $hit->valueObject->id;
428
                },
429
                $result->searchHits
430
            )
431
        );
432
    }
433
434 View Code Duplication
    public function testSortFieldText()
435
    {
436
        $locator = $this->getContentSearchHandler();
437
438
        $result = $locator->findContent(
439
            new Query(
440
                array(
441
                    'filter' => new Criterion\LogicalAnd(
442
                        array(
443
                            new Criterion\SectionId(array(1)),
444
                            new Criterion\ContentTypeIdentifier(array('article')),
445
                        )
446
                    ),
447
                    'offset' => 0,
448
                    'limit' => null,
449
                    'sortClauses' => array(
450
                        new SortClause\Field('article', 'title', Query::SORT_ASC, 'eng-US'),
451
                    ),
452
                )
453
            )
454
        );
455
456
        // There are several identical titles, need to take care about this
457
        $idMapSet = array(
458
            'aenean malesuada ligula' => array(83),
459
            'aliquam pulvinar suscipit tellus' => array(102),
460
            'asynchronous publishing' => array(148, 215),
461
            'canonical links' => array(147, 216),
462
            'class aptent taciti' => array(88),
463
            'class aptent taciti sociosqu' => array(82),
464
            'duis auctor vehicula erat' => array(89),
465
            'etiam posuere sodales arcu' => array(78),
466
            'etiam sodales mauris' => array(87),
467
            'ez publish enterprise' => array(151),
468
            'fastcgi' => array(144, 218),
469
            'fusce sagittis sagittis' => array(77),
470
            'fusce sagittis sagittis urna' => array(81),
471
            'get involved' => array(107),
472
            'how to develop with ez publish' => array(127, 211),
473
            'how to manage ez publish' => array(118, 202),
474
            'how to use ez publish' => array(108, 193),
475
            'improved block editing' => array(136),
476
            'improved front-end editing' => array(139),
477
            'improved user registration workflow' => array(132),
478
            'in hac habitasse platea' => array(79),
479
            'lots of websites, one ez publish installation' => array(130),
480
            'rest api interface' => array(150, 214),
481
            'separate content & design in ez publish' => array(191),
482
            'support for red hat enterprise' => array(145, 217),
483
            'tutorials for' => array(106),
484
        );
485
        $contentIds = array_map(
486
            function ($hit) {
487
                return $hit->valueObject->id;
488
            },
489
            $result->searchHits
490
        );
491
        $index = 0;
492
493
        foreach ($idMapSet as $idSet) {
494
            $contentIdsSubset = array_slice($contentIds, $index, $count = count($idSet));
495
            $index += $count;
496
            sort($contentIdsSubset);
497
            $this->assertEquals(
498
                $idSet,
499
                $contentIdsSubset
500
            );
501
        }
502
    }
503
504 View Code Duplication
    public function testSortFieldNumeric()
505
    {
506
        $locator = $this->getContentSearchHandler();
507
508
        $result = $locator->findContent(
509
            new Query(
510
                array(
511
                    'filter' => new Criterion\LogicalAnd(
512
                        array(
513
                            new Criterion\SectionId(array(1)),
514
                            new Criterion\ContentTypeIdentifier('product'),
515
                        )
516
                    ),
517
                    'offset' => 0,
518
                    'limit' => null,
519
                    'sortClauses' => array(
520
                        new SortClause\Field('product', 'price', Query::SORT_ASC, 'eng-US'),
521
                    ),
522
                )
523
            )
524
        );
525
526
        $this->assertEquals(
527
            array(73, 71, 72, 69),
528
            array_map(
529
                function ($hit) {
530
                    return $hit->valueObject->id;
531
                },
532
                $result->searchHits
533
            )
534
        );
535
    }
536
}
537