Enhance PHP version management in PHPManager: Implement comprehensive detection of PHP versions across multiple methods, including system checks and package manager queries. Add validation and configuration fixing for PHP installations. Introduce methods to retrieve the latest and recommended PHP versions, improving overall reliability and user feedback in the website management process.

This commit is contained in:
Master3395
2025-09-20 21:01:51 +02:00
parent f7e533db9b
commit 76f6d346f1
6 changed files with 399 additions and 36 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

View File

@@ -12,50 +12,145 @@ class PHPManager:
@staticmethod @staticmethod
def findPHPVersions(): def findPHPVersions():
# distro = ProcessUtilities.decideDistro() """
# if distro == ProcessUtilities.centos: Comprehensive PHP version detection that checks multiple locations and methods
# return ['PHP 5.3', 'PHP 5.4', 'PHP 5.5', 'PHP 5.6', 'PHP 7.0', 'PHP 7.1', 'PHP 7.2', 'PHP 7.3', 'PHP 7.4', 'PHP 8.0', 'PHP 8.1'] """
# elif distro == ProcessUtilities.cent8:
# return ['PHP 7.1','PHP 7.2', 'PHP 7.3', 'PHP 7.4', 'PHP 8.0', 'PHP 8.1']
# elif distro == ProcessUtilities.ubuntu20:
# return ['PHP 7.2', 'PHP 7.3', 'PHP 7.4', 'PHP 8.0', 'PHP 8.1']
# else:
# return ['PHP 7.0', 'PHP 7.1', 'PHP 7.2', 'PHP 7.3', 'PHP 7.4', 'PHP 8.0', 'PHP 8.1', 'PHP 8.2', 'PHP 8.3', 'PHP 8.4', 'PHP 8.5']
try: try:
finalPHPVersions = []
# Run the shell command and capture the output # Method 1: Check /usr/local/lsws directory (LiteSpeed PHP)
try:
result = ProcessUtilities.outputExecutioner('ls -la /usr/local/lsws') result = ProcessUtilities.outputExecutioner('ls -la /usr/local/lsws')
# Get the lines containing 'lsphp' in the output
lsphp_lines = [line for line in result.split('\n') if 'lsphp' in line] lsphp_lines = [line for line in result.split('\n') if 'lsphp' in line]
if os.path.exists(ProcessUtilities.debugPath): if os.path.exists(ProcessUtilities.debugPath):
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
logging.writeToFile(f'Found PHP lines in findPHPVersions: {lsphp_lines}') logging.writeToFile(f'Found PHP lines in findPHPVersions: {lsphp_lines}')
# Parse lsphp directories
for line in lsphp_lines:
try:
parts = line.split()
if len(parts) >= 9:
for part in parts:
if part.startswith('lsphp') and part != 'lsphp':
version_part = part[5:] # Remove 'lsphp' prefix
if len(version_part) >= 2:
major = version_part[0]
minor = version_part[1:]
formatted_version = f'PHP {major}.{minor}'
# Extract the version from the lines and format it as 'PHP x.y' # Validate the PHP installation
php_versions = ['PHP ' + line.split()[8][5] + '.' + line.split()[8][6:] for line in lsphp_lines] phpString = PHPManager.getPHPString(formatted_version)
php_path = f"/usr/local/lsws/lsphp{phpString}/bin/php"
lsphp_path = f"/usr/local/lsws/lsphp{phpString}/bin/lsphp"
finalPHPVersions = [] if os.path.exists(php_path) or os.path.exists(lsphp_path):
for php in php_versions: if formatted_version not in finalPHPVersions:
phpString = PHPManager.getPHPString(php) finalPHPVersions.append(formatted_version)
except (IndexError, ValueError):
continue
except Exception as e:
if os.path.exists(ProcessUtilities.debugPath):
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
logging.writeToFile(f'Error checking /usr/local/lsws: {str(e)}')
if os.path.exists("/usr/local/lsws/lsphp" + str(phpString) + "/bin/lsphp"): # Method 2: Check system-wide PHP installations
finalPHPVersions.append(php) try:
# Check for system PHP versions
system_php_versions = ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5']
for version in system_php_versions:
formatted_version = f'PHP {version}'
if formatted_version not in finalPHPVersions:
# Check if this version exists in system
try:
phpString = PHPManager.getPHPString(formatted_version)
php_path = f"/usr/local/lsws/lsphp{phpString}/bin/php"
lsphp_path = f"/usr/local/lsws/lsphp{phpString}/bin/lsphp"
if os.path.exists(php_path) or os.path.exists(lsphp_path):
finalPHPVersions.append(formatted_version)
except:
continue
except Exception as e:
if os.path.exists(ProcessUtilities.debugPath):
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
logging.writeToFile(f'Error checking system PHP: {str(e)}')
# Method 3: Check package manager for available PHP versions
try:
# Try to detect available PHP packages
if ProcessUtilities.decideDistro() in [ProcessUtilities.centos, ProcessUtilities.cent8]:
# For CentOS/RHEL/AlmaLinux
command = "yum list available | grep lsphp | grep -E 'lsphp[0-9]+' | head -20"
else:
# For Ubuntu/Debian
command = "apt list --installed | grep lsphp | grep -E 'lsphp[0-9]+' | head -20"
result = ProcessUtilities.outputExecutioner(command)
if result and result.strip():
for line in result.split('\n'):
if 'lsphp' in line:
# Extract version from package name
import re
match = re.search(r'lsphp(\d+)(\d+)', line)
if match:
major = match.group(1)
minor = match.group(2)
formatted_version = f'PHP {major}.{minor}'
if formatted_version not in finalPHPVersions:
# Validate installation
try:
phpString = PHPManager.getPHPString(formatted_version)
php_path = f"/usr/local/lsws/lsphp{phpString}/bin/php"
lsphp_path = f"/usr/local/lsws/lsphp{phpString}/bin/lsphp"
if os.path.exists(php_path) or os.path.exists(lsphp_path):
finalPHPVersions.append(formatted_version)
except:
continue
except Exception as e:
if os.path.exists(ProcessUtilities.debugPath):
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
logging.writeToFile(f'Error checking package manager: {str(e)}')
# Method 4: Fallback to checking common PHP versions
if not finalPHPVersions:
fallback_versions = ['PHP 7.4', 'PHP 8.0', 'PHP 8.1', 'PHP 8.2', 'PHP 8.3', 'PHP 8.4', 'PHP 8.5']
for version in fallback_versions:
try:
phpString = PHPManager.getPHPString(version)
php_path = f"/usr/local/lsws/lsphp{phpString}/bin/php"
lsphp_path = f"/usr/local/lsws/lsphp{phpString}/bin/lsphp"
if os.path.exists(php_path) or os.path.exists(lsphp_path):
finalPHPVersions.append(version)
except:
continue
# Sort versions (newest first)
def version_sort_key(version):
try:
# Extract version number for sorting
version_num = version.replace('PHP ', '').split('.')
major = int(version_num[0])
minor = int(version_num[1]) if len(version_num) > 1 else 0
return (major, minor)
except:
return (0, 0)
finalPHPVersions.sort(key=version_sort_key, reverse=True)
if os.path.exists(ProcessUtilities.debugPath): if os.path.exists(ProcessUtilities.debugPath):
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
logging.writeToFile(f'Found PHP versions in findPHPVersions: {finalPHPVersions}') logging.writeToFile(f'Final PHP versions found: {finalPHPVersions}')
return finalPHPVersions if finalPHPVersions else ['PHP 7.4', 'PHP 8.0', 'PHP 8.1', 'PHP 8.2', 'PHP 8.3', 'PHP 8.4', 'PHP 8.5']
# Now php_versions contains the formatted PHP versions
return finalPHPVersions
except BaseException as msg: except BaseException as msg:
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
logging.writeToFile(f'Error while finding php versions on system: {str(msg)}') logging.writeToFile(f'Error while finding php versions on system: {str(msg)}')
return ['PHP 7.0', 'PHP 7.1', 'PHP 7.2', 'PHP 7.3', 'PHP 7.4', 'PHP 8.0', 'PHP 8.1', 'PHP 8.2', 'PHP 8.3', 'PHP 8.4', 'PHP 8.5'] return ['PHP 7.4', 'PHP 8.0', 'PHP 8.1', 'PHP 8.2', 'PHP 8.3', 'PHP 8.4', 'PHP 8.5']
@staticmethod @staticmethod
def findApachePHPVersions(): def findApachePHPVersions():
@@ -137,6 +232,127 @@ class PHPManager:
return php return php
@staticmethod
def validatePHPInstallation(phpVersion):
"""
Validate that a PHP installation is properly configured and accessible
Returns: (is_valid, error_message, php_path)
"""
try:
php = PHPManager.getPHPString(phpVersion)
php_path = f'/usr/local/lsws/lsphp{php}/bin/php'
lsphp_path = f'/usr/local/lsws/lsphp{php}/bin/lsphp'
# Check if PHP binary exists
if os.path.exists(php_path):
return True, None, php_path
elif os.path.exists(lsphp_path):
return True, None, lsphp_path
else:
# Try alternative locations
alternative_paths = [
f'/usr/local/lsws/lsphp{php}/bin/lsphp',
'/usr/bin/php',
'/usr/local/bin/php'
]
for alt_path in alternative_paths:
if os.path.exists(alt_path):
return True, None, alt_path
return False, f'PHP {phpVersion} binary not found. Please install or check PHP installation.', None
except Exception as e:
return False, f'Error validating PHP installation: {str(e)}', None
@staticmethod
def fixPHPConfiguration(phpVersion):
"""
Attempt to fix common PHP configuration issues
"""
try:
php = PHPManager.getPHPString(phpVersion)
php_dir = f'/usr/local/lsws/lsphp{php}'
# Check if PHP directory exists
if not os.path.exists(php_dir):
return False, f'PHP directory {php_dir} does not exist'
# Check for missing php binary and create symlink if needed
php_binary = f'{php_dir}/bin/php'
lsphp_binary = f'{php_dir}/bin/lsphp'
if not os.path.exists(php_binary) and os.path.exists(lsphp_binary):
# Create symlink from lsphp to php
import subprocess
subprocess.run(['ln', '-sf', 'lsphp', 'php'], cwd=f'{php_dir}/bin')
return True, 'PHP binary symlink created successfully'
return True, 'PHP configuration appears to be correct'
except Exception as e:
return False, f'Error fixing PHP configuration: {str(e)}'
@staticmethod
def getLatestPHPVersion():
"""
Get the latest available PHP version from the system
Returns: (latest_version, all_versions)
"""
try:
all_versions = PHPManager.findPHPVersions()
if not all_versions:
return None, []
# Sort versions to get the latest
def version_sort_key(version):
try:
version_num = version.replace('PHP ', '').split('.')
major = int(version_num[0])
minor = int(version_num[1]) if len(version_num) > 1 else 0
return (major, minor)
except:
return (0, 0)
sorted_versions = sorted(all_versions, key=version_sort_key, reverse=True)
latest_version = sorted_versions[0]
return latest_version, all_versions
except Exception as e:
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
logging.writeToFile(f'Error getting latest PHP version: {str(e)}')
return None, []
@staticmethod
def getRecommendedPHPVersion():
"""
Get the recommended PHP version for new installations
Priority: 8.3 (recommended), 8.2, 8.4, 8.5, 8.1, 8.0, 7.4
"""
try:
all_versions = PHPManager.findPHPVersions()
if not all_versions:
return 'PHP 8.3' # Default recommendation
# Priority order for recommendations
recommended_order = ['PHP 8.3', 'PHP 8.2', 'PHP 8.4', 'PHP 8.5', 'PHP 8.1', 'PHP 8.0', 'PHP 7.4']
for recommended in recommended_order:
if recommended in all_versions:
return recommended
# If none of the recommended versions are available, return the latest
latest, _ = PHPManager.getLatestPHPVersion()
return latest if latest else 'PHP 8.3'
except Exception as e:
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
logging.writeToFile(f'Error getting recommended PHP version: {str(e)}')
return 'PHP 8.3'
@staticmethod @staticmethod
def FindPHPFPMPath(phpVersion): def FindPHPFPMPath(phpVersion):
if phpVersion == "PHP 5.3": if phpVersion == "PHP 5.3":

