GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#936)
by Tom
02:28
created

Mysqldump_Database_Backup_Engine::backup()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 47
Code Lines 20

Duplication

Lines 7
Ratio 14.89 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 7
loc 47
rs 6.7273
cc 7
eloc 20
nc 7
nop 0
1
<?php
2
3
namespace HM\BackUpWordPress;
4
5
/**
6
 * Perform a database backup using the mysqldump cli command
7
 */
8
class Mysqldump_Database_Backup_Engine extends Database_Backup_Engine {
9
10
	/**
11
	 * The path to the mysqldump executable
12
	 *
13
	 * @var string
14
	 */
15
	private $mysqldump_executable_path = '';
16
17
	public function __construct() {
18
		parent::__construct();
19
	}
20
21
	/**
22
	 * Calculate the path to the mysqldump executable.
23
	 *
24
	 * The executable path can be overridden using either the `HMBKP_MYSQLDUMP_PATH`
25
	 * Constant or the `hmbkp_mysqldump_executable_path` filter.
26
	 *
27
	 * If neither of those are set then we fallback to checking a number of
28
	 * common locations.
29
	 *
30
	 * @return string|false The path to the executable or false.
31
	 */
32
	public function get_mysqldump_executable_path() {
33
34
		// Return now if it's set in a Constant
35
		if ( defined( 'HMBKP_MYSQLDUMP_PATH' ) && HMBKP_MYSQLDUMP_PATH ) {
36
			$this->mysqldump_executable_path = HMBKP_MYSQLDUMP_PATH;
37
		}
38
39
		/**
40
		 * Allow the executable path to be set via a filter
41
		 *
42
		 * @param string The path to the mysqldump executable
43
		 */
44
		$this->mysqldump_executable_path = apply_filters( 'hmbkp_mysqldump_executable_path', '' );
45
46
		if ( ! $this->mysqldump_executable_path ) {
47
48
			// List of possible mysqldump locations
49
			$paths = array(
50
				'mysqldump',
51
				'/usr/local/bin/mysqldump',
52
				'/usr/local/mysql/bin/mysqldump',
53
				'/usr/mysql/bin/mysqldump',
54
				'/usr/bin/mysqldump',
55
				'/opt/local/lib/mysql6/bin/mysqldump',
56
				'/opt/local/lib/mysql5/bin/mysqldump',
57
				'/opt/local/lib/mysql4/bin/mysqldump',
58
				'/xampp/mysql/bin/mysqldump',
59
				'/Program Files/xampp/mysql/bin/mysqldump',
60
				'/Program Files/MySQL/MySQL Server 6.0/bin/mysqldump',
61
				'/Program Files/MySQL/MySQL Server 5.7/bin/mysqldump',
62
				'/Program Files/MySQL/MySQL Server 5.6/bin/mysqldump',
63
				'/Program Files/MySQL/MySQL Server 5.5/bin/mysqldump',
64
				'/Program Files/MySQL/MySQL Server 5.4/bin/mysqldump',
65
				'/Program Files/MySQL/MySQL Server 5.1/bin/mysqldump',
66
				'/Program Files/MySQL/MySQL Server 5.0/bin/mysqldump',
67
				'/Program Files/MySQL/MySQL Server 4.1/bin/mysqldump',
68
				'/opt/local/bin/mysqldump'
69
			);
70
71
			$this->mysqldump_executable_path = Backup_Utilities::get_executable_path( $paths );
0 ignored issues
show
Documentation Bug introduced by
It seems like \HM\BackUpWordPress\Back...executable_path($paths) can also be of type false. However, the property $mysqldump_executable_path is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
72
73
		}
74
75
		return $this->mysqldump_executable_path;
76
77
	}
78
79
	/**
80
	 * Check whether it's possible to connect to the database with the
81
	 * credentials we have.
82
	 *
83
	 * @return bool Whether the database connection was successful.
84
	 */
85
	public function check_user_can_connect_to_database_via_cli() {
86
87
		if ( ! $this->get_mysqldump_executable_path() ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->get_mysqldump_executable_path() of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
88
			return false;
89
		}
90
91
		$args = $this->get_mysql_connection_args();
92
93
		$args[] = escapeshellarg( $this->get_name() );
94
95
		// Quit immediately as we're only interesting in testing the connection
96
		$args[] = '--execute="quit"';
97
98
		// Pipe STDERR to STDOUT
99
		$args[] = ' 2>&1';
100
101
		$output = $return_status = '';
102
		$args   = implode( ' ', $args );
103
		exec( 'mysql ' . $args, $output, $return_status );
104
105
		$output = $this->ignore_mysql_password_warning( $output );
106
107
		// If there were errors connecting then track them
108 View Code Duplication
		if ( $output ) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
109
			if ( $return_status === 0 ) {
110
				$this->warning( __CLASS__, implode( ', ', $output ) );
111
			} else {
112
				$this->error( __CLASS__, implode( ', ', $output ) );
113
				return false;
114
			}
115
		}
116
117
		return true;
118
119
	}
