Sindbad~EG File Manager

Current Path : /home/copmadinaarea/thecopmadinaarea.org/portal/config/
Upload File :
Current File : /home/copmadinaarea/thecopmadinaarea.org/portal/config/config.php

<?php
/**
 * Application Configuration
 * Church Membership System
 */

// Start session if not already started (only if headers not sent)
if (session_status() === PHP_SESSION_NONE && !headers_sent()) {
    session_start();
}

// Timezone
date_default_timezone_set('UTC');

// Application Settings
define('APP_NAME', 'Church Membership System');
define('APP_VERSION', '1.0.0');

// Auto-detect BASE_URL for portability
// Since config.php is in /config/ directory, go up one level to get app root
$appRoot = dirname(__DIR__);
$documentRoot = $_SERVER['DOCUMENT_ROOT'] ?? '';

// Calculate relative path from document root to app root
if ($documentRoot && strpos($appRoot, $documentRoot) === 0) {
    $relativePath = str_replace('\\', '/', substr($appRoot, strlen($documentRoot)));
    $relativePath = '/' . trim($relativePath, '/') . '/';
} else {
    // Fallback: try to detect from SCRIPT_NAME
    $relativePath = '/';
    if (isset($_SERVER['SCRIPT_NAME'])) {
        $scriptPath = dirname($_SERVER['SCRIPT_NAME']);
        // Remove /modules, /includes, /members etc. to get to root
        $scriptPath = preg_replace('#/(modules|includes|members|api|classes|config)/.*$#', '', $scriptPath);
        $relativePath = rtrim($scriptPath, '/') . '/';
    }
}

$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443)) ? "https://" : "http://";
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
define('BASE_URL', $protocol . $host . $relativePath);
define('UPLOAD_PATH', __DIR__ . '/../uploads/');
define('MAX_UPLOAD_SIZE', 5242880); // 5MB

// Security
define('HASH_ALGO', PASSWORD_BCRYPT);
define('SESSION_LIFETIME', 3600); // 1 hour

// Pagination
define('RECORDS_PER_PAGE', 25);

// Include database configuration
require_once __DIR__ . '/database.php';

// Autoload classes
spl_autoload_register(function ($class) {
    $file = __DIR__ . '/../classes/' . $class . '.php';
    if (file_exists($file)) {
        require_once $file;
    }
});

// Helper Functions
function sanitize($data) {
    return htmlspecialchars(strip_tags(trim($data)), ENT_QUOTES, 'UTF-8');
}

function redirect($url) {
    header("Location: " . BASE_URL . $url);
    exit();
}

function isLoggedIn() {
    return isset($_SESSION['user_id']) && !empty($_SESSION['user_id']);
}

function isSuperuser() {
    return isset($_SESSION['is_superuser']) && $_SESSION['is_superuser'] === true;
}

function isAreaAdmin() {
    return getUserAccessLevel() === 'area' || isSuperuser();
}

function isDistrictAdmin() {
    return getUserAccessLevel() === 'district' || isAreaAdmin();
}

function isAssemblyAdmin() {
    return getUserAccessLevel() === 'assembly' || isDistrictAdmin();
}

function checkLogin() {
    if (!isLoggedIn()) {
        redirect('login.php');
    }
}

function getAccessLevel() {
    return $_SESSION['access_level'] ?? null;
}

function canAccess($level) {
    $accessHierarchy = ['assembly' => 1, 'district' => 2, 'area' => 3, 'superuser' => 4];
    $userLevel = $accessHierarchy[getAccessLevel()] ?? 0;
    $requiredLevel = $accessHierarchy[$level] ?? 0;
    
    return $userLevel >= $requiredLevel || isSuperuser();
}

function checkAccess($requiredLevel, $redirectUrl = 'dashboard.php') {
    if (!canAccess($requiredLevel)) {
        $_SESSION['error'] = 'You do not have permission to access this resource.';
        redirect($redirectUrl);
    }
}

