diff --git a/application/config/config.development.php b/application/config/config.development.php index e667dde..71ce7ef 100644 --- a/application/config/config.development.php +++ b/application/config/config.development.php @@ -72,8 +72,8 @@ return array( /** * Configuration for: Google reCAPTCHA v2 */ - 'RECAPTCHA_SITE_KEY' => 'recaptcha-site-key', - 'RECAPTCHA_SECRET_KEY' => 'recaptcha-secret-key', + 'RECAPTCHA_SITE_KEY' => '6Lfl-EcsAAAAAG9svnagihb5y6HCNK2cd5W9jQm-', + 'RECAPTCHA_SECRET_KEY' => '6Lfl-EcsAAAAADusuMYTprgTZ42BVIWPsF_jVtk6', /** * Configuration for: Cookies * 1209600 seconds = 2 weeks diff --git a/application/controller/DatabaseController.php b/application/controller/DatabaseController.php index 5c76c30..bb078c4 100644 --- a/application/controller/DatabaseController.php +++ b/application/controller/DatabaseController.php @@ -14,8 +14,9 @@ class DatabaseController extends Controller { parent::__construct(); - // Only logged-in users can access the database manager + // Only admin users can access the database manager Auth::checkAuthentication(); + Auth::checkAdminAuthentication(); } /** @@ -23,7 +24,7 @@ class DatabaseController extends Controller */ public function index() { - $this->View->render('database/index', array( + $this->View->renderDbManager('database/index', array( 'databases' => DatabaseModel::getAllDatabases(), 'current_db' => Config::get('DB_NAME') )); @@ -39,7 +40,7 @@ class DatabaseController extends Controller $database_name = Config::get('DB_NAME'); } - $this->View->render('database/show', array( + $this->View->renderDbManager('database/show', array( 'tables' => DatabaseModel::getTablesInDatabase($database_name), 'database_name' => $database_name, 'table_info' => DatabaseModel::getTableDetails($database_name) @@ -133,12 +134,24 @@ class DatabaseController extends Controller ]); } + /** + * Export database as raw SQL text + * @param string $database_name + */ + public function export($database_name) + { + header('Content-Type: text/plain; charset=utf-8'); + header('Content-Disposition: inline; filename="' . $database_name . '.sql"'); + + echo DatabaseModel::exportDatabase($database_name); + } + /** * Check if the request is an AJAX request */ private function isAjaxRequest() { - return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && + return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'; } } \ No newline at end of file diff --git a/application/controller/DbUserController.php b/application/controller/DbUserController.php index ccbc07f..896fb38 100644 --- a/application/controller/DbUserController.php +++ b/application/controller/DbUserController.php @@ -24,7 +24,7 @@ class DbUserController extends Controller */ public function index() { - $this->View->render('dbuser/index', array( + $this->View->renderDbManager('dbuser/index', array( 'users' => DbUserModel::getAllUsers(), 'current_user' => Config::get('DB_USER') )); @@ -39,11 +39,15 @@ class DbUserController extends Controller $username = Request::post('username'); $password = Request::post('password'); $host = Request::post('host'); - + $privileges = Request::post('privileges'); + if ($this->isAjaxRequest()) { header('Content-Type: application/json'); - + if (DbUserModel::createUser($username, $password, $host)) { + if (!empty($privileges)) { + DbUserModel::updateUserPrivileges($username, $host, $privileges); + } echo json_encode([ 'success' => true, 'message' => 'User created successfully', @@ -57,8 +61,11 @@ class DbUserController extends Controller } return; } - + if (DbUserModel::createUser($username, $password, $host)) { + if (!empty($privileges)) { + DbUserModel::updateUserPrivileges($username, $host, $privileges); + } Redirect::to('dbuser'); } else { Redirect::to('dbuser'); @@ -66,8 +73,7 @@ class DbUserController extends Controller return; } - // Show create user form - $this->View->render('dbuser/create'); + $this->View->renderDbManager('dbuser/create'); } /** @@ -127,7 +133,7 @@ class DbUserController extends Controller } // Show edit user form - $this->View->render('dbuser/edit', array( + $this->View->renderDbManager('dbuser/edit', array( 'user' => DbUserModel::getUserDetails($username, $host), 'privileges' => DbUserModel::getUserPrivileges($username, $host), 'databases' => DatabaseModel::getAllDatabases() @@ -184,7 +190,7 @@ class DbUserController extends Controller */ public function privileges($username, $host) { - $this->View->render('dbuser/privileges', array( + $this->View->renderDbManager('dbuser/privileges', array( 'user' => DbUserModel::getUserDetails($username, $host), 'privileges' => DbUserModel::getUserPrivileges($username, $host) )); diff --git a/application/controller/SqlController.php b/application/controller/SqlController.php index 4e60191..5bb0acb 100644 --- a/application/controller/SqlController.php +++ b/application/controller/SqlController.php @@ -14,8 +14,9 @@ class SqlController extends Controller { parent::__construct(); - // Only logged-in users can access the SQL console + // Only admin users can access the SQL console Auth::checkAuthentication(); + Auth::checkAdminAuthentication(); } /** @@ -28,7 +29,7 @@ class SqlController extends Controller $database_name = Config::get('DB_NAME'); } - $this->View->render('sql/index', array( + $this->View->renderDbManager('sql/index', array( 'database_name' => $database_name, 'databases' => DatabaseModel::getAllDatabases(), 'history' => SqlModel::getQueryHistory(Session::get('user_id')) diff --git a/application/controller/TableController.php b/application/controller/TableController.php index def585f..0aac645 100644 --- a/application/controller/TableController.php +++ b/application/controller/TableController.php @@ -14,8 +14,9 @@ class TableController extends Controller { parent::__construct(); - // Only logged-in users can access the table manager + // Only admin users can access the table manager Auth::checkAuthentication(); + Auth::checkAdminAuthentication(); } /** @@ -38,7 +39,7 @@ class TableController extends Controller $page = (int)$page; $per_page = 20; - $this->View->render('table/show', array( + $this->View->renderDbManager('table/show', array( 'database_name' => $database_name, 'table_name' => $table_name, 'columns' => TableModel::getTableColumns($database_name, $table_name), @@ -91,7 +92,7 @@ class TableController extends Controller } // Show create table form - $this->View->render('table/create', array( + $this->View->renderDbManager('table/create', array( 'database_name' => $database_name )); } @@ -112,7 +113,7 @@ class TableController extends Controller return; } - $this->View->render('table/structure', array( + $this->View->renderDbManager('table/structure', array( 'database_name' => $database_name, 'table_name' => $table_name, 'columns' => TableModel::getTableColumns($database_name, $table_name), @@ -172,7 +173,7 @@ class TableController extends Controller } // Show add column form - $this->View->render('table/add_column', array( + $this->View->renderDbManager('table/add_column', array( 'database_name' => $database_name, 'table_name' => $table_name )); @@ -237,12 +238,160 @@ class TableController extends Controller Redirect::to('database/show/' . urlencode($database_name)); } + /** + * Update a row in the table (AJAX) + * @param string $database_name + * @param string $table_name + */ + public function updateRow($database_name = null, $table_name = null) + { + if (!$database_name || !$table_name) { + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + echo json_encode(['success' => false, 'message' => 'Invalid parameters']); + return; + } + Redirect::to('database/index'); + return; + } + + $pk_value = Request::post('pk_value'); + $data = Request::post('data'); + + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + + if (!$pk_value || !$data) { + echo json_encode(['success' => false, 'message' => 'Missing required data']); + return; + } + + if (TableModel::updateRow($database_name, $table_name, $pk_value, $data)) { + echo json_encode([ + 'success' => true, + 'message' => 'Row updated successfully' + ]); + } else { + echo json_encode([ + 'success' => false, + 'message' => 'Failed to update row' + ]); + } + return; + } + + Redirect::to('table/show/' . urlencode($database_name) . '/' . urlencode($table_name)); + } + + /** + * Delete a row from the table (AJAX) + * @param string $database_name + * @param string $table_name + */ + public function deleteRow($database_name = null, $table_name = null) + { + if (!$database_name || !$table_name) { + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + echo json_encode(['success' => false, 'message' => 'Invalid parameters']); + return; + } + Redirect::to('database/index'); + return; + } + + $pk_value = Request::post('pk_value'); + + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + + if (!$pk_value) { + echo json_encode(['success' => false, 'message' => 'Missing primary key value']); + return; + } + + if (TableModel::deleteRow($database_name, $table_name, $pk_value)) { + echo json_encode([ + 'success' => true, + 'message' => 'Row deleted successfully' + ]); + } else { + echo json_encode([ + 'success' => false, + 'message' => 'Failed to delete row' + ]); + } + return; + } + + Redirect::to('table/show/' . urlencode($database_name) . '/' . urlencode($table_name)); + } + + /** + * Insert a new row into the table (AJAX) + * @param string $database_name + * @param string $table_name + */ + public function insertRow($database_name = null, $table_name = null) + { + if (!$database_name || !$table_name) { + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + echo json_encode(['success' => false, 'message' => 'Invalid parameters']); + return; + } + Redirect::to('database/index'); + return; + } + + $data = Request::post('data'); + + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + + if (!$data) { + echo json_encode(['success' => false, 'message' => 'Missing row data']); + return; + } + + $insertId = TableModel::insertRow($database_name, $table_name, $data); + if ($insertId !== false) { + echo json_encode([ + 'success' => true, + 'message' => 'Row inserted successfully', + 'insert_id' => $insertId + ]); + } else { + echo json_encode([ + 'success' => false, + 'message' => 'Failed to insert row' + ]); + } + return; + } + + Redirect::to('table/show/' . urlencode($database_name) . '/' . urlencode($table_name)); + } + /** * Check if the request is an AJAX request */ private function isAjaxRequest() { - return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && + return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'; } + + /** + * Export table as raw SQL text + * @param string $database_name + * @param string $table_name + */ + public function export($database_name, $table_name) + { + header('Content-Type: text/plain; charset=utf-8'); + header('Content-Disposition: inline; filename="' . $table_name . '.sql"'); + + echo DatabaseModel::exportTable($database_name, $table_name); + } } \ No newline at end of file diff --git a/application/core/View.php b/application/core/View.php index 962466b..cabc254 100644 --- a/application/core/View.php +++ b/application/core/View.php @@ -25,7 +25,28 @@ class View /* Note properties */ public $messages; public $other_user; - + + /* Group properties */ + public $groups; + + /* Database Manager properties */ + public $databases; + public $database_name; + public $current_db; + public $tables; + public $table_name; + public $table_info; + public $columns; + public $rows; + public $indexes; + public $total_rows; + public $current_page; + public $per_page; + public $history; + public $user; + public $privileges; + public $current_user; + /** * Static property to track if header has been rendered */ @@ -115,6 +136,24 @@ class View header("Content-Type: application/json"); echo json_encode($data); } + + /** + * Render a view using the database manager layout + * @param string $filename Path of the to-be-rendered view + * @param array $data Data to be used in the view + */ + public function renderDbManager($filename, $data = null) + { + if ($data) { + foreach ($data as $key => $value) { + $this->{$key} = $value; + } + } + + require Config::get('PATH_VIEW') . '_templates/dbmanager_header.php'; + require Config::get('PATH_VIEW') . $filename . '.php'; + require Config::get('PATH_VIEW') . '_templates/dbmanager_footer.php'; + } /** * Reset header render flag at start of request @@ -206,6 +245,25 @@ class View return false; } + /** + * Checks if the passed array of controllers contains the currently active controller. + * Useful for navigation items that span multiple controllers (e.g., database manager). + * + * @param string $filename + * @param array $controllers Array of controller names to check + * + * @return bool Shows if any of the controllers is active + */ + public static function checkForActiveControllers($filename, $controllers) + { + foreach ($controllers as $controller) { + if (self::checkForActiveController($filename, $controller)) { + return true; + } + } + return false; + } + /** * Converts characters to HTML entities * This is important to avoid XSS attacks, and attempts to inject malicious code in your page. diff --git a/application/model/DatabaseModel.php b/application/model/DatabaseModel.php index 82ab616..4cd9f5e 100644 --- a/application/model/DatabaseModel.php +++ b/application/model/DatabaseModel.php @@ -21,7 +21,6 @@ class DatabaseModel $databases = $query->fetchAll(PDO::FETCH_COLUMN); - // Filter out system databases $system_dbs = ['information_schema', 'performance_schema', 'mysql', 'sys']; return array_diff($databases, $system_dbs); } @@ -35,7 +34,7 @@ class DatabaseModel { $database = DatabaseFactory::getFactory()->getConnection(); - $sql = "SHOW TABLES FROM " . $database_name; + $sql = "SHOW TABLES FROM `" . $database_name . "`"; $query = $database->prepare($sql); $query->execute(); @@ -54,7 +53,7 @@ class DatabaseModel $table_details = array(); foreach ($tables as $table) { - $sql = "SHOW TABLE STATUS FROM " . $database_name . " LIKE :table_name"; + $sql = "SHOW TABLE STATUS FROM `" . $database_name . "` LIKE :table_name"; $query = $database->prepare($sql); $query->execute(array(':table_name' => $table)); @@ -87,7 +86,7 @@ class DatabaseModel $tables = self::getTablesInDatabase($database_name); foreach ($tables as $table) { - $sql = "DESCRIBE " . $database_name . "." . $table; + $sql = "DESCRIBE `" . $database_name . "`.`" . $table . "`"; $query = $database->prepare($sql); $query->execute(); @@ -152,13 +151,106 @@ class DatabaseModel { $database = DatabaseFactory::getFactory()->getConnection(); - $sql = "SHOW COLUMNS FROM " . $database_name . "." . $table_name; + $sql = "SHOW COLUMNS FROM `" . $database_name . "`.`" . $table_name . "`"; $query = $database->prepare($sql); $query->execute(); return $query->fetchAll(PDO::FETCH_ASSOC); } + /** + * Export database as SQL dump + * @param string $database_name + * @return string + */ + public static function exportDatabase($database_name) + { + $database = DatabaseFactory::getFactory()->getConnection(); + $output = "-- Database Export: " . $database_name . "\n"; + $output .= "-- Generated: " . date('Y-m-d H:i:s') . "\n\n"; + $output .= "SET FOREIGN_KEY_CHECKS=0;\n"; + $output .= "SET SQL_MODE = \"NO_AUTO_VALUE_ON_ZERO\";\n\n"; + + $tables = self::getTablesInDatabase($database_name); + + foreach ($tables as $table) { + $sql = "SHOW CREATE TABLE `" . $database_name . "`.`" . $table . "`"; + $query = $database->prepare($sql); + $query->execute(); + $row = $query->fetch(PDO::FETCH_NUM); + + $output .= "DROP TABLE IF EXISTS `" . $table . "`;\n"; + $output .= $row[1] . ";\n\n"; + + $sql = "SELECT * FROM `" . $database_name . "`.`" . $table . "`"; + $query = $database->prepare($sql); + $query->execute(); + $rows = $query->fetchAll(PDO::FETCH_ASSOC); + + if (!empty($rows)) { + foreach ($rows as $dataRow) { + $columns = array_keys($dataRow); + $values = array_map(function($val) use ($database) { + if ($val === null) { + return 'NULL'; + } + return $database->quote($val); + }, array_values($dataRow)); + + $output .= "INSERT INTO `" . $table . "` (`" . implode("`, `", $columns) . "`) VALUES (" . implode(", ", $values) . ");\n"; + } + $output .= "\n"; + } + } + + $output .= "SET FOREIGN_KEY_CHECKS=1;\n"; + return $output; + } + + /** + * Export single table as SQL dump + * @param string $database_name + * @param string $table_name + * @return string + */ + public static function exportTable($database_name, $table_name) + { + $database = DatabaseFactory::getFactory()->getConnection(); + $output = "-- Table Export: " . $table_name . " from " . $database_name . "\n"; + $output .= "-- Generated: " . date('Y-m-d H:i:s') . "\n\n"; + $output .= "SET FOREIGN_KEY_CHECKS=0;\n\n"; + + $sql = "SHOW CREATE TABLE `" . $database_name . "`.`" . $table_name . "`"; + $query = $database->prepare($sql); + $query->execute(); + $row = $query->fetch(PDO::FETCH_NUM); + + $output .= "DROP TABLE IF EXISTS `" . $table_name . "`;\n"; + $output .= $row[1] . ";\n\n"; + + $sql = "SELECT * FROM `" . $database_name . "`.`" . $table_name . "`"; + $query = $database->prepare($sql); + $query->execute(); + $rows = $query->fetchAll(PDO::FETCH_ASSOC); + + if (!empty($rows)) { + foreach ($rows as $dataRow) { + $columns = array_keys($dataRow); + $values = array_map(function($val) use ($database) { + if ($val === null) { + return 'NULL'; + } + return $database->quote($val); + }, array_values($dataRow)); + + $output .= "INSERT INTO `" . $table_name . "` (`" . implode("`, `", $columns) . "`) VALUES (" . implode(", ", $values) . ");\n"; + } + } + + $output .= "\nSET FOREIGN_KEY_CHECKS=1;\n"; + return $output; + } + /** * Format bytes to human readable format * @param int $bytes diff --git a/application/model/DbUserModel.php b/application/model/DbUserModel.php new file mode 100644 index 0000000..4583b22 --- /dev/null +++ b/application/model/DbUserModel.php @@ -0,0 +1,202 @@ +getConnection(); + + try { + $sql = "SELECT User, Host FROM mysql.user ORDER BY User, Host"; + $query = $database->prepare($sql); + $query->execute(); + + return $query->fetchAll(PDO::FETCH_OBJ); + } catch (PDOException $e) { + return array(); + } + } + + /** + * Get user details + * @param string $username + * @param string $host + * @return object|null + */ + public static function getUserDetails($username, $host) + { + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + $sql = "SELECT * FROM mysql.user WHERE User = :username AND Host = :host"; + $query = $database->prepare($sql); + $query->execute(array(':username' => $username, ':host' => $host)); + + return $query->fetch(PDO::FETCH_OBJ); + } catch (PDOException $e) { + return null; + } + } + + /** + * Get user privileges + * @param string $username + * @param string $host + * @return array + */ + public static function getUserPrivileges($username, $host) + { + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + // Escape username and host for SHOW GRANTS + $sql = "SHOW GRANTS FOR " . $database->quote($username) . "@" . $database->quote($host); + $query = $database->prepare($sql); + $query->execute(); + + $grants = array(); + while ($row = $query->fetch(PDO::FETCH_NUM)) { + $grants[] = $row[0]; + } + + return $grants; + } catch (PDOException $e) { + return array(); + } + } + + /** + * Create a new database user + * @param string $username + * @param string $password + * @param string $host + * @return bool + */ + public static function createUser($username, $password, $host) + { + if (!self::validateUsername($username) || empty($password) || empty($host)) { + return false; + } + + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + $sql = "CREATE USER " . $database->quote($username) . "@" . $database->quote($host) . + " IDENTIFIED BY " . $database->quote($password); + $database->exec($sql); + + return true; + } catch (PDOException $e) { + return false; + } + } + + /** + * Update user password + * @param string $username + * @param string $host + * @param string $password + * @return bool + */ + public static function updateUserPassword($username, $host, $password) + { + if (empty($password)) { + return false; + } + + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + $sql = "ALTER USER " . $database->quote($username) . "@" . $database->quote($host) . + " IDENTIFIED BY " . $database->quote($password); + $database->exec($sql); + + return true; + } catch (PDOException $e) { + return false; + } + } + + /** + * Update user privileges + * @param string $username + * @param string $host + * @param array $privileges + * @return bool + */ + public static function updateUserPrivileges($username, $host, $privileges) + { + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + $sql = "REVOKE ALL PRIVILEGES, GRANT OPTION FROM " . + $database->quote($username) . "@" . $database->quote($host); + $database->exec($sql); + + if (!empty($privileges) && is_array($privileges)) { + if (in_array('ALL PRIVILEGES', $privileges)) { + $sql = "GRANT ALL PRIVILEGES ON *.* TO " . + $database->quote($username) . "@" . $database->quote($host); + $database->exec($sql); + } else { + $valid_privs = array('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'DROP', 'ALTER', 'INDEX', + 'REFERENCES', 'CREATE TEMPORARY TABLES', 'LOCK TABLES', 'EXECUTE', + 'CREATE VIEW', 'SHOW VIEW', 'CREATE ROUTINE', 'ALTER ROUTINE', 'EVENT', 'TRIGGER'); + $privileges = array_intersect($privileges, $valid_privs); + + if (!empty($privileges)) { + $priv_string = implode(', ', $privileges); + $sql = "GRANT " . $priv_string . " ON *.* TO " . + $database->quote($username) . "@" . $database->quote($host); + $database->exec($sql); + } + } + } + + $database->exec("FLUSH PRIVILEGES"); + + return true; + } catch (PDOException $e) { + return false; + } + } + + /** + * Delete a database user + * @param string $username + * @param string $host + * @return bool + */ + public static function deleteUser($username, $host) + { + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + $sql = "DROP USER " . $database->quote($username) . "@" . $database->quote($host); + $database->exec($sql); + + return true; + } catch (PDOException $e) { + return false; + } + } + + /** + * Validate username format + * @param string $username + * @return bool + */ + private static function validateUsername($username) + { + return !empty($username) && preg_match('/^[a-zA-Z0-9_]+$/', $username); + } +} diff --git a/application/model/TableModel.php b/application/model/TableModel.php index ca1a628..2f849dd 100644 --- a/application/model/TableModel.php +++ b/application/model/TableModel.php @@ -131,7 +131,6 @@ class TableModel $database = DatabaseFactory::getFactory()->getConnection(); - // Build column definitions $column_definitions = array(); foreach ($columns as $column) { $definition = "`" . $column['name'] . "` " . $column['type']; @@ -151,7 +150,6 @@ class TableModel $column_definitions[] = $definition; } - // Handle primary key foreach ($columns as $column) { if (isset($column['key']) && $column['key'] === 'PRI') { $column_definitions[] = "PRIMARY KEY (`" . $column['name'] . "`)"; @@ -260,6 +258,169 @@ class TableModel } } + /** + * Get the primary key column name for a table + * @param string $database_name + * @param string $table_name + * @return string|null + */ + public static function getPrimaryKeyColumn($database_name, $table_name) + { + $columns = self::getTableColumns($database_name, $table_name); + foreach ($columns as $column) { + if ($column['Key'] === 'PRI') { + return $column['Field']; + } + } + return null; + } + + /** + * Get a single row by primary key + * @param string $database_name + * @param string $table_name + * @param mixed $pk_value + * @return array|null + */ + public static function getRow($database_name, $table_name, $pk_value) + { + $pk_column = self::getPrimaryKeyColumn($database_name, $table_name); + if (!$pk_column) { + return null; + } + + $database = DatabaseFactory::getFactory()->getConnection(); + + $sql = "SELECT * FROM `" . $database_name . "`.`" . $table_name . "` WHERE `" . $pk_column . "` = :pk_value LIMIT 1"; + $query = $database->prepare($sql); + $query->execute(array(':pk_value' => $pk_value)); + + return $query->fetch(PDO::FETCH_ASSOC); + } + + /** + * Update a row in the table + * @param string $database_name + * @param string $table_name + * @param mixed $pk_value + * @param array $data - associative array of column => value + * @return bool + */ + public static function updateRow($database_name, $table_name, $pk_value, $data) + { + if (!$database_name || !$table_name || !$pk_value || empty($data)) { + return false; + } + + $pk_column = self::getPrimaryKeyColumn($database_name, $table_name); + if (!$pk_column) { + return false; + } + + $database = DatabaseFactory::getFactory()->getConnection(); + + $set_parts = array(); + $params = array(); + $i = 0; + foreach ($data as $column => $value) { + if ($column === $pk_column) { + continue; + } + $param_name = ':param_' . $i; + $set_parts[] = "`" . $column . "` = " . $param_name; + $params[$param_name] = $value === '' ? null : $value; + $i++; + } + + if (empty($set_parts)) { + return false; + } + + $params[':pk_value'] = $pk_value; + + try { + $sql = "UPDATE `" . $database_name . "`.`" . $table_name . "` SET " . implode(', ', $set_parts) . " WHERE `" . $pk_column . "` = :pk_value"; + $query = $database->prepare($sql); + return $query->execute($params); + } catch (PDOException $e) { + return false; + } + } + + /** + * Delete a row from the table + * @param string $database_name + * @param string $table_name + * @param mixed $pk_value + * @return bool + */ + public static function deleteRow($database_name, $table_name, $pk_value) + { + if (!$database_name || !$table_name || !$pk_value) { + return false; + } + + $pk_column = self::getPrimaryKeyColumn($database_name, $table_name); + if (!$pk_column) { + return false; + } + + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + $sql = "DELETE FROM `" . $database_name . "`.`" . $table_name . "` WHERE `" . $pk_column . "` = :pk_value"; + $query = $database->prepare($sql); + return $query->execute(array(':pk_value' => $pk_value)); + } catch (PDOException $e) { + return false; + } + } + + /** + * Insert a new row into the table + * @param string $database_name + * @param string $table_name + * @param array $data - associative array of column => value + * @return bool|int - returns insert ID on success, false on failure + */ + public static function insertRow($database_name, $table_name, $data) + { + if (!$database_name || !$table_name || empty($data)) { + return false; + } + + $database = DatabaseFactory::getFactory()->getConnection(); + + $columns = array(); + $placeholders = array(); + $params = array(); + $i = 0; + + foreach ($data as $column => $value) { + if ($value === '' || $value === null) { + continue; + } + $columns[] = "`" . $column . "`"; + $param_name = ':param_' . $i; + $placeholders[] = $param_name; + $params[$param_name] = $value; + $i++; + } + + if (empty($columns)) { + return false; + } + + try { + $sql = "INSERT INTO `" . $database_name . "`.`" . $table_name . "` (" . implode(', ', $columns) . ") VALUES (" . implode(', ', $placeholders) . ")"; + $query = $database->prepare($sql); + $query->execute($params); + return $database->lastInsertId(); + } catch (PDOException $e) { + return false; + } + } + /** * Format bytes to human readable format * @param int $bytes diff --git a/application/view/_templates/dbmanager_footer.php b/application/view/_templates/dbmanager_footer.php new file mode 100644 index 0000000..924fa47 --- /dev/null +++ b/application/view/_templates/dbmanager_footer.php @@ -0,0 +1,105 @@ + + + + +
+ + + + + + + + +