Files
luos/gulliver/system/class.dbMaintenance.php

609 lines
17 KiB
PHP
Raw Normal View History

2010-12-02 23:34:41 +00:00
<?php
2010-12-02 23:34:41 +00:00
/**
2011-01-24 20:33:07 +00:00
* class.database_base.php
*
* @package gulliver.system
2010-12-02 23:34:41 +00:00
*
* ProcessMaker Open Source Edition
2011-01-24 20:33:07 +00:00
* Copyright (C) 2004 - 2008 Colosa Inc.
2010-12-02 23:34:41 +00:00
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2010-12-02 23:34:41 +00:00
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
2010-12-02 23:34:41 +00:00
*
* For more information, contact Colosa Inc, 2566 Le Jeune Rd.,
* Coral Gables, FL, 33134, USA, or email info@colosa.com.
*
*/
/**
*
*
2010-12-02 23:34:41 +00:00
* Database Maintenance class
*
2011-01-14 11:51:34 +00:00
* author Erik A. Ortiz <erik@colosa.com, aortiz.erik@gmail.com>
* date May 17th, 2010
*
* @package gulliver.system
2010-12-02 23:34:41 +00:00
*/
class DataBaseMaintenance
2010-12-02 23:34:41 +00:00
{
private $host;
private $user;
private $passwd;
2010-12-02 23:34:41 +00:00
private $link;
private $dbName;
public $result;
protected $tmpDir;
protected $outfile;
protected $infile;
2017-08-08 09:53:00 -04:00
protected $isWindows;
/**
* __construct
*
2017-12-04 13:25:35 +00:00
* @param string $host is null
* @param string $user is null
* @param string $passwd is null
*
* @return none
*/
2017-12-04 13:25:35 +00:00
public function __construct($host = null, $user = null, $passwd = null)
{
$this->tmpDir = './';
$this->link = null;
$this->dbName = null;
2017-08-08 09:53:00 -04:00
$this->isWindows = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
2017-12-04 13:25:35 +00:00
if (isset($host) && isset($user) && isset($passwd)) {
$this->host = $host;
$this->user = $user;
$this->passwd = $passwd;
}
2010-12-02 23:34:41 +00:00
}
/**
* setUser
*
* @param string $user
*
* @return none
*/
2017-12-04 13:25:35 +00:00
public function setUser($user)
{
$this->user = $user;
2010-12-02 23:34:41 +00:00
}
/**
* setPasswd
*
* @param string $passwd
*
* @return none
*/
2017-12-04 13:25:35 +00:00
public function setPasswd($passwd)
{
$this->passwd = $passwd;
2010-12-02 23:34:41 +00:00
}
/**
* setHost
*
* @param string $host
*
* @return none
*/
2017-12-04 13:25:35 +00:00
public function setHost($host)
{
$this->host = $host;
2010-12-02 23:34:41 +00:00
}
/**
* setTempDir
*
* @param string $tmpDir
*
* @return none
*/
2017-12-04 13:25:35 +00:00
public function setTempDir($tmpDir)
{
$this->tmpDir = $tmpDir;
2017-12-04 13:25:35 +00:00
if (!file_exists($tmpDir)) {
mkdir($this->tmpDir);
}
2010-12-02 23:34:41 +00:00
}
/**
* getTempDir
*
* @return $this->tmpDir
*/
2017-12-04 13:25:35 +00:00
public function getTempDir()
{
return $this->tmpDir;
2010-12-02 23:34:41 +00:00
}
/**
* status
*
* @return $this->link
*/
2017-12-04 13:25:35 +00:00
public function status()
{
return $$this->link;
2010-12-02 23:34:41 +00:00
}
/**
* connect
*
* @param string $dbname is null
*
* @return none
*/
2017-12-04 13:25:35 +00:00
public function connect($dbname = null)
{
if ($this->link != null) {
2017-12-04 13:25:35 +00:00
mysqli_close($this->link);
$this->link = null;
}
2017-12-04 13:25:35 +00:00
if (isset($dbname)) {
$this->dbName = $dbname;
}
2017-12-04 13:25:35 +00:00
$this->link = mysqli_connect($this->host, $this->user, $this->passwd, $this->dbName);
if (!$this->link) {
throw new Exception("Couldn't connect to host {$this->host} with user {$this->user}");
}
2017-12-04 13:25:35 +00:00
mysqli_query($this->link, "SET NAMES 'utf8';");
mysqli_query($this->link, "SET FOREIGN_KEY_CHECKS=0;");
if ($this->dbName != null) {
2017-12-04 13:25:35 +00:00
$this->selectDataBase($this->dbName);
}
2010-12-02 23:34:41 +00:00
}
/**
* setDbName
*
* @param string $dbname is null
*
* @return none
*/
2017-12-04 13:25:35 +00:00
public function setDbName($dbname)
{
$this->dbName = $dbname;
2010-12-02 23:34:41 +00:00
}
/**
* selectDataBase
*
* @param string $dbname
2017-12-04 13:25:35 +00:00
* @param $dbname
*
2017-12-04 13:25:35 +00:00
* @throws Exception
*/
2017-12-04 13:25:35 +00:00
public function selectDataBase($dbname)
{
2017-12-04 13:25:35 +00:00
$this->setDbName($dbname);
if (!mysqli_select_db($this->link, $this->dbName)) {
throw new Exception("Couldn't select database $dbname");
}
2010-12-02 23:34:41 +00:00
}
/**
* query
*
* @param string $sql
*
* @return $aRows
*/
2017-12-04 13:25:35 +00:00
public function query($sql)
{
2017-12-04 13:25:35 +00:00
$this->result = mysqli_query($this->link, $sql);
if ($this->result) {
2017-12-04 13:25:35 +00:00
$aRows = [];
while ($aRow = mysqli_fetch_assoc($this->result)) {
$aRows[] = $aRow;
}
return $aRows;
} else {
return false;
}
2010-12-02 23:34:41 +00:00
}
/**
* error
*
2017-12-04 13:25:35 +00:00
* @return mysqli_error()
*/
2017-12-04 13:25:35 +00:00
public function error()
{
2017-12-04 13:25:35 +00:00
return mysqli_error($this->link);
2010-12-02 23:34:41 +00:00
}
/**
* getTablesList
*
2017-12-04 13:25:35 +00:00
* @return array
*/
2017-12-04 13:25:35 +00:00
public function getTablesList()
{
2017-12-04 13:25:35 +00:00
$this->result = mysqli_query($this->link, 'SHOW TABLES;');
$rows = [];
while ($row = mysqli_fetch_row($this->result)) {
$rows[] = $row[0];
}
2017-12-04 13:25:35 +00:00
return $rows;
2010-12-02 23:34:41 +00:00
}
/**
* dumpData
*
* @param string $table
*
* @return boolean true or false
*/
2017-12-04 13:25:35 +00:00
public function dumpData($table)
{
$this->outfile = $this->tmpDir . $table . '.dump';
//if the file exists delete it
2017-12-04 13:25:35 +00:00
if (is_file($this->outfile)) {
@unlink($this->outfile);
2010-12-02 23:34:41 +00:00
}
2015-05-07 14:29:48 -04:00
$sql = "SELECT * INTO OUTFILE '{$this->outfile}' FIELDS TERMINATED BY '\t|\t' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\t\t\r\r\n' FROM $table";
// The mysql_escape_string function has been DEPRECATED as of PHP 5.3.0.
// Commented that is not assigned to a variable.
// mysql_escape_string("';");
2017-12-04 13:25:35 +00:00
if (!@mysqli_query($this->link, $sql)) {
$ws = (!empty(config('system.workspace'))) ? config('system.workspace') : 'Undefined Workspace';
Bootstrap::registerMonolog('MysqlCron', 400, mysqli_error($this->link), ['sql' => $sql], $ws, 'processmaker.log');
$varRes = mysqli_error($this->link) . "\n";
G::outRes($varRes);
return false;
2010-12-02 23:34:41 +00:00
}
return true;
2010-12-02 23:34:41 +00:00
}
/**
* restoreData
*
* @param string $backupFile
*
* @return boolean true or false
*/
2017-12-04 13:25:35 +00:00
public function restoreData($backupFile)
{
2017-12-04 13:25:35 +00:00
$tableName = str_replace('.dump', '', basename($backupFile));
2015-05-07 14:29:48 -04:00
$sql = "LOAD DATA INFILE '$backupFile' INTO TABLE $tableName FIELDS TERMINATED BY '\t|\t' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\t\t\r\r\n'";
2017-12-04 13:25:35 +00:00
if (!@mysqli_query($this->link, $sql)) {
$ws = (!empty(config("system.workspace"))) ? config("system.workspace") : "Wokspace Undefined";
Bootstrap::registerMonolog('MysqlCron', 400, mysqli_error($this->link), ['sql' => $sql], $ws, 'processmaker.log');
$varRes = mysqli_error($this->link) . "\n";
G::outRes($varRes);
return false;
}
return true;
2010-12-02 23:34:41 +00:00
}
/**
* restoreAllData
*
* @param string $type default value null
*
* @return none
*/
2017-12-04 13:25:35 +00:00
public function restoreAllData($type = null)
{
$aTables = $this->getTablesList();
foreach ($aTables as $table) {
2017-12-04 13:25:35 +00:00
if (isset($type) && $type == 'sql') {
$this->infile = $this->tmpDir . $table . ".sql";
2017-12-04 13:25:35 +00:00
if (is_file($this->infile)) {
$queries = $this->restoreFromSql($this->infile, true);
if (!isset($queries)) {
$queries = "unknown";
}
2017-12-04 13:25:35 +00:00
printf("%-59s%20s", "Restored table $table", "$queries queries\n");
}
} else {
$this->infile = $this->tmpDir . $table . ".dump";
2017-12-04 13:25:35 +00:00
if (is_file($this->infile)) {
$this->restoreData($this->infile);
printf("%20s %s %s\n", 'Restoring data from ', $this->infile, " in table $table");
}
}
2010-12-02 23:34:41 +00:00
}
}
/**
* createDb
*
* @param string $dbname
* @param string $drop default value false
*
* @return none
*/
2017-12-04 13:25:35 +00:00
public function createDb($dbname, $drop = false)
{
if ($drop) {
$sql = "DROP DATABASE IF EXISTS $dbname;";
2017-12-04 13:25:35 +00:00
if (!mysqli_query($this->link, $sql)) {
throw new Exception(mysqli_error($this->link));
}
}
$sql = "CREATE DATABASE IF NOT EXISTS $dbname DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;";
2017-12-04 13:25:35 +00:00
if (!mysqli_query($this->link, $sql)) {
throw new Exception(mysqli_error($this->link));
}
}
/**
* restoreFromSql2
*
* @param string $sqlfile
*
* @return none
*/
2017-12-04 13:25:35 +00:00
public function restoreFromSql2($sqlfile)
{
2017-12-04 13:25:35 +00:00
ini_set('memory_limit', '512M');
if (!is_file($sqlfile)) {
throw new Exception("the $sqlfile doesn't exist!");
}
2017-12-04 13:25:35 +00:00
$query = file_get_contents($sqlfile);
$mysqli = new mysqli($this->host, $this->user, $this->passwd, $this->dbName);
/* check connection */
if (mysqli_connect_errno()) {
2017-12-04 13:25:35 +00:00
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
/* execute multi query */
2017-12-04 13:25:35 +00:00
if ($mysqli->multi_query($query)) {
do {
/* store first result set */
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_row()) {
}
$result->free();
}
} while ($mysqli->next_result());
}
/* close connection */
$mysqli->close();
2010-12-02 23:34:41 +00:00
}
/**
* backupDataBaseSchema
*
* @param string $outfile
*
* @return none
*/
2017-12-04 13:25:35 +00:00
public function backupDataBase($outfile)
{
2017-08-08 09:53:00 -04:00
$password = escapeshellarg($this->passwd);
2017-12-04 13:25:35 +00:00
//On Windows, escapeshellarg() instead replaces percent signs, exclamation
//marks (delayed variable substitution) and double quotes with spaces and
2017-08-08 09:53:00 -04:00
//adds double quotes around the string.
//See: http://php.net/manual/en/function.escapeshellarg.php
if ($this->isWindows) {
$password = $this->escapeshellargCustom($this->passwd);
}
$aHost = explode(':', $this->host);
$dbHost = $aHost[0];
if (isset($aHost[1])) {
$dbPort = $aHost[1];
$command = 'mysqldump'
2017-08-02 16:06:56 -04:00
. ' --user=' . $this->user
2017-08-08 13:45:12 -04:00
. ' --password=' . $password
2017-08-02 16:06:56 -04:00
. ' --host=' . $dbHost
. ' --port=' . $dbPort
. ' --opt'
. ' --skip-comments'
. ' ' . $this->dbName
. ' > ' . $outfile;
} else {
$command = 'mysqldump'
2017-08-02 16:06:56 -04:00
. ' --host=' . $dbHost
. ' --user=' . $this->user
. ' --opt'
. ' --skip-comments'
2017-08-08 13:45:12 -04:00
. ' --password=' . $password
2017-08-02 16:06:56 -04:00
. ' ' . $this->dbName
. ' > ' . $outfile;
2010-12-02 23:34:41 +00:00
}
shell_exec($command);
}
2017-08-08 09:53:00 -04:00
/**
* string escapeshellargCustom ( string $arg , character $quotes)
2017-12-04 13:25:35 +00:00
*
* escapeshellarg() adds single quotes around a string and quotes/escapes any
* existing single quotes allowing you to pass a string directly to a shell
* function and having it be treated as a single safe argument. This function
* should be used to escape individual arguments to shell functions coming
* from user input. The shell functions include exec(), system() and the
2017-08-08 09:53:00 -04:00
* backtick operator.
2017-12-04 13:25:35 +00:00
*
* On Windows, escapeshellarg() instead replaces percent signs, exclamation
* marks (delayed variable substitution) and double quotes with spaces and
2017-08-08 09:53:00 -04:00
* adds double quotes around the string.
*/
private function escapeshellargCustom($string, $quotes = "")
{
if ($quotes === "") {
$quotes = $this->isWindows ? "\"" : "'";
}
$n = strlen($string);
$special = ["!", "%", "\""];
$substring = "";
$result1 = [];
$result2 = [];
for ($i = 0; $i < $n; $i++) {
if (in_array($string[$i], $special, true)) {
$result2[] = $string[$i];
$result1[] = $substring;
$substring = "";
} else {
$substring = $substring . $string[$i];
}
}
$result1[] = $substring;
//Rebuild the password string
$n = count($result1);
for ($i = 0; $i < $n; $i++) {
$result1[$i] = trim(escapeshellarg($result1[$i]), $quotes);
if (isset($result2[$i])) {
$result1[$i] = $result1[$i] . $result2[$i];
}
}
//add simple quotes, see escapeshellarg function
$newString = $quotes . implode("", $result1) . $quotes;
return $newString;
}
/**
* restoreFromSql
*
* @param string $sqlfile
*
* @return boolean false or true
*/
2017-12-04 13:25:35 +00:00
public function restoreFromSql($sqlfile, $type = 'file')
{
2017-12-04 13:25:35 +00:00
ini_set('memory_limit', '64M');
if ($type == 'file' && !is_file($sqlfile)) {
throw new Exception("the $sqlfile doesn't exist!");
2010-12-02 23:34:41 +00:00
}
2017-12-04 13:25:35 +00:00
$metaFile = str_replace('.sql', '.meta', $sqlfile);
$queries = 0;
2017-12-04 13:25:35 +00:00
if (is_file($metaFile)) {
echo "Using $metaFile as metadata.\n";
2017-12-04 13:25:35 +00:00
$fp = fopen($sqlfile, 'rb');
$fpmd = fopen($metaFile, 'r');
while ($offset = fgets($fpmd, 1024)) {
$buffer = intval($offset); //reading the size of $oData
$query = fread($fp, $buffer); //reading string $oData
$queries += 1;
2017-12-04 13:25:35 +00:00
if (!mysqli_query($this->link, $query)) {
$varRes = mysqli_error($this->link) . "\n";
G::outRes($varRes);
2016-08-04 14:56:58 -04:00
$varRes = "==>" . $query . "<==\n";
2017-12-04 13:25:35 +00:00
G::outRes($varRes);
}
}
2010-12-02 23:34:41 +00:00
} else {
$queries = null;
try {
2017-12-04 13:25:35 +00:00
$mysqli = new mysqli($this->host, $this->user, $this->passwd, $this->dbName);
/* check connection */
if (mysqli_connect_errno()) {
2017-12-04 13:25:35 +00:00
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
2017-12-04 13:25:35 +00:00
if ($type === 'file') {
$query = file_get_contents($sqlfile);
} elseif ($type === 'string') {
$query = $sqlfile;
} else {
return false;
}
2017-12-04 13:25:35 +00:00
if (trim($query) == "") {
return false;
}
2017-12-04 13:25:35 +00:00
/* execute multi query */
if ($mysqli->multi_query($query)) {
do {
/* store first result set */
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_row()) {
//printf("%s\n", $row[0]);
}
$result->free();
}
/* print divider */
if ($mysqli->more_results()) {
//printf("-----------------\n");
}
} while ($mysqli->next_result());
} else {
2017-12-04 13:25:35 +00:00
throw new Exception(mysqli_error($mysqli));
}
2017-12-04 13:25:35 +00:00
/* close connection */
$mysqli->close();
} catch (Exception $e) {
echo $query;
2016-08-04 14:56:58 -04:00
$token = strtotime("now");
PMException::registerErrorLog($e, $token);
2017-12-04 13:25:35 +00:00
G::outRes(G::LoadTranslation("ID_EXCEPTION_LOG_INTERFAZ", array($token)));
2010-12-02 23:34:41 +00:00
}
}
return $queries;
}
/**
* getSchemaFromTable
*
* @param string $tablename
*
* @return string $tableSchema
*/
2017-12-04 13:25:35 +00:00
public function getSchemaFromTable($tablename)
{
2015-05-07 14:29:48 -04:00
//$tableSchema = "/* Structure for table `$tablename` */\n";
//$tableSchema .= "DROP TABLE IF EXISTS `$tablename`;\n\n";
$tableSchema = "";
2015-05-07 14:29:48 -04:00
$sql = "show create table `$tablename`; ";
2017-12-04 13:25:35 +00:00
$result = mysqli_query($this->link, $sql);
if ($result) {
2017-12-04 13:25:35 +00:00
if ($row = mysqli_fetch_assoc($result)) {
$tableSchema .= $row['Create Table'] . ";\n\n";
2010-12-02 23:34:41 +00:00
}
2017-12-04 13:25:35 +00:00
mysqli_free_result($result);
} else {
2017-12-04 13:25:35 +00:00
G::outRes(mysqli_error($this->link));
}
return $tableSchema;
}
/**
* removeCommentsIntoString
*
* @param string $str
*
* @return string $str
*/
2017-12-04 13:25:35 +00:00
public function removeCommentsIntoString($str)
{
2017-12-04 13:25:35 +00:00
$str = preg_replace('/\/\*[\w\W]*\*\//', '', $str);
$str = preg_replace("/--[\w\W]*\\n/", '', $str);
$str = preg_replace("/\/\/[\w\W]*\\n/", '', $str);
$str = preg_replace("/\#[\w\W]*\\n/", '', $str);
return $str;
2010-12-02 23:34:41 +00:00
}
2017-12-04 13:25:35 +00:00
}