Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 97
0.00% covered (danger)
0.00%
0 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
CargoQueryPage
0.00% covered (danger)
0.00%
0 / 97
0.00% covered (danger)
0.00%
0 / 10
1332
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 1
110
 isExpensive
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isSyndicated
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getRecacheDB
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getQueryInfo
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
110
 linkParameters
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
30
 getOrderFields
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 sortDescending
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 formatResult
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 outputResults
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3use Wikimedia\Rdbms\IDatabase;
4use Wikimedia\Rdbms\IResultWrapper;
5
6class CargoQueryPage extends QueryPage {
7    /** @var CargoSQLQuery */
8    private $sqlQuery;
9    /** @var array */
10    private $displayParams;
11    /** @var string */
12    private $format;
13
14    public function __construct( $name = 'CargoQuery' ) {
15        parent::__construct( $name );
16
17        $req = $this->getRequest();
18        $tablesStr = trim( $req->getVal( 'tables' ) );
19        $fieldsStr = trim( $req->getVal( 'fields' ) );
20        $whereStr = trim( $req->getVal( 'where' ) );
21        $joinOnStr = trim( $req->getVal( 'join_on' ) );
22        $groupByStr = trim( $req->getVal( 'group_by' ) );
23        if ( substr( $groupByStr, -1, 1 ) == ',' ) {
24            $groupByStr = substr( $groupByStr, 0, -1 ); // Remove last comma for group by
25        }
26        $havingStr = trim( $req->getVal( 'having' ) );
27
28        $orderByStr = "";
29        $orderByValues = $req->getArray( 'order_by' );
30        $orderByOptions = $req->getArray( 'order_by_options' );
31        if ( is_array( $orderByValues ) ) {
32            foreach ( $orderByValues as $i => $curOrderBy ) {
33                if ( $curOrderBy == '' ) {
34                    continue;
35                }
36                $orderByStr .= $curOrderBy;
37                if ( $orderByOptions != null ) {
38                    $orderByStr .= ' ' . $orderByOptions[$i];
39                }
40                $orderByStr .= ',';
41            }
42        }
43        if ( substr( $orderByStr, -1, 1 ) == ',' ) {
44            $orderByStr = substr( $orderByStr, 0, -1 ); // Remove last comma for order by
45        }
46        $limitStr = trim( $req->getVal( 'limit' ) );
47        $offsetStr = trim( $req->getVal( 'offset' ) );
48
49        $this->sqlQuery = CargoSQLQuery::newFromValues( $tablesStr, $fieldsStr, $whereStr, $joinOnStr,
50                $groupByStr, $havingStr, $orderByStr, $limitStr, $offsetStr );
51
52        $formatStr = trim( $req->getVal( 'format' ) );
53        $this->format = $formatStr;
54
55        // This is needed for both the results display and the
56        // navigation links.
57        $this->displayParams = [];
58        $queryStringValues = $this->getRequest()->getValues();
59        foreach ( $queryStringValues as $key => $value ) {
60            // For some reason, getValues() turns all spaces
61            // into underlines.
62            $paramName = str_replace( '_', ' ', $key );
63            if ( !in_array( $paramName,
64                    [ 'title', 'tables', 'fields', 'join on', 'order by', 'group by', 'having', 'format',
65                    'offset' ] ) ) {
66                $this->displayParams[$paramName] = $value;
67            }
68        }
69
70        // 'dynamic table' makes its own use of 'order by'.
71        if ( $this->format == 'dynamic table' ) {
72            $this->displayParams['order by'] = $orderByStr;
73        }
74    }
75
76    public function isExpensive() {
77        return false;
78    }
79
80    public function isSyndicated() {
81        return false;
82    }
83
84    // @todo - declare a getPageHeader() function, to show some
85    // information about the query?
86
87    /** @inheritDoc */
88    public function getRecacheDB() {
89        return CargoUtils::getDB();
90    }
91
92    public function getQueryInfo() {
93        $selectOptions = [];
94        if ( $this->sqlQuery->mGroupByStr != '' ) {
95            $selectOptions['GROUP BY'] = $this->sqlQuery->mGroupByStr;
96        }
97        if ( $this->sqlQuery->mHavingStr != '' ) {
98            $selectOptions['HAVING'] = $this->sqlQuery->mHavingStr;
99        }
100
101        // "order by" is handled elsewhere, in getOrderFields().
102
103        // Field aliases need to have quotes placed around them
104        // before running the query.
105        $cdb = CargoUtils::getDB();
106        $aliasedFieldNames = [];
107        foreach ( $this->sqlQuery->mAliasedFieldNames as $alias => $fieldName ) {
108            // If it's really a field name, add quotes around it.
109            if ( strpos( $fieldName, '(' ) === false && strpos( $fieldName, '.' ) === false &&
110                !$cdb->isQuotedIdentifier( $fieldName ) && !CargoUtils::isSQLStringLiteral( $fieldName ) ) {
111                $fieldName = $cdb->addIdentifierQuotes( $fieldName );
112            }
113            $aliasedFieldNames[$alias] = $fieldName;
114        }
115
116        $queryInfo = [
117            'tables' => $this->sqlQuery->mAliasedTableNames,
118            'fields' => $aliasedFieldNames,
119            'options' => $selectOptions
120        ];
121        if ( $this->sqlQuery->mWhereStr != '' ) {
122            $queryInfo['conds'] = $this->sqlQuery->mWhereStr;
123        }
124        if ( $this->sqlQuery->mJoinConds ) {
125            $queryInfo['join_conds'] = $this->sqlQuery->mJoinConds;
126        }
127        return $queryInfo;
128    }
129
130    /**
131     * Returns an associative array that will be encoded and added to the
132     * paging links
133     * @return array
134     */
135    public function linkParameters() {
136        $possibleParams = [
137            'tables', 'fields', 'where', 'join_on', 'order_by', 'group_by', 'having', 'format'
138        ];
139        $linkParams = [];
140        $req = $this->getRequest();
141        foreach ( $possibleParams as $possibleParam ) {
142            if ( $req->getCheck( $possibleParam ) ) {
143                $linkParams[$possibleParam] = $req->getVal( $possibleParam );
144            } elseif ( $req->getArray( $possibleParam ) ) {
145                $linkParams[$possibleParam] = $req->getArray( $possibleParam );
146            }
147        }
148
149        foreach ( $this->displayParams as $key => $value ) {
150            $linkParams[$key] = $value;
151        }
152
153        return $linkParams;
154    }
155
156    public function getOrderFields() {
157        return $this->sqlQuery->mOrderBy;
158    }
159
160    public function sortDescending() {
161        return false;
162    }
163
164    public function formatResult( $skin, $result ) {
165        // This function needs to be declared, but it is not called.
166    }
167
168    /**
169     * Format and output report results using the given information plus
170     * OutputPage
171     *
172     * @param OutputPage $out OutputPage to print to
173     * @param Skin $skin User skin to use
174     * @param IDatabase $dbr Database (read) connection to use
175     * @param IResultWrapper $res Result pointer
176     * @param int $num Number of available result rows
177     * @param int $offset Paging offset
178     */
179    public function outputResults( $out, $skin, $dbr, $res, $num, $offset ) {
180        $valuesTable = [];
181        for ( $i = 0; $i < $num && $row = $res->fetchObject(); $i++ ) {
182            $valuesTable[] = get_object_vars( $row );
183        }
184        $queryDisplayer = CargoQueryDisplayer::newFromSQLQuery( $this->sqlQuery );
185        $queryDisplayer->mFieldDescriptions = $this->sqlQuery->mFieldDescriptions;
186        $queryDisplayer->mFormat = $this->format;
187        $formatter = $queryDisplayer->getFormatter( $out );
188
189        if ( $formatter->isDeferred() ) {
190            $text = $formatter->queryAndDisplay( [ $this->sqlQuery ], $this->displayParams );
191            $out->addHTML( $text );
192            return;
193        }
194
195        $this->displayParams['offset'] = $offset;
196        $queryDisplayer->mDisplayParams = $this->displayParams;
197        $html = $queryDisplayer->displayQueryResults( $formatter, $valuesTable );
198        if ( $this->format === 'template' ) {
199            $out->addWikiTextAsContent( $html );
200        } else {
201            $out->addHTML( $html );
202        }
203    }
204}