$value) { if (is_string($value)) { if ((substr($value, 0, 1) === '"' && substr($value, -1) === '"') || (substr($value, 0, 1) === "'" && substr($value, -1) === "'")) { $envVars[$key] = substr($value, 1, -1); } } } } // Global configuration $GLOBALS['config'] = [ // Application identity 'APP_NAME' => $envVars['APP_NAME'] ?? 'TINKER TICKETS', 'APP_SUBTITLE' => $envVars['APP_SUBTITLE'] ?? 'LotusGuild Infrastructure', 'APP_VERSION' => $envVars['APP_VERSION'] ?? '1.2', // Asset cache-busting version — auto-computed from key asset mtimes so // browsers always pick up changes on deploy. Override via ASSET_VERSION in .env. 'ASSET_VERSION' => (function() use ($envVars) { if (!empty($envVars['ASSET_VERSION'])) return $envVars['ASSET_VERSION']; $files = [ __DIR__ . '/../assets/css/base.css', __DIR__ . '/../assets/css/dashboard.css', __DIR__ . '/../assets/css/ticket.css', __DIR__ . '/../assets/js/base.js', __DIR__ . '/../assets/js/dashboard.js', __DIR__ . '/../assets/js/ticket.js', ]; $mtime = 0; foreach ($files as $f) { if (file_exists($f)) $mtime = max($mtime, filemtime($f)); } return $mtime ?: '20260329'; })(), // Canonical ticket statuses — single source of truth used by views and JS 'TICKET_STATUSES' => ['Open', 'Pending', 'In Progress', 'Closed'], // Database settings 'DB_HOST' => $envVars['DB_HOST'] ?? 'localhost', 'DB_USER' => $envVars['DB_USER'] ?? 'root', 'DB_PASS' => $envVars['DB_PASS'] ?? '', 'DB_NAME' => $envVars['DB_NAME'] ?? 'tinkertickets', // URL settings 'BASE_URL' => '', // Empty since we're serving from document root 'ASSETS_URL' => '/assets', // Assets URL 'API_URL' => '/api', // API URL // Matrix webhook (hookshot generic webhook URL) 'MATRIX_WEBHOOK_URL' => $envVars['MATRIX_WEBHOOK_URL'] ?? null, // Comma-separated Matrix user IDs to @mention on new tickets / status changes (e.g. @jared:matrix.lotusguild.org) 'MATRIX_NOTIFY_USERS' => $envVars['MATRIX_NOTIFY_USERS'] ?? '', // Matrix homeserver domain (e.g. matrix.lotusguild.org) — used to construct Matrix user IDs 'MATRIX_DOMAIN' => $envVars['MATRIX_DOMAIN'] ?? null, // Internal Synapse client-API base URL (e.g. http://10.10.10.29:8008) — used to verify user existence via Admin API 'SYNAPSE_ADMIN_URL' => $envVars['SYNAPSE_ADMIN_URL'] ?? null, // Synapse admin access token (generate with: register_new_matrix_user or admin API) 'SYNAPSE_ADMIN_TOKEN' => $envVars['SYNAPSE_ADMIN_TOKEN'] ?? null, // Set to '1' or 'true' to send a notification when any comment is posted 'MATRIX_NOTIFY_COMMENTS' => filter_var($envVars['MATRIX_NOTIFY_COMMENTS'] ?? false, FILTER_VALIDATE_BOOLEAN), // Set to '1' or 'true' to send a notification when a ticket is assigned 'MATRIX_NOTIFY_ASSIGNMENTS' => filter_var($envVars['MATRIX_NOTIFY_ASSIGNMENTS'] ?? false, FILTER_VALIDATE_BOOLEAN), // Domain settings for external integrations (webhooks, links, etc.) // Set APP_DOMAIN in .env to override 'APP_DOMAIN' => $envVars['APP_DOMAIN'] ?? null, // Allowed hosts for HTTP_HOST validation (comma-separated in .env) 'ALLOWED_HOSTS' => array_filter(array_map('trim', explode(',', $envVars['ALLOWED_HOSTS'] ?? 'localhost,127.0.0.1') )), // Session settings 'SESSION_TIMEOUT' => 18000, // 5 hours in seconds 'SESSION_REGENERATE_INTERVAL' => 300, // Regenerate session ID every 5 minutes // CSRF settings 'CSRF_LIFETIME' => 3600, // 1 hour in seconds // Pagination settings 'PAGINATION_DEFAULT' => 15, // Default items per page 'PAGINATION_MAX' => 100, // Maximum items per page // File upload settings 'MAX_UPLOAD_SIZE' => 10485760, // 10MB in bytes 'ALLOWED_FILE_TYPES' => [ 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'application/pdf', 'text/plain', 'text/csv', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/zip', 'application/x-7z-compressed', 'application/x-tar', 'application/gzip' ], 'UPLOAD_DIR' => __DIR__ . '/../uploads', // Rate limiting 'RATE_LIMIT_DEFAULT' => 100, // Requests per minute for general 'RATE_LIMIT_API' => 60, // Requests per minute for API // Audit log settings 'AUDIT_LOG_RETENTION_DAYS' => 90, // Timezone settings // Default: America/New_York (EST/EDT) // Common options: America/Chicago (CST), America/Denver (MST), America/Los_Angeles (PST), UTC 'TIMEZONE' => $envVars['TIMEZONE'] ?? 'America/New_York', 'TIMEZONE_OFFSET' => null, // Will be calculated below // LDAP / lldap settings (for user avatar lookups) 'LDAP_HOST' => $envVars['LDAP_HOST'] ?? '10.10.10.39', 'LDAP_PORT' => (int)($envVars['LDAP_PORT'] ?? 3890), 'LDAP_BIND_DN' => $envVars['LDAP_BIND_DN'] ?? 'uid=tinker-tickets,ou=people,dc=example,dc=com', 'LDAP_BIND_PW' => $envVars['LDAP_BIND_PW'] ?? '', 'LDAP_BASE_DN' => $envVars['LDAP_BASE_DN'] ?? 'dc=example,dc=com', 'LDAP_USER_BASE' => $envVars['LDAP_USER_BASE'] ?? 'ou=people,dc=example,dc=com', 'LDAP_ENABLED' => filter_var($envVars['LDAP_ENABLED'] ?? 'true', FILTER_VALIDATE_BOOLEAN), 'AVATAR_CACHE_DIR' => __DIR__ . '/../uploads/avatars', 'AVATAR_CACHE_TTL' => (int)($envVars['AVATAR_CACHE_TTL'] ?? 3600), // seconds ]; // Set PHP default timezone date_default_timezone_set($GLOBALS['config']['TIMEZONE']); // Calculate UTC offset for JavaScript (in minutes, negative for west of UTC) $now = new DateTime('now', new DateTimeZone($GLOBALS['config']['TIMEZONE'])); $GLOBALS['config']['TIMEZONE_OFFSET'] = $now->getOffset() / 60; // Convert seconds to minutes $GLOBALS['config']['TIMEZONE_ABBREV'] = $now->format('T'); // e.g., "EST", "EDT" ?>