<?php
declare(strict_types=1);
if(!is_file(EF_ROOT.'/config.php')){$path=parse_url($_SERVER['REQUEST_URI']??'/',PHP_URL_PATH)?:'/';if(str_contains($path,'/install')){require EF_ROOT.'/install/index.php';exit;}header('Location: /install/');exit;}
$config=require EF_ROOT.'/config.php';date_default_timezone_set($config['timezone']??'America/New_York');ini_set('display_errors','0');ini_set('log_errors','1');ini_set('error_log',EF_ROOT.'/storage/logs/php.log');$requestPath=trim(parse_url($_SERVER['REQUEST_URI']??'/',PHP_URL_PATH)?:'/','/');$adminPrefix=trim($config['admin_path']??'adminji','/');if(is_file(EF_ROOT.'/storage/maintenance.lock')&&!($requestPath===$adminPrefix||str_starts_with($requestPath,$adminPrefix.'/'))){http_response_code(503);header('Retry-After: 120');header('Cache-Control: no-store');exit('<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>Brief maintenance – Exams.fit</title><body><main><h1>Brief maintenance</h1><p>Exams.fit is being safely upgraded. Please try again in a minute.</p></main></body></html>');}session_name('examsfit_session');session_set_cookie_params(['httponly'=>true,'secure'=>true,'samesite'=>'Lax','path'=>'/']);session_start();if(!isset($_SESSION['born']))$_SESSION['born']=time();if(time()-($_SESSION['last_seen']??time())>7200){session_regenerate_id(true);$_SESSION=[];$_SESSION['born']=time();}$_SESSION['last_seen']=time();
require EF_ROOT.'/app/core.php';require EF_ROOT.'/app/importer.php';require EF_ROOT.'/app/feed.php';require EF_ROOT.'/app/addons.php';require EF_ROOT.'/app/maintenance.php';require EF_ROOT.'/app/updater.php';require EF_ROOT.'/app/blog.php';require EF_ROOT.'/app/tools.php';
function ef_dispatch():void{global$config;$path=trim(parse_url($_SERVER['REQUEST_URI']??'/',PHP_URL_PATH)?:'/','/');
 if($path==='install'||str_starts_with($path,'install/')){http_response_code(404);ef_error(404);return;}if($path==='cron'){ef_cron();return;}if($path==='robots.txt'){ef_robots();return;}if($path==='ads.txt'){header('Content-Type:text/plain; charset=utf-8');echo setting('ads_txt');return;}if($path==='sitemap_index.xml'||preg_match('~^sitemap-([a-z0-9_-]+)\.xml$~',$path,$m)){ef_sitemap_v31($m[1]??null);return;}if($path==='feed.xml'){ef_rss();return;}if($path==='blog/feed.xml'){ef_blog_rss();return;}if($path==='api/analytics'){ef_analytics_endpoint_root();return;}if($path==='api/report'){ef_report_endpoint();return;}if(preg_match('~^api/practice/(.+?)(?:/(submit))?$~',$path,$m)){ef_practice_api($m[1],$m[2]??'');return;}
 $admin=trim($config['admin_path']??'adminji','/');if($path===$admin||str_starts_with($path,$admin.'/')){require EF_ROOT.'/admin/index.php';ef_admin(substr($path,strlen($admin)));return;}if($path===''){ef_home();return;}if($path==='search'){ef_search();return;}if($path==='blog'){ef_blog_index();return;}if(preg_match('~^blog/category/([a-z0-9-]+)$~',$path,$m)){ef_blog_index($m[1]);return;}if(preg_match('~^blog/archive/(\d{4})/(\d{2})$~',$path,$m)){ef_blog_archive((int)$m[1],(int)$m[2]);return;}if($path==='tools'){ef_tools_index();return;}if(preg_match('~^tools/category/([a-z0-9-]+)$~',$path,$m)){ef_tools_index($m[1]);return;}if(in_array($path,['school','college','exams','practice-tests'],true)){ef_collection($path);return;}if(preg_match('~^category/([a-z0-9-]+)$~',$path,$m)){ef_category($m[1]);return;}if($path==='offline'){ef_layout('<section><h1>Offline</h1><p>Previously visited or saved pages may still be available.</p></section>',['title'=>'Offline','noindex'=>true]);return;}
 $redirect=one('SELECT id,target,status_code FROM redirects WHERE source=? AND enabled=1',[$path]);if($redirect){q('UPDATE redirects SET hits=hits+1 WHERE id=?',[$redirect['id']]);http_response_code((int)$redirect['status_code']);header('Location: '.(str_starts_with($redirect['target'],'http')?$redirect['target']:url($redirect['target'])));return;}ef_content($path);
}
