66 lines
2.7 KiB
PHP
66 lines
2.7 KiB
PHP
<?php
|
||
/**
|
||
* 入口文件(所有请求经此转发)
|
||
*/
|
||
define('BASE_PATH', dirname(__DIR__));
|
||
require BASE_PATH . '/app/Core/App.php';
|
||
\Core\App::init(); // 加载 Helper(含全局辅助函数)
|
||
apply_security_headers(); // 全局函数(与视图/控制器中的 e()/site_url() 等同源)
|
||
|
||
/**
|
||
* 输出缓冲:自动为内联 <script>/<style> 注入本次请求的 CSP nonce,
|
||
* 从而可移除 script-src 的 'unsafe-inline'(严格 CSP 的关键前提)。
|
||
*/
|
||
ob_start(function ($html) {
|
||
$nonce = function_exists('csp_nonce') ? csp_nonce() : '';
|
||
if ($nonce === '') return $html;
|
||
$html = preg_replace_callback('#<script(?![^>]*\bsrc=)(?![^>]*\bnonce=)([^>]*)>#i', function ($m) use ($nonce) {
|
||
return '<script nonce="' . $nonce . '"' . $m[1] . '>';
|
||
}, $html);
|
||
$html = preg_replace_callback('#<style(?![^>]*\bnonce=)([^>]*)>#i', function ($m) use ($nonce) {
|
||
return '<style nonce="' . $nonce . '"' . $m[1] . '>';
|
||
}, $html);
|
||
return $html;
|
||
});
|
||
|
||
/**
|
||
* 一键部署自愈:上传覆盖后无需手动点「数据升级」。
|
||
* 仅 MySQL 模式生效;若新模块表(crm_contacts)缺失,自动补齐表/列并刷新种子,幂等且保留已有数据。
|
||
* 数据库暂不可用时静默跳过,下次请求再尝试,绝不阻塞站点。
|
||
*/
|
||
if (\Core\Db::driver() === 'mysql') {
|
||
try {
|
||
$pdo = \Core\Db::pdo();
|
||
$has = $pdo->query("SELECT 1 FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='crm_contacts' LIMIT 1")->fetchColumn();
|
||
if (!$has) {
|
||
\Core\Installer::upgrade();
|
||
// 升级可能变更文件结构,顺带清一次 OPcache 以防 FPM 跑旧字节码
|
||
if (function_exists('opcache_reset')) @opcache_reset();
|
||
}
|
||
} catch (\Throwable $e) {
|
||
// 自愈失败不影响正常访问,留待管理员在 /admin/upgrade 手动处理
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 自动清 OPcache:覆盖部署后若发现磁盘文件比 OPcache 缓存的编译时间更新,
|
||
* 自动重置字节码缓存,免去手动重启 PHP-FPM。(仅当 OPcache 扩展可用时生效)
|
||
* 平时文件未变动时不触发,无性能开销。
|
||
*/
|
||
if (function_exists('opcache_get_status') && function_exists('opcache_reset')) {
|
||
$st = @opcache_get_status(false);
|
||
if (!empty($st['scripts'])) {
|
||
foreach ($st['scripts'] as $path => $info) {
|
||
if (isset($info['timestamp']) && is_file($path) && filemtime($path) > $info['timestamp']) {
|
||
@opcache_reset();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
\Core\App::run();
|
||
|
||
// 冲刷输出缓冲(执行 nonce 注入回调后输出)
|
||
if (ob_get_level() > 0) ob_end_flush();
|