Completed
Pull Request — master (#52)
by Mateusz
01:57
created

SSPak::extract()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 41
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 41
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 16
nc 6
nop 1
1
<?php
2
3
use SilverStripe\SsPak\DataExtractor\DatabaseConnector;
4
use SilverStripe\SsPak\DataExtractor\CsvTableWriter;
5
use SilverStripe\SsPak\DataExtractor\CsvTableReader;
6
7
/**
8
 * SSPak handler
9
 */
10
class SSPak {
11
	protected $executor;
12
13
	/**
14
	 * Create a new handler
15
	 * @param Executor $executor The Executor object to handle command execution
16
	 */
17
	function __construct($executor) {
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...
18
		$this->executor = $executor;
19
	}
20
21
	function getActions() {
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...
22
		return array(
23
			"help" => array(
24
				"description" => "Show this help message.",
25
				"method" => "help",
26
			),
27
			"save" => array(
28
				"description" => "Save an .sspak file from a SilverStripe site.",
29
				"unnamedArgs" => array("webroot", "sspak file"),
30
				"namedArgs" => array("identity"),
31
				"method" => "save",
32
			),
33
			"load" => array(
34
				"description" => "Load an .sspak file into a SilverStripe site. Does not backup - be careful!",
35
				"unnamedArgs" => array("sspak file", "[webroot]"),
36
				"namedArgs" => array("identity"),
37
				"namedFlags" => array("drop-db"),
38
				"method" => "load",
39
			),
40
			"saveexisting" => array(
41
				"description" => "Create an .sspak file from database SQL dump and/or assets. Does not require a SilverStripe site.",
42
				"unnamedArgs" => array("sspak file"),
43
				"namedArgs" => array("db", "assets"),
44
				"method" => "saveexisting"
45
			),
46
			"extract" => array(
47
				"description" => "Extract an .sspak file into the current working directory. Does not require a SilverStripe site.",
48
				"unnamedArgs" => array("sspak file", "destination path"),
49
				"method" => "extract"
50
			),
51
			"listtables" => array(
52
				"description" => "List tables in the database",
53
				"unnamedArgs" => array("webroot"),
54
				"method" => "listTables"
55
			),
56
57
			"savecsv" => array(
58
				"description" => "Save tables in the database to a collection of CSV files",
59
				"unnamedArgs" => array("webroot", "output-path"),
60
				"method" => "saveCsv"
61
			),
62
63
			"loadcsv" => array(
64
				"description" => "Load tables from collection of CSV files to a webroot",
65
				"unnamedArgs" => array("input-path", "webroot"),
66
				"method" => "loadCsv"
67
			),
68
			/*
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
69
70
			"install" => array(
71
				"description" => "Install a .sspak file into a new environment.",
72
				"unnamedArgs" => array("sspak file", "new webroot"),
73
				"method" => "install",
74
			),
75
			"bundle" => array(
76
				"description" => "Bundle a .sspak file into a self-extracting executable .sspak.phar installer.",
77
				"unnamedArgs" => array("sspak file", "executable"),
78
				"method" => "bundle",
79
			),
80
			"transfer" => array(
81
				"description" => "Transfer db & assets from one site to another (not implemented yet).",
82
				"unnamedArgs" => array("src webroot", "dest webroot"),
83
				"method" => "transfer",
84
			),
85
			*/
86
		);
87
	}
88
89
	function help($args) {
0 ignored issues
show
Unused Code introduced by
The parameter $args 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...
90
		echo "SSPak: manage SilverStripe .sspak archives.\n\nUsage:\n";
91
		foreach($this->getActions() as $action => $info) {
92
			echo "sspak $action";
93
			if(!empty($info['unnamedArgs'])) {
94
				foreach($info['unnamedArgs'] as $arg) echo " ($arg)";
0 ignored issues
show
Bug introduced by
The expression $info['unnamedArgs'] of type string|array<integer,string,{"0":"string"}> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
95
			}
96
			if(!empty($info['namedFlags'])) {
97
				foreach($info['namedFlags'] as $arg) echo " (--$arg)";
0 ignored issues
show
Bug introduced by
The expression $info['namedFlags'] of type string|array<integer,string,{"0":"string"}> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
98
			}
99
			if(!empty($info['namedArgs'])) {
100
				foreach($info['namedArgs'] as $arg) echo " --$arg=\"$arg value\"";
0 ignored issues
show
Bug introduced by
The expression $info['namedArgs'] of type string|array<integer,string,{"0":"string"}> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
101
			}
102
			echo "\n  {$info['description']}\n\n";
103
		}
104
	}
105
106
	/**
107
	 * Save an existing database and/or assets into an .sspak.phar file.
108
	 * Does the same as {@link save()} but doesn't require an existing site.
109
	 */
110
	function saveexisting($args) {
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...
111
		$executor = $this->executor;
112
113
		$args->requireUnnamed(array('sspak file'));
114
		$unnamedArgs = $args->getUnnamedArgs();
115
		$namedArgs = $args->getNamedArgs();
116
117
		$sspak = new SSPakFile($unnamedArgs[0], $executor);
118
119
		// Look up which parts of the sspak are going to be saved
120
		$pakParts = $args->pakParts();
121
122
		$filesystem = new FilesystemEntity(null, $executor);
123
124
		if($pakParts['db']) {
125
			$dbPath = escapeshellarg($namedArgs['db']);
126
			$process = $filesystem->createProcess("cat $dbPath | gzip -c");
127
			$sspak->writeFileFromProcess('database.sql.gz', $process);
128
		}
129
130
		if($pakParts['assets']) {
131
			$assetsParentArg = escapeshellarg(dirname($namedArgs['assets']));
132
			$assetsBaseArg = escapeshellarg(basename($namedArgs['assets']));
133
			$process = $filesystem->createProcess("cd $assetsParentArg && tar cfh - $assetsBaseArg | gzip -c");
134
			$sspak->writeFileFromProcess('assets.tar.gz', $process);
135
		}
136
	}
137
138
	/**
139
	 * Extracts an existing database and/or assets from a sspak into the given directory,
140
	 * defaulting the current working directory if the destination is not given.
141
	 */
142
	function extract($args) {
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...
143
		$executor = $this->executor;
144
145
		$args->requireUnnamed(array('source sspak file'));
146
		$unnamedArgs = $args->getUnnamedArgs();
147
		$file = $unnamedArgs[0];
148
		$dest = !empty($unnamedArgs[1]) ? $unnamedArgs[1] : getcwd();
149
150
		// Phar and PharData use "ustar" format for tar archives (http://php.net/manual/pl/phar.fileformat.tar.php).
151
		// Ustar does not support files larger than 8 GB.
152
		// If the sspak has been created through tar and gz directly, it will probably be in POSIX, PAX or GNU formats,
153
		// which do support >8 GB files. Such archive cannot be accessed by Phar/PharData, and needs to be handled
154
		// manually.
155
		// There is no cross-platform way of checking the assets.tar.gz size without unpacking, so we assume the size
156
		// of database is negligible which let's us approximate the size of assets.
157
		if (filesize($file) > 8*1024*1024*1024) {
158
			$msg = <<<EOM
159
160
ERROR: SSPak is unable to extract archives over 8 GB.
161
162
Packed asset or database sizes over 8 GB are not supported due to PHP Phar library limitations.
163
You can still access your data directly by using the tar utility:
164
165
	tar xzf "%s"
166
167
This tool is sorry for the inconvenience and stands aside in disgrace.
168
See http://silverstripe.github.io/sspak/, "Manual access" for more information.
169
170
EOM;
171
			printf($msg, $file);
172
			die(1);
173
		}
174
175
		$sspak = new SSPakFile($file, $executor);
176
177
		// Validation
178
		if(!$sspak->exists()) throw new Exception("File '$file' doesn't exist.");
179
180
		$phar = $sspak->getPhar();
181
		$phar->extractTo($dest);
182
	}
183
184
	function listTables($args) {
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...
185
		$args->requireUnnamed(array('webroot'));
186
		$unnamedArgs = $args->getUnnamedArgs();
187
		$webroot = $unnamedArgs[0];
188
189
		$db = new DatabaseConnector($webroot);
190
191
		print_r($db->getTables());
192
	}
193
194
	function saveCsv($args) {
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...
195
		$args->requireUnnamed(array('webroot', 'path'));
196
		$unnamedArgs = $args->getUnnamedArgs();
197
		$webroot = $unnamedArgs[0];
198
		$destPath = $unnamedArgs[1];
199
200
		if (!file_exists($destPath)) {
201
			mkdir($destPath) || die("Can't create $destPath");
202
		}
203
		if (!is_dir($destPath)) {
204
			die("$destPath isn't a directory");
205
		}
206
207
		$db = new DatabaseConnector($webroot);
208
209
		foreach($db->getTables() as $table) {
210
			$filename = $destPath . '/' . $table . '.csv';
211
			echo $filename . "...\n";
212
			touch($filename);
213
			$writer = new CsvTableWriter($filename);
214
			$db->saveTable($table, $writer);
215
		}
216
		echo "Done!";
217
	}
218
219
	function loadCsv($args) {
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...
220
		$args->requireUnnamed(array('input-path', 'webroot'));
221
		$unnamedArgs = $args->getUnnamedArgs();
222
223
		$srcPath = $unnamedArgs[0];
224
		$webroot = $unnamedArgs[1];
225
226
		if (!is_dir($srcPath)) {
227
			die("$srcPath isn't a directory");
228
		}
229
230
		$db = new DatabaseConnector($webroot);
231
232
		foreach($db->getTables() as $table) {
233
			$filename = $srcPath . '/' . $table . '.csv';
234
			if(file_exists($filename)) {
235
				echo $filename . "...\n";
236
				$reader = new CsvTableReader($filename);
237
				$db->loadTable($table, $reader);
238
			} else {
239
				echo "$filename doesn't exist; skipping.\n";
240
			}
241
		}
242
		echo "Done!";
243
	}
244
	/**
245
	 * Save a .sspak.phar file
246
	 */
247
	function save($args) {
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...
248
		$executor = $this->executor;
249
250
		$args->requireUnnamed(array('source webroot', 'dest sspak file'));
251
252
		$unnamedArgs = $args->getUnnamedArgs();
253
		$namedArgs = $args->getNamedArgs();
254
255
		$webroot = new Webroot($unnamedArgs[0], $executor);
256
		$file = $unnamedArgs[1];
257
		if(file_exists($file)) throw new Exception( "File '$file' already exists.");
258
259
		$sspak = new SSPakFile($file, $executor);
260
261
		if(!empty($namedArgs['identity'])) {
262
			// SSH private key
263
			$webroot->setSSHItentityFile($namedArgs['identity']);
264
		}
265
		if(!empty($namedArgs['from-sudo'])) $webroot->setSudo($namedArgs['from-sudo']);
266
		else if(!empty($namedArgs['sudo'])) $webroot->setSudo($namedArgs['sudo']);
267
268
		// Look up which parts of the sspak are going to be saved
269
		$pakParts = $args->pakParts();
270
271
		// Get the environment details
272
		$details = $webroot->sniff();
273
274
		// Create a build folder for the sspak file
275
		$buildFolder = "/tmp/sspak-" . rand(100000,999999);
276
		$webroot->exec(array('mkdir', $buildFolder));
0 ignored issues
show
Documentation introduced by
array('mkdir', $buildFolder) is of type array<integer,string,{"0":"string","1":"string"}>, 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...
277
278
		$dbFile = "$buildFolder/database.sql.gz";
279
		$assetsFile = "$buildFolder/assets.tar.gz";
280
		$gitRemoteFile = "$buildFolder/git-remote";
281
282
		// Files to include in the .sspak.phar file
283
		$fileList = array();
0 ignored issues
show
Unused Code introduced by
$fileList is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
284
285
		// Save DB
286
		if($pakParts['db']) {
287
			// Check the database type
288
			$dbFunction = 'getdb_'.$details['db_type'];
289 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...
290
				throw new Exception("Can't process database type '" . $details['db_type'] . "'");
291
			}
292
			$this->$dbFunction($webroot, $details, $sspak, basename($dbFile));
293
		}
294
295
		// Save Assets
296
		if($pakParts['assets']) {
297
			$this->getassets($webroot, $details['assets_path'], $sspak, basename($assetsFile));
298
		}
299
300
		// Save git-remote
301
		if($pakParts['git-remote']) {
302
			$this->getgitremote($webroot, $sspak, basename($gitRemoteFile));
303
		}
304
305
		// Remove the build folder
306
		$webroot->unlink($buildFolder);
307
	}
308
309
	function getdb_MySQLPDODatabase($webroot, $conf, $sspak, $filename) {
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...
310
		return $this->getdb_MySQLDatabase($webroot, $conf, $sspak, $filename);
311
	}
312
313
	function getdb_MySQLDatabase($webroot, $conf, $sspak, $filename) {
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...
314
		$usernameArg = escapeshellarg("--user=".$conf['db_username']);
315
		$passwordArg = escapeshellarg("--password=".$conf['db_password']);
316
		$databaseArg = escapeshellarg($conf['db_database']);
317
318
		$hostArg = '';
319
		$portArg = '';
320 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...
321
			if (strpos($conf['db_server'], ':')!==false) {
322
				// Handle "server:port" format.
323
				$server = explode(':', $conf['db_server'], 2);
324
				$hostArg = escapeshellarg("--host=".$server[0]);
325
				$portArg = escapeshellarg("--port=".$server[1]);
326
			} else {
327
				$hostArg = escapeshellarg("--host=".$conf['db_server']);
328
			}
329
		}
330
331
		$filenameArg = escapeshellarg($filename);
0 ignored issues
show
Unused Code introduced by
$filenameArg is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
332
333
		$process = $webroot->createProcess("mysqldump --skip-opt --add-drop-table --extended-insert --create-options --quick  --set-charset --default-character-set=utf8 $usernameArg $passwordArg $hostArg $portArg $databaseArg | gzip -c");
334
		$sspak->writeFileFromProcess($filename, $process);
335
		return true;
336
	}