View File

@@ -856,8 +856,50 @@ local_name %s {
print("0, %s file is symlinked." % (fileName)) print("0, %s file is symlinked." % (fileName))
return 0 return 0
numberOfTotalLines = int( # Improved wc -l parsing with better error handling
ProcessUtilities.outputExecutioner('wc -l %s' % (fileName), externalApp).split(" ")[0]) wc_output = ProcessUtilities.outputExecutioner('wc -l %s' % (fileName), externalApp)
# Handle different wc output formats and potential errors
if wc_output and wc_output.strip():
# Split by whitespace and take the first part that looks like a number
wc_parts = wc_output.strip().split()
numberOfTotalLines = 0
for part in wc_parts:
try:
numberOfTotalLines = int(part)
break
except ValueError:
continue
# If no valid number found, try to extract from common wc error formats
if numberOfTotalLines == 0:
# Handle cases like "wc: filename: No such file or directory"
if "No such file or directory" in wc_output:
print("1,None")
return "1,None"
# Handle cases where wc returns just "wc:" or similar
if "wc:" in wc_output:
# Try to get line count using alternative method
try:
alt_output = ProcessUtilities.outputExecutioner('cat %s | wc -l' % (fileName), externalApp)
if alt_output and alt_output.strip():
alt_parts = alt_output.strip().split()
for part in alt_parts:
try:
numberOfTotalLines = int(part)
break
except ValueError:
continue
except:
pass
if numberOfTotalLines == 0:
print("1,None")
return "1,None"
else:
print("1,None")
return "1,None"
if numberOfTotalLines < 25: if numberOfTotalLines < 25:
data = ProcessUtilities.outputExecutioner('cat %s' % (fileName), externalApp) data = ProcessUtilities.outputExecutioner('cat %s' % (fileName), externalApp)

View File

@@ -0,0 +1,62 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WordPress Manager Error</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f8f9fa;
margin: 0;
padding: 20px;
}
.error-container {
max-width: 600px;
margin: 50px auto;
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
text-align: center;
}
.error-icon {
font-size: 48px;
color: #dc3545;
margin-bottom: 20px;
}
.error-title {
color: #dc3545;
font-size: 24px;
margin-bottom: 15px;
}
.error-message {
color: #6c757d;
font-size: 16px;
line-height: 1.5;
margin-bottom: 30px;
}
.back-button {
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
text-decoration: none;
display: inline-block;
}
.back-button:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<div class="error-container">
<div class="error-icon">⚠️</div>
<h1 class="error-title">WordPress Manager Error</h1>
<p class="error-message">{{ error_message }}</p>
<a href="javascript:history.back()" class="back-button">Go Back</a>
</div>
</body>
</html>

