diff --git a/.devilbox/www/config.php b/.devilbox/www/config.php
index af763501..964dd730 100644
--- a/.devilbox/www/config.php
+++ b/.devilbox/www/config.php
@@ -36,9 +36,12 @@ $HTTPD_HOST_ADDR = gethostbyname($HTTPD_HOST_NAME);
$PHP_HOST_NAME = 'php';
$PHP_HOST_ADDR = gethostbyname($PHP_HOST_NAME);
-$MYSQL_HOST_NAME = 'db';
+$MYSQL_HOST_NAME = 'mysql';
$MYSQL_HOST_ADDR = gethostbyname($MYSQL_HOST_NAME);
+$POSTGRES_HOST_NAME = 'postgres';
+$POSTGRES_HOST_ADDR = gethostbyname($POSTGRES_HOST_NAME);
+
//
// Load files
@@ -46,19 +49,20 @@ $MYSQL_HOST_ADDR = gethostbyname($MYSQL_HOST_NAME);
require $LIB_DIR . DIRECTORY_SEPARATOR . 'Logger.php';
require $LIB_DIR . DIRECTORY_SEPARATOR . 'Docker.php';
require $LIB_DIR . DIRECTORY_SEPARATOR . 'Mysql.php';
+require $LIB_DIR . DIRECTORY_SEPARATOR . 'Postgres.php';
//
// Instantiate Basics
//
-$Logger = \devilbox\Logger::getInstance();
-$Docker = \devilbox\Docker::getInstance();
-$MySQL = \devilbox\Mysql::getInstance('root', $Docker->getEnv('MYSQL_ROOT_PASSWORD'), $MYSQL_HOST_ADDR);
-
+$Logger = \devilbox\Logger::getInstance();
+$Docker = \devilbox\Docker::getInstance();
+$MySQL = \devilbox\Mysql::getInstance('root', $Docker->getEnv('MYSQL_ROOT_PASSWORD'), $MYSQL_HOST_ADDR);
+$Postgres = \devilbox\Postgres::getInstance($Docker->getEnv('POSTGRES_USER'), $Docker->getEnv('POSTGRES_PASSWORD'), $POSTGRES_HOST_ADDR);
// VirtualHost DNS check
// Temporarily disable due to:
// https://github.com/cytopia/devilbox/issues/8
-$ENABLE_VHOST_DNS_CHECK = false;
+$ENABLE_VHOST_DNS_CHECK = true;
diff --git a/.devilbox/www/include/footer.php b/.devilbox/www/include/footer.php
index c6285556..9d151e59 100644
--- a/.devilbox/www/include/footer.php
+++ b/.devilbox/www/include/footer.php
@@ -9,6 +9,7 @@
+
diff --git a/.devilbox/www/include/lib/Docker.php b/.devilbox/www/include/lib/Docker.php
index cf2e989d..4e5526eb 100644
--- a/.devilbox/www/include/lib/Docker.php
+++ b/.devilbox/www/include/lib/Docker.php
@@ -108,7 +108,7 @@ class Docker
{
if (!isset($this->_env[$variable])) {
$Logger = \devilbox\Logger::getInstance();
- $logger->error('Docker environment variable not found: '.$variable);
+ $Logger->error('Docker environment variable not found: '.$variable);
return null;
}
return $this->_env[$variable];
@@ -296,7 +296,7 @@ class Docker
$version = $this->MySQL_config('version');
if (!$name && !$version) {
- return 'Unknown Version';
+ return 'Unknown MySQL version';
}
return $name . ' ' . $version;
}
@@ -342,6 +342,74 @@ class Docker
}
+ /*********************************************************************************
+ *
+ * Postgres Docker functions
+ *
+ *********************************************************************************/
+
+ /**
+ * Get Postgres Version.
+ *
+ * @return string Postgres version string.
+ */
+ public function Postgres_version()
+ {
+ $callback = function ($row, &$data) {
+ $data = $row['version'];
+ };
+
+ $version = \devilbox\Postgres::getInstance()->select('SELECT version();', $callback);
+
+ // Extract shorthand
+ preg_match('/\w+[[:space:]]*[.0-9]+/i', $version, $matches);
+ if (isset($matches[0])) {
+ return $matches[0];
+ }
+
+ // Unknown
+ if (!$version) {
+ return 'Unknown Postgres version';
+ }
+ return $version;
+ }
+
+
+ /**
+ * Read out PostgreSQL Server configuration by variable
+ *
+ * @param string|null $key Config key name
+ * @return string|mixed[]
+ */
+ public function Postgres_config($key = null)
+ {
+ // Get all configs as array
+ if ($key === null) {
+ $callback = function ($row, &$data) {
+ $key = $row['name'];
+ $val = $row['setting'];
+ $data[$key] = $val;
+ };
+
+ $sql = 'SELECT name, setting FROM pg_settings;';
+ $configs = \devilbox\Postgres::getInstance()->select($sql, $callback);
+
+ return $configs ? $configs : array();
+
+ } else { // Get single config
+
+ $callback = function ($row, &$data) use ($key) {
+ $data = isset($row['setting']) ? $row['setting'] : false;
+ };
+
+ $sql = "SELECT name, setting FROM pg_settings WHERE name = '".$key."';";
+ $val = \devilbox\Postgres::getInstance()->select($sql, $callback);
+
+ return is_array($val) ? '' : $val;
+ }
+ }
+
+
/*********************************************************************************
*
diff --git a/.devilbox/www/include/lib/Postgres.php b/.devilbox/www/include/lib/Postgres.php
new file mode 100644
index 00000000..dbd4972f
--- /dev/null
+++ b/.devilbox/www/include/lib/Postgres.php
@@ -0,0 +1,348 @@
+getConnectError())) {
+ \devilbox\Logger::getInstance()->error('Instance has errors:' . "\r\n" . var_export(static::$instance, true) . "\r\n");
+ //return null;
+ }
+ return static::$instance;
+ }
+
+ /**
+ * Connect to database
+ *
+ * @param string $err Reference to error message
+ * @param string $user Postgres username
+ * @param string $pass Postgres password
+ * @param string $host Postgres hostname
+ * @return boolean
+ */
+ public static function testConnection(&$err, $user, $pass, $host)
+ {
+ $err = false;
+
+ // Silence errors and try to connect
+ error_reporting(0);
+ $link = pg_pconnect('host='.$host.' user='.$user.' password='.$pass);
+ error_reporting(-1);
+
+ if (!$link || pg_connection_status($link) !== PGSQL_CONNECTION_OK) {
+ $err = 'Failed to connect: ' .pg_last_error($link);
+ return false;
+ }
+ pg_close($link);
+ return true;
+ }
+
+
+
+ /*********************************************************************************
+ *
+ * Private Variables
+ *
+ *********************************************************************************/
+
+ /**
+ * Postgres Resource
+ * @var resource|null
+ */
+ private $_link = null;
+
+ /**
+ * Connection error string
+ * @var string
+ */
+ private $_connect_error = '';
+
+ /**
+ * Connection error code
+ * @var integer
+ */
+ private $_connect_errno = 0;
+
+ /**
+ * Error string
+ * @var string
+ */
+ private $_error = '';
+
+
+ /**
+ * Error code
+ * @var integer
+ */
+ private $_errno = 0;
+
+
+
+ /*********************************************************************************
+ *
+ * Construct/Destructor
+ *
+ *********************************************************************************/
+
+ /**
+ * Use singleton getInstance() instead.
+ *
+ * @param string $user Username
+ * @param string $pass Password
+ * @param string $host Host
+ * @param string $database Database name
+ */
+ public function __construct($user, $pass, $host, $database = null)
+ {
+ // Silence errors and try to connect
+ error_reporting(0);
+ if ($database !== null) {
+ $link = pg_pconnect('host='.$host.' dbname='.$database.' user='.$user.' password='.$pass);
+ } else {
+ $link = pg_pconnect('host='.$host.' user='.$user.' password='.$pass);
+ }
+ error_reporting(-1);
+
+ if (!$link || pg_connection_status($link) !== PGSQL_CONNECTION_OK) {
+ $this->_connect_error = 'Failed to connect to '.$user.'@'.$host;
+ $this->_connect_errno = 1;
+ \devilbox\Logger::getInstance()->error($this->_connect_error);
+ } else {
+ $this->_link = $link;
+ }
+ }
+
+
+
+
+
+ /**
+ * Destructor
+ */
+ public function __destruct()
+ {
+ if ($this->_link) {
+ pg_close($this->_link);
+ }
+ }
+
+ /*********************************************************************************
+ *
+ * PostgreSQL Select functions
+ *
+ *********************************************************************************/
+
+ /**
+ * Query Database
+ *
+ * @param string $query Postgres Query
+ * @param function $callback Callback function
+ * @return mixed[]
+ */
+ public function select($query, $callback = null)
+ {
+ if (!$this->_link) {
+ \devilbox\Logger::getInstance()->error('Postgres error, link is no resource in select()');
+ return false;
+ }
+
+ if (!($result = pg_query($this->_link, $query))) {
+ $this->_error = 'PostgreSQL - error on result: '.pg_result_error($result)."\n" . 'query:'."\n" . $query;
+ $this->_errno = 1;
+ \devilbox\Logger::getInstance()->error($this->_error);
+ return false;
+ }
+
+ $data = array();
+
+ if ($callback) {
+ while ($row = pg_fetch_assoc($result)) {
+ $callback($row, $data);
+ }
+ } else {
+ while ($row = pg_fetch_assoc($result)) {
+ $data[] = $row;
+ }
+ }
+ pg_free_result($result);
+
+ return $data;
+ }
+
+ /**
+ * Get all PostgreSQL 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.datname AS database,
+ S.datcollate AS collation,
+ pg_encoding_to_char(S.encoding) AS charset
+ FROM
+ pg_database AS S
+ WHERE datistemplate = false;';
+
+ $databases = $this->select($sql, $callback);
+ $databases = $databases ? $databases : array();
+
+ // Get schemas for each database
+ foreach ($databases as $name => &$database) {
+ $PSQL = new Postgres('postgres', \devilbox\Docker::getInstance()->getEnv('POSTGRES_PASSWORD'), $GLOBALS['POSTGRES_HOST_ADDR'], $name);
+
+ $sql = "SELECT n.nspname AS schemas FROM pg_catalog.pg_namespace AS n WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema';";
+ $callback = function ($row, &$data) {
+ $data[$row['schemas']] = array();
+ };
+ $schemas = $PSQL->select($sql, $callback);
+ $databases[$name]['schemas'] = $schemas;
+ }
+
+ return $databases;
+ }
+
+
+ /**
+ * Get Schema size in Megabytes.
+ *
+ * @param string $database Database name.
+ * @param string $schema Schema name.
+ * @return integer
+ */
+ public function getSchemaSize($database, $schema)
+ {
+ $PSQL = new Postgres('postgres', \devilbox\Docker::getInstance()->getEnv('POSTGRES_PASSWORD'), $GLOBALS['POSTGRES_HOST_ADDR'], $database);
+ $callback = function ($row, &$data) {
+ $data = $row['size'];
+
+ };
+ $sql = "SELECT
+ ROUND(sum(table_size) / 1048576, 2) AS size
+ FROM (
+ SELECT pg_catalog.pg_namespace.nspname AS schema_name,
+ pg_relation_size(pg_catalog.pg_class.oid) AS table_size
+ FROM pg_catalog.pg_class
+ JOIN pg_catalog.pg_namespace ON relnamespace = pg_catalog.pg_namespace.oid
+ WHERE pg_catalog.pg_namespace.nspname = '".$schema."'
+ ) t
+ GROUP BY schema_name;";
+
+ $size = $PSQL->select($sql, $callback);
+ return $size ? $size : 0;
+ }
+
+ /**
+ * Get Number of Tables per Schema
+ *
+ * @param string $database Database name.
+ * @param string $schema Schema name.
+ * @return integer
+ */
+ public function getTableCount($database, $schema)
+ {
+ $PSQL = new Postgres('postgres', \devilbox\Docker::getInstance()->getEnv('POSTGRES_PASSWORD'), $GLOBALS['POSTGRES_HOST_ADDR'], $database);
+ $callback = function ($row, &$data) {
+ $data = $row['count'];
+ };
+
+ $sql = "SELECT
+ COUNT(*) AS count
+ FROM
+ information_schema.tables
+ WHERE
+ table_schema = '".$schema."'
+ AND
+ table_type = 'BASE TABLE';
+ ";
+
+ $count = $PSQL->select($sql, $callback);
+ return $count ? $count : 0;
+ }
+
+
+
+
+
+
+ /*********************************************************************************
+ *
+ * MySQL Error functions
+ *
+ *********************************************************************************/
+
+ /**
+ * Return connection error message.
+ *
+ * @return string Error message
+ */
+ public function getConnectError()
+ {
+ return $this->_connect_error;
+ }
+
+ /**
+ * Return connection errno code.
+ *
+ * @return integer Error code
+ */
+ public function getConnectErrno()
+ {
+ return $this->_connect_errno;
+ }
+
+ /**
+ * Return error message.
+ *
+ * @return string Error message
+ */
+ public function getError()
+ {
+ return $this->_error;
+ }
+
+ /**
+ * Return errno code.
+ *
+ * @return integer Error code
+ */
+ public function getErrno()
+ {
+ return $this->_errno;
+ }
+}
diff --git a/.devilbox/www/include/navigation.php b/.devilbox/www/include/navbar.php
similarity index 51%
rename from .devilbox/www/include/navigation.php
rename to .devilbox/www/include/navbar.php
index 5ad7cfb5..a3315edb 100644
--- a/.devilbox/www/include/navigation.php
+++ b/.devilbox/www/include/navbar.php
@@ -2,7 +2,7 @@
-
\ No newline at end of file
+