diff --git a/src/main/ipc/index.ts b/src/main/ipc/index.ts index bf9cece..37602b1 100644 --- a/src/main/ipc/index.ts +++ b/src/main/ipc/index.ts @@ -95,17 +95,24 @@ export function registerIpcHandlers(): void { return { success, message: success ? 'Nginx başlatıldı.' : 'Nginx devreye alınamadı (Hata loglarını kontrol edin).' } } - if (serviceName === 'php') { - const binPath = findExecutable(binDir, 'php-cgi.exe') - if (!binPath) return { success: false, message: 'PHP executable bulunamadı. Lütfen en az bir sürüm indirin.' } + if (serviceName.startsWith('php')) { + const versionMatch = serviceName.match(/^php:(.+)$/) + const phpVersion = versionMatch ? versionMatch[1] : null + const phpId = phpVersion ? `php-${phpVersion}` : null + const phpDir = phpId ? path.join(binDir, phpId) : binDir + const binPath = findExecutable(phpDir, 'php-cgi.exe') + + if (!binPath) return { success: false, message: `${phpVersion || ''} PHP executable bulunamadı. Lütfen indirin.` } + + const phpPort = phpVersion ? portMappingService.getPhpPort(phpVersion) : settings.phpPort const extDir = path.join(path.dirname(binPath), 'ext') - const configPath = await configService.generateConfig('php.ini.template', 'php.ini', { + const configPath = await configService.generateConfig('php.ini.template', `php_${phpVersion || 'default'}.ini`, { EXT_DIR: extDir }) - const success = await processManager.startService('php', binPath, ['-b', `127.0.0.1:${settings.phpPort}`, '-c', configPath], false) - return { success, message: success ? 'PHP başlatıldı.' : 'PHP devreye alınamadı (Hata loglarını kontrol edin).' } + const success = await processManager.startService(serviceName, binPath, ['-b', `127.0.0.1:${phpPort}`, '-c', configPath], false) + return { success, message: success ? `${phpVersion || ''} PHP başlatıldı.` : `${phpVersion || ''} PHP devreye alınamadı.` } } if (serviceName === 'mysql') { diff --git a/src/main/services/PhpManagerService.ts b/src/main/services/PhpManagerService.ts index 254bb49..d7e0aa9 100644 --- a/src/main/services/PhpManagerService.ts +++ b/src/main/services/PhpManagerService.ts @@ -2,6 +2,7 @@ import fs from 'fs' import path from 'path' import { app } from 'electron' import axios from 'axios' +import { portMappingService } from './PortMappingService' export interface PhpVersion { id: string @@ -9,6 +10,7 @@ export interface PhpVersion { url: string status: 'available' | 'downloading' | 'installed' progress: number + port?: number } export class PhpManagerService { @@ -136,7 +138,11 @@ export class PhpManagerService { await this.fetchAvailableVersions() } this.refreshInstalledStatus() - return this.versions + // Add ports for all versions + return this.versions.map(v => ({ + ...v, + port: portMappingService.getPhpPort(v.version) + })) } updateProgress(id: string, progress: number, status: PhpVersion['status'] = 'downloading') { diff --git a/src/main/services/ProcessManager.ts b/src/main/services/ProcessManager.ts index add393a..d25884e 100644 --- a/src/main/services/ProcessManager.ts +++ b/src/main/services/ProcessManager.ts @@ -170,11 +170,14 @@ export class ProcessManager { } getStatuses(): Record { - return { - nginx: this.isServiceRunning('nginx') ? 'running' : 'stopped', - php: this.isServiceRunning('php') ? 'running' : 'stopped', - mysql: this.isServiceRunning('mysql') ? 'running' : 'stopped' + const statuses: Record = {} + for (const name of Array.from(this.processes.keys())) { + statuses[name] = 'running' } + // Ensure defaults are present if stopped + if (!statuses['nginx']) statuses['nginx'] = 'stopped' + if (!statuses['mysql']) statuses['mysql'] = 'stopped' + return statuses } private async checkErrorLogs(name: string) { diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 880d0e7..3c2f506 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react' +import React, { useState, useEffect, Fragment } from 'react' import { Box, Typography, @@ -243,11 +243,11 @@ function App(): JSX.Element { const interval = setInterval(() => { fetchStatus() - fetchProjects() - fetchPhpVersions() - fetchMySqlVersions() - fetchNginxVersions() - }, 5000) + // fetchProjects() // Reduced frequency for these + // fetchPhpVersions() + // fetchMySqlVersions() + // fetchNginxVersions() + }, 3000) let logInterval: NodeJS.Timeout | null = null if (logDialogOpen && selectedService) { @@ -284,15 +284,15 @@ function App(): JSX.Element { } } - const handleToggleService = async (service: keyof ServiceStatus) => { + const handleToggleService = async (service: string) => { if (!window.api) return - const isStarting = status[service] === 'stopped' + const isStarting = (status[service] || 'stopped') === 'stopped' if (isStarting) { setStatus(prev => ({ ...prev, [service]: 'starting' })) } - const result = status[service] === 'running' + const result = (status[service] || 'stopped') === 'running' ? await window.api.stopService(service) : await window.api.startService(service) @@ -328,29 +328,36 @@ function App(): JSX.Element { const handleStartAll = async () => { if (!window.api) return - const services: (keyof ServiceStatus)[] = ['nginx', 'php', 'mysql'] - for (const s of services) { - if (status[s] === 'stopped') { - setStatus(prev => ({ ...prev, [s]: 'starting' })) - } + const criticalServices = ['nginx', 'mysql'] + for (const s of criticalServices) { + if (status[s] === 'stopped') setStatus(prev => ({ ...prev, [s]: 'starting' })) } - for (const s of services) { - if (status[s] !== 'running') { - await window.api.startService(s) - } + + // Also starting each installed PHP version + const phpToStart = phpVersions.filter(v => v.status === 'installed').map(v => `php:${v.version}`) + for (const s of phpToStart) { + if ((status[s] || 'stopped') === 'stopped') setStatus(prev => ({ ...prev, [s]: 'starting' })) } + + await Promise.all([ + ...criticalServices.filter(s => status[s] !== 'running').map(s => window.api?.startService(s)), + ...phpToStart.filter(s => (status[s] || 'stopped') !== 'running').map(s => window.api?.startService(s)) + ]) + fetchStatus() setNotification({ open: true, message: 'Tüm servisler başlatıldı.', severity: 'success' }) } const handleStopAll = async () => { if (!window.api) return - const services: (keyof ServiceStatus)[] = ['nginx', 'php', 'mysql'] - for (const s of services) { - if (status[s] === 'running') { - await window.api.stopService(s) - } - } + const criticalServices = ['nginx', 'mysql'] + const phpToStop = Object.keys(status).filter(s => s.startsWith('php:') && (status[s] === 'running' || status[s] === 'starting')) + + await Promise.all([ + ...criticalServices.filter(s => status[s] === 'running' || status[s] === 'starting').map(s => window.api?.stopService(s)), + ...phpToStop.map(s => window.api?.stopService(s)) + ]) + fetchStatus() setNotification({ open: true, message: 'Tüm servisler durduruldu.', severity: 'success' }) } @@ -753,22 +760,29 @@ function App(): JSX.Element { /> - - - - - - handleOpenLogs('php')} title="Logları Görüntüle"> - - - {getStatusChip(status.php)} - handleToggleService('php')} - disabled={status.php === 'starting'} - /> - - + {installedPhpVersions.map(v => ( + + + + + + + handleOpenLogs(`php:${v.version}`)} title="Logları Görüntüle"> + + + {getStatusChip(status[`php:${v.version}`] || 'stopped')} + handleToggleService(`php:${v.version}`)} + disabled={status[`php:${v.version}`] === 'starting'} + /> + + + + ))}