diff --git a/README.md b/README.md index 9cac5cc..efa17fb 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,38 @@ Implementierung einer öffentlichen Benutzerliste, die alle Benutzer und ihre Gr --- +## Notizen-App + +#### Persönliche Notizen mit Markdown-Unterstützung + +**Beschreibung:** +Implementierung einer vollständigen Notizen-Anwendung mit CRUD-Funktionalität (Create, Read, Update, Delete). Benutzer können persönliche Notizen erstellen, bearbeiten und löschen. + +**Features:** +- **Markdown-Unterstützung**: Notizen werden mit SimpleMarkdown gerendert +- **AJAX-Integration**: Alle Operationen ohne Seiten-Neuladung +- **Benutzergebunden**: Jeder Benutzer sieht nur seine eigenen Notizen +- **Echtzeit-Vorschau**: Markdown wird direkt in HTML umgewandelt + +**Technische Umsetzung:** +- NoteController mit vollständiger CRUD-Implementierung +- NoteModel für Datenbankoperationen +- SimpleMarkdown-Library für Markdown-Parsing +- AJAX-Endpoints für dynamische Interaktion + +**Zugriffsrechte:** +- Nur für angemeldete Benutzer verfügbar +- Jeder Benutzer hat nur Zugriff auf seine eigenen Notizen + +``` + +[📸 Screenshot: Notizen-Übersicht] +[📸 Screenshot: Notiz erstellen/bearbeiten] +[📸 Screenshot: Markdown-Vorschau] +``` + +--- + ## jQuery - Einführung und Grundlagen #### JavaScript Basics diff --git a/application/config/config.development.php b/application/config/config.development.php index 4fb05ea..fd599b1 100644 --- a/application/config/config.development.php +++ b/application/config/config.development.php @@ -63,7 +63,7 @@ return array( * DB_CHARSET The charset, necessary for security reasons. Check Database.php class for more info. */ 'DB_TYPE' => 'mysql', - 'DB_HOST' => 'localhost', + 'DB_HOST' => '127.0.0.1', 'DB_NAME' => 'huge', 'DB_USER' => 'root', 'DB_PASS' => 'root', diff --git a/application/controller/DatabaseController.php b/application/controller/DatabaseController.php new file mode 100644 index 0000000..5c76c30 --- /dev/null +++ b/application/controller/DatabaseController.php @@ -0,0 +1,144 @@ +View->render('database/index', array( + 'databases' => DatabaseModel::getAllDatabases(), + 'current_db' => Config::get('DB_NAME') + )); + } + + /** + * Show details of a specific database + * @param string $database_name + */ + public function show($database_name = null) + { + if (!$database_name) { + $database_name = Config::get('DB_NAME'); + } + + $this->View->render('database/show', array( + 'tables' => DatabaseModel::getTablesInDatabase($database_name), + 'database_name' => $database_name, + 'table_info' => DatabaseModel::getTableDetails($database_name) + )); + } + + /** + * Create a new database + */ + public function create() + { + $database_name = Request::post('database_name'); + + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + + if (DatabaseModel::createDatabase($database_name)) { + echo json_encode([ + 'success' => true, + 'message' => 'Database created successfully' + ]); + } else { + echo json_encode([ + 'success' => false, + 'message' => 'Failed to create database' + ]); + } + return; + } + + Redirect::to('database'); + } + + /** + * Delete a database + * @param string $database_name + */ + public function delete($database_name) + { + // Prevent deletion of the current database + if ($database_name === Config::get('DB_NAME')) { + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + echo json_encode([ + 'success' => false, + 'message' => 'Cannot delete the currently connected database' + ]); + return; + } + Redirect::to('database'); + return; + } + + $success = DatabaseModel::deleteDatabase($database_name); + + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + if ($success) { + echo json_encode([ + 'success' => true, + 'message' => 'Database deleted successfully' + ]); + } else { + echo json_encode([ + 'success' => false, + 'message' => 'Failed to delete database' + ]); + } + return; + } + + Redirect::to('database'); + } + + /** + * Get database structure as JSON (AJAX endpoint) + * @param string $database_name + */ + public function getStructure($database_name = null) + { + if (!$database_name) { + $database_name = Config::get('DB_NAME'); + } + + $structure = DatabaseModel::getDatabaseStructure($database_name); + + header('Content-Type: application/json'); + echo json_encode([ + 'success' => true, + 'structure' => $structure + ]); + } + + /** + * Check if the request is an AJAX request + */ + private function isAjaxRequest() + { + 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 new file mode 100644 index 0000000..ccbc07f --- /dev/null +++ b/application/controller/DbUserController.php @@ -0,0 +1,201 @@ +View->render('dbuser/index', array( + 'users' => DbUserModel::getAllUsers(), + 'current_user' => Config::get('DB_USER') + )); + } + + /** + * Create a new database user + */ + public function create() + { + if (Request::post('submit_create_user')) { + $username = Request::post('username'); + $password = Request::post('password'); + $host = Request::post('host'); + + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + + if (DbUserModel::createUser($username, $password, $host)) { + echo json_encode([ + 'success' => true, + 'message' => 'User created successfully', + 'reload' => true + ]); + } else { + echo json_encode([ + 'success' => false, + 'message' => 'Failed to create user' + ]); + } + return; + } + + if (DbUserModel::createUser($username, $password, $host)) { + Redirect::to('dbuser'); + } else { + Redirect::to('dbuser'); + } + return; + } + + // Show create user form + $this->View->render('dbuser/create'); + } + + /** + * Edit user details and privileges + * @param string $username + * @param string $host + */ + public function edit($username, $host) + { + if (Request::post('submit_edit_user')) { + $new_password = Request::post('password'); + $privileges = Request::post('privileges'); + + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + + $success = true; + $message = 'User updated successfully'; + + if (!empty($new_password)) { + if (!DbUserModel::updateUserPassword($username, $host, $new_password)) { + $success = false; + $message = 'Failed to update user password'; + } + } + + if ($success && !DbUserModel::updateUserPrivileges($username, $host, $privileges)) { + $success = false; + $message = 'Failed to update user privileges'; + } + + if ($success) { + echo json_encode([ + 'success' => true, + 'message' => $message + ]); + } else { + echo json_encode([ + 'success' => false, + 'message' => $message + ]); + } + return; + } + + $success = true; + if (!empty($new_password)) { + $success = DbUserModel::updateUserPassword($username, $host, $new_password); + } + + if ($success && !DbUserModel::updateUserPrivileges($username, $host, $privileges)) { + $success = false; + } + + Redirect::to('dbuser'); + return; + } + + // Show edit user form + $this->View->render('dbuser/edit', array( + 'user' => DbUserModel::getUserDetails($username, $host), + 'privileges' => DbUserModel::getUserPrivileges($username, $host), + 'databases' => DatabaseModel::getAllDatabases() + )); + } + + /** + * Delete a user + * @param string $username + * @param string $host + */ + public function delete($username, $host) + { + // Prevent deletion of current user + if ($username === Config::get('DB_USER')) { + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + echo json_encode([ + 'success' => false, + 'message' => 'Cannot delete the currently connected user' + ]); + return; + } + Redirect::to('dbuser'); + return; + } + + $success = DbUserModel::deleteUser($username, $host); + + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + + if ($success) { + echo json_encode([ + 'success' => true, + 'message' => 'User deleted successfully' + ]); + } else { + echo json_encode([ + 'success' => false, + 'message' => 'Failed to delete user' + ]); + } + return; + } + + Redirect::to('dbuser'); + } + + /** + * Show user privileges + * @param string $username + * @param string $host + */ + public function privileges($username, $host) + { + $this->View->render('dbuser/privileges', array( + 'user' => DbUserModel::getUserDetails($username, $host), + 'privileges' => DbUserModel::getUserPrivileges($username, $host) + )); + } + + /** + * Check if the request is an AJAX request + */ + private function isAjaxRequest() + { + 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/MessageController.php b/application/controller/MessageController.php index b51b586..d088593 100644 --- a/application/controller/MessageController.php +++ b/application/controller/MessageController.php @@ -5,50 +5,37 @@ class MessageController extends Controller public function __construct() { parent::__construct(); - - // Require login for all message features Auth::checkAuthentication(); } - - /** - * 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'; } - - /** - * Send a message to a specific user via URL parameters - * URL format: message/send/{receiver_id}/{subject}/{message} - */ + public function send() { - // Handle POST request if ($_SERVER['REQUEST_METHOD'] === 'POST') { $receiver_id = isset($_POST['receiver_id']) ? $_POST['receiver_id'] : null; $subject = isset($_POST['subject']) ? $_POST['subject'] : 'No Subject'; $message = isset($_POST['message']) ? $_POST['message'] : null; - + if (!$receiver_id || !$message) { - // Return JSON for AJAX requests if ($this->isAjaxRequest()) { header('Content-Type: application/json'); echo json_encode(['success' => false, 'message' => 'Receiver and message are required']); return; } - + Session::add('feedback_negative', 'Receiver and message are required'); Redirect::to('message'); return; } - - // Send the message + $sender_id = Session::get('user_id'); $success = MessageModel::sendToUser($sender_id, $receiver_id, $subject, $message); - - // Return JSON for AJAX requests + if ($this->isAjaxRequest()) { header('Content-Type: application/json'); if ($success) { @@ -58,15 +45,13 @@ class MessageController extends Controller } return; } - - // Regular request handling + if ($success) { Session::add('feedback_positive', 'Message sent successfully'); } else { Session::add('feedback_negative', 'Failed to send message'); } - - // If coming from conversation view, return there + if (isset($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], 'conversation') !== false) { Redirect::to('message/conversation/' . $receiver_id); } else { @@ -74,31 +59,29 @@ class MessageController extends Controller } return; } - - // Handle GET request + + // GET request: message/send/{receiver_id}/{subject}/{message} $url_parts = explode('/', trim($_SERVER['REQUEST_URI'], '/')); $receiver_id = isset($url_parts[2]) ? $url_parts[2] : null; $subject = isset($url_parts[3]) ? urldecode($url_parts[3]) : null; $message = isset($url_parts[4]) ? urldecode($url_parts[4]) : null; - + if (!$receiver_id || !$subject || !$message) { header('Content-Type: application/json'); echo json_encode(['success' => false, 'message' => 'Missing parameters. Use: message/send/{receiver_id}/{subject}/{message}']); return; } - - // Verify receiver exists + $receiver = UserModel::getPublicProfileOfUser($receiver_id); if (!$receiver) { header('Content-Type: application/json'); echo json_encode(['success' => false, 'message' => 'Receiver not found']); return; } - - // Send the message + $sender_id = Session::get('user_id'); $success = MessageModel::sendToUser($sender_id, $receiver_id, $subject, $message); - + header('Content-Type: application/json'); if ($success) { echo json_encode(['success' => true, 'message' => 'Message sent successfully']); @@ -106,70 +89,60 @@ class MessageController extends Controller echo json_encode(['success' => false, 'message' => 'Failed to send message']); } } - - /** - * Send a message to a group via URL parameters - * URL format: message/sendgroup/{group_type}/{subject}/{message} - * group_type can be: admins, moderators, all_users - */ + public function sendgroup() { - // Handle POST request if ($_SERVER['REQUEST_METHOD'] === 'POST') { $group_type = isset($_POST['group_type']) ? $_POST['group_type'] : null; $subject = isset($_POST['subject']) ? $_POST['subject'] : 'No Subject'; $message = isset($_POST['message']) ? $_POST['message'] : null; - + if (!$group_type || !$message) { Session::add('feedback_negative', 'Group type and message are required'); Redirect::to('message'); return; } - - // Validate group type + if (!in_array($group_type, ['admins', 'moderators', 'all_users'])) { Session::add('feedback_negative', 'Invalid group type'); Redirect::to('message'); return; } - - // Send the message + $sender_id = Session::get('user_id'); $success = MessageModel::sendToGroup($sender_id, $group_type, $subject, $message); - + if ($success) { Session::add('feedback_positive', 'Message sent to group successfully'); } else { Session::add('feedback_negative', 'Failed to send message to group'); } - + Redirect::to('message'); return; } - - // Handle GET request + + // GET request: message/sendgroup/{group_type}/{subject}/{message} $url_parts = explode('/', trim($_SERVER['REQUEST_URI'], '/')); $group_type = isset($url_parts[2]) ? $url_parts[2] : null; $subject = isset($url_parts[3]) ? urldecode($url_parts[3]) : null; $message = isset($url_parts[4]) ? urldecode($url_parts[4]) : null; - + if (!$group_type || !$subject || !$message) { header('Content-Type: application/json'); echo json_encode(['success' => false, 'message' => 'Missing parameters. Use: message/sendgroup/{group_type}/{subject}/{message}']); return; } - - // Validate group type + if (!in_array($group_type, ['admins', 'moderators', 'all_users'])) { header('Content-Type: application/json'); echo json_encode(['success' => false, 'message' => 'Invalid group type. Must be: admins, moderators, or all_users']); return; } - - // Send the message + $sender_id = Session::get('user_id'); $success = MessageModel::sendToGroup($sender_id, $group_type, $subject, $message); - + header('Content-Type: application/json'); if ($success) { echo json_encode(['success' => true, 'message' => 'Message sent to group successfully']); @@ -177,204 +150,156 @@ class MessageController extends Controller echo json_encode(['success' => false, 'message' => 'Failed to send message to group']); } } - - /** - * Handle reply to a message - */ + public function reply() { - // Always return JSON for this endpoint + while (ob_get_level()) ob_end_clean(); + header('Content-Type: application/json'); - - // Start output buffering to catch any accidental output - ob_start(); - - try { - if ($_SERVER['REQUEST_METHOD'] !== 'POST') { - echo json_encode(['success' => false, 'message' => 'Invalid request method']); - exit(); - } - - $receiver_id = isset($_POST['receiver_id']) ? $_POST['receiver_id'] : null; - $message = isset($_POST['message']) ? $_POST['message'] : null; - - if (!$receiver_id || !$message) { - echo json_encode(['success' => false, 'message' => 'Receiver and message are required']); - exit(); - } - - $sender_id = Session::get('user_id'); - if (!$sender_id) { - echo json_encode(['success' => false, 'message' => 'Not logged in']); - exit(); - } - - // Send the message (using sendToUser without subject) - $success = MessageModel::sendToUser($sender_id, $receiver_id, 'Re: Message', $message); - - if ($success) { - echo json_encode(['success' => true, 'message' => 'Reply sent successfully']); - } else { - echo json_encode(['success' => false, 'message' => 'Failed to send reply']); - } - } catch (Exception $e) { - // Catch any PHP errors - echo json_encode(['success' => false, 'message' => 'Server error: ' . $e->getMessage()]); + + if ($_SERVER['REQUEST_METHOD'] !== 'POST') { + echo json_encode(['success' => false, 'message' => 'Invalid request method']); + exit(); + } + + $receiver_id = isset($_POST['receiver_id']) ? $_POST['receiver_id'] : null; + $message = isset($_POST['message']) ? $_POST['message'] : null; + + if (!$receiver_id || !$message) { + echo json_encode(['success' => false, 'message' => 'Receiver and message are required']); + exit(); + } + + $sender_id = Session::get('user_id'); + if (!$sender_id) { + echo json_encode(['success' => false, 'message' => 'Not logged in']); + exit(); + } + + $success = MessageModel::sendToUser($sender_id, $receiver_id, 'Direct Message', $message); + + if ($success) { + echo json_encode(['success' => true, 'message' => 'Reply sent successfully']); + } else { + echo json_encode(['success' => false, 'message' => 'Failed to send reply']); } - - // Clean any output buffer and exit - ob_end_clean(); exit(); } - - /** - * Show global chat interface - */ + public function global() { - // Redirect to main messages page with global chat hash Redirect::to('message#load-global'); } - - /** - * Show the messenger interface - */ + public function index() { $user_id = Session::get('user_id'); - - // Get conversations and unread count + $conversations = MessageModel::getConversations($user_id); $unread_count = MessageModel::getUnreadCount($user_id); - + $this->View->render('message/index', array( 'conversations' => $conversations, 'unread_count' => $unread_count, 'all_users' => MessageModel::getAllUsers($user_id) )); } - - /** - * Show conversation with a specific user - */ + public function conversation() { $user_id = Session::get('user_id'); $url_parts = explode('/', trim($_SERVER['REQUEST_URI'], '/')); $other_user_id = isset($url_parts[2]) ? $url_parts[2] : null; - + if (!$other_user_id) { Redirect::to('message'); return; } - - // Get user info for the other person + $other_user = UserModel::getPublicProfileOfUser($other_user_id); if (!$other_user) { Redirect::to('message'); return; } - - // Redirect to main messages page with conversation hash + Redirect::to('message#load-conversation-' . $other_user_id); } - - /** - * Get conversation messages as JSON (AJAX endpoint) - */ + public function getConversationMessages() { + while (ob_get_level()) ob_end_clean(); + $user_id = Session::get('user_id'); $url_parts = explode('/', trim($_SERVER['REQUEST_URI'], '/')); $other_user_id = isset($url_parts[2]) ? $url_parts[2] : null; - - if (!$other_user_id) { - header('Content-Type: application/json'); - echo json_encode(['success' => false, 'message' => 'Missing user ID']); - return; - } - - // Get messages - $messages = MessageModel::getMessagesWithUser($user_id, $other_user_id); - - // Mark messages as read when loading the conversation - MessageModel::markAsRead($user_id, $other_user_id); - + header('Content-Type: application/json'); + + if (!$other_user_id) { + echo json_encode(['success' => false, 'message' => 'Missing user ID']); + exit(); + } + + $messages = MessageModel::getMessagesWithUser($user_id, $other_user_id); + MessageModel::markAsRead($user_id, $other_user_id); + echo json_encode(['success' => true, 'messages' => $messages]); + exit(); } - - /** - * Get global chat messages as JSON (AJAX endpoint) - */ + public function getGlobalMessages() { - // Always return JSON for this endpoint + while (ob_get_level()) ob_end_clean(); + header('Content-Type: application/json'); - $messages = MessageModel::getGlobalMessages(); echo json_encode(['success' => true, 'messages' => $messages]); - - // Stop any further execution exit(); } - - /** - * Send message to global chat - */ + public function sendToGlobal() { - // Always return JSON for this endpoint + while (ob_get_level()) ob_end_clean(); + header('Content-Type: application/json'); - - // Start output buffering to catch any accidental output - ob_start(); - - try { - if ($_SERVER['REQUEST_METHOD'] !== 'POST') { - echo json_encode(['success' => false, 'message' => 'Invalid request method']); - exit(); - } - - $message = isset($_POST['message']) ? $_POST['message'] : null; - $sender_id = Session::get('user_id'); - - if (!$message) { - echo json_encode(['success' => false, 'message' => 'Message is required']); - exit(); - } - - if (!$sender_id) { - echo json_encode(['success' => false, 'message' => 'Not logged in']); - exit(); - } - - $success = MessageModel::sendToGlobal($sender_id, $message); - - if ($success) { - echo json_encode(['success' => true, 'message' => 'Message sent to global chat']); - } else { - echo json_encode(['success' => false, 'message' => 'Failed to send message']); - } - } catch (Exception $e) { - // Catch any PHP errors - echo json_encode(['success' => false, 'message' => 'Server error: ' . $e->getMessage()]); + + if ($_SERVER['REQUEST_METHOD'] !== 'POST') { + echo json_encode(['success' => false, 'message' => 'Invalid request method']); + exit(); + } + + $message = isset($_POST['message']) ? $_POST['message'] : null; + $sender_id = Session::get('user_id'); + + if (!$message) { + echo json_encode(['success' => false, 'message' => 'Message is required']); + exit(); + } + + if (!$sender_id) { + echo json_encode(['success' => false, 'message' => 'Not logged in']); + exit(); + } + + $success = MessageModel::sendToGlobal($sender_id, $message); + + if ($success) { + echo json_encode(['success' => true, 'message' => 'Message sent to global chat']); + } else { + echo json_encode(['success' => false, 'message' => 'Failed to send message']); } - - // Clean any output buffer and exit - ob_end_clean(); exit(); } - - /** - * Get unread count as JSON - */ + public function unreadcount() { + while (ob_get_level()) ob_end_clean(); + $user_id = Session::get('user_id'); $unread_count = MessageModel::getUnreadCount($user_id); - + header('Content-Type: application/json'); echo json_encode(['unread_count' => $unread_count]); + exit(); } -} \ No newline at end of file +} diff --git a/application/controller/SqlController.php b/application/controller/SqlController.php new file mode 100644 index 0000000..4e60191 --- /dev/null +++ b/application/controller/SqlController.php @@ -0,0 +1,181 @@ +View->render('sql/index', array( + 'database_name' => $database_name, + 'databases' => DatabaseModel::getAllDatabases(), + 'history' => SqlModel::getQueryHistory(Session::get('user_id')) + )); + } + + /** + * Execute SQL query + */ + public function execute() + { + $database_name = Request::post('database_name') ?: Config::get('DB_NAME'); + $sql_query = Request::post('sql_query'); + + if (empty($sql_query)) { + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + echo json_encode([ + 'success' => false, + 'message' => 'SQL query cannot be empty' + ]); + return; + } + Redirect::to('sql'); + return; + } + + $result = SqlModel::executeQuery($database_name, $sql_query, Session::get('user_id')); + + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + + if ($result['success']) { + echo json_encode([ + 'success' => true, + 'message' => $result['message'], + 'result' => $result['result'], + 'affected_rows' => $result['affected_rows'], + 'execution_time' => $result['execution_time'], + 'query_type' => $result['query_type'] + ]); + } else { + echo json_encode([ + 'success' => false, + 'message' => $result['message'], + 'error' => $result['error'] + ]); + } + return; + } + + // Non-AJAX: redirect with results in session + Session::set('sql_result', $result); + Redirect::to('sql/index/' . urlencode($database_name)); + } + + /** + * Get query history as JSON (AJAX endpoint) + */ + public function getHistory() + { + $history = SqlModel::getQueryHistory(Session::get('user_id')); + + header('Content-Type: application/json'); + echo json_encode([ + 'success' => true, + 'history' => $history + ]); + } + + /** + * Clear query history + */ + public function clearHistory() + { + $success = SqlModel::clearQueryHistory(Session::get('user_id')); + + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + + if ($success) { + echo json_encode([ + 'success' => true, + 'message' => 'Query history cleared successfully' + ]); + } else { + echo json_encode([ + 'success' => false, + 'message' => 'Failed to clear query history' + ]); + } + return; + } + + Redirect::to('sql'); + } + + /** + * Get database schema for autocomplete + * @param string $database_name + */ + public function getSchema($database_name = null) + { + if (!$database_name) { + $database_name = Config::get('DB_NAME'); + } + + $schema = SqlModel::getDatabaseSchema($database_name); + + header('Content-Type: application/json'); + echo json_encode([ + 'success' => true, + 'schema' => $schema + ]); + } + + /** + * Format SQL query (AJAX endpoint) + */ + public function formatQuery() + { + $query = Request::post('query'); + + if (empty($query)) { + header('Content-Type: application/json'); + echo json_encode([ + 'success' => false, + 'message' => 'Query cannot be empty' + ]); + return; + } + + $formatted = SqlModel::formatQuery($query); + + header('Content-Type: application/json'); + echo json_encode([ + 'success' => true, + 'formatted' => $formatted + ]); + } + + /** + * Check if the request is an AJAX request + */ + private function isAjaxRequest() + { + 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/TableController.php b/application/controller/TableController.php new file mode 100644 index 0000000..def585f --- /dev/null +++ b/application/controller/TableController.php @@ -0,0 +1,248 @@ +View->render('table/show', array( + 'database_name' => $database_name, + 'table_name' => $table_name, + 'columns' => TableModel::getTableColumns($database_name, $table_name), + 'rows' => TableModel::getTableRows($database_name, $table_name, $page, $per_page), + 'total_rows' => TableModel::getTableRowCount($database_name, $table_name), + 'current_page' => $page, + 'per_page' => $per_page, + 'table_info' => TableModel::getTableInfo($database_name, $table_name) + )); + } + + /** + * Create a new table + * @param string $database_name + */ + public function create($database_name = null) + { + if (!$database_name) { + $database_name = Config::get('DB_NAME'); + } + + if (Request::post('submit_create_table')) { + $table_name = Request::post('table_name'); + $columns = Request::post('columns'); + + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + + if (TableModel::createTable($database_name, $table_name, $columns)) { + echo json_encode([ + 'success' => true, + 'message' => 'Table created successfully', + 'redirect' => Config::get('URL') . 'table/show/' . urlencode($database_name) . '/' . urlencode($table_name) + ]); + } else { + echo json_encode([ + 'success' => false, + 'message' => 'Failed to create table' + ]); + } + return; + } + + if (TableModel::createTable($database_name, $table_name, $columns)) { + Redirect::to('table/show/' . urlencode($database_name) . '/' . urlencode($table_name)); + } else { + Redirect::to('database/show/' . urlencode($database_name)); + } + return; + } + + // Show create table form + $this->View->render('table/create', array( + 'database_name' => $database_name + )); + } + + /** + * Show table structure + * @param string $database_name + * @param string $table_name + */ + public function structure($database_name = null, $table_name = null) + { + if (!$database_name) { + $database_name = Config::get('DB_NAME'); + } + + if (!$table_name) { + Redirect::to('database/show/' . urlencode($database_name)); + return; + } + + $this->View->render('table/structure', array( + 'database_name' => $database_name, + 'table_name' => $table_name, + 'columns' => TableModel::getTableColumns($database_name, $table_name), + 'indexes' => TableModel::getTableIndexes($database_name, $table_name), + 'table_info' => TableModel::getTableInfo($database_name, $table_name) + )); + } + + /** + * Add a column to a table + * @param string $database_name + * @param string $table_name + */ + public function addColumn($database_name = null, $table_name = null) + { + if (!$database_name) { + $database_name = Config::get('DB_NAME'); + } + + if (!$table_name) { + Redirect::to('database/show/' . urlencode($database_name)); + return; + } + + if (Request::post('submit_add_column')) { + $column_name = Request::post('column_name'); + $column_type = Request::post('column_type'); + $column_null = Request::post('column_null'); + $column_key = Request::post('column_key'); + $column_default = Request::post('column_default'); + $column_extra = Request::post('column_extra'); + + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + + if (TableModel::addColumn($database_name, $table_name, $column_name, $column_type, $column_null, $column_key, $column_default, $column_extra)) { + echo json_encode([ + 'success' => true, + 'message' => 'Column added successfully', + 'reload' => true + ]); + } else { + echo json_encode([ + 'success' => false, + 'message' => 'Failed to add column' + ]); + } + return; + } + + if (TableModel::addColumn($database_name, $table_name, $column_name, $column_type, $column_null, $column_key, $column_default, $column_extra)) { + Redirect::to('table/structure/' . urlencode($database_name) . '/' . urlencode($table_name)); + } else { + Redirect::to('table/structure/' . urlencode($database_name) . '/' . urlencode($table_name)); + } + return; + } + + // Show add column form + $this->View->render('table/add_column', array( + 'database_name' => $database_name, + 'table_name' => $table_name + )); + } + + /** + * Drop a column from a table + * @param string $database_name + * @param string $table_name + * @param string $column_name + */ + public function dropColumn($database_name, $table_name, $column_name) + { + $success = TableModel::dropColumn($database_name, $table_name, $column_name); + + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + if ($success) { + echo json_encode([ + 'success' => true, + 'message' => 'Column dropped successfully', + 'reload' => true + ]); + } else { + echo json_encode([ + 'success' => false, + 'message' => 'Failed to drop column' + ]); + } + return; + } + + Redirect::to('table/structure/' . urlencode($database_name) . '/' . urlencode($table_name)); + } + + /** + * Delete a table + * @param string $database_name + * @param string $table_name + */ + public function delete($database_name, $table_name) + { + $success = TableModel::deleteTable($database_name, $table_name); + + if ($this->isAjaxRequest()) { + header('Content-Type: application/json'); + if ($success) { + echo json_encode([ + 'success' => true, + 'message' => 'Table deleted successfully', + 'redirect' => Config::get('URL') . 'database/show/' . urlencode($database_name) + ]); + } else { + echo json_encode([ + 'success' => false, + 'message' => 'Failed to delete table' + ]); + } + return; + } + + Redirect::to('database/show/' . urlencode($database_name)); + } + + /** + * Check if the request is an AJAX request + */ + private function isAjaxRequest() + { + return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && + strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'; + } +} \ No newline at end of file diff --git a/application/model/DatabaseModel.php b/application/model/DatabaseModel.php new file mode 100644 index 0000000..82ab616 --- /dev/null +++ b/application/model/DatabaseModel.php @@ -0,0 +1,183 @@ +getConnection(); + + $sql = "SHOW DATABASES"; + $query = $database->prepare($sql); + $query->execute(); + + $databases = $query->fetchAll(PDO::FETCH_COLUMN); + + // Filter out system databases + $system_dbs = ['information_schema', 'performance_schema', 'mysql', 'sys']; + return array_diff($databases, $system_dbs); + } + + /** + * Get all tables in a specific database + * @param string $database_name + * @return array + */ + public static function getTablesInDatabase($database_name) + { + $database = DatabaseFactory::getFactory()->getConnection(); + + $sql = "SHOW TABLES FROM " . $database_name; + $query = $database->prepare($sql); + $query->execute(); + + return $query->fetchAll(PDO::FETCH_COLUMN); + } + + /** + * Get detailed information about tables in a database + * @param string $database_name + * @return array + */ + public static function getTableDetails($database_name) + { + $database = DatabaseFactory::getFactory()->getConnection(); + $tables = self::getTablesInDatabase($database_name); + $table_details = array(); + + foreach ($tables as $table) { + $sql = "SHOW TABLE STATUS FROM " . $database_name . " LIKE :table_name"; + $query = $database->prepare($sql); + $query->execute(array(':table_name' => $table)); + + $details = $query->fetch(PDO::FETCH_ASSOC); + if ($details) { + $table_details[$table] = array( + 'engine' => $details['Engine'], + 'rows' => $details['Rows'], + 'data_size' => self::formatBytes($details['Data_length']), + 'index_size' => self::formatBytes($details['Index_length']), + 'total_size' => self::formatBytes($details['Data_length'] + $details['Index_length']), + 'collation' => $details['Collation'], + 'comment' => $details['Comment'] + ); + } + } + + return $table_details; + } + + /** + * Get complete database structure (tables and columns) + * @param string $database_name + * @return array + */ + public static function getDatabaseStructure($database_name) + { + $database = DatabaseFactory::getFactory()->getConnection(); + $structure = array(); + $tables = self::getTablesInDatabase($database_name); + + foreach ($tables as $table) { + $sql = "DESCRIBE " . $database_name . "." . $table; + $query = $database->prepare($sql); + $query->execute(); + + $columns = $query->fetchAll(PDO::FETCH_ASSOC); + $structure[$table] = $columns; + } + + return $structure; + } + + /** + * Create a new database + * @param string $database_name + * @return bool + */ + public static function createDatabase($database_name) + { + if (!$database_name || !preg_match('/^[a-zA-Z0-9_]+$/', $database_name)) { + return false; + } + + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + $sql = "CREATE DATABASE `" . $database_name . "` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"; + $query = $database->prepare($sql); + return $query->execute(); + } catch (PDOException $e) { + return false; + } + } + + /** + * Delete a database + * @param string $database_name + * @return bool + */ + public static function deleteDatabase($database_name) + { + if (!$database_name) { + return false; + } + + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + $sql = "DROP DATABASE `" . $database_name . "`"; + $query = $database->prepare($sql); + return $query->execute(); + } catch (PDOException $e) { + return false; + } + } + + /** + * Get table columns with details + * @param string $database_name + * @param string $table_name + * @return array + */ + public static function getTableColumns($database_name, $table_name) + { + $database = DatabaseFactory::getFactory()->getConnection(); + + $sql = "SHOW COLUMNS FROM " . $database_name . "." . $table_name; + $query = $database->prepare($sql); + $query->execute(); + + return $query->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * Format bytes to human readable format + * @param int $bytes + * @return string + */ + private static function formatBytes($bytes) + { + if ($bytes >= 1073741824) { + return number_format($bytes / 1073741824, 2) . ' GB'; + } elseif ($bytes >= 1048576) { + return number_format($bytes / 1048576, 2) . ' MB'; + } elseif ($bytes >= 1024) { + return number_format($bytes / 1024, 2) . ' KB'; + } elseif ($bytes > 1) { + return $bytes . ' bytes'; + } elseif ($bytes == 1) { + return '1 byte'; + } else { + return '0 bytes'; + } + } +} \ No newline at end of file diff --git a/application/model/SqlModel.php b/application/model/SqlModel.php new file mode 100644 index 0000000..3925f56 --- /dev/null +++ b/application/model/SqlModel.php @@ -0,0 +1,289 @@ +getConnection(); + + // Determine query type + $query_type = self::getQueryType($sql_query); + + // Execute the query + $query = $database->prepare($sql_query); + $query->execute(); + + $execution_time = number_format((microtime(true) - $start_time) * 1000, 2); + + // Handle different query types + if ($query_type === 'SELECT' || $query_type === 'SHOW' || $query_type === 'DESCRIBE' || $query_type === 'EXPLAIN') { + // Return result set + $result = $query->fetchAll(PDO::FETCH_ASSOC); + $message = 'Query executed successfully. ' . count($result) . ' rows returned.'; + + return array( + 'success' => true, + 'message' => $message, + 'result' => $result, + 'query_type' => $query_type, + 'execution_time' => $execution_time, + 'affected_rows' => 0 + ); + } else { + // Return affected rows count + $affected_rows = $query->rowCount(); + $message = 'Query executed successfully. ' . $affected_rows . ' row(s) affected.'; + + return array( + 'success' => true, + 'message' => $message, + 'query_type' => $query_type, + 'execution_time' => $execution_time, + 'affected_rows' => $affected_rows, + 'result' => array() + ); + } + } catch (PDOException $e) { + return array( + 'success' => false, + 'message' => 'Query execution failed', + 'error' => $e->getMessage(), + 'query_type' => 'ERROR', + 'execution_time' => 0, + 'result' => array() + ); + } + } + + /** + * Save query to history + * @param int $user_id + * @param string $database_name + * @param string $sql_query + * @return bool + */ + private static function saveQueryToHistory($user_id, $database_name, $sql_query) + { + // Create history table if it doesn't exist + self::createHistoryTableIfNotExists(); + + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + $sql = "INSERT INTO sql_query_history (user_id, database_name, query_text, query_timestamp) + VALUES (:user_id, :database_name, :query_text, NOW())"; + $query = $database->prepare($sql); + $query->execute(array( + ':user_id' => $user_id, + ':database_name' => $database_name, + ':query_text' => $sql_query + )); + + // Keep only last 50 queries per user + $sql = "DELETE FROM sql_query_history + WHERE user_id = :user_id + AND id NOT IN ( + SELECT id FROM ( + SELECT id FROM sql_query_history + WHERE user_id = :user_id + ORDER BY query_timestamp DESC + LIMIT 50 + ) AS temp + )"; + $query = $database->prepare($sql); + $query->execute(array(':user_id' => $user_id)); + + return true; + } catch (PDOException $e) { + return false; + } + } + + /** + * Create SQL query history table if it doesn't exist + */ + private static function createHistoryTableIfNotExists() + { + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + $sql = "CREATE TABLE IF NOT EXISTS sql_query_history ( + id INT AUTO_INCREMENT PRIMARY KEY, + user_id INT NOT NULL, + database_name VARCHAR(64) NOT NULL, + query_text TEXT NOT NULL, + query_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + INDEX idx_user_timestamp (user_id, query_timestamp) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"; + $database->exec($sql); + } catch (PDOException $e) { + // Table creation failed + } + } + + /** + * Get query history for a user + * @param int $user_id + * @param int $limit + * @return array + */ + public static function getQueryHistory($user_id, $limit = 50) + { + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + $sql = "SELECT database_name, query_text, query_timestamp + FROM sql_query_history + WHERE user_id = :user_id + ORDER BY query_timestamp DESC + LIMIT :limit"; + $query = $database->prepare($sql); + $query->bindValue(':user_id', $user_id, PDO::PARAM_INT); + $query->bindValue(':limit', $limit, PDO::PARAM_INT); + $query->execute(); + + return $query->fetchAll(PDO::FETCH_ASSOC); + } catch (PDOException $e) { + return array(); + } + } + + /** + * Clear query history for a user + * @param int $user_id + * @return bool + */ + public static function clearQueryHistory($user_id) + { + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + $sql = "DELETE FROM sql_query_history WHERE user_id = :user_id"; + $query = $database->prepare($sql); + return $query->execute(array(':user_id' => $user_id)); + } catch (PDOException $e) { + return false; + } + } + + /** + * Get database schema for autocomplete + * @param string $database_name + * @return array + */ + public static function getDatabaseSchema($database_name) + { + $database = DatabaseFactory::getFactory()->getConnection(); + $schema = array(); + + try { + // Get all tables + $sql = "SHOW TABLES FROM " . $database_name; + $query = $database->prepare($sql); + $query->execute(); + $tables = $query->fetchAll(PDO::FETCH_COLUMN); + + foreach ($tables as $table) { + // Get columns for each table + $sql = "SHOW COLUMNS FROM " . $database_name . "." . $table; + $query = $database->prepare($sql); + $query->execute(); + $columns = $query->fetchAll(PDO::FETCH_ASSOC); + + $schema[$table] = array_map(function($column) { + return $column['Field']; + }, $columns); + } + + return $schema; + } catch (PDOException $e) { + return array(); + } + } + + /** + * Format SQL query (basic formatting) + * @param string $query + * @return string + */ + public static function formatQuery($query) + { + // Basic SQL formatting + $query = trim($query); + + // Uppercase SQL keywords + $keywords = array( + 'SELECT', 'FROM', 'WHERE', 'AND', 'OR', 'ORDER BY', 'GROUP BY', + 'HAVING', 'LIMIT', 'OFFSET', 'INSERT', 'INTO', 'VALUES', + 'UPDATE', 'SET', 'DELETE', 'CREATE', 'TABLE', 'ALTER', 'DROP', + 'INDEX', 'PRIMARY KEY', 'FOREIGN KEY', 'REFERENCES', 'JOIN', + 'INNER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'ON', 'AS', 'DISTINCT', + 'COUNT', 'SUM', 'AVG', 'MIN', 'MAX', 'EXISTS', 'IN', 'BETWEEN', + 'LIKE', 'IS NULL', 'IS NOT NULL', 'UNION', 'ALL' + ); + + foreach ($keywords as $keyword) { + $query = preg_replace('/\b' . preg_quote($keyword) . '\b/i', $keyword, $query); + } + + // Add line breaks for better readability + $query = preg_replace('/\b(FROM|WHERE|GROUP BY|ORDER BY|HAVING|LIMIT|UNION)\b/', "\n$1", $query); + $query = preg_replace('/,\s*(\w)/', ",\n $1", $query); + + return $query; + } + + /** + * Determine the type of SQL query + * @param string $sql_query + * @return string + */ + private static function getQueryType($sql_query) + { + $query = strtoupper(trim($sql_query)); + + if (strpos($query, 'SELECT') === 0) { + return 'SELECT'; + } elseif (strpos($query, 'INSERT') === 0) { + return 'INSERT'; + } elseif (strpos($query, 'UPDATE') === 0) { + return 'UPDATE'; + } elseif (strpos($query, 'DELETE') === 0) { + return 'DELETE'; + } elseif (strpos($query, 'CREATE') === 0) { + return 'CREATE'; + } elseif (strpos($query, 'ALTER') === 0) { + return 'ALTER'; + } elseif (strpos($query, 'DROP') === 0) { + return 'DROP'; + } elseif (strpos($query, 'SHOW') === 0) { + return 'SHOW'; + } elseif (strpos($query, 'DESCRIBE') === 0) { + return 'DESCRIBE'; + } elseif (strpos($query, 'EXPLAIN') === 0) { + return 'EXPLAIN'; + } else { + return 'OTHER'; + } + } +} \ No newline at end of file diff --git a/application/model/TableModel.php b/application/model/TableModel.php new file mode 100644 index 0000000..ca1a628 --- /dev/null +++ b/application/model/TableModel.php @@ -0,0 +1,284 @@ +getConnection(); + + $offset = ($page - 1) * $per_page; + + $sql = "SELECT * FROM `" . $database_name . "`.`" . $table_name . "` LIMIT :offset, :per_page"; + $query = $database->prepare($sql); + $query->bindParam(':offset', $offset, PDO::PARAM_INT); + $query->bindParam(':per_page', $per_page, PDO::PARAM_INT); + $query->execute(); + + return $query->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * Get total number of rows in a table + * @param string $database_name + * @param string $table_name + * @return int + */ + public static function getTableRowCount($database_name, $table_name) + { + $database = DatabaseFactory::getFactory()->getConnection(); + + $sql = "SELECT COUNT(*) as count FROM `" . $database_name . "`.`" . $table_name . "`"; + $query = $database->prepare($sql); + $query->execute(); + + $result = $query->fetch(PDO::FETCH_ASSOC); + return (int)$result['count']; + } + + /** + * Get table column information + * @param string $database_name + * @param string $table_name + * @return array + */ + public static function getTableColumns($database_name, $table_name) + { + $database = DatabaseFactory::getFactory()->getConnection(); + + $sql = "SHOW COLUMNS FROM `" . $database_name . "`.`" . $table_name . "`"; + $query = $database->prepare($sql); + $query->execute(); + + return $query->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * Get table indexes + * @param string $database_name + * @param string $table_name + * @return array + */ + public static function getTableIndexes($database_name, $table_name) + { + $database = DatabaseFactory::getFactory()->getConnection(); + + $sql = "SHOW INDEX FROM `" . $database_name . "`.`" . $table_name . "`"; + $query = $database->prepare($sql); + $query->execute(); + + return $query->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * Get table information + * @param string $database_name + * @param string $table_name + * @return array + */ + public static function getTableInfo($database_name, $table_name) + { + $database = DatabaseFactory::getFactory()->getConnection(); + + $sql = "SHOW TABLE STATUS FROM `" . $database_name . "` LIKE :table_name"; + $query = $database->prepare($sql); + $query->execute(array(':table_name' => $table_name)); + + $result = $query->fetch(PDO::FETCH_ASSOC); + + if ($result) { + return array( + 'engine' => $result['Engine'], + 'rows' => $result['Rows'], + 'data_size' => self::formatBytes($result['Data_length']), + 'index_size' => self::formatBytes($result['Index_length']), + 'total_size' => self::formatBytes($result['Data_length'] + $result['Index_length']), + 'collation' => $result['Collation'], + 'comment' => $result['Comment'], + 'auto_increment' => $result['Auto_increment'], + 'create_time' => $result['Create_time'], + 'update_time' => $result['Update_time'] + ); + } + + return array(); + } + + /** + * Create a new table + * @param string $database_name + * @param string $table_name + * @param array $columns + * @return bool + */ + public static function createTable($database_name, $table_name, $columns) + { + if (!$database_name || !$table_name || empty($columns)) { + return false; + } + + $database = DatabaseFactory::getFactory()->getConnection(); + + // Build column definitions + $column_definitions = array(); + foreach ($columns as $column) { + $definition = "`" . $column['name'] . "` " . $column['type']; + + if (isset($column['null']) && $column['null'] === 'NO') { + $definition .= " NOT NULL"; + } + + if (isset($column['default']) && $column['default'] !== '') { + $definition .= " DEFAULT '" . $column['default'] . "'"; + } + + if (isset($column['extra']) && $column['extra'] === 'auto_increment') { + $definition .= " AUTO_INCREMENT"; + } + + $column_definitions[] = $definition; + } + + // Handle primary key + foreach ($columns as $column) { + if (isset($column['key']) && $column['key'] === 'PRI') { + $column_definitions[] = "PRIMARY KEY (`" . $column['name'] . "`)"; + break; + } + } + + $columns_sql = implode(', ', $column_definitions); + + try { + $sql = "CREATE TABLE `" . $database_name . "`.`" . $table_name . "` (" . $columns_sql . ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"; + $query = $database->prepare($sql); + return $query->execute(); + } catch (PDOException $e) { + return false; + } + } + + /** + * Delete a table + * @param string $database_name + * @param string $table_name + * @return bool + */ + public static function deleteTable($database_name, $table_name) + { + if (!$database_name || !$table_name) { + return false; + } + + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + $sql = "DROP TABLE `" . $database_name . "`.`" . $table_name . "`"; + $query = $database->prepare($sql); + return $query->execute(); + } catch (PDOException $e) { + return false; + } + } + + /** + * Add a column to a table + * @param string $database_name + * @param string $table_name + * @param string $column_name + * @param string $column_type + * @param string $column_null + * @param string $column_key + * @param string $column_default + * @param string $column_extra + * @return bool + */ + public static function addColumn($database_name, $table_name, $column_name, $column_type, $column_null, $column_key, $column_default, $column_extra) + { + if (!$database_name || !$table_name || !$column_name || !$column_type) { + return false; + } + + $database = DatabaseFactory::getFactory()->getConnection(); + + $definition = "`" . $column_name . "` " . $column_type; + + if ($column_null === 'NO') { + $definition .= " NOT NULL"; + } + + if ($column_default !== '') { + $definition .= " DEFAULT '" . $column_default . "'"; + } + + if ($column_extra === 'auto_increment') { + $definition .= " AUTO_INCREMENT"; + } + + try { + $sql = "ALTER TABLE `" . $database_name . "`.`" . $table_name . "` ADD " . $definition; + $query = $database->prepare($sql); + return $query->execute(); + } catch (PDOException $e) { + return false; + } + } + + /** + * Drop a column from a table + * @param string $database_name + * @param string $table_name + * @param string $column_name + * @return bool + */ + public static function dropColumn($database_name, $table_name, $column_name) + { + if (!$database_name || !$table_name || !$column_name) { + return false; + } + + $database = DatabaseFactory::getFactory()->getConnection(); + + try { + $sql = "ALTER TABLE `" . $database_name . "`.`" . $table_name . "` DROP COLUMN `" . $column_name . "`"; + $query = $database->prepare($sql); + return $query->execute(); + } catch (PDOException $e) { + return false; + } + } + + /** + * Format bytes to human readable format + * @param int $bytes + * @return string + */ + private static function formatBytes($bytes) + { + if ($bytes >= 1073741824) { + return number_format($bytes / 1073741824, 2) . ' GB'; + } elseif ($bytes >= 1048576) { + return number_format($bytes / 1048576, 2) . ' MB'; + } elseif ($bytes >= 1024) { + return number_format($bytes / 1024, 2) . ' KB'; + } elseif ($bytes > 1) { + return $bytes . ' bytes'; + } elseif ($bytes == 1) { + return '1 byte'; + } else { + return '0 bytes'; + } + } +} \ No newline at end of file diff --git a/application/view/message/index.php b/application/view/message/index.php index 7a072f5..c56a02a 100644 --- a/application/view/message/index.php +++ b/application/view/message/index.php @@ -2,98 +2,82 @@