Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
54 / 54
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
DeleteOldRevisions
100.00% covered (success)
100.00%
54 / 54
100.00% covered (success)
100.00%
3 / 3
10
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 execute
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 doDelete
100.00% covered (success)
100.00%
48 / 48
100.00% covered (success)
100.00%
1 / 1
8
1<?php
2/**
3 * Delete old (non-current) revisions from the database
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 * @ingroup Maintenance
22 * @author Rob Church <robchur@gmail.com>
23 */
24
25use MediaWiki\Maintenance\Maintenance;
26
27// @codeCoverageIgnoreStart
28require_once __DIR__ . '/Maintenance.php';
29// @codeCoverageIgnoreEnd
30
31/**
32 * Maintenance script that deletes old (non-current) revisions from the database.
33 *
34 * @ingroup Maintenance
35 */
36class DeleteOldRevisions extends Maintenance {
37    public function __construct() {
38        parent::__construct();
39        $this->addDescription( 'Delete old (non-current) revisions from the database' );
40        $this->addOption( 'delete', 'Actually perform the deletion' );
41        $this->addArg( 'page_id', 'List of page ids to work on', false, true );
42    }
43
44    public function execute() {
45        $this->output( "Delete old revisions\n\n" );
46        $this->doDelete( $this->hasOption( 'delete' ), $this->getArgs( 'page_id' ) );
47    }
48
49    private function doDelete( $delete = false, $pageIds = [] ) {
50        # Data should come off the master, wrapped in a transaction
51        $dbw = $this->getPrimaryDB();
52        $this->beginTransaction( $dbw, __METHOD__ );
53
54        $pageConds = [];
55        $revConds = [];
56
57        # If a list of page_ids was provided, limit results to that set of page_ids
58        if ( count( $pageIds ) > 0 ) {
59            $pageConds['page_id'] = $pageIds;
60            $revConds['rev_page'] = $pageIds;
61            $this->output( "Limiting to page IDs " . implode( ',', $pageIds ) . "\n" );
62        }
63
64        # Get "active" revisions from the page table
65        $this->output( "Searching for active revisions..." );
66        $res = $dbw->newSelectQueryBuilder()
67            ->select( 'page_latest' )
68            ->from( 'page' )
69            ->where( $pageConds )
70            ->caller( __METHOD__ )
71            ->fetchResultSet();
72        $latestRevs = [];
73        foreach ( $res as $row ) {
74            $latestRevs[] = $row->page_latest;
75        }
76        $this->output( "done.\n" );
77
78        # Get all revisions that aren't in this set
79        $this->output( "Searching for inactive revisions..." );
80        if ( count( $latestRevs ) > 0 ) {
81            $revConds[] = $dbw->expr( 'rev_id', '!=', $latestRevs );
82        }
83        $res = $dbw->newSelectQueryBuilder()
84            ->select( 'rev_id' )
85            ->from( 'revision' )
86            ->where( $revConds )
87            ->caller( __METHOD__ )
88            ->fetchResultSet();
89        $oldRevs = [];
90        foreach ( $res as $row ) {
91            $oldRevs[] = $row->rev_id;
92        }
93        $this->output( "done.\n" );
94
95        # Inform the user of what we're going to do
96        $count = count( $oldRevs );
97        $this->output( "$count old revisions found.\n" );
98
99        # Delete as appropriate
100        if ( $delete && $count ) {
101            $this->output( "Deleting..." );
102            $dbw->newDeleteQueryBuilder()
103                ->deleteFrom( 'revision' )
104                ->where( [ 'rev_id' => $oldRevs ] )
105                ->caller( __METHOD__ )->execute();
106            $dbw->newDeleteQueryBuilder()
107                ->deleteFrom( 'ip_changes' )
108                ->where( [ 'ipc_rev_id' => $oldRevs ] )
109                ->caller( __METHOD__ )->execute();
110            $this->output( "done.\n" );
111        }
112
113        # Purge redundant text records
114        $this->commitTransaction( $dbw, __METHOD__ );
115        if ( $delete ) {
116            $this->purgeRedundantText( true );
117        }
118    }
119}
120
121// @codeCoverageIgnoreStart
122$maintClass = DeleteOldRevisions::class;
123require_once RUN_MAINTENANCE_IF_MAIN;
124// @codeCoverageIgnoreEnd