Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
CheckImages
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
2 / 2
8
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 execute
100.00% covered (success)
100.00%
33 / 33
100.00% covered (success)
100.00%
1 / 1
7
1<?php
2/**
3 * Check images to see if they exist, are readable, etc.
4 *
5 * @license GPL-2.0-or-later
6 * @file
7 * @ingroup Maintenance
8 */
9
10use MediaWiki\FileRepo\File\FileSelectQueryBuilder;
11use MediaWiki\Maintenance\Maintenance;
12use Wikimedia\Rdbms\SelectQueryBuilder;
13
14// @codeCoverageIgnoreStart
15require_once __DIR__ . '/Maintenance.php';
16// @codeCoverageIgnoreEnd
17
18/**
19 * Maintenance script to check images to see if they exist, are readable, etc.
20 *
21 * @ingroup Maintenance
22 */
23class CheckImages extends Maintenance {
24
25    public function __construct() {
26        parent::__construct();
27        $this->addDescription( 'Check images to see if they exist, are readable, etc' );
28        $this->setBatchSize( 1000 );
29    }
30
31    public function execute() {
32        $start = '';
33        $dbr = $this->getReplicaDB();
34
35        $numImages = 0;
36        $numGood = 0;
37
38        $repo = $this->getServiceContainer()->getRepoGroup()->getLocalRepo();
39        do {
40            $res = FileSelectQueryBuilder::newForFile( $dbr )
41                ->where( $dbr->expr( 'img_name', '>', $start ) )
42                ->limit( $this->getBatchSize() )
43                ->orderBy( 'img_name', SelectQueryBuilder::SORT_ASC )
44                ->caller( __METHOD__ )
45                ->fetchResultSet();
46            foreach ( $res as $row ) {
47                $numImages++;
48                $start = $row->img_name;
49                $file = $repo->newFileFromRow( $row );
50                $path = $file->getPath();
51                if ( !$path ) {
52                    $this->output( "{$row->img_name}: not locally accessible\n" );
53                    continue;
54                }
55                $size = $repo->getFileSize( $file->getPath() );
56                if ( $size === false ) {
57                    $this->output( "{$row->img_name}: missing\n" );
58                    continue;
59                }
60
61                if ( $size == 0 && $row->img_size != 0 ) {
62                    $this->output( "{$row->img_name}: truncated, was {$row->img_size}\n" );
63                    continue;
64                }
65
66                if ( $size != $row->img_size ) {
67                    $this->output( "{$row->img_name}: size mismatch DB={$row->img_size}"
68                        . "actual={$size}\n" );
69                    continue;
70                }
71
72                $numGood++;
73            }
74        } while ( $res->numRows() );
75
76        $this->output( "Good images: $numGood/$numImages\n" );
77    }
78}
79
80// @codeCoverageIgnoreStart
81$maintClass = CheckImages::class;
82require_once RUN_MAINTENANCE_IF_MAIN;
83// @codeCoverageIgnoreEnd