Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
43.86% covered (danger)
43.86%
25 / 57
40.00% covered (danger)
40.00%
4 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialWithoutInterwiki
44.64% covered (danger)
44.64%
25 / 56
40.00% covered (danger)
40.00%
4 / 10
41.67
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 execute
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getPageHeader
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
6
 sortDescending
100.00% covered (success)
100.00%
1 / 1
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
 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
 getQueryInfo
71.43% covered (warning)
71.43%
15 / 21
0.00% covered (danger)
0.00%
0 / 1
2.09
 getRecacheDB
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * @license GPL-2.0-or-later
4 * @file
5 */
6
7namespace MediaWiki\Specials;
8
9use MediaWiki\Deferred\LinksUpdate\LangLinksTable;
10use MediaWiki\HTMLForm\HTMLForm;
11use MediaWiki\Language\LanguageConverterFactory;
12use MediaWiki\Page\LinkBatchFactory;
13use MediaWiki\SpecialPage\PageQueryPage;
14use MediaWiki\Title\NamespaceInfo;
15use MediaWiki\Title\Title;
16use Wikimedia\Rdbms\IConnectionProvider;
17use Wikimedia\Rdbms\IExpression;
18use Wikimedia\Rdbms\LikeValue;
19
20/**
21 * List of pages without any language links
22 *
23 * @ingroup SpecialPage
24 * @author Rob Church <robchur@gmail.com>
25 */
26class SpecialWithoutInterwiki extends PageQueryPage {
27    /** @var string */
28    private $prefix = '';
29
30    public function __construct(
31        private readonly NamespaceInfo $namespaceInfo,
32        IConnectionProvider $dbProvider,
33        LinkBatchFactory $linkBatchFactory,
34        LanguageConverterFactory $languageConverterFactory
35    ) {
36        parent::__construct( 'Withoutinterwiki' );
37        $this->setDatabaseProvider( $dbProvider );
38        $this->setLinkBatchFactory( $linkBatchFactory );
39        $this->setLanguageConverter( $languageConverterFactory->getLanguageConverter( $this->getContentLanguage() ) );
40    }
41
42    /** @inheritDoc */
43    public function execute( $par ) {
44        $prefix = $this->getRequest()->getVal( 'prefix', $par );
45        $this->prefix = $prefix !== null ? Title::capitalize( $prefix, NS_MAIN ) : '';
46        parent::execute( $par );
47    }
48
49    /** @inheritDoc */
50    protected function getPageHeader() {
51        # Do not show useless input form if special page is cached
52        if ( $this->isCached() ) {
53            return '';
54        }
55
56        $formDescriptor = [
57            'prefix' => [
58                'label-message' => 'allpagesprefix',
59                'name' => 'prefix',
60                'id' => 'wiprefix',
61                'type' => 'text',
62                'size' => 20,
63                'default' => $this->prefix
64            ]
65        ];
66
67        HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
68            ->setWrapperLegend( '' )
69            ->setSubmitTextMsg( 'withoutinterwiki-submit' )
70            ->setMethod( 'get' )
71            ->prepareForm()
72            ->displayForm( false );
73        return '';
74    }
75
76    /** @inheritDoc */
77    protected function sortDescending() {
78        return false;
79    }
80
81    /** @inheritDoc */
82    protected function getOrderFields() {
83        return [ 'page_namespace', 'page_title' ];
84    }
85
86    /** @inheritDoc */
87    public function isExpensive() {
88        return true;
89    }
90
91    /** @inheritDoc */
92    public function isSyndicated() {
93        return false;
94    }
95
96    /** @inheritDoc */
97    public function getQueryInfo() {
98        $query = [
99            'tables' => [ 'page', 'langlinks' ],
100            'fields' => [
101                'namespace' => 'page_namespace',
102                'title' => 'page_title',
103            ],
104            'conds' => [
105                'll_title' => null,
106                'page_namespace' => $this->namespaceInfo->getContentNamespaces(),
107                'page_is_redirect' => 0
108            ],
109            'join_conds' => [ 'langlinks' => [ 'LEFT JOIN', 'll_from = page_id' ] ]
110        ];
111
112        if ( $this->prefix ) {
113            $dbr = $this->getRecacheDB();
114            $query['conds'][] = $dbr->expr(
115                'page_title',
116                IExpression::LIKE,
117                new LikeValue( $this->prefix, $dbr->anyString() )
118            );
119        }
120
121        return $query;
122    }
123
124    /** @inheritDoc */
125    protected function getRecacheDB() {
126        return $this->getDatabaseProvider()->getReplicaDatabase(
127            LangLinksTable::VIRTUAL_DOMAIN,
128            'vslow'
129        );
130    }
131
132    /** @inheritDoc */
133    protected function getGroupName() {
134        return 'maintenance';
135    }
136}
137
138/**
139 * Retain the old class name for backwards compatibility.
140 * @deprecated since 1.41
141 */
142class_alias( SpecialWithoutInterwiki::class, 'SpecialWithoutInterwiki' );