Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 67
0.00% covered (danger)
0.00%
0 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialListRedirects
0.00% covered (danger)
0.00%
0 / 66
0.00% covered (danger)
0.00%
0 / 11
306
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 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
 sortDescending
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 / 14
0.00% covered (danger)
0.00%
0 / 1
2
 getOrderFields
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 preprocessResults
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
20
 getRedirectTarget
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
12
 formatResult
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
6
 execute
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Copyright © 2006 Rob Church
4 *
5 * @license GPL-2.0-or-later
6 * @file
7 */
8
9namespace MediaWiki\Specials;
10
11use MediaWiki\Html\Html;
12use MediaWiki\Page\LinkBatchFactory;
13use MediaWiki\Page\RedirectLookup;
14use MediaWiki\Page\WikiPageFactory;
15use MediaWiki\Skin\Skin;
16use MediaWiki\SpecialPage\QueryPage;
17use MediaWiki\Title\Title;
18use stdClass;
19use Wikimedia\Rdbms\IConnectionProvider;
20use Wikimedia\Rdbms\IReadableDatabase;
21use Wikimedia\Rdbms\IResultWrapper;
22
23/**
24 * Lists all the redirecting pages on the wiki.
25 *
26 * @ingroup SpecialPage
27 * @author Rob Church <robchur@gmail.com>
28 */
29class SpecialListRedirects extends QueryPage {
30
31    private LinkBatchFactory $linkBatchFactory;
32    private WikiPageFactory $wikiPageFactory;
33    private RedirectLookup $redirectLookup;
34
35    public function __construct(
36        LinkBatchFactory $linkBatchFactory,
37        IConnectionProvider $dbProvider,
38        WikiPageFactory $wikiPageFactory,
39        RedirectLookup $redirectLookup
40    ) {
41        parent::__construct( 'Listredirects' );
42        $this->linkBatchFactory = $linkBatchFactory;
43        $this->setDatabaseProvider( $dbProvider );
44        $this->wikiPageFactory = $wikiPageFactory;
45        $this->redirectLookup = $redirectLookup;
46    }
47
48    /** @inheritDoc */
49    public function isExpensive() {
50        return true;
51    }
52
53    /** @inheritDoc */
54    public function isSyndicated() {
55        return false;
56    }
57
58    /** @inheritDoc */
59    protected function sortDescending() {
60        return false;
61    }
62
63    /** @inheritDoc */
64    public function getQueryInfo() {
65        return [
66            'tables' => [ 'page', 'redirect' ],
67            'fields' => [ 'namespace' => 'page_namespace',
68                'title' => 'page_title',
69                'rd_namespace',
70                'rd_title',
71                'rd_fragment',
72                'rd_interwiki',
73            ],
74            'conds' => [ 'page_is_redirect' => 1 ],
75            'join_conds' => [ 'redirect' => [
76                'LEFT JOIN', 'rd_from=page_id' ],
77            ]
78        ];
79    }
80
81    /** @inheritDoc */
82    protected function getOrderFields() {
83        return [ 'page_namespace', 'page_title' ];
84    }
85
86    /**
87     * Cache page existence for performance
88     *
89     * @param IReadableDatabase $db
90     * @param IResultWrapper $res
91     */
92    public function preprocessResults( $db, $res ) {
93        if ( !$res->numRows() ) {
94            return;
95        }
96
97        $batch = $this->linkBatchFactory->newLinkBatch()->setCaller( __METHOD__ );
98        foreach ( $res as $row ) {
99            $batch->add( $row->namespace, $row->title );
100            $redirTarget = $this->getRedirectTarget( $row );
101            if ( $redirTarget ) {
102                $batch->addObj( $redirTarget );
103            }
104        }
105        $batch->execute();
106
107        // Back to start for display
108        $res->seek( 0 );
109    }
110
111    protected function getRedirectTarget( stdClass $row ): ?Title {
112        if ( isset( $row->rd_title ) ) {
113            return Title::makeTitle(
114                $row->rd_namespace,
115                $row->rd_title,
116                $row->rd_fragment,
117                $row->rd_interwiki
118            );
119        } else {
120            $title = Title::makeTitle( $row->namespace, $row->title );
121            if ( !$title->canExist() ) {
122                return null;
123            }
124
125            return Title::castFromLinkTarget(
126                $this->redirectLookup->getRedirectTarget( $title )
127            );
128        }
129    }
130
131    /**
132     * @param Skin $skin
133     * @param stdClass $result Result row
134     * @return string
135     */
136    public function formatResult( $skin, $result ) {
137        $linkRenderer = $this->getLinkRenderer();
138        # Make a link to the redirect itself
139        $rd_title = Title::makeTitle( $result->namespace, $result->title );
140        $rd_link = $linkRenderer->makeLink(
141            $rd_title,
142            null,
143            [],
144            [ 'redirect' => 'no' ]
145        );
146
147        # Find out where the redirect leads
148        $target = $this->getRedirectTarget( $result );
149        if ( $target ) {
150            # Make a link to the destination page
151            $lang = $this->getLanguage();
152            $arr = $lang->getArrow();
153            $rd_link = Html::rawElement( 'bdi', [ 'dir' => $lang->getDir() ], $rd_link );
154            $targetLink = $linkRenderer->makeLink( $target, $target->getFullText() );
155            $targetLink = Html::rawElement( 'bdi', [ 'dir' => $lang->getDir() ], $targetLink );
156
157            return "$rd_link $arr $targetLink";
158        } else {
159            return "<del>$rd_link</del>";
160        }
161    }
162
163    /** @inheritDoc */
164    public function execute( $par ) {
165        $this->addHelpLink( 'Help:Redirects' );
166        parent::execute( $par );
167    }
168
169    /** @inheritDoc */
170    protected function getGroupName() {
171        return 'pages';
172    }
173}
174
175/** @deprecated class alias since 1.41 */
176class_alias( SpecialListRedirects::class, 'SpecialListRedirects' );