Completed
Push — master ( e7ab71...04fb30 )
by Damian
8s
created

Webroot::putdb_MySQLPDODatabase()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 3
1
<?php
2
3
/**
4
 * Represents one webroot, local or remote, that sspak interacts with
5
 */
6
class Webroot extends FilesystemEntity {
7
	protected $sudo = null;
8
	protected $details = null;
9
10
	function setSudo($sudo) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
11
		$this->sudo = $sudo;
12
	}
13
14
	/**
15
	 * Return a map of the db & asset config details.
16
	 * Calls sniff once and then caches
17
	 */
18
	function details() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
19
		if(!$this->details) $this->details = $this->sniff();
20
		return $this->details;
21
	}
22
23
	/**
24
	 * Return a map of the db & asset config details, acquired with ssnap-sniffer
25
	 */
26
	function sniff() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
27
		global $snifferFileContent;
28
29
		if(!$snifferFileContent) $snifferFileContent = file_get_contents(PACKAGE_ROOT . 'src/sspak-sniffer.php');
30
31
		$remoteSniffer = '/tmp/sspak-sniffer-' . rand(100000,999999) . '.php';
32
		$this->uploadContent($snifferFileContent, $remoteSniffer);
33
34
		$result = $this->execSudo(array('/usr/bin/env', 'php', $remoteSniffer, $this->path));
0 ignored issues
show
Documentation introduced by
array('/usr/bin/env', 'p...teSniffer, $this->path) is of type array<integer,?,{"0":"st...,"2":"string","3":"?"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
35
		$this->unlink($remoteSniffer);
36
37
		$parsed = @unserialize($result['output']);
38
		if(!$parsed) throw new Exception("Could not parse sspak-sniffer content:\n{$result['output']}\n");
39
		return $parsed;
40
	}
41
42
	/**
43
	 * Execute a command on the relevant server, using the given sudo option
44
	 * @param  string $command Shell command, either a fully escaped string or an array
45
	 */
46
	function execSudo($command) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
47
		if($this->sudo) {
48
			if(is_array($command)) $command = $this->executor->commandArrayToString($command);
49
			// Try running sudo without asking for a password
50
			try {
51
				return $this->exec("sudo -n -u " . escapeshellarg($this->sudo) . " " . $command);
52
53
			// Otherwise capture SUDO password ourselves and pass it in through STDIN
54
			} catch(Exception $e) {
55
				echo "[sspak sudo] Enter your password: ";
56
				$stdin = fopen( 'php://stdin', 'r');
57
				$password = fgets($stdin);
58
59
				return $this->exec("sudo -S -p '' -u " . escapeshellarg($this->sudo) . " " . $command, array('inputContent' => $password));
60
			}
61
		
62
		} else {
63
			return $this->exec($command);
64
		}
65
	}
66
67
	/**
68
	 * Put the database from the given sspak file into this webroot.
69
	 * @param array $details The previously sniffed details of this webroot
0 ignored issues
show
Bug introduced by
There is no parameter named $details. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
70
	 * @param bool $dropdb Drop the DB prior to install
71
	 * @param string $sspakFile Filename
0 ignored issues
show
Bug introduced by
There is no parameter named $sspakFile. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
72
	 */
73
	function putdb($sspak, $dropdb) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
74
		$details = $this->details();
75
76
		// Check the database type
77
		$dbFunction = 'putdb_'.$details['db_type'];
78 View Code Duplication
		if(!method_exists($this,$dbFunction)) {
0 ignored issues
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...
79
			throw new Exception("Can't process database type '" . $details['db_type'] . "'");
80
		}
81
82
		// Extract DB direct from sspak file
83
		return $this->$dbFunction($details, $sspak, $dropdb);
84
	}
85
86
	function putdb_MySQLPDODatabase($conf, $sspak, $dropdb) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
87
		return $this->putdb_MySQLDatabase($conf, $sspak, $dropdb);
88
	}
89
90
	function putdb_MySQLDatabase($conf, $sspak, $dropdb) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
91
		$usernameArg = escapeshellarg("--user=".$conf['db_username']);
92
		$passwordArg = escapeshellarg("--password=".$conf['db_password']);
93
		$databaseArg = escapeshellarg($conf['db_database']);
