Sindbad~EG File Manager
<?php
require_once 'config/config.php';
// Check if user is superuser
session_start();
if (!isset($_SESSION['user_id']) || $_SESSION['account_type'] !== 'superuser') {
die('Access denied. Superuser privileges required.');
}
$database = new Database();
$conn = $database->getConnection();
$migration_log = [];
$errors = [];
function log_migration($message, $success = true) {
global $migration_log;
$migration_log[] = [
'message' => $message,
'success' => $success,
'timestamp' => date('Y-m-d H:i:s')
];
echo ($success ? '[SUCCESS] ' : '[ERROR] ') . $message . "\n";
}
function execute_query($conn, $query, $description) {
global $errors;
try {
$result = $conn->exec($query);
log_migration($description);
return true;
} catch (PDOException $e) {
$error_msg = "$description - Error: " . $e->getMessage();
log_migration($error_msg, false);
$errors[] = $error_msg;
return false;
}
}
echo "Starting Proofreading System Migration...\n";
echo "==========================================\n\n";
// 1. Add 'editor' to users account_type enum
$query1 = "ALTER TABLE users MODIFY COLUMN account_type ENUM('user', 'admin', 'superuser', 'editor') NOT NULL DEFAULT 'user'";
execute_query($conn, $query1, "Added 'editor' to users account_type enum");
// 2. Add editorial permission fields to users table
$query2 = "ALTER TABLE users
ADD COLUMN can_edit_others BOOLEAN DEFAULT FALSE AFTER account_type,
ADD COLUMN editorial_scope ENUM('assembly', 'district', 'area') NULL AFTER can_edit_others";
execute_query($conn, $query2, "Added editorial permission fields to users table");
// 3. Extend news status enum
$query3 = "ALTER TABLE news MODIFY COLUMN status ENUM('draft', 'published', 'archived', 'pending_review', 'approved', 'rejected') NOT NULL DEFAULT 'draft'";
execute_query($conn, $query3, "Extended news status enum with proofreading statuses");
// 4. Add editorial fields to news table
$query4 = "ALTER TABLE news
ADD COLUMN assigned_editor_id INT NULL AFTER user_id,
ADD COLUMN submitted_for_review_at TIMESTAMP NULL AFTER created_at,
ADD COLUMN reviewed_at TIMESTAMP NULL AFTER submitted_for_review_at,
ADD COLUMN approved_at TIMESTAMP NULL AFTER reviewed_at,
ADD COLUMN published_at TIMESTAMP NULL AFTER approved_at,
ADD COLUMN review_comments TEXT NULL AFTER published_at,
ADD COLUMN internal_notes TEXT NULL AFTER review_comments,
ADD INDEX idx_assigned_editor (assigned_editor_id),
ADD INDEX idx_status_location (status, location_id),
ADD INDEX idx_submitted_review (submitted_for_review_at),
ADD FOREIGN KEY (assigned_editor_id) REFERENCES users(id) ON DELETE SET NULL";
execute_query($conn, $query4, "Added editorial fields and indexes to news table");
// 5. Create news_reviews table
$query5 = "CREATE TABLE news_reviews (
id INT AUTO_INCREMENT PRIMARY KEY,
news_id INT NOT NULL,
reviewer_id INT NOT NULL,
action ENUM('approve', 'reject', 'request_changes') NOT NULL,
comments TEXT NULL,
internal_notes TEXT NULL,
reviewed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_news_id (news_id),
INDEX idx_reviewer_id (reviewer_id),
INDEX idx_reviewed_at (reviewed_at),
FOREIGN KEY (news_id) REFERENCES news(id) ON DELETE CASCADE,
FOREIGN KEY (reviewer_id) REFERENCES users(id) ON DELETE CASCADE
)";
execute_query($conn, $query5, "Created news_reviews table");
// 6. Create editor_assignments table
$query6 = "CREATE TABLE editor_assignments (
id INT AUTO_INCREMENT PRIMARY KEY,
editor_id INT NOT NULL,
location_id INT NOT NULL,
assigned_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_active BOOLEAN DEFAULT TRUE,
created_by INT NOT NULL,
UNIQUE KEY unique_editor_location (editor_id, location_id),
INDEX idx_editor_id (editor_id),
INDEX idx_location_id (location_id),
INDEX idx_active (is_active),
FOREIGN KEY (editor_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (location_id) REFERENCES locations(id) ON DELETE CASCADE,
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE
)";
execute_query($conn, $query6, "Created editor_assignments table");
// 7. Create review_notifications table
$query7 = "CREATE TABLE review_notifications (
id INT AUTO_INCREMENT PRIMARY KEY,
news_id INT NOT NULL,
recipient_id INT NOT NULL,
notification_type ENUM('submitted', 'approved', 'rejected', 'published') NOT NULL,
message TEXT NOT NULL,
is_read BOOLEAN DEFAULT FALSE,
sent_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
read_at TIMESTAMP NULL,
INDEX idx_recipient_id (recipient_id),
INDEX idx_news_id (news_id),
INDEX idx_type (notification_type),
INDEX idx_unread (is_read, recipient_id),
FOREIGN KEY (news_id) REFERENCES news(id) ON DELETE CASCADE,
FOREIGN KEY (recipient_id) REFERENCES users(id) ON DELETE CASCADE
)";
execute_query($conn, $query7, "Created review_notifications table");
// 8. Insert sample editor users
$sample_editors = [
[
'username' => 'editor_accra',
'email' => 'editor.accra@copnews.org',
'password' => password_hash('editor123', PASSWORD_DEFAULT),
'user_name' => 'Accra District Editor',
'location_id' => 5, // Accra Central District
'account_type' => 'editor',
'can_edit_others' => 1,
'editorial_scope' => 'district'
],
[
'username' => 'editor_tema',
'email' => 'editor.tema@copnews.org',
'password' => password_hash('editor123', PASSWORD_DEFAULT),
'user_name' => 'Tema District Editor',
'location_id' => 4, // Tema District
'account_type' => 'editor',
'can_edit_others' => 1,
'editorial_scope' => 'district'
],
[
'username' => 'editor_area_accra',
'email' => 'area.editor.accra@copnews.org',
'password' => password_hash('editor123', PASSWORD_DEFAULT),
'user_name' => 'Greater Accra Area Editor',
'location_id' => 1, // Greater Accra Area
'account_type' => 'editor',
'can_edit_others' => 1,
'editorial_scope' => 'area'
]
];
foreach ($sample_editors as $editor) {
$query = "INSERT INTO users (username, email, password, user_name, location_id, account_type, can_edit_others, editorial_scope, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())";
try {
$stmt = $conn->prepare($query);
$stmt->execute([
$editor['username'],
$editor['email'],
$editor['password'],
$editor['user_name'],
$editor['location_id'],
$editor['account_type'],
$editor['can_edit_others'],
$editor['editorial_scope']
]);
log_migration("Created sample editor: " . $editor['user_name']);
} catch (PDOException $e) {
if ($e->getCode() == 23000) { // Duplicate entry
log_migration("Sample editor already exists: " . $editor['user_name']);
} else {
log_migration("Failed to create sample editor " . $editor['user_name'] . ": " . $e->getMessage(), false);
}
}
}
// 9. Create editor assignments for sample editors
$assignments = [
['editor_username' => 'editor_accra', 'location_id' => 5], // Accra Central District
['editor_username' => 'editor_accra', 'location_id' => 8], // Osu Assembly
['editor_username' => 'editor_tema', 'location_id' => 4], // Tema District
['editor_username' => 'editor_tema', 'location_id' => 7], // Community 1/9 Assembly
['editor_username' => 'editor_area_accra', 'location_id' => 1], // Greater Accra Area
];
foreach ($assignments as $assignment) {
$query = "INSERT INTO editor_assignments (editor_id, location_id, created_by)
SELECT u.id, ?, 1 FROM users u WHERE u.username = ? AND NOT EXISTS (
SELECT 1 FROM editor_assignments ea WHERE ea.editor_id = u.id AND ea.location_id = ?
)";
try {
$stmt = $conn->prepare($query);
$stmt->execute([
$assignment['location_id'],
$assignment['editor_username'],
$assignment['location_id']
]);
if ($stmt->rowCount() > 0) {
log_migration("Created editor assignment: " . $assignment['editor_username'] . " -> Location ID " . $assignment['location_id']);
} else {
log_migration("Editor assignment already exists: " . $assignment['editor_username'] . " -> Location ID " . $assignment['location_id']);
}
} catch (PDOException $e) {
log_migration("Failed to create editor assignment: " . $e->getMessage(), false);
}
}
// 10. Add system settings for editorial workflow
$settings = [
['setting_key' => 'editorial_auto_assign', 'setting_value' => '1', 'description' => 'Automatically assign editors based on location hierarchy'],
['setting_key' => 'editorial_email_notifications', 'setting_value' => '1', 'description' => 'Send email notifications for editorial actions'],
['setting_key' => 'editorial_review_timeout_days', 'setting_value' => '7', 'description' => 'Days before review timeout notification'],
['setting_key' => 'editorial_require_comments_on_reject', 'setting_value' => '1', 'description' => 'Require comments when rejecting articles']
];
foreach ($settings as $setting) {
$query = "INSERT INTO settings (setting_key, setting_value, description, created_at)
VALUES (?, ?, ?, NOW())
ON DUPLICATE KEY UPDATE
setting_value = VALUES(setting_value),
description = VALUES(description)";
try {
$stmt = $conn->prepare($query);
$stmt->execute([$setting['setting_key'], $setting['setting_value'], $setting['description']]);
log_migration("Added/updated setting: " . $setting['setting_key']);
} catch (PDOException $e) {
log_migration("Failed to add setting " . $setting['setting_key'] . ": " . $e->getMessage(), false);
}
}
// 11. Create audit log entries for migration
$audit_query = "INSERT INTO audit_logs (user_id, action, table_name, record_id, details, ip_address, created_at)
VALUES (?, 'MIGRATION', 'SYSTEM', 0, ?, ?, NOW())";
try {
$stmt = $conn->prepare($audit_query);
$stmt->execute([
$_SESSION['user_id'],
'Proofreading system migration completed with ' . count($migration_log) . ' operations',
$_SERVER['REMOTE_ADDR'] ?? '127.0.0.1'
]);
log_migration("Created audit log entry for migration");
} catch (PDOException $e) {
log_migration("Failed to create audit log entry: " . $e->getMessage(), false);
}
echo "\n==========================================\n";
echo "Migration Summary:\n";
echo "==========================================\n";
$success_count = 0;
$error_count = 0;
foreach ($migration_log as $entry) {
if ($entry['success']) {
$success_count++;
} else {
$error_count++;
}
}
echo "Total operations: " . count($migration_log) . "\n";
echo "Successful: $success_count\n";
echo "Errors: $error_count\n\n";
if ($error_count > 0) {
echo "ERRORS ENCOUNTERED:\n";
echo "===================\n";
foreach ($errors as $error) {
echo "- $error\n";
}
echo "\nPlease review and fix errors before proceeding.\n";
} else {
echo "✅ Migration completed successfully!\n\n";
echo "Next steps:\n";
echo "1. Test the editorial dashboard at: editorial/dashboard.php\n";
echo "2. Login with sample editor accounts:\n";
echo " - Username: editor_accra, Password: editor123\n";
echo " - Username: editor_tema, Password: editor123\n";
echo " - Username: editor_area_accra, Password: editor123\n";
echo "3. Create a test article and submit it for review\n";
echo "4. Test the complete proofreading workflow\n\n";
}
echo "Migration log saved. You can now use the proofreading system.\n";
?>
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists