Quellcode durchsuchen

Initial version

svalavuo vor 6 Tagen
Ursprung
Commit
c01d10a8cb
14 geänderte Dateien mit 2452 neuen und 0 gelöschten Zeilen
  1. 233 0
      README.md
  2. 179 0
      admin/edit.php
  3. 136 0
      admin/index.php
  4. 66 0
      admin/login.php
  5. 10 0
      admin/logout.php
  6. 751 0
      css/style.css
  7. 64 0
      includes/auth.php
  8. 121 0
      includes/database.php
  9. 252 0
      includes/publication.php
  10. 160 0
      public/index.php
  11. 125 0
      public/publication.php
  12. 125 0
      public/search.php
  13. 62 0
      setup/database.sql
  14. 168 0
      setup/setup.php

+ 233 - 0
README.md

@@ -0,0 +1,233 @@
+# Web Publication System
+
+A simple, clean web publication system built with PHP and MariaDB. This system allows you to create, manage, and publish articles or blog posts with categories, search functionality, and a responsive admin interface.
+
+## Features
+
+- **Admin Panel**: Secure login and dashboard for managing publications
+- **Publication Management**: Create, edit, delete, and publish articles
+- **Categories**: Organize publications with categories
+- **Search**: Full-text search across publications
+- **Responsive Design**: Mobile-friendly interface for both admin and public sites
+- **User Authentication**: Secure login system with password hashing
+- **SEO Friendly**: Clean URLs and meta information
+
+## Requirements
+
+- PHP 7.4 or higher
+- MariaDB 10.3+ or MySQL 5.7+
+- Web server (Apache, Nginx, or PHP built-in server)
+- PHP extensions: PDO, PDO_MySQL, mbstring
+
+## Installation
+
+### 1. Setup Database
+
+Create a database and user for the system:
+
+```sql
+CREATE DATABASE webpub;
+CREATE USER 'webpub_user'@'localhost' IDENTIFIED BY 'your_password';
+GRANT ALL PRIVILEGES ON webpub.* TO 'webpub_user'@'localhost';
+FLUSH PRIVILEGES;
+```
+
+### 2. Web Server Setup
+
+Place the files in your web root or a subdirectory. For example:
+
+```
+/var/www/html/web-pub-system/
+```
+
+### 3. Run Setup Script
+
+1. Ensure the `setup/` directory is accessible via web browser
+2. Navigate to: `http://your-domain.com/web-pub-system/setup/`
+3. Follow the installation wizard:
+   - Enter database connection details
+   - Set site title and admin credentials
+   - Complete the installation
+
+### 4. Secure Installation
+
+After successful installation:
+
+1. **Delete the setup directory** for security:
+   ```bash
+   rm -rf /path/to/web-pub-system/setup/
+   ```
+
+2. **Set proper file permissions**:
+   ```bash
+   chmod 755 /path/to/web-pub-system/
+   chmod 644 /path/to/web-pub-system/includes/config.php
+   ```
+
+## Directory Structure
+
+```
+web-pub-system/
+|-- admin/                  # Admin interface files
+|   |-- index.php          # Dashboard
+|   |-- login.php          # Login page
+|   |-- edit.php           # Create/edit publications
+|   |-- logout.php         # Logout handler
+|   |-- publications.php   # Publication management
+|   |-- categories.php     # Category management
+|-- public/                 # Public-facing pages
+|   |-- index.php          # Homepage with publication list
+|   |-- publication.php   # Individual publication view
+|   |-- search.php         # Search results
+|   |-- categories.php     # Category listings
+|-- includes/              # Core PHP classes
+|   |-- config.php         # Configuration (created during setup)
+|   |-- database.php       # Database connection class
+|   |-- auth.php           # Authentication class
+|   |-- publication.php    # Publication model class
+|-- css/                   # Stylesheets
+|   |-- style.css          # Main stylesheet
+|-- setup/                 # Installation files (delete after use)
+|   |-- setup.php          # Setup wizard
+|   |-- database.sql       # Database schema
+|-- README.md              # This file
+```
+
+## Usage
+
+### Admin Panel
+
+1. Access the admin panel at: `http://your-domain.com/web-pub-system/admin/`
+2. Login with the credentials you created during setup
+3. From the dashboard you can:
+   - Create new publications
+   - Edit existing publications
+   - Manage categories
+   - View statistics
+
+### Creating Publications
+
+1. Click "Create New Publication" from the dashboard
+2. Fill in the publication details:
+   - Title (required)
+   - Summary (optional, for preview)
+   - Content (required)
+   - Author (defaults to logged-in user)
+   - Status (Draft, Published, or Archived)
+   - Categories (optional)
+3. Save the publication
+
+### Public Site
+
+The public site is available at: `http://your-domain.com/web-pub-system/public/`
+
+Features:
+- Browse all published publications
+- Filter by categories
+- Search publications
+- View individual publications
+- Responsive design for mobile devices
+
+## Configuration
+
+The main configuration is stored in `includes/config.php` and is created during setup. Key settings include:
+
+```php
+// Database configuration
+define('DB_HOST', 'localhost');
+define('DB_NAME', 'webpub');
+define('DB_USER', 'your_db_user');
+define('DB_PASS', 'your_db_password');
+
+// Site configuration
+define('SITE_TITLE', 'Web Publication System');
+define('SITE_URL', 'http://your-domain.com/web-pub-system/');
+define('ADMIN_EMAIL', 'admin@example.com');
+```
+
+## Security Considerations
+
+1. **Delete setup directory**: Always remove the `setup/` directory after installation
+2. **Strong passwords**: Use strong admin passwords
+3. **File permissions**: Ensure proper file permissions on sensitive files
+4. **HTTPS**: Use HTTPS in production for secure login
+5. **Regular updates**: Keep PHP and MariaDB updated
+
+## Customization
+
+### Styling
+
+Edit `css/style.css` to customize the appearance. The CSS is organized with clear sections for:
+
+- Base styles and typography
+- Admin interface styles
+- Public site styles
+- Responsive design breakpoints
+
+### Database Schema
+
+The database schema is defined in `setup/database.sql`. You can extend it by:
+
+1. Adding new tables to the SQL file
+2. Updating the Publication model class
+3. Modifying forms and templates as needed
+
+### Adding Features
+
+The system is built with an object-oriented approach, making it easy to extend:
+
+- **New Models**: Create new model classes in the `includes/` directory
+- **Admin Pages**: Add new admin pages in the `admin/` directory
+- **Public Pages**: Add new public pages in the `public/` directory
+
+## Troubleshooting
+
+### Common Issues
+
+1. **Database Connection Error**
+   - Check database credentials in `includes/config.php`
+   - Ensure database server is running
+   - Verify user permissions
+
+2. **Blank Pages**
+   - Check PHP error logs
+   - Ensure all required PHP extensions are installed
+   - Verify file permissions
+
+3. **Login Issues**
+   - Clear browser cookies and session
+   - Check if sessions are properly configured
+   - Verify password was correctly hashed
+
+### Error Logging
+
+Enable PHP error logging for debugging:
+
+```php
+// Add to top of index.php or config.php
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+```
+
+## License
+
+This project is open source and available under the MIT License.
+
+## Support
+
+For issues and questions:
+
+1. Check this README file
+2. Review the code comments
+3. Test with the sample data provided during setup
+
+## Version History
+
+- **v1.0.0**: Initial release with basic publication management
+  - Admin interface with authentication
+  - Publication CRUD operations
+  - Category system
+  - Search functionality
+  - Responsive design
+  - Setup wizard

+ 179 - 0
admin/edit.php

