Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 89
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 / 89
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 / 23
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 / 16
0.00% covered (danger)
0.00%
0 / 1
6
 getExamplesMessages
0.00% covered (danger)
0.00%
0 / 10
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 MediaWiki\Api\ApiBase;
6use MediaWiki\Api\ApiQuery;
7use MediaWiki\Api\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    public function __construct( ApiQuery $query, string $moduleName ) {
18        parent::__construct( $query, $moduleName, 'pa' );
19    }
20
21    /**
22     * Evaluate the parameters, perform the requested query, and set up the result
23     */
24    public function execute() {
25        $params = $this->extractRequestParams();
26        $pages = $this->getPageSet()->getGoodPages();
27        // are there pages to get project/assessment info for?
28        if ( !count( $pages ) ) {
29            // If not, return so other prop modules can run
30            return;
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        // build basic DB query
85        $this->addTables( [ 'page_assessments', 'page_assessments_projects' ] );
86        $this->addFields( [
87            'project_id' => 'pa_project_id',
88            'class' => 'pa_class',
89            'importance' => 'pa_importance',
90            'page_id' => 'pa_page_id',
91            'project_name' => 'pap_project_title'
92        ] );
93        $this->addJoinConds( [
94            'page_assessments_projects' => [
95                'JOIN',
96                [ 'pa_project_id = pap_project_id' ],
97            ]
98        ] );
99        $this->addWhereFld( 'pa_page_id', array_keys( $pages ) );
100        // If this wiki distinguishes between projects and subprojects, exclude
101        // subprojects (i.e. projects with parents) unless explicitly asked for.
102        if ( $this->getConfig()->get( 'PageAssessmentsSubprojects' ) && !$params['subprojects'] ) {
103            $this->addWhere( [ 'pap_parent_id' => null ] );
104        }
105        $this->addOption( 'LIMIT', $params['limit'] + 1 );
106
107        // handle continuation if present
108        if ( $params['continue'] !== null ) {
109            $this->handleQueryContinuation( $params['continue'] );
110        }
111
112        // assure strict ordering, but mysql gets cranky if you order by a field
113        // when there's only one to sort
114        if ( count( $pages ) > 1 ) {
115            $this->addOption( 'ORDER BY', [ 'pa_page_id', 'pa_project_id' ] );
116        } else {
117            $this->addOption( 'ORDER BY', 'pa_project_id' );
118        }
119    }
120
121    /**
122     * @param string $continueParam
123     */
124    private function handleQueryContinuation( $continueParam ) {
125        $continues = $this->parseContinueParamOrDie( $continueParam, [ 'int', 'int' ] );
126        $this->addWhere( $this->getDB()->buildComparison( '>=', [
127            'pa_page_id' => $continues[0],
128            'pa_project_id' => $continues[1],
129        ] ) );
130    }
131
132    /** @inheritDoc */
133    public function getAllowedParams() {
134        $allowedParams = [
135            'continue' => [ ApiBase::PARAM_HELP_MSG => 'api-help-param-continue' ],
136            'limit' => [
137                ParamValidator::PARAM_DEFAULT => 10,
138                ParamValidator::PARAM_TYPE => 'limit',
139                IntegerDef::PARAM_MIN => 1,
140                IntegerDef::PARAM_MAX => ApiBase::LIMIT_BIG1,
141                IntegerDef::PARAM_MAX2 => ApiBase::LIMIT_BIG2,
142            ],
143        ];
144        if ( $this->getConfig()->get( 'PageAssessmentsSubprojects' ) ) {
145            $allowedParams[ 'subprojects' ] = [
146                ParamValidator::PARAM_DEFAULT => false,
147                ParamValidator::PARAM_TYPE => 'boolean',
148            ];
149        }
150        return $allowedParams;
151    }
152
153    /** @inheritDoc */
154    public function getExamplesMessages() {
155        $exampleMessages = [
156            'action=query&prop=pageassessments&titles=Apple|Pear&formatversion=2'
157                => 'apihelp-query+pageassessments-example-formatversion',
158            'action=query&prop=pageassessments&titles=Apple'
159                => 'apihelp-query+pageassessments-example-simple',
160        ];
161        if ( $this->getConfig()->get( 'PageAssessmentsSubprojects' ) ) {
162            $exampleMessages['action=query&prop=pageassessments&titles=Apple&pasubprojects=true'] =
163                'apihelp-query+pageassessments-example-subprojects';
164        }
165        return $exampleMessages;
166    }
167
168    /** @inheritDoc */
169    public function getHelpUrls() {
170        return 'https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:PageAssessments';
171    }
172}