Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 92
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiQueryPageAssessments
0.00% covered (danger)
0.00%
0 / 92
0.00% covered (danger)
0.00%
0 / 7
342
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 33
0.00% covered (danger)
0.00%
0 / 1
42
 buildDbQuery
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
30
 handleQueryContinuation
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 getAllowedParams
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
6
 getExamplesMessages
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 getHelpUrls
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Extension\PageAssessments\Api;
4
5use ApiBase;
6use ApiQuery;
7use ApiQueryBase;
8use Wikimedia\ParamValidator\ParamValidator;
9use Wikimedia\ParamValidator\TypeDef\IntegerDef;
10
11/*
12 * API query module that returns associated projects and assessment data for a given set
13 * of pages. (T119997)
14 */
15class ApiQueryPageAssessments extends ApiQueryBase {
16
17    /** @inheritDoc */
18    public function __construct( ApiQuery $query, $moduleName ) {
19        parent::__construct( $query, $moduleName, 'pa' );
20    }
21
22    /**
23     * Evaluate the parameters, perform the requested query, and set up the result
24     */
25    public function execute() {
26        $params = $this->extractRequestParams();
27        $pages = $this->getPageSet()->getGoodTitles();
28        // are there pages to get project/assessment info for?
29        if ( !count( $pages ) ) {
30            return;  // If not, return so other prop modules can run
31        }
32
33        $this->buildDbQuery( $pages, $params );
34        $db_res = $this->select( __METHOD__ );
35
36        // API result
37        $result = $this->getResult();
38
39        $count = 0;
40        foreach ( $db_res as $row ) {
41            // One more than limit, so there are additional projects in the list
42            if ( ++$count > $params['limit'] ) {
43                $this->setContinueEnumParameter( 'continue', "$row->page_id|$row->project_id" );
44                break;
45            }
46
47            $projectValues = [
48                'class' => $row->class,
49                'importance' => $row->importance,
50            ];
51
52            $projectName = $row->project_name;
53            // If the project name can't be found, skip adding it to the results.
54            if ( !$projectName ) {
55                continue;
56            }
57
58            $fit = $result->addValue(
59                [ 'query', 'pages', $row->page_id, $this->getModuleName() ],
60                $projectName,
61                $projectValues
62            );
63
64            if ( !$fit ) {
65                $this->setContinueEnumParameter( 'continue', "$row->page_id|$row->project_id" );
66                break;
67            }
68
69            // Make it easier to parse XML-formatted results
70            $result->addArrayType(
71                [ 'query', 'pages', $row->page_id, $this->getModuleName() ], 'kvp', 'project'
72            );
73            $result->addIndexedTagName(
74                [ 'query', 'pages', $row->page_id, $this->getModuleName() ], 'p'
75            );
76        }
77    }
78
79    /**
80     * @param array $pages
81     * @param array $params
82     */
83    private function buildDbQuery( array $pages, array $params ) {
84        global $wgPageAssessmentsSubprojects;
85
86        // build basic DB query
87        $this->addTables( [ 'page_assessments', 'page_assessments_projects' ] );
88        $this->addFields( [
89            'project_id' => 'pa_project_id',
90            'class' => 'pa_class',
91            'importance' => 'pa_importance',
92            'page_id' => 'pa_page_id',
93            'project_name' => 'pap_project_title'
94        ] );
95        $this->addJoinConds( [
96            'page_assessments_projects' => [
97                'JOIN',
98                [ 'pa_project_id = pap_project_id' ],
99            ]
100        ] );
101        $this->addWhereFld( 'pa_page_id', array_keys( $pages ) );
102        // If this wiki distinguishes between projects and subprojects, exclude
103        // subprojects (i.e. projects with parents) unless explicitly asked for.
104        if ( $wgPageAssessmentsSubprojects && !$params['subprojects'] ) {
105            $this->addWhere( [ 'pap_parent_id' => null ] );
106        }
107        $this->addOption( 'LIMIT', $params['limit'] + 1 );
108
109        // handle continuation if present
110        if ( $params['continue'] !== null ) {
111            $this->handleQueryContinuation( $params['continue'] );
112        }
113
114        // assure strict ordering, but mysql gets cranky if you order by a field
115        // when there's only one to sort
116        if ( count( $pages ) > 1 ) {
117            $this->addOption( 'ORDER BY', [ 'pa_page_id', 'pa_project_id' ] );
118        } else {
119            $this->addOption( 'ORDER BY', 'pa_project_id' );
120        }
121    }
122
123    /**
124     * @param string $continueParam
125     */
126    private function handleQueryContinuation( $continueParam ) {
127        $continues = $this->parseContinueParamOrDie( $continueParam, [ 'int', 'int' ] );
128        $this->addWhere( $this->getDB()->buildComparison( '>=', [
129            'pa_page_id' => $continues[0],
130            'pa_project_id' => $continues[1],
131        ] ) );
132    }
133
134    /** @inheritDoc */
135    public function getAllowedParams() {
136        global $wgPageAssessmentsSubprojects;
137
138        $allowedParams = [
139            'continue' => [ ApiBase::PARAM_HELP_MSG => 'api-help-param-continue' ],
140            'limit' => [
141                ParamValidator::PARAM_DEFAULT => 10,
142                ParamValidator::PARAM_TYPE => 'limit',
143                IntegerDef::PARAM_MIN => 1,
144                IntegerDef::PARAM_MAX => ApiBase::LIMIT_BIG1,
145                IntegerDef::PARAM_MAX2 => ApiBase::LIMIT_BIG2,
146            ],
147        ];
148        if ( $wgPageAssessmentsSubprojects ) {
149            $allowedParams[ 'subprojects' ] = [
150                ParamValidator::PARAM_DEFAULT => false,
151                ParamValidator::PARAM_TYPE => 'boolean',
152            ];
153        }
154        return $allowedParams;
155    }
156
157    /** @inheritDoc */
158    public function getExamplesMessages() {
159        global $wgPageAssessmentsSubprojects;
160
161        $exampleMessages = [
162            'action=query&prop=pageassessments&titles=Apple|Pear&formatversion=2'
163                => 'apihelp-query+pageassessments-example-formatversion',
164            'action=query&prop=pageassessments&titles=Apple'
165                => 'apihelp-query+pageassessments-example-simple',
166        ];
167        if ( $wgPageAssessmentsSubprojects ) {
168            $exampleMessages['action=query&prop=pageassessments&titles=Apple&pasubprojects=true'] =
169                'apihelp-query+pageassessments-example-subprojects';
170        }
171        return $exampleMessages;
172    }
173
174    /** @inheritDoc */
175    public function getHelpUrls() {
176        return 'https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:PageAssessments';
177    }
178}