@@ -0,0 +1,179 @@
+<?php
+require_once '../includes/config.php';
+require_once '../includes/database.php';
+require_once '../includes/auth.php';
+require_once '../includes/publication.php';
+
+$auth = new Auth();
+$auth->requireAuth();
+
+$publication = new Publication();
+$user = $auth->getUser();
+
+$pubId = $_GET['id'] ?? null;
+$pub = null;
+$categories = [];
+$selectedCategories = [];
+
+// Get all available categories
+$allCategories = $publication->getCategories();
+
+if ($pubId) {
+    $pub = $publication->getById($pubId);
+    if (!$pub) {
+        die('Publication not found');
+    }
+}
+
+// Handle form submission
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+    $title = trim($_POST['title'] ?? '');
+    $content = trim($_POST['content'] ?? '');
+    $summary = trim($_POST['summary'] ?? '');
+    $author = trim($_POST['author'] ?? $user['username']);
+    $status = $_POST['status'] ?? 'draft';
+    $categoryIds = $_POST['categories'] ?? [];
+    
+    $errors = [];
+    
+    if (empty($title)) $errors[] = 'Title is required';
+    if (empty($content)) $errors[] = 'Content is required';
+    if (empty($author)) $errors[] = 'Author is required';
+    
+    if (empty($errors)) {
+        $data = [
+            'title' => $title,
+            'content' => $content,
+            'summary' => $summary,
+            'author' => $author,
+            'status' => $status
+        ];
+        
+        try {
+            if ($pubId) {
+                $publication->update($pubId, $data, $categoryIds);
+                $message = 'Publication updated successfully';
+            } else {
+                $publication->create($data, $categoryIds);
+                $message = 'Publication created successfully';
+                header('Location: index.php?message=' . urlencode($message));
+                exit;
+            }
+        } catch (Exception $e) {
+            $errors[] = 'Error saving publication: ' . $e->getMessage();
+        }
+    }
+    
+    // Preserve form data on error
+    $pub = [
+        'title' => $title,
+        'content' => $content,
+        'summary' => $summary,
+        'author' => $author,
+        'status' => $status
+    ];
+    $selectedCategories = $categoryIds;
+} elseif ($pub) {
+    // Get selected categories for existing publication
+    $sql = "SELECT category_id FROM publication_categories WHERE publication_id = ?";
+    $selectedCategories = array_column($publication->db->fetchAll($sql, [$pubId]), 'category_id');
+}
+?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title><?php echo $pubId ? 'Edit' : 'Create'; ?> Publication - <?php echo SITE_TITLE; ?></title>
+    <link rel="stylesheet" href="../css/style.css">
+</head>
+<body>
+    <div class="admin-layout">
+        <header class="admin-header">
+            <div class="header-content">
+                <h1><?php echo SITE_TITLE; ?></h1>
+                <nav class="admin-nav">
+                    <a href="index.php" class="nav-link">Dashboard</a>
+                    <a href="publications.php" class="nav-link">Publications</a>
+                    <a href="categories.php" class="nav-link">Categories</a>
+                    <a href="logout.php" class="nav-link">Logout</a>
+                </nav>
+                <div class="user-info">
+                    Welcome, <?php echo htmlspecialchars($user['username']); ?>
+                </div>
+            </div>
+        </header>
+
+        <main class="admin-main">
+            <h2><?php echo $pubId ? 'Edit' : 'Create'; ?> Publication</h2>
+            
+            <?php if (!empty($errors)): ?>
+                <div class="alert alert-error">
+                    <?php foreach ($errors as $error): ?>
+                        <p><?php echo htmlspecialchars($error); ?></p>
+                    <?php endforeach; ?>
+                </div>
+            <?php endif; ?>
+            
+            <?php if (isset($message)): ?>
+                <div class="alert alert-success">
+                    <?php echo htmlspecialchars($message); ?>
+                </div>
+            <?php endif; ?>
+
+            <form method="post" class="publication-form">
+                <div class="form-group">
+                    <label for="title">Title *</label>
+                    <input type="text" id="title" name="title" 
+                           value="<?php echo htmlspecialchars($pub['title'] ?? ''); ?>" required>
+                </div>
+
+                <div class="form-group">
+                    <label for="summary">Summary</label>
+                    <textarea id="summary" name="summary" rows="3"><?php echo htmlspecialchars($pub['summary'] ?? ''); ?></textarea>
+                </div>
+
+                <div class="form-group">
+                    <label for="author">Author *</label>
+                    <input type="text" id="author" name="author" 
+                           value="<?php echo htmlspecialchars($pub['author'] ?? $user['username']); ?>" required>
+                </div>
+
+                <div class="form-group">
+                    <label for="status">Status</label>
+                    <select id="status" name="status">
+                        <option value="draft" <?php echo ($pub['status'] ?? 'draft') === 'draft' ? 'selected' : ''; ?>>Draft</option>
+                        <option value="published" <?php echo ($pub['status'] ?? '') === 'published' ? 'selected' : ''; ?>>Published</option>
+                        <option value="archived" <?php echo ($pub['status'] ?? '') === 'archived' ? 'selected' : ''; ?>>Archived</option>
+                    </select>
+                </div>
+
+                <div class="form-group">
+                    <label>Categories</label>
+                    <div class="category-checkboxes">
+                        <?php foreach ($allCategories as $category): ?>
+                            <label class="checkbox-label">
+                                <input type="checkbox" name="categories[]" value="<?php echo $category['id']; ?>"
+                                       <?php echo in_array($category['id'], $selectedCategories) ? 'checked' : ''; ?>>
+                                <?php echo htmlspecialchars($category['name']); ?>
+                            </label>
+                        <?php endforeach; ?>
+                    </div>
+                </div>
+
+                <div class="form-group">
+                    <label for="content">Content *</label>
+                    <textarea id="content" name="content" rows="20" required><?php echo htmlspecialchars($pub['content'] ?? ''); ?></textarea>
+                </div>
+
+                <div class="form-actions">
+                    <button type="submit" class="btn btn-primary">
+                        <?php echo $pubId ? 'Update' : 'Create'; ?> Publication
+                    </button>
+                    <a href="index.php" class="btn btn-secondary">Cancel</a>
+                </div>
+            </form>
+        </main>
+    </div>
+</body>
+</html>

+ 136 - 0
admin/index.php

@@ -0,0 +1,136 @@
+<?php
+require_once '../includes/config.php';
+require_once '../includes/database.php';
+require_once '../includes/auth.php';
+require_once '../includes/publication.php';
+
+$auth = new Auth();
+$auth->requireAuth();
+
+$publication = new Publication();
+$user = $auth->getUser();
+
+// Handle actions
+$action = $_GET['action'] ?? '';
+$message = '';
+
+if ($action === 'delete' && isset($_GET['id'])) {
+    $id = (int)$_GET['id'];
+    try {
+        $publication->delete($id);
+        $message = 'Publication deleted successfully';
+    } catch (Exception $e) {
+        $message = 'Error deleting publication: ' . $e->getMessage();
+    }
+}
+
+// Get statistics
+$stats = $publication->getStats();
+
+// Get recent publications
+$recentPublications = $publication->getAll('all', 10);
+?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Admin Dashboard - <?php echo SITE_TITLE; ?></title>
+    <link rel="stylesheet" href="../css/style.css">
+</head>
+<body>
+    <div class="admin-layout">
+        <header class="admin-header">
+            <div class="header-content">
+                <h1><?php echo SITE_TITLE; ?></h1>
+                <nav class="admin-nav">
+                    <a href="index.php" class="nav-link active">Dashboard</a>
+                    <a href="publications.php" class="nav-link">Publications</a>
+                    <a href="categories.php" class="nav-link">Categories</a>
+                    <a href="logout.php" class="nav-link">Logout</a>
+                </nav>
+                <div class="user-info">
+                    Welcome, <?php echo htmlspecialchars($user['username']); ?>
+                </div>
+            </div>
+        </header>
+
+        <main class="admin-main">
+            <?php if ($message): ?>
+                <div class="alert alert-<?php echo strpos($message, 'Error') === false ? 'success' : 'error'; ?>">
+                    <?php echo htmlspecialchars($message); ?>
+                </div>
+            <?php endif; ?>
+
+            <section class="dashboard-stats">
+                <h2>Overview</h2>
+                <div class="stats-grid">
+                    <div class="stat-card">
+                        <h3>Total Publications</h3>
+                        <p class="stat-number"><?php echo $stats['total']; ?></p>
+                    </div>
+                    <div class="stat-card">
+                        <h3>Published</h3>
+                        <p class="stat-number"><?php echo $stats['published']; ?></p>
+                    </div>
+                    <div class="stat-card">
+                        <h3>Drafts</h3>
+                        <p class="stat-number"><?php echo $stats['draft']; ?></p>
+                    </div>
+                    <div class="stat-card">
+                        <h3>Archived</h3>
+                        <p class="stat-number"><?php echo $stats['archived']; ?></p>
+                    </div>
+                </div>
+            </section>
+
+            <section class="recent-publications">
+                <h2>Recent Publications</h2>
+                <div class="table-container">
+                    <table class="admin-table">
+                        <thead>
+                            <tr>
+                                <th>Title</th>
+                                <th>Author</th>
+                                <th>Status</th>
+                                <th>Created</th>
+                                <th>Actions</th>
+                            </tr>
+                        </thead>
+                        <tbody>
+                            <?php foreach ($recentPublications as $pub): ?>
+                                <tr>
+                                    <td>
+                                        <a href="edit.php?id=<?php echo $pub['id']; ?>">
+                                            <?php echo htmlspecialchars($pub['title']); ?>
+                                        </a>
+                                    </td>
+                                    <td><?php echo htmlspecialchars($pub['author']); ?></td>
+                                    <td>
+                                        <span class="status-badge status-<?php echo $pub['status']; ?>">
+                                            <?php echo ucfirst($pub['status']); ?>
+                                        </span>
+                                    </td>
+                                    <td><?php echo date('M j, Y', strtotime($pub['created_at'])); ?></td>
+                                    <td>
+                                        <a href="edit.php?id=<?php echo $pub['id']; ?>" class="btn btn-sm">Edit</a>
+                                        <a href="index.php?action=delete&id=<?php echo $pub['id']; ?>" 
+                                           class="btn btn-sm btn-danger" 
+                                           onclick="return confirm('Are you sure you want to delete this publication?')">
+                                            Delete
+                                        </a>
+                                    </td>
+                                </tr>
+                            <?php endforeach; ?>
+                        </tbody>
+                    </table>
+                </div>
+                
+                <div class="actions">
+                    <a href="edit.php" class="btn btn-primary">Create New Publication</a>
+                </div>
+            </section>
+        </main>
+    </div>
+</body>
+</html>

+ 66 - 0
admin/login.php

@@ -0,0 +1,66 @@
+<?php
+require_once '../includes/config.php';
+require_once '../includes/database.php';
+require_once '../includes/auth.php';
+
+$auth = new Auth();
+
+if ($auth->isLoggedIn()) {
+    header('Location: index.php');
+    exit;
+}
+
+$errors = [];
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+    $username = trim($_POST['username'] ?? '');
+    $password = $_POST['password'] ?? '';
+    
+    if (empty($username) || empty($password)) {
+        $errors[] = 'Please enter both username and password';
+    } elseif ($auth->login($username, $password)) {
+        header('Location: index.php');
+        exit;
+    } else {
+        $errors[] = 'Invalid username or password';
+    }
+}
+?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Admin Login - <?php echo SITE_TITLE; ?></title>
+    <link rel="stylesheet" href="../css/style.css">
+</head>
+<body class="login-page">
+    <div class="container">
+        <div class="login-form">
+            <h1>Admin Login</h1>
+            
+            <?php if (!empty($errors)): ?>
+                <div class="alert alert-error">
+                    <?php foreach ($errors as $error): ?>
+                        <p><?php echo htmlspecialchars($error); ?></p>
+                    <?php endforeach; ?>
+                </div>
+            <?php endif; ?>
+            
+            <form method="post">
+                <div class="form-group">
+                    <label for="username">Username:</label>
+                    <input type="text" id="username" name="username" required>
+                </div>
+                
+                <div class="form-group">
+                    <label for="password">Password:</label>
+                    <input type="password" id="password" name="password" required>
+                </div>
+                
+                <button type="submit" class="btn btn-primary">Login</button>
+            </form>
+        </div>
+    </div>
+</body>
+</html>

+ 10 - 0
admin/logout.php

@@ -0,0 +1,10 @@
+<?php
+require_once '../includes/config.php';
+require_once '../includes/auth.php';
+
+$auth = new Auth();
+$auth->logout();
+
+header('Location: login.php');
+exit;
+?>

+ 751 - 0
css/style.css

