diff --git a/app/Http/Controllers/SystemStatusController.php b/app/Http/Controllers/SystemStatusController.php index 9045e91..13682a8 100644 --- a/app/Http/Controllers/SystemStatusController.php +++ b/app/Http/Controllers/SystemStatusController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Models\Setting; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Symfony\Component\Process\Process; @@ -16,9 +17,12 @@ class SystemStatusController extends Controller } $phpDefaultPath = $this->resolveBinary('php'); - $phpSelectedPath = PHP_BINARY ?: $phpDefaultPath; + $phpConfiguredPath = trim((string) Setting::where('key', 'system.php_binary')->value('value')); + $phpSelectedPath = $phpConfiguredPath ?: (PHP_BINARY ?: $phpDefaultPath); $phpSelectedOk = (bool) $phpSelectedPath; - $phpSelectedVersion = PHP_VERSION; + $phpSelectedVersion = $phpSelectedPath + ? ($this->resolvePhpVersion($phpSelectedPath) ?? PHP_VERSION) + : PHP_VERSION; $minVersions = $this->resolveMinVersions(); $composerPath = $this->resolveBinary('composer'); $nodePath = $this->resolveBinary('node'); @@ -40,6 +44,7 @@ class SystemStatusController extends Controller return response()->json([ 'php' => PHP_VERSION, 'php_default' => $phpDefaultPath, + 'php_configured' => $phpConfiguredPath ?: null, 'php_selected_path' => $phpSelectedPath, 'php_selected_ok' => $phpSelectedOk, 'php_selected_version' => $phpSelectedVersion, diff --git a/app/Http/Controllers/SystemUpdateController.php b/app/Http/Controllers/SystemUpdateController.php index 45a50be..85151cd 100644 --- a/app/Http/Controllers/SystemUpdateController.php +++ b/app/Http/Controllers/SystemUpdateController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Models\Setting; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\File; @@ -169,7 +170,10 @@ class SystemUpdateController extends Controller ], 500); } - $phpBinary = env('SYSTEM_UPDATE_PHP_BINARY') ?: (PHP_BINARY ?: 'php'); + $phpBinary = trim((string) Setting::where('key', 'system.php_binary')->value('value')); + if ($phpBinary === '') { + $phpBinary = env('SYSTEM_UPDATE_PHP_BINARY') ?: (PHP_BINARY ?: 'php'); + } $append("Running migrations (using {$phpBinary})..."); $migrate = new Process([$phpBinary, 'artisan', 'migrate', '--force'], base_path()); $migrate->setTimeout(600); diff --git a/composer.json b/composer.json index e28ebeb..b39ad37 100644 --- a/composer.json +++ b/composer.json @@ -98,5 +98,5 @@ "minimum-stability": "stable", "prefer-stable": true, "version": "26.0.2", - "build": "49" + "build": "52" } diff --git a/git_update.sh b/git_update.sh index fa23878..b913d9a 100755 --- a/git_update.sh +++ b/git_update.sh @@ -21,14 +21,41 @@ git pull --ff-only echo "Installing PHP dependencies..." composer install --no-dev --optimize-autoloader +resolve_php_bin() { + if [[ -n "${PHP_BIN:-}" ]]; then + echo "$PHP_BIN" + return + fi + if command -v keyhelp-php84 >/dev/null 2>&1; then + echo "keyhelp-php84" + return + fi + if command -v php >/dev/null 2>&1; then + echo "php" + return + fi + echo "php" +} + +PHP_BIN="$(resolve_php_bin)" + +if [[ -x "artisan" ]]; then + CONFIGURED_PHP="$($PHP_BIN artisan tinker --execute="echo \\App\\Models\\Setting::where('key','system.php_binary')->value('value') ?? '';" 2>/dev/null || true)" + if [[ -n "$CONFIGURED_PHP" ]]; then + if command -v "$CONFIGURED_PHP" >/dev/null 2>&1; then + PHP_BIN="$CONFIGURED_PHP" + elif [[ -x "$CONFIGURED_PHP" ]]; then + PHP_BIN="$CONFIGURED_PHP" + fi + fi +fi + echo "Installing JS dependencies..." npm install echo "Building assets..." npm run build -PHP_BIN="${PHP_BIN:-php}" - echo "Running migrations..." $PHP_BIN artisan migrate --force diff --git a/resources/js/pages/Acp.jsx b/resources/js/pages/Acp.jsx index eec859a..6ef03a7 100644 --- a/resources/js/pages/Acp.jsx +++ b/resources/js/pages/Acp.jsx @@ -201,6 +201,11 @@ function Acp({ isAdmin }) { favicon_128: '', favicon_256: '', }) + const [systemCliSettings, setSystemCliSettings] = useState({ + php_binary: '', + }) + const [systemCliSaving, setSystemCliSaving] = useState(false) + const [systemCliError, setSystemCliError] = useState('') const settingsDetailMap = { forum_name: 'forumName', default_theme: 'defaultTheme', @@ -292,6 +297,9 @@ function Acp({ isAdmin }) { favicon_256: settingsMap.get('favicon_256') || '', } setGeneralSettings(next) + setSystemCliSettings({ + php_binary: settingsMap.get('system.php_binary') || '', + }) setAttachmentSettings({ display_images_inline: settingsMap.get('attachments.display_images_inline') || 'true', create_thumbnails: settingsMap.get('attachments.create_thumbnails') || 'true', @@ -373,6 +381,23 @@ function Acp({ isAdmin }) { } } + const handleSystemCliSave = async (event) => { + event.preventDefault() + setSystemCliSaving(true) + setSystemCliError('') + try { + const value = typeof systemCliSettings.php_binary === 'string' + ? systemCliSettings.php_binary.trim() + : String(systemCliSettings.php_binary ?? '') + await saveSetting('system.php_binary', value) + setSystemCliSettings((prev) => ({ ...prev, php_binary: value })) + } catch (err) { + setSystemCliError(err.message) + } finally { + setSystemCliSaving(false) + } + } + const handleLogoUpload = async (file, settingKey) => { if (!file) return setGeneralUploading(true) @@ -3588,9 +3613,30 @@ function Acp({ isAdmin }) {
CLI
-

- Placeholder: CLI upgrade commands and automation helpers will live here. -

+ {systemCliError &&

{systemCliError}

} +
+ + PHP interpreter + + setSystemCliSettings((prev) => ({ + ...prev, + php_binary: event.target.value, + })) + } + /> + + Used for CLI-based updates and maintenance tasks. Leave empty to use + the system default. + + + +
)}