337
338
	function getdb_PostgreSQLDatabase($webroot, $conf, $sspak, $filename) {
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...
339
		$usernameArg = escapeshellarg("--username=".$conf['db_username']);
340
		$passwordArg = "PGPASSWORD=".escapeshellarg($conf['db_password']);
341
		$databaseArg = escapeshellarg($conf['db_database']);
342
		$hostArg = escapeshellarg("--host=".$conf['db_server']);
343
		$filenameArg = escapeshellarg($filename);
0 ignored issues
show
Unused Code introduced by
$filenameArg is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
344
345
		$process = $webroot->createProcess("$passwordArg pg_dump --clean --no-owner --no-tablespaces $usernameArg $hostArg $databaseArg | gzip -c");
346
		$sspak->writeFileFromProcess($filename, $process);
347
		return true;
348
	}
349
350
	function getassets($webroot, $assetsPath, $sspak, $filename) {
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...
351
		$assetsParentArg = escapeshellarg(dirname($assetsPath));
352
		$assetsBaseArg = escapeshellarg(basename($assetsPath));
353
354
		$process = $webroot->createProcess("cd $assetsParentArg && tar cfh - $assetsBaseArg | gzip -c");
355
		$sspak->writeFileFromProcess($filename, $process);
356
	}
357
358
	function getgitremote($webroot, $sspak, $gitRemoteFile) {
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...
359
		// Only do anything if we're copying from a git checkout
360
		$gitRepo = $webroot->getPath() .'/.git';
361
		if($webroot->exists($gitRepo)) {
362
			// Identify current branch
363
			$output = $webroot->exec(array('git', '--git-dir='.$gitRepo, 'branch'));
364
			if(preg_match("/\* ([^ \n]*)/", $output['output'], $matches) && strpos("(no branch)", $matches[1])===false) {
365
				// If there is a current branch, use that branch's remove
366
				$currentBranch = trim($matches[1]);
367
				$output = $webroot->exec(array('git', '--git-dir='.$gitRepo, 'config','--get',"branch.$currentBranch.remote"));
368
				$remoteName = trim($output['output']);
369
				if(!$remoteName) $remoteName = 'origin';
370
371
			// Default to origin
372
			} else {
373
				$currentBranch = null;
374
				$remoteName = 'origin';
375
			}
376
377
			// Determine the URL of that remote
378
			$output = $webroot->exec(array('git', '--git-dir='.$gitRepo, 'config','--get',"remote.$remoteName.url"));
379
			$remoteURL = trim($output['output']);
380
381
			// Determine the current SHA
382
			$output = $webroot->exec(array('git', '--git-dir='.$gitRepo, 'log','-1','--format=%H'));
383
			$sha = trim($output['output']);
384
385
			$content = "remote = $remoteURL\nbranch = $currentBranch\nsha = $sha\n";
386
387
			$sspak->writeFile($gitRemoteFile, $content);
388
389
			return true;
390
		}
391
		return false;
392
	}
