Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialUnwatchedPages
0.00% covered (danger)
0.00%
0 / 50
0.00% covered (danger)
0.00%
0 / 10
182
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
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
 preprocessResults
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
 getQueryInfo
0.00% covered (danger)
0.00%
0 / 17
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
 getOrderFields
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 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 formatResult
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
6
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Implements Special:Unwatchedpages
4 *
5 * Copyright © 2005 Ævar Arnfjörð Bjarmason
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * http://www.gnu.org/copyleft/gpl.html
21 *
22 * @file
23 * @ingroup SpecialPage
24 * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
25 */
26
27namespace MediaWiki\Specials;
28
29use HtmlArmor;
30use ILanguageConverter;
31use MediaWiki\Cache\LinkBatchFactory;
32use MediaWiki\Html\Html;
33use MediaWiki\Languages\LanguageConverterFactory;
34use MediaWiki\Linker\Linker;
35use MediaWiki\SpecialPage\QueryPage;
36use MediaWiki\Title\Title;
37use Skin;
38use stdClass;
39use Wikimedia\Rdbms\IConnectionProvider;
40use Wikimedia\Rdbms\IDatabase;
41use Wikimedia\Rdbms\IResultWrapper;
42
43/**
44 * A special page that displays a list of pages that are not on anyone's watchlist.
45 *
46 * @ingroup SpecialPage
47 */
48class SpecialUnwatchedPages extends QueryPage {
49
50    private LinkBatchFactory $linkBatchFactory;
51    private ILanguageConverter $languageConverter;
52
53    /**
54     * @param LinkBatchFactory $linkBatchFactory
55     * @param IConnectionProvider $dbProvider
56     * @param LanguageConverterFactory $languageConverterFactory
57     */
58    public function __construct(
59        LinkBatchFactory $linkBatchFactory,
60        IConnectionProvider $dbProvider,
61        LanguageConverterFactory $languageConverterFactory
62    ) {
63        parent::__construct( 'Unwatchedpages', 'unwatchedpages' );
64        $this->linkBatchFactory = $linkBatchFactory;
65        $this->setDatabaseProvider( $dbProvider );
66        $this->languageConverter = $languageConverterFactory->getLanguageConverter( $this->getContentLanguage() );
67    }
68
69    public function isExpensive() {
70        return true;
71    }
72
73    public function isSyndicated() {
74        return false;
75    }
76
77    /**
78     * Pre-cache page existence to speed up link generation
79     *
80     * @param IDatabase $db
81     * @param IResultWrapper $res
82     */
83    public function preprocessResults( $db, $res ) {
84        if ( !$res->numRows() ) {
85            return;
86        }
87
88        $batch = $this->linkBatchFactory->newLinkBatch();
89        foreach ( $res as $row ) {
90            $batch->add( $row->namespace, $row->title );
91        }
92        $batch->execute();
93
94        $res->seek( 0 );
95    }
96
97    public function getQueryInfo() {
98        $dbr = $this->getDatabaseProvider()->getReplicaDatabase();
99        return [
100            'tables' => [ 'page', 'watchlist' ],
101            'fields' => [
102                'namespace' => 'page_namespace',
103                'title' => 'page_title',
104                'value' => 'page_namespace'
105            ],
106            'conds' => [
107                'wl_title' => null,
108                'page_is_redirect' => 0,
109                $dbr->expr( 'page_namespace', '!=', NS_MEDIAWIKI ),
110            ],
111            'join_conds' => [ 'watchlist' => [
112                'LEFT JOIN', [ 'wl_title = page_title',
113                    'wl_namespace = page_namespace' ] ] ]
114        ];
115    }
116
117    protected function sortDescending() {
118        return false;
119    }
120
121    protected function getOrderFields() {
122        return [ 'page_namespace', 'page_title' ];
123    }
124
125    /**
126     * Add the JS
127     * @param string|null $par
128     */
129    public function execute( $par ) {
130        parent::execute( $par );
131        $this->getOutput()->addModules( 'mediawiki.special.unwatchedPages' );
132        $this->addHelpLink( 'Help:Watchlist' );
133    }
134
135    /**
136     * @param Skin $skin
137     * @param stdClass $result Result row
138     * @return string
139     */
140    public function formatResult( $skin, $result ) {
141        $nt = Title::makeTitleSafe( $result->namespace, $result->title );
142        if ( !$nt ) {
143            return Html::element( 'span', [ 'class' => 'mw-invalidtitle' ],
144                Linker::getInvalidTitleDescription( $this->getContext(), $result->namespace, $result->title ) );
145        }
146
147        $text = $this->languageConverter->convertHtml( $nt->getPrefixedText() );
148
149        $linkRenderer = $this->getLinkRenderer();
150
151        $plink = $linkRenderer->makeKnownLink( $nt, new HtmlArmor( $text ) );
152        $wlink = $linkRenderer->makeKnownLink(
153            $nt,
154            $this->msg( 'watch' )->text(),
155            [ 'class' => 'mw-watch-link' ],
156            [ 'action' => 'watch' ]
157        );
158
159        return $this->getLanguage()->specialList( $plink, $wlink );
160    }
161
162    protected function getGroupName() {
163        return 'maintenance';
164    }
165}
166
167/**
168 * Retain the old class name for backwards compatibility.
169 * @deprecated since 1.41
170 */
171class_alias( SpecialUnwatchedPages::class, 'SpecialUnwatchedPages' );