Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 128
0.00% covered (danger)
0.00%
0 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
RenameQueueTablePager
0.00% covered (danger)
0.00%
0 / 128
0.00% covered (danger)
0.00%
0 / 13
1640
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 showOpenRequests
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 showClosedRequests
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 / 17
0.00% covered (danger)
0.00%
0 / 1
2
 getQueryInfoConds
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
42
 getIndexField
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isFieldSortable
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
110
 formatValue
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
72
 formatDateTime
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 formatTypeValue
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 formatActionValue
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 getDefaultSort
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getFieldNames
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2/**
3 * @section LICENSE
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 * http://www.gnu.org/copyleft/gpl.html
18 *
19 * @file
20 * @ingroup SpecialPage
21 */
22
23namespace MediaWiki\Extension\CentralAuth\Special;
24
25use MediaWiki\Context\IContextSource;
26use MediaWiki\Extension\CentralAuth\CentralAuthDatabaseManager;
27use MediaWiki\Extension\CentralAuth\GlobalRename\GlobalRenameRequest;
28use MediaWiki\Extension\CentralAuth\User\CentralAuthUser;
29use MediaWiki\Html\Html;
30use MediaWiki\Linker\LinkRenderer;
31use MediaWiki\Pager\TablePager;
32use MediaWiki\SpecialPage\SpecialPage;
33use MediaWiki\User\UserNameUtils;
34use MediaWiki\WikiMap\WikiMap;
35use stdClass;
36
37/**
38 * Paginated table of search results.
39 * @ingroup Pager
40 */
41class RenameQueueTablePager extends TablePager {
42
43    private UserNameUtils $userNameUtils;
44
45    /**
46     * @var string
47     */
48    protected $mPage;
49
50    /**
51     * @var string[]|null
52     */
53    protected $mFieldNames;
54
55    public function __construct(
56        IContextSource $context,
57        LinkRenderer $linkRenderer,
58        CentralAuthDatabaseManager $databaseManager,
59        UserNameUtils $userNameUtils,
60        string $page
61    ) {
62        $this->setContext( $context );
63        $this->mPage = $page;
64        $this->mDb = $databaseManager->getCentralReplicaDB();
65        $this->userNameUtils = $userNameUtils;
66
67        $limit = $this->getRequest()->getInt( 'limit', 25 );
68        // Override default cap of 5000
69        $this->setLimit( min( 100, $limit ) );
70
71        if ( $this->showOpenRequests() ) {
72            $this->mDefaultDirection = self::DIR_ASCENDING;
73        } else {
74            $this->mDefaultDirection = self::DIR_DESCENDING;
75        }
76        parent::__construct( null, $linkRenderer );
77    }
78
79    protected function showOpenRequests() {
80        return $this->mPage === SpecialGlobalRenameQueue::PAGE_OPEN_QUEUE;
81    }
82
83    protected function showClosedRequests() {
84        return $this->mPage === SpecialGlobalRenameQueue::PAGE_CLOSED_QUEUE;
85    }
86
87    /** @inheritDoc */
88    public function getQueryInfo() {
89        return [
90            'tables' => 'renameuser_queue',
91            'fields' => [
92                'rq_id',
93                'rq_name',
94                'rq_wiki',
95                'rq_newname',
96                'rq_reason',
97                'rq_requested_ts',
98                'rq_status',
99                'rq_completed_ts',
100                # 'rq_deleted', not implemented yet
101                'rq_performer',
102                'rq_comments',
103                'rq_type',
104            ],
105            'conds' => $this->getQueryInfoConds(),
106        ];
107    }
108
109    /** @inheritDoc */
110    protected function getQueryInfoConds() {
111        $conds = [];
112
113        $username = $this->getRequest()->getText( 'username' );
114        $username = $this->userNameUtils->getCanonical( $username );
115        if ( $username ) {
116            $conds['rq_name'] = $username;
117        }
118
119        $newname = $this->getRequest()->getText( 'newname' );
120        $newname = $this->userNameUtils->getCanonical( $newname );
121        if ( $newname ) {
122            $conds['rq_newname'] = $newname;
123        }
124
125        $type = $this->getRequest()->getVal( 'type', 'all' );
126        if ( $type !== 'all' ) {
127            $conds['rq_type'] = $type;
128        }
129
130        if ( $this->showOpenRequests() ) {
131            $conds['rq_status'] = GlobalRenameRequest::PENDING;
132        } else {
133            $status = $this->getRequest()->getVal( 'status', 'all' );
134            $closedStatuses = [ GlobalRenameRequest::APPROVED, GlobalRenameRequest::REJECTED ];
135            if ( in_array( $status, $closedStatuses ) ) {
136                // User requested closed status - either approved or rejected
137                $conds['rq_status'] = $status;
138            } else {
139                // All closed requests
140                $conds[] = $this->mDb->expr( 'rq_status', '!=', GlobalRenameRequest::PENDING );
141            }
142        }
143
144        return $conds;
145    }
146
147    /**
148     * @return array
149     */
150    public function getIndexField() {
151        return [ [ parent::getIndexField(), 'rq_id' ] ];
152    }
153
154    /**
155     * @param string $field
156     * @return bool
157     */
158    public function isFieldSortable( $field ) {
159        $sortable = false;
160        switch ( $field ) {
161            case 'rq_name':
162            case 'rq_wiki':
163            case 'rq_newname':
164            case 'rq_reason':
165            case 'rq_requested_ts':
166            case 'rq_status':
167            case 'rq_completed_ts':
168            case 'rq_performer':
169            case 'rq_type':
170                $sortable = true;
171        }
172        return $sortable;
173    }
174
175    /**
176     * @param string $name The database field name
177     * @param string|null $value The value retrieved from the database
178     * @return string HTML to place inside table cell
179     */
180    public function formatValue( $name, $value ) {
181        $formatted = htmlspecialchars( $value ?? '' );
182        switch ( $name ) {
183            case 'rq_requested_ts':
184            case 'rq_completed_ts':
185                $formatted = $this->formatDateTime( $value );
186                break;
187            case 'rq_name':
188            case 'rq_newname':
189                $title = SpecialPage::getTitleFor( 'CentralAuth', $value );
190                $formatted = $this->getLinkRenderer()->makeLink( $title, $value );
191                break;
192            case 'rq_performer':
193                $renamer = CentralAuthUser::newFromId( (int)$value );
194                $formatted = '<span class="plainlinks">' .
195                    WikiMap::foreignUserLink(
196                    $renamer->getHomeWiki(),
197                    $renamer->getName(),
198                    $renamer->getName()
199                ) . '</span>';
200                break;
201            case 'rq_type':
202                $formatted = $this->formatTypeValue( (int)$value );
203                break;
204            case 'row_actions':
205                $formatted = $this->formatActionValue( $this->mCurrentRow );
206                break;
207        }
208        return $formatted;
209    }
210
211    /**
212     * @param string $value
213     * @return string Formatted table cell contents
214     */
215    protected function formatDateTime( $value ) {
216        return htmlspecialchars(
217            $this->getLanguage()->userTimeAndDate( $value, $this->getUser() )
218        );
219    }
220
221    /**
222     * @param int $type
223     * @return string Formatted and translated table cell contents
224     */
225    protected function formatTypeValue( $type ) {
226        return $type === GlobalRenameRequest::VANISH
227            ? $this->msg( 'globalrenamequeue-type-vanish' )->text()
228            : $this->msg( 'globalrenamequeue-type-rename' )->text();
229    }
230
231    /**
232     * @param stdClass $row
233     * @return string Formatted table cell contents
234     */
235    protected function formatActionValue( $row ) {
236        $target = SpecialGlobalRenameQueue::PAGE_PROCESS_REQUEST . '/' . $row->rq_id;
237        if ( $this->showOpenRequests() ) {
238            $label = 'globalrenamequeue-action-address';
239        } else {
240            $target .= '/' . SpecialGlobalRenameQueue::ACTION_VIEW;
241            $label = 'globalrenamequeue-action-view';
242        }
243        return Html::element( 'a',
244            [
245                'href' => SpecialPage::getTitleFor( 'GlobalRenameQueue', $target )->getFullURL(),
246            ],
247            $this->msg( $label )->text()
248        );
249    }
250
251    /**
252     * @return string
253     */
254    public function getDefaultSort() {
255        if ( $this->showOpenRequests() ) {
256            return 'rq_requested_ts';
257        } else {
258            return 'rq_completed_ts';
259        }
260    }
261
262    /**
263     * @return string[]
264     */
265    public function getFieldNames() {
266        if ( $this->mFieldNames === null ) {
267            $this->mFieldNames = [
268                'rq_name' => $this->msg( 'globalrenamequeue-column-rq-name' )->text(),
269                'rq_newname' => $this->msg( 'globalrenamequeue-column-rq-newname' )->text(),
270                'rq_wiki' => $this->msg( 'globalrenamequeue-column-rq-wiki' )->text(),
271                'rq_requested_ts' =>
272                    $this->msg( 'globalrenamequeue-column-rq-requested-ts' )->text(),
273                'rq_type' => $this->msg( 'globalrenamequeue-column-rq-type' )->text(),
274                'row_actions' => $this->msg( 'globalrenamequeue-column-row-actions' )->text(),
275            ];
276
277            if ( $this->showClosedRequests() ) {
278                // Remove action column
279                array_pop( $this->mFieldNames );
280
281                $this->mFieldNames += [
282                    'rq_completed_ts' =>
283                        $this->msg( 'globalrenamequeue-column-rq-completed-ts' )->text(),
284                    'rq_status' => $this->msg( 'globalrenamequeue-column-rq-status' )->text(),
285                    'rq_performer' => $this->msg( 'globalrenamequeue-column-rq-performer' )->text(),
286                    'row_actions' => $this->msg( 'globalrenamequeue-column-row-actions' )->text(),
287                ];
288            }
289        }
290        return $this->mFieldNames;
291    }
292}