Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 101 |
|
0.00% |
0 / 10 |
CRAP | |
0.00% |
0 / 1 |
CargoQueryPage | |
0.00% |
0 / 101 |
|
0.00% |
0 / 10 |
1482 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 43 |
|
0.00% |
0 / 1 |
156 | |||
isExpensive | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isSyndicated | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getRecacheDB | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getQueryInfo | |
0.00% |
0 / 22 |
|
0.00% |
0 / 1 |
110 | |||
linkParameters | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
30 | |||
getOrderFields | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
sortDescending | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
formatResult | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
outputResults | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
30 |
1 | <?php |
2 | |
3 | use Wikimedia\Rdbms\IDatabase; |
4 | use Wikimedia\Rdbms\IResultWrapper; |
5 | |
6 | class 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 | // Not display params. |
67 | } elseif ( in_array( $paramName, [ 'intro', 'outro', 'default' ] ) ) { |
68 | // These already get parsed/escaped during regular display, so no need to |
69 | // further escape them here (and they can't be arrays). |
70 | $this->displayParams[$paramName] = $value; |
71 | } else { |
72 | if ( is_array( $value ) ) { |
73 | $this->displayParams[$paramName] = array_map( 'htmlspecialchars', $value ); |
74 | } else { |
75 | $this->displayParams[$paramName] = htmlspecialchars( $value ); |
76 | } |
77 | } |
78 | } |
79 | |
80 | // 'dynamic table' makes its own use of 'order by'. |
81 | if ( $this->format == 'dynamic table' ) { |
82 | $this->displayParams['order by'] = $orderByStr; |
83 | } |
84 | } |
85 | |
86 | public function isExpensive() { |
87 | return false; |
88 | } |
89 | |
90 | public function isSyndicated() { |
91 | return false; |
92 | } |
93 | |
94 | // @todo - declare a getPageHeader() function, to show some |
95 | // information about the query? |
96 | |
97 | /** @inheritDoc */ |
98 | public function getRecacheDB() { |
99 | return CargoUtils::getDB(); |
100 | } |
101 | |
102 | public function getQueryInfo() { |
103 | $selectOptions = []; |
104 | if ( $this->sqlQuery->mGroupByStr != '' ) { |
105 | $selectOptions['GROUP BY'] = $this->sqlQuery->mGroupByStr; |
106 | } |
107 | if ( $this->sqlQuery->mHavingStr != '' ) { |
108 | $selectOptions['HAVING'] = $this->sqlQuery->mHavingStr; |
109 | } |
110 | |
111 | // "order by" is handled elsewhere, in getOrderFields(). |
112 | |
113 | // Field aliases need to have quotes placed around them |
114 | // before running the query. |
115 | $cdb = CargoUtils::getDB(); |
116 | $aliasedFieldNames = []; |
117 | foreach ( $this->sqlQuery->mAliasedFieldNames as $alias => $fieldName ) { |
118 | // If it's really a field name, add quotes around it. |
119 | if ( strpos( $fieldName, '(' ) === false && strpos( $fieldName, '.' ) === false && |
120 | !$cdb->isQuotedIdentifier( $fieldName ) && !CargoUtils::isSQLStringLiteral( $fieldName ) ) { |
121 | $fieldName = $cdb->addIdentifierQuotes( $fieldName ); |
122 | } |
123 | $aliasedFieldNames[$alias] = $fieldName; |
124 | } |
125 | |
126 | $queryInfo = [ |
127 | 'tables' => $this->sqlQuery->mAliasedTableNames, |
128 | 'fields' => $aliasedFieldNames, |
129 | 'options' => $selectOptions |
130 | ]; |
131 | if ( $this->sqlQuery->mWhereStr != '' ) { |
132 | $queryInfo['conds'] = $this->sqlQuery->mWhereStr; |
133 | } |
134 | if ( $this->sqlQuery->mJoinConds ) { |
135 | $queryInfo['join_conds'] = $this->sqlQuery->mJoinConds; |
136 | } |
137 | return $queryInfo; |
138 | } |
139 | |
140 | /** |
141 | * Returns an associative array that will be encoded and added to the |
142 | * paging links |
143 | * @return array |
144 | */ |
145 | public function linkParameters() { |
146 | $possibleParams = [ |
147 | 'tables', 'fields', 'where', 'join_on', 'order_by', 'group_by', 'having', 'format' |
148 | ]; |
149 | $linkParams = []; |
150 | $req = $this->getRequest(); |
151 | foreach ( $possibleParams as $possibleParam ) { |
152 | if ( $req->getCheck( $possibleParam ) ) { |
153 | $linkParams[$possibleParam] = $req->getVal( $possibleParam ); |
154 | } elseif ( $req->getArray( $possibleParam ) ) { |
155 | $linkParams[$possibleParam] = $req->getArray( $possibleParam ); |
156 | } |
157 | } |
158 | |
159 | foreach ( $this->displayParams as $key => $value ) { |
160 | $linkParams[$key] = $value; |
161 | } |
162 | |
163 | return $linkParams; |
164 | } |
165 | |
166 | public function getOrderFields() { |
167 | return $this->sqlQuery->mOrderBy; |
168 | } |
169 | |
170 | public function sortDescending() { |
171 | return false; |
172 | } |
173 | |
174 | public function formatResult( $skin, $result ) { |
175 | // This function needs to be declared, but it is not called. |
176 | } |
177 | |
178 | /** |
179 | * Format and output report results using the given information plus |
180 | * OutputPage |
181 | * |
182 | * @param OutputPage $out OutputPage to print to |
183 | * @param Skin $skin User skin to use |
184 | * @param IDatabase $dbr Database (read) connection to use |
185 | * @param IResultWrapper $res Result pointer |
186 | * @param int $num Number of available result rows |
187 | * @param int $offset Paging offset |
188 | */ |
189 | public function outputResults( $out, $skin, $dbr, $res, $num, $offset ) { |
190 | $valuesTable = []; |
191 | for ( $i = 0; $i < $num && $row = $res->fetchObject(); $i++ ) { |
192 | $valuesTable[] = get_object_vars( $row ); |
193 | } |
194 | $queryDisplayer = CargoQueryDisplayer::newFromSQLQuery( $this->sqlQuery ); |
195 | $queryDisplayer->mFieldDescriptions = $this->sqlQuery->mFieldDescriptions; |
196 | $queryDisplayer->mFormat = $this->format; |
197 | $formatter = $queryDisplayer->getFormatter( $out ); |
198 | |
199 | if ( $formatter->isDeferred() ) { |
200 | $text = $formatter->queryAndDisplay( [ $this->sqlQuery ], $this->displayParams ); |
201 | $out->addHTML( $text ); |
202 | return; |
203 | } |
204 | |
205 | $this->displayParams['offset'] = $offset; |
206 | $queryDisplayer->mDisplayParams = $this->displayParams; |
207 | $html = $queryDisplayer->displayQueryResults( $formatter, $valuesTable ); |
208 | if ( $this->format === 'template' ) { |
209 | $out->addWikiTextAsContent( $html ); |
210 | } else { |
211 | $out->addHTML( $html ); |
212 | } |
213 | } |
214 | } |