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 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
DeleteOldPhonosFiles
0.00% covered (danger)
0.00%
0 / 45
0.00% covered (danger)
0.00%
0 / 2
72
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 1
56
1<?php
2
3use MediaWiki\Extension\Phonos\Engine\Engine;
4use MediaWiki\Maintenance\Maintenance;
5use MediaWiki\Status\Status;
6
7$IP = getenv( 'MW_INSTALL_PATH' );
8if ( $IP === false ) {
9    $IP = __DIR__ . '/../../..';
10}
11require_once "$IP/maintenance/Maintenance.php";
12
13/**
14 * Maintenance script to delete old Phonos files from storage.
15 *
16 * Based on Extension:Score's DeleteOldScoreFiles.php, GPLv2+
17 *
18 * @ingroup Maintenance
19 */
20class DeleteOldPhonosFiles extends Maintenance {
21
22    public function __construct() {
23        parent::__construct();
24        $this->addDescription( 'Deletes old Phonos files from storage' );
25        $this->addOption(
26            'date',
27            'Delete Phonos files that were created before this date (e.g. 20220101000000)',
28            true,
29            true
30        );
31        $this->requireExtension( 'Phonos' );
32    }
33
34    public function execute(): void {
35        $services = $this->getServiceContainer();
36        $backend = Engine::getFileBackend(
37            $services->getFileBackendGroup(),
38            $services->getMainConfig()
39        );
40        $dir = $backend->getRootStoragePath() . '/' . Engine::STORAGE_PREFIX;
41
42        $filesToDelete = [];
43        $deleteDate = $this->getOption( 'date' );
44        foreach (
45            $backend->getFileList( [ 'dir' => $dir, 'adviseStat' => true ] ) as $file
46        ) {
47            $fullPath = $dir . '/' . $file;
48            $timestamp = $backend->getFileTimestamp( [ 'src' => $fullPath ] );
49            if ( $timestamp < $deleteDate ) {
50                $filesToDelete[] = [ 'op' => 'delete', 'src' => $fullPath ];
51            }
52        }
53
54        $count = count( $filesToDelete );
55
56        if ( !$count ) {
57            $this->output( "No old Phonos files to delete.\n" );
58            return;
59        }
60
61        $this->output( "$count old Phonos files to be deleted.\n" );
62
63        $deletedCount = 0;
64        foreach ( array_chunk( $filesToDelete, 1000 ) as $chunk ) {
65            $ret = $backend->doQuickOperations( $chunk );
66
67            if ( $ret->isOK() ) {
68                $deletedCount += count( $chunk );
69                $this->output( "$deletedCount...\n" );
70            } else {
71                $status = Status::wrap( $ret );
72                $this->output( "Deleting old Phonos files errored.\n" );
73                $this->fatalError( $status->getWikiText( false, false, 'en' ) );
74            }
75        }
76
77        $this->output( "$deletedCount old Phonos files deleted.\n" );
78
79        // Remove empty directories.
80        $ret = $backend->clean( [
81            'dir' => $dir,
82            'recursive' => true,
83        ] );
84        if ( !$ret->isOK() ) {
85            $status = Status::wrap( $ret );
86            $this->output( "Cleaning empty directories errored.\n" );
87            $this->fatalError( $status->getWikiText( false, false, 'en' ) );
88        }
89    }
90}
91
92$maintClass = DeleteOldPhonosFiles::class;
93require_once RUN_MAINTENANCE_IF_MAIN;