Completed
Branch master (b92a94)
by
unknown
34:34
created

CloneDatabase::changeDBPrefix()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Helper class for making a copy of the database, mostly for unit testing.
4
 *
5
 * Copyright © 2010 Chad Horohoe <[email protected]>
6
 * https://www.mediawiki.org/
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License along
19
 * with this program; if not, write to the Free Software Foundation, Inc.,
20
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
 * http://www.gnu.org/copyleft/gpl.html
22
 *
23
 * @file
24
 * @ingroup Database
25
 */
26
27
class CloneDatabase {
28
	/** @var string Table prefix for cloning */
29
	private $newTablePrefix = '';
30
31
	/** @var string Current table prefix */
32
	private $oldTablePrefix = '';
33
34
	/** @var array List of tables to be cloned */
35
	private $tablesToClone = [];
36
37
	/** @var bool Should we DROP tables containing the new names? */
38
	private $dropCurrentTables = true;
39
40
	/** @var bool Whether to use temporary tables or not */
41
	private $useTemporaryTables = true;
42
43
	/**
44
	 * Constructor
45
	 *
46
	 * @param DatabaseBase $db A database subclass
47
	 * @param array $tablesToClone An array of tables to clone, unprefixed
48
	 * @param string $newTablePrefix Prefix to assign to the tables
49
	 * @param string $oldTablePrefix Prefix on current tables, if not $wgDBprefix
50
	 * @param bool $dropCurrentTables
51
	 */
52
	public function __construct( DatabaseBase $db, array $tablesToClone,
53
		$newTablePrefix, $oldTablePrefix = '', $dropCurrentTables = true
54
	) {
55
		$this->db = $db;
0 ignored issues
show
Bug introduced by
The property db does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
56
		$this->tablesToClone = $tablesToClone;
57
		$this->newTablePrefix = $newTablePrefix;
58
		$this->oldTablePrefix = $oldTablePrefix ? $oldTablePrefix : $this->db->tablePrefix();
59
		$this->dropCurrentTables = $dropCurrentTables;
60
	}
61
62
	/**
63
	 * Set whether to use temporary tables or not
64
	 * @param bool $u Use temporary tables when cloning the structure
65
	 */
66
	public function useTemporaryTables( $u = true ) {
67
		$this->useTemporaryTables = $u;
68
	}
69
70
	/**
71
	 * Clone the table structure
72
	 */
73
	public function cloneTableStructure() {
74
		global $wgSharedTables, $wgSharedDB;
75
		foreach ( $this->tablesToClone as $tbl ) {
76
			if ( $wgSharedDB && in_array( $tbl, $wgSharedTables, true ) ) {
77
				// Shared tables don't work properly when cloning due to
78
				// how prefixes are handled (bug 65654)
79
				throw new MWException( "Cannot clone shared table $tbl." );
80
			}
81
			# Clean up from previous aborted run.  So that table escaping
82
			# works correctly across DB engines, we need to change the pre-
83
			# fix back and forth so tableName() works right.
84
85
			self::changePrefix( $this->oldTablePrefix );
86
			$oldTableName = $this->db->tableName( $tbl, 'raw' );
87
88
			self::changePrefix( $this->newTablePrefix );
89
			$newTableName = $this->db->tableName( $tbl, 'raw' );
90
91
			if ( $this->dropCurrentTables
92
				&& !in_array( $this->db->getType(), [ 'postgres', 'oracle' ] )
93
			) {
94
				if ( $oldTableName === $newTableName ) {
95
					// Last ditch check to avoid data loss
96
					throw new MWException( "Not dropping new table, as '$newTableName'"
97
						. " is name of both the old and the new table." );
98
				}
99
				$this->db->dropTable( $tbl, __METHOD__ );
100
				wfDebug( __METHOD__ . " dropping {$newTableName}\n" );
101
				// Dropping the oldTable because the prefix was changed
102
			}
103
104
			# Create new table
105
			wfDebug( __METHOD__ . " duplicating $oldTableName to $newTableName\n" );
106
			$this->db->duplicateTableStructure( $oldTableName, $newTableName, $this->useTemporaryTables );
107
		}
108
	}
109
110
	/**
111
	 * Change the prefix back to the original.
112
	 * @param bool $dropTables Optionally drop the tables we created
113
	 */
114
	public function destroy( $dropTables = false ) {
115
		if ( $dropTables ) {
116
			self::changePrefix( $this->newTablePrefix );
117
			foreach ( $this->tablesToClone as $tbl ) {
118
				$this->db->dropTable( $tbl );
119
			}
120
		}
121
		self::changePrefix( $this->oldTablePrefix );
122
	}
123
124
	/**
125
	 * Change the table prefix on all open DB connections/
126
	 *
127
	 * @param string $prefix
128
	 * @return void
129
	 */
130
	public static function changePrefix( $prefix ) {
131
		global $wgDBprefix;
132
		wfGetLBFactory()->forEachLB( function( $lb ) use ( $prefix ) {
0 ignored issues
show
Deprecated Code introduced by
The function wfGetLBFactory() has been deprecated with message: since 1.27, use MediaWikiServices::getDBLoadBalancerFactory() instead.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
133
			$lb->forEachOpenConnection( function ( $db ) use ( $prefix ) {
134
				$db->tablePrefix( $prefix );
135
			} );
136
		} );
137
		$wgDBprefix = $prefix;
138
	}
139
}
140