Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 105 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 1 |
CargoCompoundQuery | |
0.00% |
0 / 105 |
|
0.00% |
0 / 2 |
930 | |
0.00% |
0 / 1 |
run | |
0.00% |
0 / 67 |
|
0.00% |
0 / 1 |
420 | |||
getOrDisplayQueryResultsFromStrings | |
0.00% |
0 / 38 |
|
0.00% |
0 / 1 |
110 |
1 | <?php |
2 | /** |
3 | * CargoCompoundQuery - class for the #cargo_compound_query parser function. |
4 | * |
5 | * @author Yaron Koren |
6 | * @ingroup Cargo |
7 | */ |
8 | |
9 | class CargoCompoundQuery { |
10 | |
11 | /** |
12 | * Handles the #cargo_compound_query parser function - calls a |
13 | * "compound query", consisting of two or more queries of the |
14 | * Cargo data stored in the database, and then displays their |
15 | * results together. |
16 | * |
17 | * This function is based conceptually on the #compound_query |
18 | * parser function defined by the Semantic Compound Queries |
19 | * extension. |
20 | * |
21 | * @param Parser $parser |
22 | * @return string|array Error message string, or an array holding output text and format flags |
23 | */ |
24 | public static function run( $parser ) { |
25 | $params = func_get_args(); |
26 | array_shift( $params ); // we already know the $parser... |
27 | |
28 | // Split up the parameters into query params and other params - |
29 | // we do that just by looking for the string "tables="; |
30 | // hopefully that will never show up in non-query params. |
31 | // Another possibility is to always check for ";", but query |
32 | // params can in theory hold a "tables=" clause and nothing |
33 | // else. |
34 | $queryParams = $otherParams = []; |
35 | foreach ( $params as $param ) { |
36 | if ( strpos( $param, 'tables=' ) !== false ) { |
37 | $queryParams[] = $param; |
38 | } else { |
39 | $otherParams[] = $param; |
40 | } |
41 | } |
42 | |
43 | $sqlQueries = []; |
44 | $querySpecificParams = []; |
45 | foreach ( $queryParams as $param ) { |
46 | $tablesStr = null; |
47 | $fieldsStr = null; |
48 | $whereStr = null; |
49 | $joinOnStr = null; |
50 | $groupByStr = null; |
51 | $havingStr = null; |
52 | $orderByStr = null; |
53 | $limitStr = null; |
54 | $offsetStr = null; |
55 | |
56 | $queryClauses = CargoUtils::smartSplit( ';', $param ); |
57 | $displayParamsForThisQuery = []; |
58 | foreach ( $queryClauses as $clause ) { |
59 | $parts = explode( '=', $clause, 2 ); |
60 | if ( count( $parts ) != 2 ) { |
61 | continue; |
62 | } |
63 | $key = trim( $parts[0] ); |
64 | $value = trim( $parts[1] ); |
65 | if ( $key == 'tables' ) { |
66 | $tablesStr = $value; |
67 | } elseif ( $key == 'fields' ) { |
68 | $fieldsStr = $value; |
69 | } elseif ( $key == 'where' ) { |
70 | $whereStr = $value; |
71 | } elseif ( $key == 'join on' ) { |
72 | $joinOnStr = $value; |
73 | } elseif ( $key == 'group by' ) { |
74 | $groupByStr = $value; |
75 | } elseif ( $key == 'having' ) { |
76 | $havingStr = $value; |
77 | } elseif ( $key == 'order by' ) { |
78 | $orderByStr = $value; |
79 | } elseif ( $key == 'limit' ) { |
80 | $limitStr = $value; |
81 | } elseif ( $key == 'offset' ) { |
82 | $offsetStr = $value; |
83 | } else { |
84 | $displayParamsForThisQuery[$key] = $value; |
85 | } |
86 | } |
87 | try { |
88 | $sqlQueries[] = CargoSQLQuery::newFromValues( $tablesStr, $fieldsStr, $whereStr, $joinOnStr, |
89 | $groupByStr, $havingStr, $orderByStr, $limitStr, $offsetStr ); |
90 | } catch ( Exception $e ) { |
91 | return CargoUtils::formatError( $e->getMessage() ); |
92 | } |
93 | $querySpecificParams[] = $displayParamsForThisQuery; |
94 | } |
95 | |
96 | $format = 'auto'; // default |
97 | $displayParams = []; |
98 | foreach ( $otherParams as $param ) { |
99 | $parts = explode( '=', $param, 2 ); |
100 | |
101 | if ( count( $parts ) != 2 ) { |
102 | continue; |
103 | } |
104 | $key = trim( $parts[0] ); |
105 | $value = trim( $parts[1] ); |
106 | if ( $key == 'format' ) { |
107 | $format = $value; |
108 | } else { |
109 | // We'll assume it's going to the formatter. |
110 | $displayParams[$key] = $value; |
111 | } |
112 | } |
113 | |
114 | try { |
115 | $queryResults = self::getOrDisplayQueryResultsFromStrings( $sqlQueries, $querySpecificParams, |
116 | $format, $displayParams, $parser ); |
117 | } catch ( Exception $e ) { |
118 | return CargoUtils::formatError( $e->getMessage() ); |
119 | } |
120 | |
121 | return $queryResults; |
122 | } |
123 | |
124 | /** |
125 | * @todo - this should probably be streamlined and renamed. |
126 | */ |
127 | public static function getOrDisplayQueryResultsFromStrings( $sqlQueries, $querySpecificParams, |
128 | $format, $displayParams, Parser $parser ) { |
129 | $queryDisplayer = new CargoQueryDisplayer(); |
130 | $queryDisplayer->mParser = $parser; |
131 | $queryDisplayer->mFormat = $format; |
132 | $formatter = $queryDisplayer->getFormatter( $parser->getOutput() ); |
133 | if ( $formatter->isDeferred() ) { |
134 | $text = $formatter->queryAndDisplay( $sqlQueries, $displayParams, $querySpecificParams ); |
135 | return [ $text, 'noparse' => true, 'isHTML' => true ]; |
136 | } |
137 | |
138 | $allQueryResults = []; |
139 | $formattedQueryResults = []; |
140 | $allFieldDescriptions = []; |
141 | |
142 | $rowNum = 0; |
143 | foreach ( $sqlQueries as $i => $sqlQuery ) { |
144 | $queryResults = $sqlQuery->run(); |
145 | $allQueryResults = array_merge( $allQueryResults, $queryResults ); |
146 | $queryDisplayer->mFieldDescriptions = $sqlQuery->mFieldDescriptions; |
147 | $formattedQueryResults = array_merge( $formattedQueryResults, |
148 | $queryDisplayer->getFormattedQueryResults( $queryResults ) ); |
149 | // $formattedQueryResultsArray[] = $formattedQueryResults; |
150 | foreach ( $sqlQuery->mFieldDescriptions as $alias => $description ) { |
151 | $allFieldDescriptions[$alias] = $description; |
152 | } |
153 | |
154 | // Now add this query's own display parameters to |
155 | // the row for every result of that query within an |
156 | // array contained in the $diaplayParams object. |
157 | $numResultsForThisQuery = count( $queryResults ); |
158 | $displayParamsForThisQuery = $querySpecificParams[$i]; |
159 | foreach ( $displayParamsForThisQuery as $paramName => $paramValue ) { |
160 | if ( array_key_exists( $paramName, $displayParams ) ) { |
161 | // Just make sure it's an array. |
162 | if ( !is_array( $displayParams[$paramName] ) ) { |
163 | throw new MWException( "Error: \"$paramName\" cannot be used as both a " |
164 | . "query-specific parameter and an overall display parameter." ); |
165 | } |
166 | } else { |
167 | $displayParams[$paramName] = []; |
168 | } |
169 | // Now, add it in for each row. |
170 | for ( $j = $rowNum; $j < $rowNum + $numResultsForThisQuery; $j++ ) { |
171 | $displayParams[$paramName][$j] = $paramValue; |
172 | } |
173 | } |
174 | |
175 | $rowNum += $numResultsForThisQuery; |
176 | } |
177 | |
178 | if ( $format === null ) { |
179 | return $allQueryResults; |
180 | } |
181 | |
182 | // Finally, do the display, based on the format. |
183 | $text = $formatter->display( $allQueryResults, $formattedQueryResults, $allFieldDescriptions, |
184 | $displayParams ); |
185 | |
186 | // The 'template' format gets special parsing, because |
187 | // it can be used to display a larger component, like a table, |
188 | // which means that everything needs to be parsed together |
189 | // instead of one instance at a time. Also, the template will |
190 | // contain wikitext, not HTML. |
191 | $displayHTML = ( $format != 'template' ); |
192 | |
193 | // Don't show a "view more" link. |
194 | // @TODO - is such a thing possible for a compound query, |
195 | // especially if there's a limit set for each query? |
196 | |
197 | if ( $displayHTML ) { |
198 | return [ $text, 'noparse' => true, 'isHTML' => true ]; |
199 | } else { |
200 | return [ $text, 'noparse' => false ]; |
201 | } |
202 | } |
203 | |
204 | } |