Completed
Push — ezp26175-exception_on_non_defa... ( 77d2f3...ca5fc8 )
by
unknown
39:33
created

HandlerContentSortTest::getContentSearchHandler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 48
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

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