393
394
	/**
395
	 * Load an .sspak into an environment.
396
	 * Does not backup - be careful! */
397
	function load($args) {
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...
398
		$executor = $this->executor;
399
400
		$args->requireUnnamed(array('source sspak file'));
401
402
		// Set-up
403
		$file = $args->unnamed(0);
404
		$sspak = new SSPakFile($file, $executor);
405
		$webroot = new Webroot(($args->unnamed(1) ?: '.'), $executor);
406
		$webroot->setSudo($args->sudo('to'));
407
		$pakParts = $args->pakParts();
408
409
		$namedArgs = $args->getNamedArgs();
410
		if(!empty($namedArgs['identity'])) {
411
			// SSH private key
412
			$webroot->setSSHItentityFile($namedArgs['identity']);
413
		}
414
415
		// Validation
416
		if(!$sspak->exists()) throw new Exception( "File '$file' doesn't exist.");
417
418
		// Push database, if necessary
419
		$namedArgs = $args->getNamedArgs();
420
		if($pakParts['db'] && $sspak->contains('database.sql.gz')) {
421
			$webroot->putdb($sspak, isset($namedArgs['drop-db']));
422
		}
423
424
		// Push assets, if neccessary
425
		if($pakParts['assets'] && $sspak->contains('assets.tar.gz')) {
426
			$webroot->putassets($sspak);
427
		}
428
	}
