Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 162
0.00% covered (danger)
0.00%
0 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialCargoQuery
0.00% covered (danger)
0.00%
0 / 162
0.00% covered (danger)
0.00%
0 / 9
1056
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 / 20
0.00% covered (danger)
0.00%
0 / 1
20
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 displayInputRow
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 displayTextArea
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 displayOrderByInput
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 1
42
 displayInputForm
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 1
42
 getWikitextForQuery
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 1
132
 displayBottomPane
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Shows the results of a Cargo query.
4 *
5 * @author Yaron Koren
6 * @ingroup Cargo
7 */
8
9class SpecialCargoQuery extends SpecialPage {
10
11    /**
12     * Constructor
13     */
14    public function __construct() {
15        parent::__construct( 'CargoQuery', 'runcargoqueries' );
16    }
17
18    public function execute( $query ) {
19        $this->checkPermissions();
20
21        $this->setHeaders();
22        $out = $this->getOutput();
23        $req = $this->getRequest();
24        $out->enableOOUI();
25
26        $out->addModules( 'ext.cargo.main' );
27        $out->addModules( 'ext.cargo.cargoquery' );
28
29        if ( $req->getCheck( 'tables' ) ) {
30            try {
31                $rep = new CargoQueryPage();
32            } catch ( MWException $e ) {
33                $out->addHTML( CargoUtils::formatError( $e->getMessage() ) );
34                return;
35            }
36            $rep->execute( $query );
37        }
38
39        $formHTML = $this->displayInputForm();
40
41        if ( $req->getCheck( 'tables' ) ) {
42            $html = $this->displayBottomPane( $this->msg( 'cargo-viewdata-modifyquery' ), $formHTML );
43            $wikitext = $this->getWikitextForQuery();
44            $html .= $this->displayBottomPane( $this->msg( 'cargo-viewdata-viewwikitext' ), $wikitext );
45        } else {
46            $html = $formHTML;
47        }
48
49        $out->addHTML( $html );
50    }
51
52    protected function getGroupName() {
53        return 'cargo';
54    }
55
56    /**
57     * This method is used for generating the input fields
58     * @param string $labelText
59     * @param string $fieldName
60     * @param int $size
61     * @return string
62     */
63    public function displayInputRow( $labelText, $fieldName, $size ) {
64        $req = $this->getRequest();
65
66        $label = Html::element( 'label', [ 'for' => $fieldName ], $labelText );
67        $row = "\n\t" . Html::rawElement( 'td', [ 'class' => 'mw-label' ], $label );
68        $input = new OOUI\TextInputWidget( [
69            'classes' => [ 'ext-cargo-' . $fieldName ],
70            'value' => $req->getVal( $fieldName )
71        ] );
72        $row .= "\n\t" . Html::rawElement( 'td', null, $input );
73        return Html::rawElement( 'tr', [ 'class' => 'ext-cargo-tr-' . $fieldName ], $row ) . "\n";
74    }
75
76    public function displayTextArea( $labelText, $fieldName, $size ) {
77        $req = $this->getRequest();
78
79        $label = Html::element( 'label', [ 'for' => $fieldName ], $labelText );
80        $row = "\n\t" . Html::rawElement( 'td', [ 'class' => 'mw-label' ], $label );
81        $input = new OOUI\MultilineTextInputWidget( [
82            'classes' => [ 'ext-cargo-' . $fieldName ],
83            'value' => $req->getVal( $fieldName )
84        ] );
85        $row .= "\n\t" . Html::rawElement( 'td', null, $input ) . "\n";
86        return Html::rawElement( 'tr', [ 'class' => 'ext-cargo-tr-' . $fieldName ], $row ) . "\n";
87    }
88
89    public function displayOrderByInput( $rowNum, $orderByValue, $orderByDirection ) {
90        $text = "\n" . '<tr class="orderByRow" data-order-by-num=' . $rowNum . '>';
91        if ( $rowNum == 0 ) {
92            $text .= '<td class="mw-label">' .
93                '<label for="order_by">' . $this->msg( 'cargo-viewdata-orderby' )->parse() . '</td>';
94        } else {
95            $text .= '<td></td>';
96        }
97        $options = [];
98        $value = '';
99        array_push( $options, [ 'data' => 'ASC', 'label' => 'ASC' ] );
100        if ( $orderByDirection == 'ASC' ) {
101            $value = 'ASC';
102        }
103        array_push( $options, [ 'data' => 'DESC', 'label' => 'DESC' ] );
104        if ( $orderByDirection == 'DESC' ) {
105            $value = 'DESC';
106        }
107        $directionSelect = new OOUI\DropdownInputWidget( [
108            'options' => $options,
109            'id' => 'order_by_options[' . $rowNum . ']',
110            'value' => $value,
111            'name' => 'order_by_options[' . $rowNum . ']'
112        ] );
113        $orderByInput = new OOUI\TextInputWidget( [
114            'id' => 'order_by[' . $rowNum . ']',
115            'value' => $orderByValue
116        ] );
117        $button = new OOUI\ButtonWidget( [
118            'id' => ( $rowNum == 0 ) ? 'addButton' : 'deleteButton',
119            'icon' => ( $rowNum == 0 ) ? 'add' : 'subtract'
120        ] );
121        $orderByRow = new OOUI\HorizontalLayout( [
122            'items' => [
123                $orderByInput,
124                $directionSelect,
125                $button,
126            ]
127        ] );
128        $text .= '<td>' . $orderByRow;
129
130        return $text;
131    }
132
133    public function displayInputForm() {
134        $req = $this->getRequest();
135        // Add the name of this special page as a hidden input, in
136        // case the wiki doesn't use nice URLs.
137        $hiddenTitleInput = Html::hidden( 'title', $this->getPageTitle()->getFullText() );
138
139        $text = <<<END
140<form id="queryform">
141$hiddenTitleInput
142<table class="cargoQueryTable" id="cargoQueryTable" >
143<tbody>
144END;
145
146        $text .= $this->displayInputRow( $this->msg( 'cargo-viewdata-tables' )->parse(), 'tables', 100 );
147        $text .= $this->displayInputRow( $this->msg( 'cargo-viewdata-fields' )->parse(), 'fields', 100 );
148        $text .= $this->displayTextArea( $this->msg( 'cargo-viewdata-where' )->parse(), 'where', 100 );
149        $text .= $this->displayTextArea( $this->msg( 'cargo-viewdata-joinon' )->parse(), 'join_on', 100 );
150        $text .= $this->displayInputRow( $this->msg( 'cargo-viewdata-groupby' )->parse(), 'group_by', 100 );
151        $text .= $this->displayTextArea( $this->msg( 'cargo-viewdata-having' )->parse(), 'having', 100 );
152        $orderByValues = $req->getArray( 'order_by' );
153        if ( $orderByValues != null ) {
154            $orderByDirections = $req->getArray( 'order_by_options' );
155            $rowNum = 0;
156            foreach ( $orderByValues as $i => $curOrderBy ) {
157                $orderByDir = ( $orderByDirections == null ) ? null : $orderByDirections[$i];
158                $text .= $this->displayOrderByInput( $rowNum++, $curOrderBy, $orderByDir );
159            }
160        } else {
161            $text .= $this->displayOrderByInput( 0, null, null );
162        }
163        $text .= $this->displayInputRow( $this->msg( 'cargo-viewdata-limit' )->parse(), 'limit', 3 );
164        $text .= $this->displayInputRow( $this->msg( 'cargo-viewdata-offset' )->parse(), 'offset', 3 );
165        $formatLabel = '<label for="format">' . $this->msg( 'cargo-viewdata-format' )->parse();
166        $options = [];
167        $formatOptionDefault = $this->msg( 'cargo-viewdata-defaultformat' )->parse();
168        array_push( $options, [ 'data' => '', 'label' => '(' . $formatOptionDefault . ')' ] );
169        $value = '';
170        $formatClasses = CargoQueryDisplayer::getAllFormatClasses();
171        foreach ( $formatClasses as $formatName => $formatClass ) {
172            if ( $formatName == $req->getVal( 'format' ) ) {
173                $value = $formatName;
174            }
175            array_push( $options, [ 'data' => $formatName, 'label' => $formatName ] );
176        }
177        $formatDropdown = new OOUI\DropdownInputWIdget( [
178            'options' => $options,
179            'name' => 'format',
180            'id' => 'format',
181            'value' => $value
182        ] );
183        $text .= <<<END
184<tr class="ext-cargo-tr-format">
185<td class="mw-label">
186$formatLabel
187</td>
188<td>$formatDropdown
189
190END;
191        $submitButton = new OOUI\ButtonInputWidget( [
192            'label' => $this->msg( 'htmlform-submit' )->parse(),
193            'type' => 'submit',
194            'flags' => [ 'primary', 'progressive' ]
195        ] );
196        $text .= <<<END
197
198</select>
199</td>
200</tr>
201</tbody>
202</table>
203<br>
204$submitButton
205</form>
206
207END;
208        return $text;
209    }
210
211    public function getWikitextForQuery() {
212        $req = $this->getRequest();
213
214        $wikitext = "{{#cargo_query:\n";
215        $vals = $req->getValues();
216        $firstParam = true;
217        foreach ( $vals as $key => $val ) {
218            if ( $key == 'title' || $key == 'order_by_options' ) {
219                continue;
220            }
221            $key = str_replace( '_', ' ', $key );
222            if ( $key == 'order by' && is_array( $val ) ) {
223                // Possibly no longer necessary.
224                $orderByVal = '';
225                foreach ( $val as $i => $orderByField ) {
226                    if ( $orderByField == '' ) {
227                        continue;
228                    }
229                    if ( array_key_exists( 'order_by_options', $vals ) ) {
230                        $option = $vals['order_by_options'][$i];
231                    } else {
232                        $option = '';
233                    }
234                    $orderByVal .= $orderByField . ' ' . $option . ', ';
235                }
236                $val = $orderByVal;
237            }
238            $val = trim( $val );
239            $val = trim( $val, ',' );
240            if ( $val == '' ) {
241                continue;
242            }
243            if ( $firstParam ) {
244                $firstParam = false;
245            } else {
246                $wikitext .= '|';
247            }
248            $wikitext .= "$key=$val\n";
249        }
250        $wikitext .= "}}";
251
252        return '<pre>' . htmlspecialchars( $wikitext ) . '</pre>';
253    }
254
255    private function displayBottomPane( $paneName, $paneText ) {
256        $html = <<<END
257<div style="max-width: 70em;">
258<span style="width: 100%;" class="oo-ui-widget oo-ui-widget-enabled oo-ui-buttonElement oo-ui-buttonElement-framed oo-ui-indicatorElement oo-ui-labelElement oo-ui-buttonWidget">
259<a href="#" class="specialCargoQuery-extraPane-toggle oo-ui-buttonElement-button" role="button" tabindex="0" aria-disabled="false" rel="nofollow">
260$paneName
261<span class="oo-ui-indicatorElement-indicator oo-ui-indicator-down"></span>
262</a>
263</span>
264<div class="specialCargoQuery-extraPane">
265$paneText
266</div>
267</div>
268
269END;
270        return $html;
271    }
272
273}