Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
69.12% covered (warning)
69.12%
47 / 68
33.33% covered (danger)
33.33%
2 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
CargoQueryAPI
69.12% covered (warning)
69.12%
47 / 68
33.33% covered (danger)
33.33%
2 / 6
16.24
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
86.21% covered (warning)
86.21%
25 / 29
0.00% covered (danger)
0.00%
0 / 1
7.13
 getAllowedParams
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
1
 getParamDescription
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
2
 getDescription
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getExamples
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Adds and handles the 'cargoquery' action to the MediaWiki API.
4 *
5 * @ingroup Cargo
6 * @author Yaron Koren
7 */
8
9class CargoQueryAPI extends ApiBase {
10
11    public function __construct( $query, $moduleName ) {
12        parent::__construct( $query, $moduleName );
13    }
14
15    public function execute() {
16        $this->checkUserRightsAny( 'runcargoqueries' );
17
18        $params = $this->extractRequestParams();
19        $tablesStr = $params['tables'];
20        $fieldsStr = $params['fields'];
21        $whereStr = $params['where'];
22        $joinOnStr = $params['join_on'];
23        $orderByStr = $params['order_by'];
24        $groupByStr = $params['group_by'];
25        $havingStr = $params['having'];
26        $limitStr = $params['limit'];
27        $offsetStr = $params['offset'];
28
29        if ( $tablesStr == '' ) {
30            $this->dieWithError( 'The tables must be specified', 'param_substr' );
31        }
32
33        // Allow operators to control how many Cargo queries may be run via the API or Special:CargoQuery (T331689)
34        if ( $this->getUser()->pingLimiter( 'cargo-query' ) ) {
35            $this->dieWithError( 'apierror-ratelimited' );
36        }
37
38        $sqlQuery = CargoSQLQuery::newFromValues( $tablesStr, $fieldsStr, $whereStr, $joinOnStr,
39                $groupByStr, $havingStr, $orderByStr, $limitStr, $offsetStr );
40
41        foreach ( $sqlQuery->mFieldStringAliases as $fieldStrAlias ) {
42            if ( $fieldStrAlias[0] == '_' ) {
43                $this->dieWithError( [ 'apierror-cargoquery-invalidfieldalias', $fieldStrAlias ] );
44            }
45        }
46
47        try {
48            $queryResults = $sqlQuery->run();
49        } catch ( Exception $e ) {
50            $this->dieWithError( $e, 'db_error' );
51        }
52
53        // Format data as the API requires it.
54        $formattedData = [];
55        foreach ( $queryResults as $row ) {
56            // We HTML-unescape the values, because the API display will escape them again.
57            $formattedData[] = [ 'title' => array_map( 'html_entity_decode', $row ) ];
58        }
59
60        // Set top-level elements.
61        $result = $this->getResult();
62        $result->setIndexedTagName( $formattedData, 'p' );
63        $result->addValue( null, $this->getModuleName(), $formattedData );
64    }
65
66    protected function getAllowedParams() {
67        return [
68            'limit' => [
69                ApiBase::PARAM_TYPE => 'limit',
70                ApiBase::PARAM_DFLT => 50,
71                ApiBase::PARAM_MIN => 1,
72                ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
73                ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
74            ],
75            'tables' => null,
76            'fields' => null,
77            'where' => null,
78            'join_on' => null,
79            'group_by' => null,
80            'having' => null,
81            'order_by' => null,
82            'offset' => [
83                ApiBase::PARAM_TYPE => 'integer',
84                ApiBase::PARAM_DFLT => 0,
85                ApiBase::PARAM_MIN => 0,
86            ],
87        ];
88    }
89
90    protected function getParamDescription() {
91        return [
92            'tables' => 'The Cargo database table or tables on which to search',
93            'fields' => 'The table field(s) to retrieve',
94            'where' => 'The conditions for the query, corresponding to an SQL WHERE clause',
95            'join_on' => 'Conditions for joining multiple tables, corresponding to an SQL JOIN ON clause',
96            'order_by' => 'The order of results, corresponding to an SQL ORDER BY clause',
97            'group_by' => 'Field(s) on which to group results, corresponding to an SQL GROUP BY clause',
98            'having' => 'Conditions for grouped values, corresponding to an SQL HAVING clause',
99            'limit' => 'A limit on the number of results returned',
100            'offset' => 'The query offset number',
101        ];
102    }
103
104    protected function getDescription() {
105        return 'An SQL-style query used for data tables, provided by the Cargo extension '
106            . '(https://www.mediawiki.org/Extension:Cargo)';
107    }
108
109    protected function getExamples() {
110        return [
111            'api.php?action=cargoquery&tables=Items&fields=_pageName=Item,Source,Date=Publication_date'
112            . '&where=Source+LIKE+\'%New%\'&order_by=Date&limit=100'
113        ];
114    }
115
116}