Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.24% covered (success)
95.24%
40 / 42
83.33% covered (warning)
83.33%
5 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
ListsPagesHandler
95.24% covered (success)
95.24%
40 / 42
83.33% covered (warning)
83.33%
5 / 6
8
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 execute
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 doGetLists
66.67% covered (warning)
66.67%
4 / 6
0.00% covered (danger)
0.00%
0 / 1
2.15
 makeNext
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 decodeNext
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getParamSettings
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace MediaWiki\Extension\ReadingLists\Rest;
4
5use MediaWiki\Config\Config;
6use MediaWiki\Extension\ReadingLists\Doc\ReadingListRow;
7use MediaWiki\Extension\ReadingLists\ReadingListRepositoryException;
8use MediaWiki\Rest\Validator\Validator;
9use MediaWiki\User\CentralId\CentralIdLookup;
10use Wikimedia\ParamValidator\ParamValidator;
11use Wikimedia\ParamValidator\TypeDef\NumericDef;
12use Wikimedia\Rdbms\IResultWrapper;
13use Wikimedia\Rdbms\LBFactory;
14
15/**
16 * Handle GET requests to /readinglists/v0/lists/pages.
17 * This endpoint is for finding lists that contain a given page.
18 */
19class ListsPagesHandler extends ListsHandler {
20    // Temporarily limit paging sizes per T164990#3264314 / T168984#3659998
21    private const MAX_LIMIT = 10;
22
23    /**
24     * @param LBFactory $dbProvider
25     * @param Config $config
26     * @param CentralIdLookup $centralIdLookup
27     */
28    public function __construct(
29        LBFactory $dbProvider,
30        Config $config,
31        CentralIdLookup $centralIdLookup
32    ) {
33        parent::__construct( $dbProvider, $config, $centralIdLookup );
34    }
35
36    /**
37     * @return array
38     */
39    public function execute() {
40        // We don't expose sorting parameters for this endpoint, so include happy defaults
41        $params = $this->getValidatedParams();
42        $params['sort'] = 'name';
43        $params['dir'] = 'ascending';
44
45        return $this->getLists( $params );
46    }
47
48    /**
49     * Worker function for getting Reading Lists.
50     *
51     * @param array $params all parameters (path and query)
52     * @return IResultWrapper<ReadingListRow>
53     */
54    protected function doGetLists( array $params ) {
55        $repository = $this->getRepository();
56
57        try {
58            return $repository->getListsByPage(
59                $params['project'], $params['title'], $params['limit'] + 1, $params['next']
60            );
61        } catch ( ReadingListRepositoryException $e ) {
62            $this->die( $e->getMessageObject() );
63        }
64    }
65
66    /**
67     * Extract continuation data from item position and serialize it into a string.
68     * Overrides the trait version to customize continuation behavior for this endpoint.
69     *
70     * @param array $item Result item to continue from.
71     * @param string $sort One of the SORT_BY_* constants.
72     * @param string $name The item name
73     * @return string
74     */
75    protected function makeNext( array $item, string $sort, string $name ): string {
76        return $item['id'];
77    }
78
79    /**
80     * Recover continuation data after it has been roundtripped to the client.
81     * Overrides the trait version to customize continuation behavior for this endpoint.
82     *
83     * @param string|null $next Continuation parameter returned by the client.
84     * @param string $sort One of the SORT_BY_* constants.
85     * @return null|int|string[]
86     *  Continuation token format is:
87     *   - null if there was no continuation parameter OR
88     *   - id for lists/pages/{project}/{title} OR
89     *   - [ name, id ] when sorting by name OR
90     *   - [ date_updated, id ] when sorting by updated time
91     */
92    protected function decodeNext( $next, $sort ) {
93        if ( !$next ) {
94            return null;
95        }
96
97        $this->dieIf( $next !== (string)(int)$next, 'apierror-badcontinue' );
98        return (int)$next;
99    }
100
101    /**
102     * @return array[]
103     */
104    public function getParamSettings() {
105        return [
106            'project' => [
107                self::PARAM_SOURCE => 'path',
108                ParamValidator::PARAM_TYPE => 'string',
109                ParamValidator::PARAM_REQUIRED => true,
110            ],
111
112            // TODO: investigate "title" type vs "string" type. Consider PARAM_RETURN_OBJECT.
113            //  However, T303619 might make phpunit tests problematic.
114            'title' => [
115                self::PARAM_SOURCE => 'path',
116                ParamValidator::PARAM_TYPE => 'string',
117                ParamValidator::PARAM_REQUIRED => true,
118            ],
119            'next' => [
120                self::PARAM_SOURCE => 'query',
121                ParamValidator::PARAM_TYPE => 'string',
122                ParamValidator::PARAM_REQUIRED => false,
123                ParamValidator::PARAM_DEFAULT => '',
124            ],
125            'limit' => [
126                Validator::PARAM_SOURCE => 'query',
127                ParamValidator::PARAM_TYPE => 'integer',
128                ParamValidator::PARAM_REQUIRED => false,
129                ParamValidator::PARAM_DEFAULT => 10,
130                NumericDef::PARAM_MIN => 1,
131                NumericDef::PARAM_MAX => self::MAX_LIMIT,
132            ],
133        ];
134    }
135}