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