Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 55
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialUnusedImages
0.00% covered (danger)
0.00%
0 / 54
0.00% covered (danger)
0.00%
0 / 8
156
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
 sortDescending
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
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 1
20
 usesTimestamps
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPageHeader
0.00% covered (danger)
0.00%
0 / 5
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 * @license GPL-2.0-or-later
4 * @file
5 */
6
7namespace MediaWiki\Specials;
8
9use MediaWiki\MainConfigNames;
10use MediaWiki\SpecialPage\ImageQueryPage;
11use Wikimedia\Rdbms\IConnectionProvider;
12
13/**
14 * List of unused images
15 *
16 * @ingroup SpecialPage
17 */
18class SpecialUnusedImages extends ImageQueryPage {
19
20    private int $fileMigrationStage;
21    private int $imageLinksMigrationStage;
22
23    public function __construct( IConnectionProvider $dbProvider ) {
24        parent::__construct( 'Unusedimages' );
25        $this->setDatabaseProvider( $dbProvider );
26        $this->fileMigrationStage = $this->getConfig()->get( MainConfigNames::FileSchemaMigrationStage );
27        $this->imageLinksMigrationStage = $this->getConfig()->get( MainConfigNames::ImageLinksSchemaMigrationStage );
28    }
29
30    /** @inheritDoc */
31    public function isExpensive() {
32        return true;
33    }
34
35    /** @inheritDoc */
36    protected function sortDescending() {
37        return false;
38    }
39
40    /** @inheritDoc */
41    public function isSyndicated() {
42        return false;
43    }
44
45    /** @inheritDoc */
46    public function getQueryInfo() {
47        if ( $this->fileMigrationStage & SCHEMA_COMPAT_READ_OLD ) {
48            $imageTables = [ 'image' ];
49            $nameField = 'img_name';
50            $timestampField = 'img_timestamp';
51            $fileConds = [];
52            $fileJoins = [];
53        } else {
54            $imageTables = [ 'file', 'filerevision' ];
55            $nameField = 'file_name';
56            $timestampField = 'fr_timestamp';
57            $fileConds = [ 'file_deleted' => 0 ];
58            $fileJoins = [ 'filerevision' => [ 'JOIN', 'file_latest = fr_id' ] ];
59        }
60
61        if ( $this->imageLinksMigrationStage & SCHEMA_COMPAT_READ_OLD ) {
62            $linksTables = [ 'imagelinks' ];
63            $linksConds = [ 'il_to' => null ];
64            $linksJoins = [
65                'imagelinks' => [ 'LEFT JOIN', 'il_to = ' . $nameField ]
66            ];
67        } else {
68            $linksTables = [ 'linktarget', 'imagelinks' ];
69            $linksConds = [ 'il_target_id' => null ];
70            $linksJoins = [
71                'linktarget' => [ 'LEFT JOIN', [ 'lt_title = ' . $nameField, 'lt_namespace' => NS_FILE ] ],
72                'imagelinks' => [ 'LEFT JOIN', 'il_target_id = lt_id' ]
73            ];
74        }
75
76        $retval = [
77            'tables' => array_merge( $imageTables, $linksTables ),
78            'fields' => [
79                'namespace' => NS_FILE,
80                'title' => $nameField,
81                'value' => $timestampField,
82            ],
83            'conds' => array_merge( $linksConds, $fileConds ),
84            'join_conds' => array_merge( $fileJoins, $linksJoins ),
85        ];
86
87        if ( $this->getConfig()->get( MainConfigNames::CountCategorizedImagesAsUsed ) ) {
88            // Order is significant
89            $retval['tables'] = [ ...$imageTables, 'page', 'categorylinks', ...$linksTables ];
90            $retval['conds']['page_namespace'] = NS_FILE;
91            $retval['conds']['cl_from'] = null;
92            $retval['join_conds']['page'] = [ 'JOIN', $nameField . ' = page_title' ];
93            $retval['join_conds']['categorylinks'] = [ 'LEFT JOIN', 'cl_from = page_id' ];
94        }
95
96        return $retval;
97    }
98
99    /** @inheritDoc */
100    public function usesTimestamps() {
101        return true;
102    }
103
104    /** @inheritDoc */
105    protected function getPageHeader() {
106        if ( $this->getConfig()->get( MainConfigNames::CountCategorizedImagesAsUsed ) ) {
107            return $this->msg(
108                'unusedimagestext-categorizedimgisused'
109            )->parseAsBlock();
110        }
111        return $this->msg( 'unusedimagestext' )->parseAsBlock();
112    }
113
114    /** @inheritDoc */
115    protected function getGroupName() {
116        return 'maintenance';
117    }
118}
119
120/**
121 * Retain the old class name for backwards compatibility.
122 * @deprecated since 1.41
123 */
124class_alias( SpecialUnusedImages::class, 'SpecialUnusedImages' );