@@ -0,0 +1,751 @@
+/* Web Publication System Styles */
+
+/* Reset and Base Styles */
+* {
+    margin: 0;
+    padding: 0;
+    box-sizing: border-box;
+}
+
+body {
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
+    line-height: 1.6;
+    color: #333;
+    background-color: #f8f9fa;
+}
+
+.container {
+    max-width: 1200px;
+    margin: 0 auto;
+    padding: 0 20px;
+}
+
+/* Typography */
+h1, h2, h3, h4, h5, h6 {
+    margin-bottom: 1rem;
+    font-weight: 600;
+    line-height: 1.2;
+}
+
+h1 { font-size: 2.5rem; }
+h2 { font-size: 2rem; }
+h3 { font-size: 1.5rem; }
+h4 { font-size: 1.25rem; }
+
+p {
+    margin-bottom: 1rem;
+}
+
+a {
+    color: #007bff;
+    text-decoration: none;
+    transition: color 0.2s ease;
+}
+
+a:hover {
+    color: #0056b3;
+    text-decoration: underline;
+}
+
+/* Buttons */
+.btn {
+    display: inline-block;
+    padding: 0.5rem 1rem;
+    font-size: 0.875rem;
+    font-weight: 500;
+    text-align: center;
+    text-decoration: none;
+    border: 1px solid transparent;
+    border-radius: 0.375rem;
+    cursor: pointer;
+    transition: all 0.2s ease;
+}
+
+.btn-primary {
+    color: white;
+    background-color: #007bff;
+    border-color: #007bff;
+}
+
+.btn-primary:hover {
+    background-color: #0056b3;
+    border-color: #0056b3;
+    color: white;
+    text-decoration: none;
+}
+
+.btn-secondary {
+    color: #6c757d;
+    background-color: #fff;
+    border-color: #6c757d;
+}
+
+.btn-secondary:hover {
+    background-color: #6c757d;
+    color: white;
+    text-decoration: none;
+}
+
+.btn-danger {
+    color: white;
+    background-color: #dc3545;
+    border-color: #dc3545;
+}
+
+.btn-danger:hover {
+    background-color: #c82333;
+    border-color: #c82333;
+    color: white;
+    text-decoration: none;
+}
+
+.btn-sm {
+    padding: 0.25rem 0.5rem;
+    font-size: 0.75rem;
+}
+
+/* Forms */
+.form-group {
+    margin-bottom: 1.5rem;
+}
+
+.form-group label {
+    display: block;
+    margin-bottom: 0.5rem;
+    font-weight: 500;
+}
+
+input[type="text"],
+input[type="email"],
+input[type="password"],
+textarea,
+select {
+    width: 100%;
+    padding: 0.75rem;
+    border: 1px solid #ddd;
+    border-radius: 0.375rem;
+    font-size: 1rem;
+    transition: border-color 0.2s ease;
+}
+
+input:focus,
+textarea:focus,
+select:focus {
+    outline: none;
+    border-color: #007bff;
+    box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
+}
+
+textarea {
+    resize: vertical;
+    min-height: 100px;
+}
+
+/* Alerts */
+.alert {
+    padding: 1rem;
+    margin-bottom: 1.5rem;
+    border: 1px solid transparent;
+    border-radius: 0.375rem;
+}
+
+.alert-success {
+    color: #155724;
+    background-color: #d4edda;
+    border-color: #c3e6cb;
+}
+
+.alert-error {
+    color: #721c24;
+    background-color: #f8d7da;
+    border-color: #f5c6cb;
+}
+
+/* Login Page */
+.login-page {
+    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+    min-height: 100vh;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.login-form {
+    background: white;
+    padding: 2rem;
+    border-radius: 0.5rem;
+    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
+    width: 100%;
+    max-width: 400px;
+}
+
+.login-form h1 {
+    text-align: center;
+    margin-bottom: 2rem;
+    color: #333;
+}
+
+/* Admin Layout */
+.admin-layout {
+    min-height: 100vh;
+    background-color: #f8f9fa;
+}
+
+.admin-header {
+    background: white;
+    border-bottom: 1px solid #dee2e6;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.header-content {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 1rem 2rem;
+    max-width: 1200px;
+    margin: 0 auto;
+}
+
+.admin-nav {
+    display: flex;
+    gap: 2rem;
+}
+
+.nav-link {
+    color: #6c757d;
+    text-decoration: none;
+    padding: 0.5rem 0;
+    border-bottom: 2px solid transparent;
+    transition: all 0.2s ease;
+}
+
+.nav-link:hover,
+.nav-link.active {
+    color: #007bff;
+    border-bottom-color: #007bff;
+}
+
+.user-info {
+    color: #6c757d;
+    font-size: 0.875rem;
+}
+
+.admin-main {
+    padding: 2rem;
+    max-width: 1200px;
+    margin: 0 auto;
+}
+
+/* Dashboard Stats */
+.stats-grid {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+    gap: 1.5rem;
+    margin-bottom: 2rem;
+}
+
+.stat-card {
+    background: white;
+    padding: 1.5rem;
+    border-radius: 0.5rem;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    text-align: center;
+}
+
+.stat-card h3 {
+    color: #6c757d;
+    font-size: 0.875rem;
+    margin-bottom: 0.5rem;
+}
+
+.stat-number {
+    font-size: 2rem;
+    font-weight: 600;
+    color: #007bff;
+}
+
+/* Tables */
+.table-container {
+    background: white;
+    border-radius: 0.5rem;
+    overflow: hidden;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    margin-bottom: 1.5rem;
+}
+
+.admin-table {
+    width: 100%;
+    border-collapse: collapse;
+}
+
+.admin-table th,
+.admin-table td {
+    padding: 1rem;
+    text-align: left;
+    border-bottom: 1px solid #dee2e6;
+}
+
+.admin-table th {
+    background-color: #f8f9fa;
+    font-weight: 600;
+    color: #495057;
+}
+
+.admin-table tr:hover {
+    background-color: #f8f9fa;
+}
+
+.status-badge {
+    padding: 0.25rem 0.5rem;
+    border-radius: 0.25rem;
+    font-size: 0.75rem;
+    font-weight: 500;
+    text-transform: uppercase;
+}
+
+.status-published {
+    background-color: #d4edda;
+    color: #155724;
+}
+
+.status-draft {
+    background-color: #fff3cd;
+    color: #856404;
+}
+
+.status-archived {
+    background-color: #f8d7da;
+    color: #721c24;
+}
+
+/* Publication Form */
+.publication-form {
+    background: white;
+    padding: 2rem;
+    border-radius: 0.5rem;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.category-checkboxes {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+    gap: 0.5rem;
+}
+
+.checkbox-label {
+    display: flex;
+    align-items: center;
+    gap: 0.5rem;
+    cursor: pointer;
+}
+
+.checkbox-label input[type="checkbox"] {
+    width: auto;
+}
+
+.form-actions {
+    display: flex;
+    gap: 1rem;
+    margin-top: 2rem;
+}
+
+/* Public Site Styles */
+.site-header {
+    background: white;
+    border-bottom: 1px solid #dee2e6;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.site-header .container {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 1rem 20px;
+}
+
+.site-header h1 {
+    margin: 0;
+}
+
+.site-header h1 a {
+    color: #333;
+    text-decoration: none;
+}
+
+.main-nav {
+    display: flex;
+    gap: 2rem;
+}
+
+.main-nav a {
+    color: #6c757d;
+    text-decoration: none;
+    padding: 0.5rem 0;
+    border-bottom: 2px solid transparent;
+    transition: all 0.2s ease;
+}
+
+.main-nav a:hover {
+    color: #007bff;
+    border-bottom-color: #007bff;
+}
+
+/* Content Layout */
+.content-layout {
+    display: grid;
+    grid-template-columns: 300px 1fr;
+    gap: 2rem;
+    margin-top: 2rem;
+}
+
+/* Sidebar */
+.sidebar {
+    background: white;
+    padding: 1.5rem;
+    border-radius: 0.5rem;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    height: fit-content;
+}
+
+.sidebar-section {
+    margin-bottom: 2rem;
+}
+
+.sidebar-section:last-child {
+    margin-bottom: 0;
+}
+
+.sidebar-section h3 {
+    font-size: 1.125rem;
+    margin-bottom: 1rem;
+    color: #333;
+}
+
+.search-form {
+    display: flex;
+    gap: 0.5rem;
+}
+
+.search-form input {
+    flex: 1;
+}
+
+.category-list {
+    list-style: none;
+}
+
+.category-list li {
+    margin-bottom: 0.5rem;
+}
+
+.category-list a {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0.5rem;
+    color: #6c757d;
+    text-decoration: none;
+    border-radius: 0.25rem;
+    transition: all 0.2s ease;
+}
+
+.category-list a:hover,
+.category-list a.active {
+    background-color: #f8f9fa;
+    color: #007bff;
+}
+
+.category-list .count {
+    font-size: 0.875rem;
+    color: #6c757d;
+}
+
+/* Main Content */
+.main-content {
+    min-height: 400px;
+}
+
+/* Publication Lists */
+.publication-list {
+    display: flex;
+    flex-direction: column;
+    gap: 1.5rem;
+}
+
+.publication-summary {
+    background: white;
+    padding: 1.5rem;
+    border-radius: 0.5rem;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.publication-summary h3 {
+    margin-bottom: 0.5rem;
+}
+
+.publication-summary h3 a {
+    color: #333;
+    text-decoration: none;
+}
+
+.publication-summary h3 a:hover {
+    color: #007bff;
+}
+
+.publication-summary .summary {
+    color: #6c757d;
+    margin-bottom: 1rem;
+}
+
+.publication-summary .meta {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 1rem;
+    font-size: 0.875rem;
+    color: #6c757d;
+}
+
+.category-tag {
+    background-color: #e9ecef;
+    color: #495057;
+    padding: 0.25rem 0.5rem;
+    border-radius: 0.25rem;
+    font-size: 0.75rem;
+    text-decoration: none;
+}
+
+.category-tag:hover {
+    background-color: #dee2e6;
+    color: #495057;
+    text-decoration: none;
+}
+
+/* Full Publication */
+.publication-full {
+    background: white;
+    padding: 2rem;
+    border-radius: 0.5rem;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    margin-bottom: 2rem;
+}
+
+.publication-header {
+    margin-bottom: 2rem;
+    padding-bottom: 1rem;
+    border-bottom: 1px solid #dee2e6;
+}
+
+.publication-header h1 {
+    margin-bottom: 1rem;
+}
+
+.publication-meta {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 1rem;
+    font-size: 0.875rem;
+    color: #6c757d;
+    margin-bottom: 1rem;
+}
+
+.publication-categories {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 0.5rem;
+}
+
+.publication-summary {
+    background-color: #f8f9fa;
+    padding: 1rem;
+    border-radius: 0.375rem;
+    margin-bottom: 2rem;
+    border-left: 4px solid #007bff;
+}
+
+.publication-body {
+    font-size: 1.125rem;
+    line-height: 1.8;
+}
+
+/* Related Publications */
+.related-publications {
+    margin-bottom: 2rem;
+}
+
+.publication-grid {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+    gap: 1.5rem;
+    margin-top: 1.5rem;
+}
+
+.publication-card {
+    background: white;
+    padding: 1.5rem;
+    border-radius: 0.5rem;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.publication-card h3 {
+    margin-bottom: 0.5rem;
+}
+
+.publication-card h3 a {
+    color: #333;
+    text-decoration: none;
+}
+
+.publication-card h3 a:hover {
+    color: #007bff;
+}
+
+.publication-card .summary {
+    color: #6c757d;
+    margin-bottom: 1rem;
+}
+
+.publication-card .meta {
+    font-size: 0.875rem;
+    color: #6c757d;
+}
+
+/* Search */
+.search-form-large {
+    background: white;
+    padding: 2rem;
+    border-radius: 0.5rem;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    margin-bottom: 2rem;
+    display: flex;
+    gap: 1rem;
+}
+
+.search-form-large input {
+    flex: 1;
+    font-size: 1.125rem;
+}
+
+.search-results h3 {
+    margin-bottom: 1rem;
+}
+
+.results-count {
+    color: #6c757d;
+    margin-bottom: 1.5rem;
+}
+
+/* Pagination */
+.pagination {
+    display: flex;
+    justify-content: center;
+    gap: 0.5rem;
+    margin-top: 2rem;
+}
+
+.pagination-link,
+.pagination-current {
+    padding: 0.5rem 0.75rem;
+    border: 1px solid #dee2e6;
+    border-radius: 0.375rem;
+    text-decoration: none;
+    color: #007bff;
+}
+
+.pagination-current {
+    background-color: #007bff;
+    color: white;
+    border-color: #007bff;
+}
+
+.pagination-link:hover {
+    background-color: #e9ecef;
+    color: #007bff;
+}
+
+/* Footer */
+.site-footer {
+    background: white;
+    border-top: 1px solid #dee2e6;
+    margin-top: 3rem;
+    padding: 2rem 0;
+    text-align: center;
+    color: #6c757d;
+}
+
+/* Actions */
+.actions {
+    margin-top: 1.5rem;
+}
+
+.publication-actions {
+    text-align: center;
+    margin-top: 2rem;
+}
+
+/* Responsive Design */
+@media (max-width: 768px) {
+    .content-layout {
+        grid-template-columns: 1fr;
+    }
+    
+    .header-content {
+        flex-direction: column;
+        gap: 1rem;
+        text-align: center;
+    }
+    
+    .admin-nav {
+        flex-wrap: wrap;
+        justify-content: center;
+        gap: 1rem;
+    }
+    
+    .stats-grid {
+        grid-template-columns: repeat(2, 1fr);
+    }
+    
+    .publication-grid {
+        grid-template-columns: 1fr;
+    }
+    
+    .publication-meta,
+    .publication-summary .meta {
+        flex-direction: column;
+        gap: 0.5rem;
+    }
+    
+    .search-form-large {
+        flex-direction: column;
+    }
+    
+    .form-actions {
+        flex-direction: column;
+    }
+    
+    .category-checkboxes {
+        grid-template-columns: 1fr;
+    }
+}
+
+@media (max-width: 480px) {
+    .container {
+        padding: 0 15px;
+    }
+    
+    .admin-main {
+        padding: 1rem;
+    }
+    
+    .publication-full,
+    .publication-form {
+        padding: 1rem;
+    }
+    
+    .stats-grid {
+        grid-template-columns: 1fr;
+    }
+    
+    .table-container {
+        overflow-x: auto;
+    }
+}

+ 64 - 0
includes/auth.php

@@ -0,0 +1,64 @@
+<?php
+/**
+ * Authentication Class
+ * Handles user login, logout, and session management
+ */
+
+class Auth {
+    private $db;
+    
+    public function __construct() {
+        $this->db = Database::getInstance();
+    }
+    
+    public function login($username, $password) {
+        $sql = "SELECT * FROM users WHERE username = ?";
+        $user = $this->db->fetch($sql, [$username]);
+        
+        if ($user && password_verify($password, $user['password'])) {
+            $_SESSION['user_id'] = $user['id'];
+            $_SESSION['username'] = $user['username'];
+            $_SESSION['role'] = $user['role'];
+            $_SESSION['logged_in'] = true;
+            return true;
+        }
+        
+        return false;
+    }
+    
+    public function logout() {
+        session_destroy();
+        unset($_SESSION);
+    }
+    
+    public function isLoggedIn() {
+        return isset($_SESSION['logged_in']) && $_SESSION['logged_in'] === true;
+    }
+    
+    public function requireAuth() {
+        if (!$this->isLoggedIn()) {
+            header('Location: login.php');
+            exit;
+        }
+    }
+    
+    public function getUser() {
+        if ($this->isLoggedIn()) {
+            return [
+                'id' => $_SESSION['user_id'],
+                'username' => $_SESSION['username'],
+                'role' => $_SESSION['role']
+            ];
+        }
+        return null;
+    }
+    
+    public function isAdmin() {
+        return $this->isLoggedIn() && $_SESSION['role'] === 'admin';
+    }
+}
+
+// Initialize session
+if (session_status() === PHP_SESSION_NONE) {
+    session_start();
+}

+ 121 - 0
includes/database.php

@@ -0,0 +1,121 @@
+<?php
+/**
+ * Database Connection Class
+ * Handles PDO database connections and basic operations
+ */
+
+class Database {
+    private static $instance = null;
+    private $pdo;
+    private $host;
+    private $name;
+    private $user;
+    private $pass;
+
+    private function __construct() {
+        $this->host = DB_HOST;
+        $this->name = DB_NAME;
+        $this->user = DB_USER;
+        $this->pass = DB_PASS;
+        
+        $this->connect();
+    }
+
+    public static function getInstance() {
+        if (self::$instance === null) {
+            self::$instance = new self();
+        }
+        return self::$instance;
+    }
+
+    private function connect() {
+        try {
+            $dsn = "mysql:host={$this->host};dbname={$this->name};charset=utf8mb4";
+            $options = [
+                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
+                PDO::ATTR_EMULATE_PREPARES => false,
+            ];
+            
+            $this->pdo = new PDO($dsn, $this->user, $this->pass, $options);
+        } catch (PDOException $e) {
+            throw new Exception("Database connection failed: " . $e->getMessage());
+        }
+    }
+
+    public function getConnection() {
+        return $this->pdo;
+    }
+
+    public function query($sql, $params = []) {
+        try {
+            $stmt = $this->pdo->prepare($sql);
+            $stmt->execute($params);
+            return $stmt;
+        } catch (PDOException $e) {
+            throw new Exception("Query failed: " . $e->getMessage());
+        }
+    }
+
+    public function fetch($sql, $params = []) {
+        $stmt = $this->query($sql, $params);
+        return $stmt->fetch();
+    }
+
+    public function fetchAll($sql, $params = []) {
+        $stmt = $this->query($sql, $params);
+        return $stmt->fetchAll();
+    }
+
+    public function insert($table, $data) {
+        $columns = implode(', ', array_keys($data));
+        $placeholders = implode(', ', array_fill(0, count($data), '?'));
+        $values = array_values($data);
+        
+        $sql = "INSERT INTO $table ($columns) VALUES ($placeholders)";
+        $this->query($sql, $values);
+        
+        return $this->pdo->lastInsertId();
+    }
+
+    public function update($table, $data, $where, $whereParams = []) {
+        $setParts = [];
+        $values = [];
+        
+        foreach ($data as $column => $value) {
+            $setParts[] = "$column = ?";
+            $values[] = $value;
+        }
+        
+        $setClause = implode(', ', $setParts);
+        $sql = "UPDATE $table SET $setClause WHERE $where";
+        
+        $values = array_merge($values, $whereParams);
+        $stmt = $this->query($sql, $values);
+        
+        return $stmt->rowCount();
+    }
+
+    public function delete($table, $where, $params = []) {
+        $sql = "DELETE FROM $table WHERE $where";
+        $stmt = $this->query($sql, $params);
+        
+        return $stmt->rowCount();
+    }
+
+    public function beginTransaction() {
+        return $this->pdo->beginTransaction();
+    }
+
+    public function commit() {
+        return $this->pdo->commit();
+    }
+
+    public function rollback() {
+        return $this->pdo->rollBack();
+    }
+
+    public function lastInsertId() {
+        return $this->pdo->lastInsertId();
+    }
+}

+ 252 - 0
includes/publication.php

@@ -0,0 +1,252 @@
+<?php
+/**
+ * Publication Model Class
+ * Handles all publication-related database operations
+ */
+
+class Publication {
+    private $db;
+    
+    public function __construct() {
+        $this->db = Database::getInstance();
+    }
+    
+    public function getAll($status = 'published', $limit = null, $offset = 0) {
+        $sql = "SELECT p.*, GROUP_CONCAT(c.name) as categories 
+                FROM publications p 
+                LEFT JOIN publication_categories pc ON p.id = pc.publication_id 
+                LEFT JOIN categories c ON pc.category_id = c.id";
+        
+        $params = [];
+        
+        if ($status !== 'all') {
+            $sql .= " WHERE p.status = ?";
+            $params[] = $status;
+        }
+        
+        $sql .= " GROUP BY p.id ORDER BY p.created_at DESC";
+        
+        if ($limit) {
+            $sql .= " LIMIT ? OFFSET ?";
+            $params[] = (int)$limit;
+            $params[] = (int)$offset;
+        }
+        
+        return $this->db->fetchAll($sql, $params);
+    }
+    
+    public function getById($id) {
+        $sql = "SELECT p.*, GROUP_CONCAT(c.name) as categories 
+                FROM publications p 
+                LEFT JOIN publication_categories pc ON p.id = pc.publication_id 
+                LEFT JOIN categories c ON pc.category_id = c.id 
+                WHERE p.id = ? 
+                GROUP BY p.id";
+        
+        $publication = $this->db->fetch($sql, [$id]);
+        
+        if ($publication && $publication['categories']) {
+            $publication['categories_array'] = explode(',', $publication['categories']);
+        } else {
+            $publication['categories_array'] = [];
+        }
+        
+        return $publication;
+    }
+    
+    public function getBySlug($slug) {
+        $sql = "SELECT p.*, GROUP_CONCAT(c.name) as categories 
+                FROM publications p 
+                LEFT JOIN publication_categories pc ON p.id = pc.publication_id 
+                LEFT JOIN categories c ON pc.category_id = c.id 
+                WHERE p.slug = ? 
+                GROUP BY p.id";
+        
+        $publication = $this->db->fetch($sql, [$slug]);
+        
+        if ($publication && $publication['categories']) {
+            $publication['categories_array'] = explode(',', $publication['categories']);
+        } else {
+            $publication['categories_array'] = [];
+        }
+        
+        return $publication;
+    }
+    
+    public function create($data, $categories = []) {
+        $this->db->beginTransaction();
+        
+        try {
+            // Generate slug from title
+            $slug = $this->generateSlug($data['title']);
+            $data['slug'] = $slug;
+            
+            // Set published_at if status is published
+            if ($data['status'] === 'published' && !isset($data['published_at'])) {
+                $data['published_at'] = date('Y-m-d H:i:s');
+            }
+            
+            $publicationId = $this->db->insert('publications', $data);
+            
+            // Add categories
+            if (!empty($categories)) {
+                $this->updateCategories($publicationId, $categories);
+            }
+            
+            $this->db->commit();
+            return $publicationId;
+            
+        } catch (Exception $e) {
+            $this->db->rollback();
+            throw $e;
+        }
+    }
+    
+    public function update($id, $data, $categories = []) {
+        $this->db->beginTransaction();
+        
+        try {
+            // Update slug if title changed
+            if (isset($data['title'])) {
+                $data['slug'] = $this->generateSlug($data['title'], $id);
+            }
+            
+            // Set published_at if status changed to published
+            if (isset($data['status']) && $data['status'] === 'published') {
+                $current = $this->getById($id);
+                if ($current['status'] !== 'published') {
+                    $data['published_at'] = date('Y-m-d H:i:s');
+                }
+            }
+            
+            $this->db->update('publications', $data, 'id = ?', [$id]);
+            
+            // Update categories if provided
+            if (!empty($categories)) {
+                $this->updateCategories($id, $categories);
+            }
+            
+            $this->db->commit();
+            return true;
+            
+        } catch (Exception $e) {
+            $this->db->rollback();
+            throw $e;
+        }
+    }
+    
+    public function delete($id) {
+        $this->db->beginTransaction();
+        
+        try {
+            // Delete category associations
+            $this->db->delete('publication_categories', 'publication_id = ?', [$id]);
+            
+            // Delete publication
+            $this->db->delete('publications', 'id = ?', [$id]);
+            
+            $this->db->commit();
+            return true;
+            
+        } catch (Exception $e) {
+            $this->db->rollback();
+            throw $e;
+        }
+    }
+    
+    public function search($query, $status = 'published') {
+        $sql = "SELECT p.*, GROUP_CONCAT(c.name) as categories 
+                FROM publications p 
+                LEFT JOIN publication_categories pc ON p.id = pc.publication_id 
+                LEFT JOIN categories c ON pc.category_id = c.id 
+                WHERE (p.title LIKE ? OR p.content LIKE ? OR p.summary LIKE ?)";
+        
+        $params = ["%$query%", "%$query%", "%$query%"];
+        
+        if ($status !== 'all') {
+            $sql .= " AND p.status = ?";
+            $params[] = $status;
+        }
+        
+        $sql .= " GROUP BY p.id ORDER BY p.created_at DESC";
+        
+        return $this->db->fetchAll($sql, $params);
+    }
+    
+    public function getByCategory($categoryName, $status = 'published') {
+        $sql = "SELECT p.*, GROUP_CONCAT(c.name) as categories 
+                FROM publications p 
+                LEFT JOIN publication_categories pc ON p.id = pc.publication_id 
+                LEFT JOIN categories c ON pc.category_id = c.id 
+                WHERE c.name = ?";
+        
+        $params = [$categoryName];
+        
+        if ($status !== 'all') {
+            $sql .= " AND p.status = ?";
+            $params[] = $status;
+        }
+        
+        $sql .= " GROUP BY p.id ORDER BY p.created_at DESC";
+        
+        return $this->db->fetchAll($sql, $params);
+    }
+    
+    public function getCategories() {
+        $sql = "SELECT c.*, COUNT(pc.publication_id) as publication_count 
+                FROM categories c 
+                LEFT JOIN publication_categories pc ON c.id = pc.category_id 
+                LEFT JOIN publications p ON pc.publication_id = p.id AND p.status = 'published'
+                GROUP BY c.id 
+                ORDER BY c.name";
+        
+        return $this->db->fetchAll($sql);
+    }
+    
+    private function updateCategories($publicationId, $categories) {
+        // Delete existing category associations
+        $this->db->delete('publication_categories', 'publication_id = ?', [$publicationId]);
+        
+        // Add new category associations
+        foreach ($categories as $categoryId) {
+            $this->db->insert('publication_categories', [
+                'publication_id' => $publicationId,
+                'category_id' => $categoryId
+            ]);
+        }
+    }
+    
+    private function generateSlug($title, $excludeId = null) {
+        $slug = strtolower($title);
+        $slug = preg_replace('/[^a-z0-9]+/', '-', $slug);
+        $slug = trim($slug, '-');
+        
+        // Check for uniqueness
+        $sql = "SELECT COUNT(*) as count FROM publications WHERE slug = ?";
+        $params = [$slug];
+        
+        if ($excludeId) {
+            $sql .= " AND id != ?";
+            $params[] = $excludeId;
+        }
+        
+        $result = $this->db->fetch($sql, $params);
+        
+        if ($result['count'] > 0) {
+            $slug .= '-' . time();
+        }
+        
+        return $slug;
+    }
+    
+    public function getStats() {
+        $stats = [];
+        
+        $stats['total'] = $this->db->fetch("SELECT COUNT(*) as count FROM publications")['count'];
+        $stats['published'] = $this->db->fetch("SELECT COUNT(*) as count FROM publications WHERE status = 'published'")['count'];
+        $stats['draft'] = $this->db->fetch("SELECT COUNT(*) as count FROM publications WHERE status = 'draft'")['count'];
+        $stats['archived'] = $this->db->fetch("SELECT COUNT(*) as count FROM publications WHERE status = 'archived'")['count'];
+        
+        return $stats;
+    }
+}

+ 160 - 0
public/index.php

@@ -0,0 +1,160 @@
+<?php
+require_once '../includes/config.php';
+require_once '../includes/database.php';
+require_once '../includes/publication.php';
+
+$publication = new Publication();
+
+// Get search query
+$search = $_GET['search'] ?? '';
+$category = $_GET['category'] ?? '';
+$page = max(1, (int)($_GET['page'] ?? 1));
+$limit = 10;
+$offset = ($page - 1) * $limit;
+
+// Get publications
+if ($search) {
+    $publications = $publication->search($search, 'published');
+    $totalPublications = count($publications);
+} elseif ($category) {
+    $publications = $publication->getByCategory($category, 'published');
+    $totalPublications = count($publications);
+} else {
+    $publications = $publication->getAll('published', $limit, $offset);
+    $totalPublications = $publication->db->fetch("SELECT COUNT(*) as count FROM publications WHERE status = 'published'")['count'];
+}
+
+// Get categories for sidebar
+$categories = $publication->getCategories();
+
+// Calculate pagination
+$totalPages = ceil($totalPublications / $limit);
+?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title><?php echo SITE_TITLE; ?></title>
+    <link rel="stylesheet" href="../css/style.css">
+</head>
+<body>
+    <header class="site-header">
+        <div class="container">
+            <h1><a href="index.php"><?php echo SITE_TITLE; ?></a></h1>
+            <nav class="main-nav">
+                <a href="index.php">Home</a>
+                <a href="categories.php">Categories</a>
+                <a href="search.php">Search</a>
+            </nav>
+        </div>
+    </header>
+
+    <div class="container">
+        <div class="content-layout">
+            <aside class="sidebar">
+                <div class="sidebar-section">
+                    <h3>Search</h3>
+                    <form method="get" class="search-form">
+                        <input type="text" name="search" placeholder="Search publications..." 
+                               value="<?php echo htmlspecialchars($search); ?>">
+                        <button type="submit" class="btn btn-sm">Search</button>
+                    </form>
+                </div>
+
+                <div class="sidebar-section">
+                    <h3>Categories</h3>
+                    <ul class="category-list">
+                        <li>
+                            <a href="index.php" <?php echo empty($category) ? 'class="active"' : ''; ?>>
+                                All Categories
+                            </a>
+                        </li>
+                        <?php foreach ($categories as $cat): ?>
+                            <li>
+                                <a href="index.php?category=<?php echo urlencode($cat['name']); ?>" 
+                                   <?php echo $category === $cat['name'] ? 'class="active"' : ''; ?>>
+                                    <?php echo htmlspecialchars($cat['name']); ?>
+                                    <span class="count">(<?php echo $cat['publication_count']; ?>)</span>
+                                </a>
+                            </li>
+                        <?php endforeach; ?>
+                    </ul>
+                </div>
+            </aside>
+
+            <main class="main-content">
+                <?php if ($search): ?>
+                    <h2>Search Results for "<?php echo htmlspecialchars($search); ?>"</h2>
+                    <p class="results-count">Found <?php echo $totalPublications; ?> publications</p>
+                <?php elseif ($category): ?>
+                    <h2>Category: <?php echo htmlspecialchars($category); ?></h2>
+                    <p class="results-count"><?php echo $totalPublications; ?> publications</p>
+                <?php else: ?>
+                    <h2>Latest Publications</h2>
+                <?php endif; ?>
+
+                <?php if (empty($publications)): ?>
+                    <p>No publications found.</p>
+                <?php else: ?>
+                    <div class="publication-list">
+                        <?php foreach ($publications as $pub): ?>
+                            <article class="publication-summary">
+                                <h3>
+                                    <a href="publication.php?id=<?php echo $pub['id']; ?>">
+                                        <?php echo htmlspecialchars($pub['title']); ?>
+                                    </a>
+                                </h3>
+                                
+                                <?php if ($pub['summary']): ?>
+                                    <p class="summary"><?php echo htmlspecialchars($pub['summary']); ?></p>
+                                <?php endif; ?>
+                                
+                                <div class="meta">
+                                    <span class="author">By <?php echo htmlspecialchars($pub['author']); ?></span>
+                                    <span class="date"><?php echo date('F j, Y', strtotime($pub['created_at'])); ?></span>
+                                    <?php if ($pub['categories']): ?>
+                                        <span class="categories">
+                                            <?php foreach (explode(',', $pub['categories']) as $cat): ?>
+                                                <a href="index.php?category=<?php echo urlencode(trim($cat)); ?>" class="category-tag">
+                                                    <?php echo htmlspecialchars(trim($cat)); ?>
+                                                </a>
+                                            <?php endforeach; ?>
+                                        </span>
+                                    <?php endif; ?>
+                                </div>
+                            </article>
+                        <?php endforeach; ?>
+                    </div>
+
+                    <?php if (!$search && !$category && $totalPages > 1): ?>
+                        <div class="pagination">
+                            <?php if ($page > 1): ?>
+                                <a href="?page=<?php echo $page - 1; ?>" class="pagination-link">« Previous</a>
+                            <?php endif; ?>
+
+                            <?php for ($i = 1; $i <= $totalPages; $i++): ?>
+                                <?php if ($i == $page): ?>
+                                    <span class="pagination-current"><?php echo $i; ?></span>
+                                <?php else: ?>
+                                    <a href="?page=<?php echo $i; ?>" class="pagination-link"><?php echo $i; ?></a>
+                                <?php endif; ?>
+                            <?php endfor; ?>
+
+                            <?php if ($page < $totalPages): ?>
+                                <a href="?page=<?php echo $page + 1; ?>" class="pagination-link">Next »</a>
+                            <?php endif; ?>
+                        </div>
+                    <?php endif; ?>
+                <?php endif; ?>
+            </main>
+        </div>
+    </div>
+
+    <footer class="site-footer">
+        <div class="container">
+            <p>&copy; <?php echo date('Y'); ?> <?php echo SITE_TITLE; ?>. All rights reserved.</p>
+        </div>
+    </footer>
+</body>
+</html>

+ 125 - 0
public/publication.php

@@ -0,0 +1,125 @@
+<?php
+require_once '../includes/config.php';
+require_once '../includes/database.php';
+require_once '../includes/publication.php';
+
+$publication = new Publication();
+
+$id = (int)($_GET['id'] ?? 0);
+$pub = $publication->getById($id);
+
+if (!$pub || $pub['status'] !== 'published') {
+    http_response_code(404);
+    echo '<h1>Publication Not Found</h1>';
+    echo '<p>The requested publication could not be found.</p>';
+    exit;
+}
+
+// Get related publications
+$relatedPublications = [];
+if ($pub['categories_array']) {
+    $firstCategory = $pub['categories_array'][0];
+    $relatedPublications = $publication->getByCategory($firstCategory, 'published');
+    // Remove current publication from related list
+    $relatedPublications = array_filter($relatedPublications, function($p) use ($id) {
+        return $p['id'] != $id;
+    });
+    // Limit to 3 related publications
+    $relatedPublications = array_slice($relatedPublications, 0, 3);
+}
+?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title><?php echo htmlspecialchars($pub['title']); ?> - <?php echo SITE_TITLE; ?></title>
+    <link rel="stylesheet" href="../css/style.css">
+</head>
+<body>
+    <header class="site-header">
+        <div class="container">
+            <h1><a href="index.php"><?php echo SITE_TITLE; ?></a></h1>
+            <nav class="main-nav">
+                <a href="index.php">Home</a>
+                <a href="categories.php">Categories</a>
+                <a href="search.php">Search</a>
+            </nav>
+        </div>
+    </header>
+
+    <div class="container">
+        <article class="publication-full">
+            <header class="publication-header">
+                <h1><?php echo htmlspecialchars($pub['title']); ?></h1>
+                
+                <div class="publication-meta">
+                    <span class="author">By <?php echo htmlspecialchars($pub['author']); ?></span>
+                    <span class="date"><?php echo date('F j, Y', strtotime($pub['created_at'])); ?></span>
+                    <?php if ($pub['published_at']): ?>
+                        <span class="published-date">Published <?php echo date('F j, Y', strtotime($pub['published_at'])); ?></span>
+                    <?php endif; ?>
+                </div>
+
+                <?php if ($pub['categories_array']): ?>
+                    <div class="publication-categories">
+                        <?php foreach ($pub['categories_array'] as $category): ?>
+                            <a href="index.php?category=<?php echo urlencode(trim($category)); ?>" class="category-tag">
+                                <?php echo htmlspecialchars(trim($category)); ?>
+                            </a>
+                        <?php endforeach; ?>
+                    </div>
+                <?php endif; ?>
+            </header>
+
+            <div class="publication-content">
+                <?php if ($pub['summary']): ?>
+                    <div class="publication-summary">
+                        <p><?php echo htmlspecialchars($pub['summary']); ?></p>
+                    </div>
+                <?php endif; ?>
+
+                <div class="publication-body">
+                    <?php echo nl2br(htmlspecialchars($pub['content'])); ?>
+                </div>
+            </div>
+        </article>
+
+        <?php if (!empty($relatedPublications)): ?>
+            <section class="related-publications">
+                <h2>Related Publications</h2>
+                <div class="publication-grid">
+                    <?php foreach ($relatedPublications as $related): ?>
+                        <article class="publication-card">
+                            <h3>
+                                <a href="publication.php?id=<?php echo $related['id']; ?>">
+                                    <?php echo htmlspecialchars($related['title']); ?>
+                                </a>
+                            </h3>
+                            
+                            <?php if ($related['summary']): ?>
+                                <p class="summary"><?php echo htmlspecialchars($related['summary']); ?></p>
+                            <?php endif; ?>
+                            
+                            <div class="meta">
+                                <span class="author"><?php echo htmlspecialchars($related['author']); ?></span>
+                                <span class="date"><?php echo date('M j, Y', strtotime($related['created_at'])); ?></span>
+                            </div>
+                        </article>
+                    <?php endforeach; ?>
+                </div>
+            </section>
+        <?php endif; ?>
+
+        <div class="publication-actions">
+            <a href="index.php" class="btn">Back to Publications</a>
+        </div>
+    </div>
+
+    <footer class="site-footer">
+        <div class="container">
+            <p>&copy; <?php echo date('Y'); ?> <?php echo SITE_TITLE; ?>. All rights reserved.</p>
+        </div>
+    </footer>
+</body>
+</html>

+ 125 - 0
public/search.php

@@ -0,0 +1,125 @@
+<?php
+require_once '../includes/config.php';
+require_once '../includes/database.php';
+require_once '../includes/publication.php';
+
+$publication = new Publication();
+
+$query = $_GET['q'] ?? '';
+$page = max(1, (int)($_GET['page'] ?? 1));
+$limit = 10;
+$offset = ($page - 1) * $limit;
+
+$results = [];
+$totalResults = 0;
+
+if ($query) {
+    $results = $publication->search($query, 'published');
+    $totalResults = count($results);
+    
+    // Apply pagination
+    $results = array_slice($results, $offset, $limit);
+}
+?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Search - <?php echo SITE_TITLE; ?></title>
+    <link rel="stylesheet" href="../css/style.css">
+</head>
+<body>
+    <header class="site-header">
+        <div class="container">
+            <h1><a href="index.php"><?php echo SITE_TITLE; ?></a></h1>
+            <nav class="main-nav">
+                <a href="index.php">Home</a>
+                <a href="categories.php">Categories</a>
+                <a href="search.php">Search</a>
+            </nav>
+        </div>
+    </header>
+
+    <div class="container">
+        <main class="main-content">
+            <h2>Search Publications</h2>
+            
+            <form method="get" class="search-form-large">
+                <input type="text" name="q" placeholder="Search for publications..." 
+                       value="<?php echo htmlspecialchars($query); ?>" required>
+                <button type="submit" class="btn btn-primary">Search</button>
+            </form>
+
+            <?php if ($query): ?>
+                <div class="search-results">
+                    <h3>Search Results for "<?php echo htmlspecialchars($query); ?>"</h3>
+                    
+                    <?php if (empty($results)): ?>
+                        <p>No publications found matching your search.</p>
+                    <?php else: ?>
+                        <p class="results-count">Found <?php echo $totalResults; ?> publications</p>
+                        
+                        <div class="publication-list">
+                            <?php foreach ($results as $pub): ?>
+                                <article class="publication-summary">
+                                    <h3>
+                                        <a href="publication.php?id=<?php echo $pub['id']; ?>">
+                                            <?php echo htmlspecialchars($pub['title']); ?>
+                                        </a>
+                                    </h3>
+                                    
+                                    <?php if ($pub['summary']): ?>
+                                        <p class="summary"><?php echo htmlspecialchars($pub['summary']); ?></p>
+                                    <?php endif; ?>
+                                    
+                                    <div class="meta">
+                                        <span class="author">By <?php echo htmlspecialchars($pub['author']); ?></span>
+                                        <span class="date"><?php echo date('F j, Y', strtotime($pub['created_at'])); ?></span>
+                                        <?php if ($pub['categories']): ?>
+                                            <span class="categories">
+                                                <?php foreach (explode(',', $pub['categories']) as $cat): ?>
+                                                    <a href="index.php?category=<?php echo urlencode(trim($cat)); ?>" class="category-tag">
+                                                        <?php echo htmlspecialchars(trim($cat)); ?>
+                                                    </a>
+                                                <?php endforeach; ?>
+                                            </span>
+                                        <?php endif; ?>
+                                    </div>
+                                </article>
+                            <?php endforeach; ?>
+                        </div>
+
+                        <?php $totalPages = ceil($totalResults / $limit); ?>
+                        <?php if ($totalPages > 1): ?>
+                            <div class="pagination">
+                                <?php if ($page > 1): ?>
+                                    <a href="?q=<?php echo urlencode($query); ?>&page=<?php echo $page - 1; ?>" class="pagination-link">« Previous</a>
+                                <?php endif; ?>
+
+                                <?php for ($i = 1; $i <= $totalPages; $i++): ?>
+                                    <?php if ($i == $page): ?>
+                                        <span class="pagination-current"><?php echo $i; ?></span>
+                                    <?php else: ?>
+                                        <a href="?q=<?php echo urlencode($query); ?>&page=<?php echo $i; ?>" class="pagination-link"><?php echo $i; ?></a>
+                                    <?php endif; ?>
+                                <?php endfor; ?>
+
+                                <?php if ($page < $totalPages): ?>
+                                    <a href="?q=<?php echo urlencode($query); ?>&page=<?php echo $page + 1; ?>" class="pagination-link">Next »</a>
+                                <?php endif; ?>
+                            </div>
+                        <?php endif; ?>
+                    <?php endif; ?>
+                </div>
+            <?php endif; ?>
+        </main>
+    </div>
+
+    <footer class="site-footer">
+        <div class="container">
+            <p>&copy; <?php echo date('Y'); ?> <?php echo SITE_TITLE; ?>. All rights reserved.</p>
+        </div>
+    </footer>
+</body>
+</html>

+ 62 - 0
setup/database.sql

@@ -0,0 +1,62 @@
+-- Web Publication System Database Schema
+-- MariaDB/MySQL compatible
+
+CREATE DATABASE IF NOT EXISTS webpub;
+USE webpub;
+
+-- Publications table
+CREATE TABLE publications (
+    id INT AUTO_INCREMENT PRIMARY KEY,
+    title VARCHAR(255) NOT NULL,
+    content TEXT NOT NULL,
+    summary VARCHAR(500),
+    author VARCHAR(100) NOT NULL,
+    status ENUM('draft', 'published', 'archived') DEFAULT 'draft',
+    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    published_at TIMESTAMP NULL
+);
+
+-- Users table for admin authentication
+CREATE TABLE users (
+    id INT AUTO_INCREMENT PRIMARY KEY,
+    username VARCHAR(50) UNIQUE NOT NULL,
+    password VARCHAR(255) NOT NULL,
+    email VARCHAR(255),
+    role ENUM('admin', 'editor') DEFAULT 'editor',
+    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+-- Categories table
+CREATE TABLE categories (
+    id INT AUTO_INCREMENT PRIMARY KEY,
+    name VARCHAR(100) UNIQUE NOT NULL,
+    description TEXT,
+    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+-- Publication categories junction table
+CREATE TABLE publication_categories (
+    publication_id INT,
+    category_id INT,
+    PRIMARY KEY (publication_id, category_id),
+    FOREIGN KEY (publication_id) REFERENCES publications(id) ON DELETE CASCADE,
+    FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
+);
+
+-- Insert default admin user (password: admin123)
+INSERT INTO users (username, password, email, role) VALUES 
+('admin', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'admin@example.com', 'admin');
+
+-- Insert sample categories
+INSERT INTO categories (name, description) VALUES 
+('Technology', 'Articles about technology and programming'),
+('News', 'Current events and news articles'),
+('Tutorial', 'How-to guides and tutorials'),
+('Opinion', 'Editorials and opinion pieces');
+
+-- Insert sample publications
+INSERT INTO publications (title, content, summary, author, status) VALUES 
+('Welcome to Web Publication System', 'This is a sample publication to demonstrate the system capabilities. You can edit or delete this publication from the admin panel.', 'A welcome message for new users', 'admin', 'published'),
+('Getting Started with PHP', 'PHP is a popular server-side scripting language designed for web development. This article covers the basics of getting started with PHP development.', 'Introduction to PHP programming', 'admin', 'published'),
+('Database Design Best Practices', 'Good database design is crucial for application performance and maintainability. This article covers essential principles and practices.', 'Tips for designing efficient databases', 'admin', 'draft');

+ 168 - 0
setup/setup.php

@@ -0,0 +1,168 @@
+<?php
+/**
+ * Web Publication System Setup Script
+ * This script will set up the database and create necessary configuration files
+ */
+
+// Prevent direct access if already installed
+if (file_exists('../includes/config.php')) {
+    die("System appears to be already installed. Please remove includes/config.php to reinstall.");
+}
+
+// Database configuration form handling
+$db_host = 'localhost';
+$db_name = 'webpub';
+$db_user = '';
+$db_pass = '';
+$site_title = 'Web Publication System';
+$admin_username = 'admin';
+$admin_password = '';
+$admin_email = '';
+
+$errors = [];
+$success = false;
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+    // Validate and sanitize input
+    $db_host = trim($_POST['db_host'] ?? 'localhost');
+    $db_name = trim($_POST['db_name'] ?? 'webpub');
+    $db_user = trim($_POST['db_user'] ?? '');
+    $db_pass = trim($_POST['db_pass'] ?? '');
+    $site_title = trim($_POST['site_title'] ?? 'Web Publication System');
+    $admin_username = trim($_POST['admin_username'] ?? 'admin');
+    $admin_password = trim($_POST['admin_password'] ?? '');
+    $admin_email = trim($_POST['admin_email'] ?? '');
+
+    // Validation
+    if (empty($db_user)) $errors[] = 'Database username is required';
+    if (empty($admin_password)) $errors[] = 'Admin password is required';
+    if (empty($admin_email)) $errors[] = 'Admin email is required';
+    if (!filter_var($admin_email, FILTER_VALIDATE_EMAIL)) $errors[] = 'Invalid email format';
+
+    if (empty($errors)) {
+        try {
+            // Test database connection
+            $pdo = new PDO("mysql:host=$db_host", $db_user, $db_pass);
+            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+            // Create database if it doesn't exist
+            $pdo->exec("CREATE DATABASE IF NOT EXISTS `$db_name` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
+            $pdo->exec("USE `$db_name`");
+
+            // Import SQL schema
+            $sql = file_get_contents('database.sql');
+            $pdo->exec($sql);
+
+            // Update admin user with provided credentials
+            $hashed_password = password_hash($admin_password, PASSWORD_DEFAULT);
+            $stmt = $pdo->prepare("UPDATE users SET username = ?, password = ?, email = ? WHERE username = 'admin'");
+            $stmt->execute([$admin_username, $hashed_password, $admin_email]);
+
+            // Create configuration file
+            $config_content = "<?php\n";
+            $config_content .= "// Database configuration\n";
+            $config_content .= "define('DB_HOST', '$db_host');\n";
+            $config_content .= "define('DB_NAME', '$db_name');\n";
+            $config_content .= "define('DB_USER', '$db_user');\n";
+            $config_content .= "define('DB_PASS', '$db_pass');\n\n";
+            $config_content .= "// Site configuration\n";
+            $config_content .= "define('SITE_TITLE', '$site_title');\n";
+            $config_content .= "define('SITE_URL', '" . ($_SERVER['HTTPS'] ? 'https' : 'http') . "://{$_SERVER['HTTP_HOST']}" . dirname($_SERVER['PHP_SELF']) . "/../');\n";
+            $config_content .= "define('ADMIN_EMAIL', '$admin_email');\n";
+
+            if (file_put_contents('../includes/config.php', $config_content)) {
+                $success = true;
+            } else {
+                $errors[] = 'Failed to create configuration file. Check file permissions.';
+            }
+
+        } catch (PDOException $e) {
+            $errors[] = 'Database error: ' . $e->getMessage();
+        }
+    }
+}
+?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Web Publication System Setup</title>
+    <link rel="stylesheet" href="../css/style.css">
+</head>
+<body>
+    <div class="container">
+        <h1>Web Publication System Setup</h1>
+        
+        <?php if ($success): ?>
+            <div class="alert alert-success">
+                <h3>Installation Complete!</h3>
+                <p>The system has been successfully installed. You can now:</p>
+                <ul>
+                    <li><a href="../admin/">Access the admin panel</a></li>
+                    <li><a href="../public/">View the public site</a></li>
+                </ul>
+                <p><strong>Important:</strong> Delete the setup directory for security.</p>
+            </div>
+        <?php else: ?>
+            <?php if (!empty($errors)): ?>
+                <div class="alert alert-error">
+                    <?php foreach ($errors as $error): ?>
+                        <p><?php echo htmlspecialchars($error); ?></p>
+                    <?php endforeach; ?>
+                </div>
+            <?php endif; ?>
+
+            <form method="post" class="setup-form">
+                <h2>Database Configuration</h2>
+                
+                <div class="form-group">
+                    <label for="db_host">Database Host:</label>
+                    <input type="text" id="db_host" name="db_host" value="<?php echo htmlspecialchars($db_host); ?>" required>
+                </div>
+
+                <div class="form-group">
+                    <label for="db_name">Database Name:</label>
+                    <input type="text" id="db_name" name="db_name" value="<?php echo htmlspecialchars($db_name); ?>" required>
+                </div>
+
+                <div class="form-group">
+                    <label for="db_user">Database Username:</label>
+                    <input type="text" id="db_user" name="db_user" value="<?php echo htmlspecialchars($db_user); ?>" required>
+                </div>
+
+                <div class="form-group">
+                    <label for="db_pass">Database Password:</label>
+                    <input type="password" id="db_pass" name="db_pass">
+                </div>
+
+                <h2>Site Configuration</h2>
+
+                <div class="form-group">
+                    <label for="site_title">Site Title:</label>
+                    <input type="text" id="site_title" name="site_title" value="<?php echo htmlspecialchars($site_title); ?>" required>
+                </div>
+
+                <h2>Administrator Account</h2>
+
+                <div class="form-group">
+                    <label for="admin_username">Admin Username:</label>
+                    <input type="text" id="admin_username" name="admin_username" value="<?php echo htmlspecialchars($admin_username); ?>" required>
+                </div>
+
+                <div class="form-group">
+                    <label for="admin_password">Admin Password:</label>
+                    <input type="password" id="admin_password" name="admin_password" required>
+                </div>
+
+                <div class="form-group">
+                    <label for="admin_email">Admin Email:</label>
+                    <input type="email" id="admin_email" name="admin_email" value="<?php echo htmlspecialchars($admin_email); ?>" required>
+                </div>
+
+                <button type="submit" class="btn btn-primary">Install System</button>
+            </form>
+        <?php endif; ?>
+    </div>
+</body>
+</html>