429
430
	/**
431
	 * Install an .sspak into a new environment.
432
	 */
433
	function install($args) {
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...
434
		$executor = $this->executor;
435
436
		$args->requireUnnamed(array('source sspak file', 'dest new webroot'));
437
438
		// Set-up
439
		$file = $args->unnamed(0);
440
		$webrootDir = $args->unnamed(1);
441
		$sspak = new SSPakFile($file, $executor);
442
		$webroot = new Webroot($webrootDir, $executor);
443
		$webroot->setSudo($args->sudo('to'));
444
		$pakParts = $args->pakParts();
445
446
		// Validation
447
		if($webroot->exists($webroot->getPath())) throw new Exception( "Webroot '$webrootDir' already exists.");
448
		if(!$sspak->exists()) throw new Exception( "File '$file' doesn't exist.");
449
450
		// Create new dir
451
		$webroot->exec(array('mkdir', $webroot->getPath()));
0 ignored issues
show
Documentation introduced by
array('mkdir', $webroot->getPath()) is of type array<integer,?,{"0":"string","1":"?"}>, 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...
452
453
		if($sspak->contains('git-remote')) {
454
			$details = $sspak->gitRemoteDetails();
455
			$webroot->putgit($details);
456
		}
457
458
		// TODO: composer install needed.
459
460
		// Push database, if necessary
461
		$namedArgs = $args->getNamedArgs();
462
		if($pakParts['db'] && $sspak->contains('database.sql.gz')) {
463
			$webroot->putdb($sspak, isset($namedArgs['drop-db']));
464
		}
465
466
		// Push assets, if neccessary
467
		if($pakParts['assets'] && $sspak->contains('assets.tar.gz')) {
468
			$webroot->putassets($sspak);
469
		}
470
	}