94
95
		$hostArg = '';
96
		$portArg = '';
97 View Code Duplication
		if (!empty($conf['db_server']) && $conf['db_server'] != 'localhost') {
0 ignored issues
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...
98
			if (strpos($conf['db_server'], ':')!==false) {
99
				// Handle "server:port" format.
100
				$server = explode(':', $conf['db_server'], 2);
101
				$hostArg = escapeshellarg("--host=".$server[0]);
102
				$portArg = escapeshellarg("--port=".$server[1]);
103
			} else {
104
				$hostArg = escapeshellarg("--host=".$conf['db_server']);
105
			}
106
		}
107
		$dbCommand = "create database if not exists `" . addslashes($conf['db_database']) . "`";
108
		if($dropdb) {
109
			$dbCommand = "drop database if exists `" . addslashes($conf['db_database']) . "`; " . $dbCommand;
110
		}
111
112
		$this->exec("echo '$dbCommand' | mysql $usernameArg $passwordArg $hostArg $portArg");
113
114
		$stream = $sspak->readStreamForFile('database.sql.gz');
115
		$this->exec("gunzip -c | sed '/^CREATE DATABASE/d;/^USE/d' | mysql --default-character-set=utf8 $usernameArg $passwordArg $hostArg $portArg $databaseArg", array('inputStream' => $stream));
116
		fclose($stream);
117
		return true;
118
	}
119
120
	function putdb_PostgreSQLDatabase($conf, $sspak, $dropdb) {
0 ignored issues
show
Unused Code introduced by
The parameter $dropdb is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
121
		// TODO: Support dropdb for postgresql
122
		$usernameArg = escapeshellarg("--username=".$conf['db_username']);
123
		$passwordArg = "PGPASSWORD=".escapeshellarg($conf['db_password']);
124
		$databaseArg = escapeshellarg($conf['db_database']);
125
		$hostArg = escapeshellarg("--host=".$conf['db_server']);
126
127
		// Create database if needed
128
		$result = $this->exec("echo \"select count(*) from pg_catalog.pg_database where datname = $databaseArg\" | $passwordArg psql $usernameArg $hostArg $databaseArg -qt");
129
		if(trim($result['output']) == '0') {
130
			$this->exec("$passwordArg createdb $usernameArg $hostArg $databaseArg");
131
		}
132
133
		$stream = $sspak->readStreamForFile('database.sql.gz');
134
		return $this->exec("gunzip -c | $passwordArg psql $usernameArg $hostArg $databaseArg", array('inputStream' => $stream));
135
		fclose($stream);
0 ignored issues
show
Unused Code introduced by
fclose($stream); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
136
	}
137
138
	function putassets($sspak) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
139
		$details = $this->details();
140
		$assetsPath = $details['assets_path'];
141
142
		$assetsParentArg = escapeshellarg(dirname($assetsPath));
143
		$assetsBaseArg = escapeshellarg(basename($assetsPath));
144
		$assetsBaseOldArg = escapeshellarg(basename($assetsPath).'.old');
145
146
		// Move existing assets to assets.old
147
		$this->exec("if [ -d $assetsBaseArg ]; then mv $assetsBaseArg $assetsBaseOldArg; fi");
148
149
		// Extract assets
150
		$stream = $sspak->readStreamForFile('assets.tar.gz');
151
		$this->exec("tar xzf - -C $assetsParentArg", array('inputStream' => $stream));
152
		fclose($stream);
153
154
		// Remove assets.old
155
		$this->exec("if [ -d $assetsBaseOldArg ]; then rm -rf $assetsBaseOldArg; fi");
156
	}
157
158
	/**
159
	 * Load a git remote into this webroot.
160
	 * It expects that this remote is an empty directory.
161
	 * 
162
	 * @param array $details Map of git details
163
	 */
164
	function putgit($details) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
165
		$this->exec(array('git', 'clone', $details['remote'], $this->path));
0 ignored issues
show
Documentation introduced by
array('git', 'clone', $d...'remote'], $this->path) is of type array<integer,?,{"0":"st...ring","2":"?","3":"?"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
166
		$this->exec("cd $this->path && git checkout " . escapeshellarg($details['branch']));
167
		return true;
168
	}
169
}
170