2016-11-06 12:36:07 +00:00
|
|
|
<?php
|
|
|
|
namespace devilbox;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @requires devilbox::Logger
|
|
|
|
*/
|
2017-05-15 06:56:17 +00:00
|
|
|
class Mysql extends BaseClass implements BaseInterface
|
2016-11-06 12:36:07 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
/*********************************************************************************
|
|
|
|
*
|
2017-05-15 06:56:17 +00:00
|
|
|
* Variables
|
2016-11-06 12:36:07 +00:00
|
|
|
*
|
|
|
|
*********************************************************************************/
|
|
|
|
|
|
|
|
/**
|
2017-05-15 06:56:17 +00:00
|
|
|
* MySQL connection link
|
|
|
|
* @var null
|
2016-11-06 12:36:07 +00:00
|
|
|
*/
|
2017-05-15 06:56:17 +00:00
|
|
|
private $_link = null;
|
2016-11-06 12:36:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************************
|
|
|
|
*
|
2017-05-15 06:56:17 +00:00
|
|
|
* Constructor Overwrite
|
2016-11-06 12:36:07 +00:00
|
|
|
*
|
|
|
|
*********************************************************************************/
|
|
|
|
|
2017-05-15 06:56:17 +00:00
|
|
|
public function __construct($hostname, $data = array())
|
|
|
|
{
|
|
|
|
parent::__construct($hostname, $data);
|
2016-11-06 12:36:07 +00:00
|
|
|
|
2017-05-15 06:56:17 +00:00
|
|
|
$user = $data['user'];
|
|
|
|
$pass = $data['pass'];
|
2016-11-06 12:36:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Silence errors and try to connect
|
|
|
|
error_reporting(0);
|
2018-04-08 10:18:44 +00:00
|
|
|
$link = @mysqli_connect($hostname, $user, $pass);
|
2016-11-06 12:36:07 +00:00
|
|
|
error_reporting(-1);
|
|
|
|
|
|
|
|
if (mysqli_connect_errno()) {
|
2017-05-06 09:13:33 +00:00
|
|
|
$this->setConnectError('Failed to connect: ' .mysqli_connect_error());
|
|
|
|
$this->setConnectErrno(mysqli_connect_errno());
|
|
|
|
//loadClass('Logger')->error($this->_connect_error);
|
2016-11-06 12:36:07 +00:00
|
|
|
} else {
|
|
|
|
$this->_link = $link;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function __destruct()
|
|
|
|
{
|
|
|
|
if ($this->_link) {
|
|
|
|
mysqli_close($this->_link);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-15 06:56:17 +00:00
|
|
|
|
2016-11-06 12:36:07 +00:00
|
|
|
/*********************************************************************************
|
|
|
|
*
|
2017-05-15 06:56:17 +00:00
|
|
|
* Select Functions
|
2016-11-06 12:36:07 +00:00
|
|
|
*
|
|
|
|
*********************************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Query Database
|
|
|
|
*
|
|
|
|
* @param string $query MySQL Query
|
|
|
|
* @param function $callback Callback function
|
|
|
|
* @return mixed[]
|
|
|
|
*/
|
|
|
|
public function select($query, $callback = null)
|
|
|
|
{
|
|
|
|
if (!$this->_link) {
|
2017-05-06 09:13:33 +00:00
|
|
|
loadClass('Logger')->error('MySQL error, link is no resource in select(): '.$query);
|
2016-11-06 12:36:07 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!($result = mysqli_query($this->_link, $query))) {
|
2017-05-06 09:13:33 +00:00
|
|
|
$this->setError(mysqli_error($this->_link));
|
|
|
|
$this->setErrno(mysqli_errno($this->_link));
|
|
|
|
loadClass('Logger')->error($this->getError());
|
2016-11-06 12:36:07 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$data = array();
|
|
|
|
|
|
|
|
if ($callback) {
|
|
|
|
while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
|
|
|
|
$callback($row, $data);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
|
|
|
|
$data[] = $row;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mysqli_free_result($result);
|
|
|
|
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get all MySQL Databases.
|
|
|
|
* @return mixed[] Array of databases
|
|
|
|
*/
|
|
|
|
public function getDatabases()
|
|
|
|
{
|
|
|
|
$callback = function ($row, &$data) {
|
|
|
|
$data[$row['database']] = array(
|
|
|
|
'charset' => $row['charset'],
|
|
|
|
'collation' => $row['collation']
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
$sql = "SELECT
|
|
|
|
S.SCHEMA_NAME AS 'database',
|
|
|
|
S.DEFAULT_COLLATION_NAME AS 'collation',
|
|
|
|
S.default_character_set_name AS 'charset'
|
|
|
|
FROM
|
2017-05-06 09:13:33 +00:00
|
|
|
information_schema.SCHEMATA AS S;";
|
2016-11-06 12:36:07 +00:00
|
|
|
|
|
|
|
$databases = $this->select($sql, $callback);
|
|
|
|
|
|
|
|
return $databases ? $databases : array();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get Database size in Megabytes.
|
|
|
|
*
|
|
|
|
* @param string $database Database name.
|
|
|
|
* @return integer
|
|
|
|
*/
|
|
|
|
public function getDBSize($database)
|
|
|
|
{
|
|
|
|
$callback = function ($row, &$data) {
|
|
|
|
$data = $row['size'];
|
|
|
|
};
|
|
|
|
|
|
|
|
$sql = "SELECT
|
|
|
|
ROUND( SUM((T.data_length+T.index_length)/1048576), 2 ) AS 'size'
|
|
|
|
FROM
|
|
|
|
information_schema.TABLES AS T
|
|
|
|
WHERE
|
|
|
|
T.TABLE_SCHEMA = '".$database."';";
|
|
|
|
|
|
|
|
$size = $this->select($sql, $callback);
|
|
|
|
return $size ? $size : 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get Number of Tables per Database
|
|
|
|
*
|
|
|
|
* @param string $database Database name.
|
|
|
|
* @return integer
|
|
|
|
*/
|
|
|
|
public function getTableCount($database)
|
|
|
|
{
|
|
|
|
$callback = function ($row, &$data) {
|
|
|
|
$data = $row['count'];
|
|
|
|
};
|
|
|
|
|
|
|
|
$sql = "SELECT
|
|
|
|
COUNT(*) AS 'count'
|
|
|
|
FROM
|
|
|
|
information_schema.TABLES AS T
|
|
|
|
WHERE
|
|
|
|
T.TABLE_SCHEMA = '".$database."';";
|
|
|
|
|
|
|
|
$count = $this->select($sql, $callback);
|
|
|
|
return $count ? $count : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-06 09:13:33 +00:00
|
|
|
/**
|
|
|
|
* Read out MySQL Server configuration by variable
|
|
|
|
*
|
|
|
|
* @param string|null $key Config key name
|
|
|
|
* @return string|mixed[]
|
|
|
|
*/
|
|
|
|
public function getConfig($key = null)
|
|
|
|
{
|
|
|
|
// Get all configs as array
|
|
|
|
if ($key === null) {
|
|
|
|
$callback = function ($row, &$data) {
|
|
|
|
$key = $row['Variable_name'];
|
|
|
|
$val = $row['Value'];
|
|
|
|
$data[$key] = $val;
|
|
|
|
};
|
|
|
|
|
2017-05-08 07:22:10 +00:00
|
|
|
$config = $this->select('SHOW VARIABLES;', $callback);
|
|
|
|
if (!$config) {
|
|
|
|
$config = array();
|
|
|
|
}
|
|
|
|
return $config;
|
2017-05-06 09:13:33 +00:00
|
|
|
|
|
|
|
} else { // Get single config
|
|
|
|
|
|
|
|
$key = str_replace('-', '_', $key);
|
|
|
|
|
|
|
|
$callback = function ($row, &$data) use ($key) {
|
|
|
|
$data = isset($row['Value']) ? $row['Value'] : false;
|
|
|
|
};
|
2016-11-06 12:36:07 +00:00
|
|
|
|
2017-05-06 09:13:33 +00:00
|
|
|
$sql = 'SHOW VARIABLES WHERE Variable_Name = "'.$key.'";';
|
|
|
|
$val = $this->select($sql, $callback);
|
|
|
|
|
|
|
|
if (is_array($val) && $val) {
|
2018-05-12 14:01:31 +00:00
|
|
|
$array_values = array_values($val);
|
|
|
|
return $array_values[0];
|
2017-05-06 09:13:33 +00:00
|
|
|
} else {
|
|
|
|
return $val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-06 12:36:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************************
|
|
|
|
*
|
2017-05-06 09:13:33 +00:00
|
|
|
* Interface required functions
|
2016-11-06 12:36:07 +00:00
|
|
|
*
|
|
|
|
*********************************************************************************/
|
|
|
|
|
2017-05-15 06:56:17 +00:00
|
|
|
private $_can_connect = array();
|
|
|
|
private $_can_connect_err = array();
|
|
|
|
|
|
|
|
private $_name = null;
|
|
|
|
private $_version = null;
|
|
|
|
|
|
|
|
public function canConnect(&$err, $hostname, $data = array())
|
|
|
|
{
|
|
|
|
$err = false;
|
|
|
|
|
|
|
|
// Return if already cached
|
|
|
|
if (isset($this->_can_connect[$hostname])) {
|
|
|
|
// Assume error for unset error message
|
|
|
|
$err = isset($this->_can_connect_err[$hostname]) ? $this->_can_connect_err[$hostname] : true;
|
|
|
|
return $this->_can_connect[$hostname];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Silence errors and try to connect
|
|
|
|
error_reporting(0);
|
|
|
|
$link = mysqli_connect($hostname, $data['user'], $data['pass']);
|
|
|
|
error_reporting(-1);
|
|
|
|
|
|
|
|
if (mysqli_connect_errno()) {
|
|
|
|
$err = 'Failed to connect: ' .mysqli_connect_error();
|
|
|
|
$this->_can_connect[$hostname] = false;
|
|
|
|
} else {
|
|
|
|
$this->_can_connect[$hostname] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($link) {
|
|
|
|
mysqli_close($link);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->_can_connect_err[$hostname] = $err;
|
|
|
|
return $this->_can_connect[$hostname];
|
|
|
|
}
|
|
|
|
|
2017-05-06 09:13:33 +00:00
|
|
|
public function getName($default = 'MySQL')
|
2016-11-06 12:36:07 +00:00
|
|
|
{
|
2017-05-15 06:56:17 +00:00
|
|
|
// Return if already cached
|
|
|
|
if ($this->_name !== null) {
|
|
|
|
return $this->_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return default if not available
|
|
|
|
if (!$this->isAvailable()) {
|
2017-05-06 09:13:33 +00:00
|
|
|
return $default;
|
|
|
|
}
|
2016-11-06 12:36:07 +00:00
|
|
|
|
2017-05-15 06:56:17 +00:00
|
|
|
$name = loadClass('Helper')->egrep('/[a-zA-Z0-9]+/', $this->getConfig('version_comment'));
|
2016-11-06 12:36:07 +00:00
|
|
|
|
2017-05-06 09:13:33 +00:00
|
|
|
if (!$name) {
|
|
|
|
loadClass('Logger')->error('Could not get MySQL Name');
|
2017-05-15 06:56:17 +00:00
|
|
|
$this->_name = $default;
|
|
|
|
} else {
|
|
|
|
$this->_name = $name;
|
2017-05-06 09:13:33 +00:00
|
|
|
}
|
2016-11-06 12:36:07 +00:00
|
|
|
|
2017-05-15 06:56:17 +00:00
|
|
|
return $this->_name;
|
|
|
|
}
|
2017-05-06 09:13:33 +00:00
|
|
|
|
|
|
|
public function getVersion()
|
2016-11-06 12:36:07 +00:00
|
|
|
{
|
2017-05-15 06:56:17 +00:00
|
|
|
// Return if already cached
|
|
|
|
if ($this->_version !== null) {
|
|
|
|
return $this->_version;
|
2017-05-06 09:13:33 +00:00
|
|
|
}
|
|
|
|
|
2017-05-15 06:56:17 +00:00
|
|
|
// Return empty if not available
|
|
|
|
if (!$this->isAvailable()) {
|
|
|
|
$this->_version = '';
|
|
|
|
return $this->_version;
|
|
|
|
}
|
|
|
|
|
|
|
|
$version = loadClass('Helper')->egrep('/[.0-9]+/', $this->getConfig('version'));
|
2017-05-06 09:13:33 +00:00
|
|
|
|
|
|
|
if (!$version) {
|
2017-05-15 06:56:17 +00:00
|
|
|
loadClass('Logger')->error('Could not get MySQL Version');
|
|
|
|
$this->_version = '';
|
|
|
|
} else {
|
|
|
|
$this->_version = $version;
|
2017-05-06 09:13:33 +00:00
|
|
|
}
|
2017-05-15 06:56:17 +00:00
|
|
|
|
|
|
|
return $this->_version;
|
2016-11-06 12:36:07 +00:00
|
|
|
}
|
|
|
|
}
|