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