feat: implement Nginx configuration management, PHP environment initialization, and extension management UI
This commit is contained in:
@@ -14,8 +14,8 @@ expose_php = On
|
||||
max_execution_time = 300
|
||||
max_input_time = 120
|
||||
memory_limit = 512M
|
||||
error_reporting = E_ALL
|
||||
display_errors = On
|
||||
error_reporting = {{ERROR_REPORTING}}
|
||||
display_errors = {{DISPLAY_ERRORS}}
|
||||
display_startup_errors = On
|
||||
log_errors = On
|
||||
log_errors_max_len = 1024
|
||||
|
||||
+19
-19
@@ -194,15 +194,27 @@ export function registerIpcHandlers(): void {
|
||||
|
||||
// --- 1. Get extensions from local php.ini ---
|
||||
let extensionsList = ''
|
||||
let errorReporting = 'E_ALL'
|
||||
let displayErrors = 'On'
|
||||
|
||||
const localIniPath = path.join(phpDir, 'php.ini')
|
||||
const mustHaves = ['curl', 'mbstring', 'openssl', 'mysqli', 'pdo_mysql', 'gd', 'fileinfo', 'exif', 'intl', 'bz2', 'gettext', 'soap', 'xsl']
|
||||
|
||||
if (fs.existsSync(localIniPath)) {
|
||||
const localIniContent = fs.readFileSync(localIniPath, 'utf8')
|
||||
|
||||
// 1. Get extensions
|
||||
const extMatches = localIniContent.match(/^\s*extension\s*=.*$/gm)
|
||||
if (extMatches) {
|
||||
extensionsList = extMatches.join('\n')
|
||||
}
|
||||
|
||||
// 2. Get error settings
|
||||
const erMatch = localIniContent.match(/^\s*error_reporting\s*=\s*(.+)$/m)
|
||||
if (erMatch) errorReporting = erMatch[1].trim()
|
||||
|
||||
const deMatch = localIniContent.match(/^\s*display_errors\s*=\s*(.+)$/m)
|
||||
if (deMatch) displayErrors = deMatch[1].trim()
|
||||
} else {
|
||||
// Fallback formatting based on version
|
||||
const prefix = (phpVersion?.startsWith('5.') || phpVersion?.startsWith('7.')) ? 'php_' : ''
|
||||
@@ -215,7 +227,9 @@ export function registerIpcHandlers(): void {
|
||||
GD_EXT: gdExtName,
|
||||
SESSION_DIR: sessionDir,
|
||||
TEMP_DIR: tempDir,
|
||||
EXTENSIONS: extensionsList
|
||||
EXTENSIONS: extensionsList,
|
||||
ERROR_REPORTING: errorReporting,
|
||||
DISPLAY_ERRORS: displayErrors
|
||||
})
|
||||
|
||||
// Add a small delay to ensure previous instance (if any) is fully killed
|
||||
@@ -374,23 +388,10 @@ export function registerIpcHandlers(): void {
|
||||
ipcMain.handle('php:extensions:toggle', async (_event, { version, extName, enabled }) => {
|
||||
const result = await phpManagerService.toggleExtension(version, extName, enabled)
|
||||
if (result.success) {
|
||||
// Automatically restart the PHP service if it's running
|
||||
const serviceName = `php:${version}`
|
||||
if (processManager.isServiceRunning(serviceName)) {
|
||||
console.log(`Restarting ${serviceName} due to extension change...`)
|
||||
await processManager.stopService(serviceName)
|
||||
// We need to re-run the start logic or just let the user do it?
|
||||
// The user said "Proceed with the decision that you think is the most optimal"
|
||||
// Optimal is to restart it exactly as it was.
|
||||
// However, the start logic in 'services:start' has many parameters (ports, ini templates).
|
||||
// It's better to just stop it and tell the user it needs to be started again,
|
||||
// OR I can try to trigger the same start logic.
|
||||
// Given the current architecture, I'll just stop it and return a message.
|
||||
// Wait, I can't easily call 'services:start' from here without the event object.
|
||||
// Actually, I can just not restart it here and let the renderer handle it if they want.
|
||||
// NO, I'll just return that it's updated. PHP usually needs a restart anyway.
|
||||
// I'll update the message to reflect that.
|
||||
result.message += ". Please restart the PHP service to apply changes."
|
||||
result.message += " (Service stopped for restart)"
|
||||
}
|
||||
}
|
||||
return result
|
||||
@@ -413,13 +414,12 @@ export function registerIpcHandlers(): void {
|
||||
const iniPath = path.join(phpDir, 'php.ini')
|
||||
fs.writeFileSync(iniPath, content)
|
||||
|
||||
// Return a result that indicates a restart is needed
|
||||
const serviceName = `php:${version}`
|
||||
const isRunning = processManager.isServiceRunning(serviceName)
|
||||
if (isRunning) {
|
||||
if (processManager.isServiceRunning(serviceName)) {
|
||||
await processManager.stopService(serviceName)
|
||||
}
|
||||
return { success: true, message: `php.ini saved.${isRunning ? ' Current PHP service stopped. Please restart to apply.' : ''}` }
|
||||
|
||||
return { success: true, message: 'Configuration saved.' }
|
||||
})
|
||||
|
||||
// MariaDB Versions
|
||||
|
||||
@@ -71,18 +71,34 @@ const PhpExtensionManager: React.FC<PhpExtensionManagerProps> = ({ open, onClose
|
||||
|
||||
const handleSaveRaw = async () => {
|
||||
setIsSavingRaw(true)
|
||||
Swal.fire({
|
||||
title: 'Yapılandırma Kaydediliyor',
|
||||
text: 'PHP servisi yeniden başlatılıyor...',
|
||||
allowOutsideClick: false,
|
||||
didOpen: () => {
|
||||
Swal.showLoading()
|
||||
},
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
})
|
||||
|
||||
try {
|
||||
const result = await window.api.invoke('php:config:save', { version: phpVersion, content: rawConfig })
|
||||
if (result.success) {
|
||||
// Trigger restart
|
||||
await window.api.invoke('services:start', `php:${phpVersion}`)
|
||||
|
||||
Swal.fire({
|
||||
title: 'Başarılı',
|
||||
text: result.message,
|
||||
text: 'Yapılandırma kaydedildi ve servis yeniden başlatıldı.',
|
||||
icon: 'success',
|
||||
timer: 2000,
|
||||
showConfirmButton: false,
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
})
|
||||
setIsRawEditorOpen(false)
|
||||
fetchExtensions() // Refresh extension list too
|
||||
fetchExtensions()
|
||||
}
|
||||
} catch (error: any) {
|
||||
Swal.fire({ title: 'Hata', text: error.message, icon: 'error', background: '#1e1e1e', color: '#fff' })
|
||||
@@ -99,36 +115,37 @@ const PhpExtensionManager: React.FC<PhpExtensionManagerProps> = ({ open, onClose
|
||||
|
||||
const handleToggle = async (extName: string, enabled: boolean) => {
|
||||
setSaving(extName)
|
||||
|
||||
// Show a non-blocking toast or a small overlay if we want, but for "Restart" let's be more explicit if it was running
|
||||
const wasRunning = await window.api.invoke('service:status', `php:${phpVersion}`) === 'running'
|
||||
|
||||
if (wasRunning) {
|
||||
Swal.fire({
|
||||
title: 'Eklenti Ayarlanıyor',
|
||||
text: `${extName} ${enabled ? 'aktif ediliyor' : 'devre dışı bırakılıyor'} ve PHP yeniden başlatılıyor...`,
|
||||
allowOutsideClick: false,
|
||||
didOpen: () => {
|
||||
Swal.showLoading()
|
||||
},
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await window.api.invoke('php:extensions:toggle', { version: phpVersion, extName, enabled })
|
||||
if (result.success) {
|
||||
setExtensions(prev => prev.map(ext => ext.name === extName ? { ...ext, enabled } : ext))
|
||||
if (result.message.includes('restart')) {
|
||||
Swal.fire({
|
||||
title: 'Bilgi',
|
||||
text: result.message,
|
||||
icon: 'info',
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
})
|
||||
|
||||
if (wasRunning) {
|
||||
await window.api.invoke('services:start', `php:${phpVersion}`)
|
||||
Swal.close()
|
||||
}
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: 'Hata',
|
||||
text: result.message,
|
||||
icon: 'error',
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
})
|
||||
Swal.fire({ title: 'Hata', text: result.message, icon: 'error', background: '#1e1e1e', color: '#fff' })
|
||||
}
|
||||
} catch (error: any) {
|
||||
Swal.fire({
|
||||
title: 'Hata',
|
||||
text: error.message,
|
||||
icon: 'error',
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
})
|
||||
Swal.fire({ title: 'Hata', text: error.message, icon: 'error', background: '#1e1e1e', color: '#fff' })
|
||||
} finally {
|
||||
setSaving(null)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user