View File

@@ -478,6 +478,27 @@ class WebsiteManager:
php = PHPManager.getPHPString(WPobj.owner.phpSelection) php = PHPManager.getPHPString(WPobj.owner.phpSelection)
FinalPHPPath = '/usr/local/lsws/lsphp%s/bin/php' % (php) FinalPHPPath = '/usr/local/lsws/lsphp%s/bin/php' % (php)
# Validate PHP binary exists before proceeding
is_valid, error_msg, php_path = PHPManager.validatePHPInstallation(WPobj.owner.phpSelection)
if not is_valid:
# Try to fix PHP configuration
fix_success, fix_msg = PHPManager.fixPHPConfiguration(WPobj.owner.phpSelection)
if fix_success:
# Re-validate after fix attempt
is_valid, error_msg, php_path = PHPManager.validatePHPInstallation(WPobj.owner.phpSelection)
if not is_valid:
# Return error page if no PHP binary found
from django.shortcuts import render
return render(request, 'websiteFunctions/error.html', {
'error_message': f'PHP configuration issue: {error_msg}. Fix attempt: {fix_msg}'
})
else:
FinalPHPPath = php_path
else:
FinalPHPPath = php_path
url = "https://platform.cyberpersons.com/CyberpanelAdOns/Adonpermission" url = "https://platform.cyberpersons.com/CyberpanelAdOns/Adonpermission"
data = { data = {
"name": "wp-manager", "name": "wp-manager",
@@ -852,6 +873,28 @@ class WebsiteManager:
php = ACLManager.getPHPString(PHPVersion) php = ACLManager.getPHPString(PHPVersion)
FinalPHPPath = '/usr/local/lsws/lsphp%s/bin/php' % (php) FinalPHPPath = '/usr/local/lsws/lsphp%s/bin/php' % (php)
# Validate PHP binary exists before proceeding
from managePHP.phpManager import PHPManager
is_valid, error_msg, php_path = PHPManager.validatePHPInstallation(PHPVersion)
if not is_valid:
# Try to fix PHP configuration
fix_success, fix_msg = PHPManager.fixPHPConfiguration(PHPVersion)
if fix_success:
# Re-validate after fix attempt
is_valid, error_msg, php_path = PHPManager.validatePHPInstallation(PHPVersion)
if not is_valid:
final_json = json.dumps({
'status': 0,
'error_message': f'PHP configuration issue: {error_msg}. Fix attempt: {fix_msg}'
})
return HttpResponse(final_json)
else:
FinalPHPPath = php_path
else:
FinalPHPPath = php_path
command = 'sudo -u %s %s -d error_reporting=0 /usr/bin/wp core version --skip-plugins --skip-themes --path=%s 2>/dev/null' % ( command = 'sudo -u %s %s -d error_reporting=0 /usr/bin/wp core version --skip-plugins --skip-themes --path=%s 2>/dev/null' % (
Vhuser, FinalPHPPath, path) Vhuser, FinalPHPPath, path)
version = ProcessUtilities.outputExecutioner(command, None, True) version = ProcessUtilities.outputExecutioner(command, None, True)