471
472
	/**
473
	 * Bundle a .sspak into a self-extracting executable installer.
474
	 */
475
	function bundle($args) {
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...
476
		// TODO: throws require_once errors, fix before re-enabling.
477
478
		$executor = $this->executor;
479
480
		$args->requireUnnamed(array('source sspak file', 'dest executable file'));
481
482
		// Set-up
483
		$sourceFile = $args->unnamed(0);
484
		$destFile = $args->unnamed(1);
485
486
		$sspakScript = file_get_contents($_SERVER['argv'][0]);
487
		// Broken up to not get detected by our sed command
488
		$sspakScript .= "\n__halt_compiler();\n"."//"." TAR START?>\n";
489
490
		// Mark as self-extracting
491
		$sspakScript = str_replace('$isSelfExtracting = false;', '$isSelfExtracting = true;', $sspakScript);
492
493
		// Load the sniffer file
494
		$snifferFile = dirname(__FILE__) . '/sspak-sniffer.php';
495
		$sspakScript = str_replace("\$snifferFileContent = '';\n",
496
			"\$snifferFileContent = '"
497
			. str_replace(array("\\","'"),array("\\\\", "\\'"), file_get_contents($snifferFile)) . "';\n", $sspakScript);
498
499
		file_put_contents($destFile, $sspakScript);
500
		chmod($destFile, 0775);
501
502
		$executor->execLocal(array('cat', $sourceFile), array(
0 ignored issues
show
Documentation introduced by
array('cat', $sourceFile) is of type array<integer,?,{"0":"string","1":"?"}>, 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...
503
			'outputFile' => $destFile,
504
			'outputFileAppend' => true
505
		));
506
	}
507
508
	/**
509
	 * Transfer between environments without creating an sspak file
510
	 */
511
	function transfer($args) {
0 ignored issues
show
Unused Code introduced by
The parameter $args 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...
512
		echo "Not implemented yet.\n";
513
	}
514
}
515