120
121
	/**
122
	 * Perform the database backup.
123
	 *
124
	 * @return bool Whether the backup completed successfully or not.
125
	 */
126
	public function backup() {
127
128
		if ( ! $this->check_user_can_connect_to_database_via_cli() || ! $this->get_mysqldump_executable_path() ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->get_mysqldump_executable_path() of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
129
			return false;
130
		}
131
132
		$output = $return_status = '';
133
134
		// Grab the database connections args
135
		$args = $this->get_mysql_connection_args();
136
137
		// We don't want to create a new DB
138
		$args[] = '--no-create-db';
139
140
		// Allow lock-tables to be overridden
141
		if ( defined( 'HMBKP_MYSQLDUMP_SINGLE_TRANSACTION' ) && HMBKP_MYSQLDUMP_SINGLE_TRANSACTION  ) {
142
			$args[] = '--single-transaction';
143
		}
144
145
		// Make sure binary data is exported properly
146
		$args[] = '--hex-blob';
147
148
		// The file we're saving too
149
		$args[] = '-r ' . escapeshellarg( $this->get_backup_filepath() );
150
151
		// The database we're dumping
152
		$args[] = escapeshellarg( $this->get_name() );
153
154
		// Pipe STDERR to STDOUT
155
		$args[] = '2>&1';
156
157
		exec( escapeshellcmd( $this->get_mysqldump_executable_path() ) . ' ' . implode( ' ', $args ), $output, $return_status );
158
159
		$output = $this->ignore_mysql_password_warning( $output );
160
161
		// Track any errors
162 View Code Duplication
		if ( $output ) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
163
			if ( $return_status === 0 ) {
164
				$this->warning( __CLASS__, implode( ', ', $output ) );
165
			} else {
166
				$this->error( __CLASS__, implode( ', ', $output ) );
167
			}
168
		}
169
170
		return $this->verify_backup();
171
172
	}
173
174
	/**
175
	 * Get the connection args for the mysqldump command
176
	 *
177
	 * @return array The array of connection args
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
178
	 */
179
	public function get_mysql_connection_args() {
180
181
		$args = array();
182
183
		$args[] = '-u ' . escapeshellarg( $this->get_user() );
184
185
		if ( $this->get_password() ) {
186
			$args[] = '-p' . escapeshellarg( $this->get_password() );
187
		}
188
189
		$args[] = '-h ' . escapeshellarg( $this->get_host() );
190
191
		if ( $this->get_port() ) {
192
			$args[] = '-P ' . escapeshellarg( $this->get_port() );
193
		}
194
195
		if ( $this->get_socket() ) {
196
			$args[] = '--protocol=socket -S ' . escapeshellarg( $this->get_socket() );
197
		}
198
199
		return $args;
200
201
	}
202
203
	private function ignore_mysql_password_warning( $output ) {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
204
205
		$key = array_search( 'Warning: Using a password on the command line interface can be insecure.', $output );
206
207
		if ( $key !== false ) {
208
			unset( $output[ $key ] );
209
		}
210
211
		return $output;
212
213
	}
214
215
}
216