function canAccessModule($moduleName) {
    try {
        $db = Database::getInstance()->getConnection();
        $userAccessLevel = getUserAccessLevel();
        
        // Check if module exists and is active, and if user's access level is enabled
        $stmt = $db->prepare("
            SELECT mal.is_enabled
            FROM module_management m
            INNER JOIN module_access_levels mal ON m.id = mal.module_id
            WHERE m.module_name = :module_name
            AND m.is_active = 1
            AND mal.access_level = :access_level
        ");
        $stmt->execute([
            'module_name' => $moduleName,
            'access_level' => $userAccessLevel
        ]);
        $result = $stmt->fetch();
        
        if (!$result) {
            return false;
        }
        
        return (bool)$result['is_enabled'];
    } catch (Exception $e) {
        error_log("canAccessModule error: " . $e->getMessage());
        return false;
    }
}

function formatDate($date, $format = 'Y-m-d') {
    if (empty($date)) return '';
    return date($format, strtotime($date));
}

function timeAgo($datetime) {
    $timestamp = strtotime($datetime);
    $difference = time() - $timestamp;
    
    $periods = [
        'year' => 31536000,
        'month' => 2592000,
        'week' => 604800,
        'day' => 86400,
        'hour' => 3600,
        'minute' => 60,
        'second' => 1
    ];
    
    foreach ($periods as $key => $value) {
        if ($difference >= $value) {
            $time = floor($difference / $value);
            return $time . ' ' . $key . ($time > 1 ? 's' : '') . ' ago';
        }
    }
    
    return 'Just now';
}

function generateMemberId($areaCode, $districtCode, $assemblyCode) {
    $timestamp = time();
    $random = mt_rand(100, 999);
    return strtoupper($areaCode . $districtCode . $assemblyCode . $timestamp . $random);
}

function sendJsonResponse($success, $message = '', $data = []) {
    header('Content-Type: application/json');
    echo json_encode([
        'success' => $success,
        'message' => $message,
        'data' => $data
    ]);
    exit();
}

function getCurrentUserName() {
    return $_SESSION['full_name'] ?? $_SESSION['username'] ?? 'User';
}

function getCurrentUserPhoto() {
    return !empty($_SESSION['profile_photo']) ? BASE_URL . 'uploads/profiles/' . $_SESSION['profile_photo'] : BASE_URL . 'assets/images/default-avatar.png';
}

function getUserAccessLevel() {
    return $_SESSION['access_level'] ?? 'assembly';
}

function getUserAreaId() {
    return $_SESSION['area_id'] ?? null;
}

function getUserDistrictId() {
    return $_SESSION['district_id'] ?? null;
}

function getUserAssemblyId() {
    return $_SESSION['assembly_id'] ?? null;
}

/**
 * Apply access level restrictions to SQL query
 * Returns array with 'where' clause and 'params'
 * 
 * @param string $tableAlias The table alias (e.g., 'm' for members)
 * @param array $options Configuration options:
 *   - 'area_column' => column name for area_id (default: 'area_id')
 *   - 'district_column' => column name for district_id (default: 'district_id')
 *   - 'assembly_column' => column name for assembly_id (default: 'assembly_id')
 *   - 'bypass_superuser' => if true, superusers also get filtered (default: false)
 * @return array ['where' => string, 'params' => array]
 */
function applyAccessLevelFilter($tableAlias = '', $options = []) {
    // Default options
    $defaults = [
        'area_column' => 'area_id',
        'district_column' => 'district_id',
        'assembly_column' => 'assembly_id',
        'bypass_superuser' => false
    ];
    $options = array_merge($defaults, $options);
    
    // Superusers see everything (unless bypassed)
    if (!$options['bypass_superuser'] && isSuperuser()) {
        return ['where' => '', 'params' => []];
    }
    
    $accessLevel = getUserAccessLevel();
    $prefix = $tableAlias ? $tableAlias . '.' : '';
    $where = '';
    $params = [];
    
    switch ($accessLevel) {
        case 'assembly':
            $assemblyId = getUserAssemblyId();
            if ($assemblyId) {
                $where = " AND {$prefix}{$options['assembly_column']} = :access_assembly_id";
                $params['access_assembly_id'] = $assemblyId;
            }
            break;
            
        case 'district':
            $districtId = getUserDistrictId();
            if ($districtId) {
                $where = " AND {$prefix}{$options['district_column']} = :access_district_id";
                $params['access_district_id'] = $districtId;
            }
            break;
            
        case 'area':
            $areaId = getUserAreaId();
            if ($areaId) {
                $where = " AND {$prefix}{$options['area_column']} = :access_area_id";
                $params['access_area_id'] = $areaId;
            }
            break;
    }
    
    return ['where' => $where, 'params' => $params];
}

/**
 * Get WHERE clause for access level filtering
 * Quick helper that returns just the WHERE string
 */
function getAccessLevelWhere($tableAlias = '', $options = []) {
    $filter = applyAccessLevelFilter($tableAlias, $options);
    return $filter['where'];
}

/**
 * Get params for access level filtering
 * Quick helper that returns just the params array
 */
function getAccessLevelParams($tableAlias = '', $options = []) {
    $filter = applyAccessLevelFilter($tableAlias, $options);
    return $filter['params'];
}

/**
 * Check if current user can view specific record based on location
 */
function canAccessRecord($recordAreaId, $recordDistrictId, $recordAssemblyId) {
    if (isSuperuser()) {
        return true;
    }
    
    $accessLevel = getUserAccessLevel();
    
    switch ($accessLevel) {
        case 'assembly':
            return $recordAssemblyId == getUserAssemblyId();
            
        case 'district':
            return $recordDistrictId == getUserDistrictId();
            
        case 'area':
            return $recordAreaId == getUserAreaId();
            
        default:
            return false;
    }
}

/**
 * Get user's access scope description
 */
function getUserAccessScope() {
    if (isSuperuser()) {
        return 'All Areas';
    }
    
    $db = Database::getInstance()->getConnection();
    $accessLevel = getUserAccessLevel();
    
    try {
        switch ($accessLevel) {
            case 'assembly':
                $assemblyId = getUserAssemblyId();
                if ($assemblyId) {
                    $stmt = $db->prepare("SELECT assembly_name FROM assemblies WHERE id = :id");
                    $stmt->execute(['id' => $assemblyId]);
                    $result = $stmt->fetch();
                    return $result ? $result['assembly_name'] . ' Assembly' : 'Assembly Level';
                }
                return 'Assembly Level';
                
            case 'district':
                $districtId = getUserDistrictId();
                if ($districtId) {
                    $stmt = $db->prepare("SELECT district_name FROM districts WHERE id = :id");
                    $stmt->execute(['id' => $districtId]);
                    $result = $stmt->fetch();
                    return $result ? $result['district_name'] . ' District' : 'District Level';
                }
                return 'District Level';
                
            case 'area':
                $areaId = getUserAreaId();
                if ($areaId) {
                    $stmt = $db->prepare("SELECT area_name FROM areas WHERE id = :id");
                    $stmt->execute(['id' => $areaId]);
                    $result = $stmt->fetch();
                    return $result ? $result['area_name'] . ' Area' : 'Area Level';
                }
                return 'Area Level';
                
            default:
                return 'Unknown';
        }
    } catch (Exception $e) {
        return ucfirst($accessLevel) . ' Level';
    }
}

/**
 * Get display badge for user access level
 */
function getUserAccessBadge() {
    $level = getUserAccessLevel();
    $scope = getUserAccessScope();
    
    $badges = [
        'superuser' => '<span class="px-3 py-1 rounded-full text-xs font-semibold bg-gradient-to-r from-purple-500 to-pink-500 text-white"><i class="fas fa-crown mr-1"></i>Superuser - All Access</span>',
        'area' => '<span class="px-3 py-1 rounded-full text-xs font-semibold bg-blue-100 text-blue-800"><i class="fas fa-map mr-1"></i>' . htmlspecialchars($scope) . '</span>',
        'district' => '<span class="px-3 py-1 rounded-full text-xs font-semibold bg-green-100 text-green-800"><i class="fas fa-map-marked-alt mr-1"></i>' . htmlspecialchars($scope) . '</span>',
        'assembly' => '<span class="px-3 py-1 rounded-full text-xs font-semibold bg-yellow-100 text-yellow-800"><i class="fas fa-church mr-1"></i>' . htmlspecialchars($scope) . '</span>'
    ];
    
    if (isSuperuser()) {
        return $badges['superuser'];
    }
    
    return $badges[$level] ?? '<span class="px-3 py-1 rounded-full text-xs font-semibold bg-gray-100 text-gray-800">' . htmlspecialchars($scope) . '</span>';
}

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists