Bearsampp 2026.3.26
API documentation
Loading...
Searching...
No Matches
ActionStartup Class Reference

Public Member Functions

 __construct ($args)
 processWindow ($window, $id, $ctrl, $param1, $param2)

Data Fields

const GAUGE_OTHERS = 19
const GAUGE_SERVICES = 5

Private Member Functions

 changePath ()
 checkApacheServiceWithTimeout ($service)
 checkBinsRegKey ()
 checkBrowser ()
 checkLaunchStartup ()
 checkMySQLServiceWithTimeout ($service, $bin)
 checkPath ()
 checkPathRegKey ()
 checkSystemPathRegKey ()
 cleanOldBehaviors ()
 cleanTmpFolders ()
 createSslCrts ()
 installServices ()
 installServicesSequential ($bearsamppBins, $bearsamppLang)
 killOldInstances ()
 prepareService ($sName, $service, $bearsamppBins, $bearsamppLang, $currentIndex=0, $totalCount=0)
 refreshAliases ()
 refreshGitRepos ()
 refreshHostname ()
 refreshVhosts ()
 rotationLogs ()
 savePath ()
 scanFolders ()
 sysInfos ()
 updateConfig ()
 writeLog ($log)

Private Attributes

 $error
 $filesToScan
 $restart
 $rootPath
 $splash
 $startTime

Detailed Description

Class ActionStartup Handles the startup process of the Bearsampp application, including initializing services, cleaning temporary files, refreshing configurations, and more.

Definition at line 16 of file class.action.startup.php.

Constructor & Destructor Documentation

◆ __construct()

__construct ( $args)

ActionStartup constructor. Initializes the startup process, including the splash screen and various configurations.

Parameters
array$argsCommand line arguments.

Definition at line 35 of file class.action.startup.php.

36 {
37 global $bearsamppRoot, $bearsamppCore, $bearsamppLang, $bearsamppBins, $bearsamppWinbinder;
38 $this->writeLog( 'Starting ' . APP_TITLE );
39
40 // Init
41 $this->splash = new Splash();
42 $this->restart = false;
43 $this->startTime = Util::getMicrotime();
44 $this->error = '';
45
46 $this->rootPath = $bearsamppRoot->getRootPath();
47 $this->filesToScan = array();
48
49 $gauge = self::GAUGE_SERVICES * count( $bearsamppBins->getServices() );
50 $gauge += self::GAUGE_OTHERS + 1;
51
52 // Start splash screen
53 $this->splash->init(
54 $bearsamppLang->getValue( Lang::STARTUP ),
55 $gauge,
56 sprintf( $bearsamppLang->getValue( Lang::STARTUP_STARTING_TEXT ), APP_TITLE . ' ' . $bearsamppCore->getAppVersion() )
57 );
58
59 $bearsamppWinbinder->setHandler( $this->splash->getWbWindow(), $this, 'processWindow', 1000 );
60 $bearsamppWinbinder->mainLoop();
61 $bearsamppWinbinder->reset();
62 }
global $bearsamppBins
global $bearsamppLang
global $bearsamppRoot
global $bearsamppCore
const STARTUP_STARTING_TEXT
const STARTUP
static getMicrotime()
const APP_TITLE
Definition root.php:13

References $bearsamppBins, $bearsamppCore, $bearsamppLang, $bearsamppRoot, APP_TITLE, Util\getMicrotime(), Lang\STARTUP, Lang\STARTUP_STARTING_TEXT, and writeLog().

Member Function Documentation

◆ changePath()

changePath ( )
private

Changes the application path and logs the number of files and occurrences changed.

Definition at line 706 of file class.action.startup.php.

707 {
708 global $bearsamppLang;
709
710 $this->splash->setTextLoading( sprintf( $bearsamppLang->getValue( Lang::STARTUP_CHANGE_PATH_TEXT ), $this->rootPath ) );
711 $this->splash->incrProgressBar();
712
713 $result = Util::changePath( $this->filesToScan, $this->rootPath );
714 $this->writeLog( 'Nb files changed: ' . $result['countChangedFiles'] );
715 $this->writeLog( 'Nb occurences changed: ' . $result['countChangedOcc'] );
716 }
$result
const STARTUP_CHANGE_PATH_TEXT
static changePath($filesToScan, $rootPath=null)

References $bearsamppLang, $result, Util\changePath(), Lang\STARTUP_CHANGE_PATH_TEXT, and writeLog().

Referenced by processWindow().

◆ checkApacheServiceWithTimeout()

checkApacheServiceWithTimeout ( $service)
private

Specialized method to check Apache service with timeout protection. Apache service checks can sometimes hang, so this method provides a safer way to check.

Parameters
object$serviceThe Apache service object
Returns
mixed Service info array or false if service not installed or check timed out

Definition at line 1205 of file class.action.startup.php.

1206 {
1207 Util::logTrace('Starting specialized Apache service check with timeout protection');
1208
1209 // Set a timeout for the Apache service check
1210 $serviceCheckStartTime = microtime(true);
1211 $serviceCheckTimeout = 10; // 10 seconds timeout
1212
1213 try {
1214 // Use a non-blocking approach to check service
1215 $serviceInfos = false;
1216
1217 // First try a quick check if the service exists in the list
1218 $serviceList = Win32Service::getServices();
1219 if (is_array($serviceList) && isset($serviceList[$service->getName()])) {
1220 Util::logTrace('Apache service found in service list, getting details');
1221
1222 // Service exists, now try to get its details with timeout protection
1223 $startTime = microtime(true);
1224 $serviceInfos = $service->infos();
1225
1226 // Check if we've exceeded our timeout
1227 if (microtime(true) - $serviceCheckStartTime > $serviceCheckTimeout) {
1228 Util::logTrace("Apache service check timeout exceeded, assuming service needs reinstall");
1229 return false;
1230 }
1231 } else {
1232 Util::logTrace('Apache service not found in service list');
1233 return false;
1234 }
1235
1236 return $serviceInfos;
1237 } catch (\Exception $e) {
1238 Util::logTrace("Exception during Apache service check: " . $e->getMessage());
1239 return false;
1240 } catch (\Throwable $e) {
1241 Util::logTrace("Throwable during Apache service check: " . $e->getMessage());
1242 return false;
1243 }
1244 }
static logTrace($data, $file=null)

References $startTime, and Util\logTrace().

Referenced by prepareService().

◆ checkBinsRegKey()

checkBinsRegKey ( )
private

Checks and updates the application bins registry key. If the current registry key does not match the generated key, it updates the registry key. Logs the current and generated registry keys. Sets an error message if the registry key update fails. Sets a restart flag if the registry key is updated.

Definition at line 765 of file class.action.startup.php.

766 {
767 global $bearsamppLang, $bearsamppRegistry;
768
769 $this->splash->setTextLoading( sprintf( $bearsamppLang->getValue( Lang::STARTUP_REGISTRY_TEXT ), Registry::APP_BINS_REG_ENTRY ) );
770 $this->splash->incrProgressBar();
771
772 $currentAppBinsRegKey = Util::getAppBinsRegKey();
773 $genAppBinsRegKey = Util::getAppBinsRegKey( false );
774 $this->writeLog( 'Current app bins reg key: ' . $currentAppBinsRegKey );
775 $this->writeLog( 'Gen app bins reg key: ' . $genAppBinsRegKey );
776 if ( $currentAppBinsRegKey != $genAppBinsRegKey ) {
777 if ( !Util::setAppBinsRegKey( $genAppBinsRegKey ) ) {
778 if ( !empty( $this->error ) ) {
779 $this->error .= PHP_EOL . PHP_EOL;
780 }
782 $this->error .= PHP_EOL . $bearsamppRegistry->getLatestError();
783 }
784 else {
785 $this->writeLog( 'Need restart: checkBinsRegKey' );
786 $this->restart = true;
787 }
788 }
789 }
const STARTUP_REGISTRY_ERROR_TEXT
const STARTUP_REGISTRY_TEXT
const APP_BINS_REG_ENTRY
static getAppBinsRegKey($fromRegistry=true)
static setAppBinsRegKey($value)

References $bearsamppLang, Registry\APP_BINS_REG_ENTRY, Util\getAppBinsRegKey(), Util\setAppBinsRegKey(), Lang\STARTUP_REGISTRY_ERROR_TEXT, Lang\STARTUP_REGISTRY_TEXT, and writeLog().

Referenced by processWindow().

◆ checkBrowser()

checkBrowser ( )
private

Checks and sets the default browser configuration.

Definition at line 595 of file class.action.startup.php.

596 {
598
599 $this->splash->setTextLoading( $bearsamppLang->getValue( Lang::STARTUP_CHECK_BROWSER_TEXT ) );
600 $this->splash->incrProgressBar();
601 $this->writeLog( 'Check browser' );
602
603 $currentBrowser = $bearsamppConfig->getBrowser();
604 if ( empty( $currentBrowser ) || !file_exists( $currentBrowser ) ) {
606 }
607 }
const CFG_BROWSER
const STARTUP_CHECK_BROWSER_TEXT
static getDefaultBrowser()
Definition class.vbs.php:81
global $bearsamppConfig
Definition homepage.php:41

References $bearsamppConfig, $bearsamppLang, Config\CFG_BROWSER, Vbs\getDefaultBrowser(), Lang\STARTUP_CHECK_BROWSER_TEXT, and writeLog().

Referenced by processWindow().

◆ checkLaunchStartup()

checkLaunchStartup ( )
private

Checks and sets the launch startup configuration.

Definition at line 578 of file class.action.startup.php.

579 {
580 global $bearsamppConfig;
581
582 $this->writeLog( 'Check launch startup' );
583
584 if ( $bearsamppConfig->isLaunchStartup() ) {
586 }
587 else {
589 }
590 }
static disableLaunchStartup()
static enableLaunchStartup()

References $bearsamppConfig, Util\disableLaunchStartup(), Util\enableLaunchStartup(), and writeLog().

Referenced by processWindow().

◆ checkMySQLServiceWithTimeout()

checkMySQLServiceWithTimeout ( $service,
$bin )
private

Specialized method to check MySQL service with timeout protection. MySQL service checks can sometimes hang, so this method provides a safer way to check.

Parameters
object$serviceThe MySQL service object
object$binThe MySQL bin object
Returns
mixed Service info array or false if service not installed or check timed out

Definition at line 1254 of file class.action.startup.php.

1255 {
1256 Util::logTrace('Starting specialized MySQL service check with timeout protection');
1257
1258 // Set a timeout for the MySQL service check
1259 $serviceCheckStartTime = microtime(true);
1260 $serviceCheckTimeout = 8; // 8 seconds timeout
1261
1262 try {
1263 // Use a non-blocking approach to check service
1264 $serviceInfos = false;
1265
1266 // First check if the service exists in the list
1267 $serviceList = Win32Service::getServices();
1268 if (is_array($serviceList) && isset($serviceList[$service->getName()])) {
1269 Util::logTrace('MySQL service found in service list, getting details');
1270
1271 // Service exists, now try to get its details with timeout protection
1272 $serviceInfos = $service->infos();
1273
1274 // Check if we've exceeded our timeout
1275 if (microtime(true) - $serviceCheckStartTime > $serviceCheckTimeout) {
1276 Util::logTrace("MySQL service check timeout exceeded, assuming service needs reinstall");
1277 return false;
1278 }
1279 } else {
1280 Util::logTrace('MySQL service not found in service list');
1281 return false;
1282 }
1283
1284 return $serviceInfos;
1285 } catch (\Exception $e) {
1286 Util::logTrace("Exception during MySQL service check: " . $e->getMessage());
1287 return false;
1288 } catch (\Throwable $e) {
1289 Util::logTrace("Throwable during MySQL service check: " . $e->getMessage());
1290 return false;
1291 }
1292 }

References Util\logTrace().

Referenced by prepareService().

◆ checkPath()

checkPath ( )
private

Checks the application path and logs the last path content.

Definition at line 654 of file class.action.startup.php.

655 {
657
658 $this->splash->setTextLoading( $bearsamppLang->getValue( Lang::STARTUP_CHECK_PATH_TEXT ) );
659 $this->splash->incrProgressBar();
660
661 $this->writeLog( 'Last path: ' . $bearsamppCore->getLastPathContent() );
662 }
const STARTUP_CHECK_PATH_TEXT

References $bearsamppCore, $bearsamppLang, Lang\STARTUP_CHECK_PATH_TEXT, and writeLog().

Referenced by processWindow().

◆ checkPathRegKey()

checkPathRegKey ( )
private

Checks and updates the application path registry key.

Definition at line 732 of file class.action.startup.php.

733 {
734 global $bearsamppRoot, $bearsamppLang, $bearsamppRegistry;
735
736 $this->splash->setTextLoading( sprintf( $bearsamppLang->getValue( Lang::STARTUP_REGISTRY_TEXT ), Registry::APP_PATH_REG_ENTRY ) );
737 $this->splash->incrProgressBar();
738
739 $currentAppPathRegKey = Util::getAppPathRegKey();
740 $genAppPathRegKey = Util::formatWindowsPath( $bearsamppRoot->getRootPath() );
741 $this->writeLog( 'Current app path reg key: ' . $currentAppPathRegKey );
742 $this->writeLog( 'Gen app path reg key: ' . $genAppPathRegKey );
743 if ( $currentAppPathRegKey != $genAppPathRegKey ) {
744 if ( !Util::setAppPathRegKey( $genAppPathRegKey ) ) {
745 if ( !empty( $this->error ) ) {
746 $this->error .= PHP_EOL . PHP_EOL;
747 }
749 $this->error .= PHP_EOL . $bearsamppRegistry->getLatestError();
750 }
751 else {
752 $this->writeLog( 'Need restart: checkPathRegKey' );
753 $this->restart = true;
754 }
755 }
756 }
const APP_PATH_REG_ENTRY
static setAppPathRegKey($value)
static getAppPathRegKey()
static formatWindowsPath($path)

References $bearsamppLang, $bearsamppRoot, Registry\APP_PATH_REG_ENTRY, Util\formatWindowsPath(), Util\getAppPathRegKey(), Util\setAppPathRegKey(), Lang\STARTUP_REGISTRY_ERROR_TEXT, Lang\STARTUP_REGISTRY_TEXT, and writeLog().

Referenced by processWindow().

◆ checkSystemPathRegKey()

checkSystemPathRegKey ( )
private

Checks and updates the system PATH registry key. Ensures the application bins registry entry is at the beginning of the system PATH. Logs the current and new system PATH. Sets an error message if the system PATH update fails. Sets a restart flag if the system PATH is updated.

Definition at line 798 of file class.action.startup.php.

799 {
800 global $bearsamppLang, $bearsamppRegistry;
801
802 $this->splash->setTextLoading( sprintf( $bearsamppLang->getValue( Lang::STARTUP_REGISTRY_TEXT ), Registry::SYSPATH_REG_ENTRY ) );
803 $this->splash->incrProgressBar();
804
805 $currentSysPathRegKey = Util::getSysPathRegKey();
806 $this->writeLog( 'Current system PATH: ' . $currentSysPathRegKey );
807
808 $newSysPathRegKey = str_replace( '%' . Registry::APP_BINS_REG_ENTRY . '%;', '', $currentSysPathRegKey );
809 $newSysPathRegKey = str_replace( '%' . Registry::APP_BINS_REG_ENTRY . '%', '', $newSysPathRegKey );
810 $newSysPathRegKey = '%' . Registry::APP_BINS_REG_ENTRY . '%;' . $newSysPathRegKey;
811 $this->writeLog( 'New system PATH: ' . $newSysPathRegKey );
812
813 if ( $currentSysPathRegKey != $newSysPathRegKey ) {
814 if ( !Util::setSysPathRegKey( $newSysPathRegKey ) ) {
815 if ( !empty( $this->error ) ) {
816 $this->error .= PHP_EOL . PHP_EOL;
817 }
819 $this->error .= PHP_EOL . $bearsamppRegistry->getLatestError();
820 }
821 else {
822 $this->writeLog( 'Need restart: checkSystemPathRegKey' );
823 $this->restart = true;
824 }
825 }
826 else {
827 $this->writeLog( 'Refresh system PATH: ' . $currentSysPathRegKey );
828 Util::setSysPathRegKey( str_replace( '%' . Registry::APP_BINS_REG_ENTRY . '%', '', $currentSysPathRegKey ) );
829 Util::setSysPathRegKey( $currentSysPathRegKey );
830 }
831 }
const SYSPATH_REG_ENTRY
static setSysPathRegKey($value)
static getSysPathRegKey()

References $bearsamppLang, Registry\APP_BINS_REG_ENTRY, Util\getSysPathRegKey(), Util\setSysPathRegKey(), Lang\STARTUP_REGISTRY_ERROR_TEXT, Lang\STARTUP_REGISTRY_TEXT, Registry\SYSPATH_REG_ENTRY, and writeLog().

Referenced by processWindow().

◆ cleanOldBehaviors()

cleanOldBehaviors ( )
private

Cleans old behaviors by removing outdated registry entries.

Definition at line 509 of file class.action.startup.php.

510 {
511 global $bearsamppLang, $bearsamppRegistry;
512
513 $this->writeLog( 'Clean old behaviors' );
514
515 $this->splash->setTextLoading( $bearsamppLang->getValue( Lang::STARTUP_CLEAN_OLD_BEHAVIORS_TEXT ) );
516 $this->splash->incrProgressBar();
517
518 // App >= 1.0.13
519 $bearsamppRegistry->deleteValue(
521 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run',
523 );
524 }
const STARTUP_CLEAN_OLD_BEHAVIORS_TEXT
const HKEY_LOCAL_MACHINE

References $bearsamppLang, APP_TITLE, Registry\HKEY_LOCAL_MACHINE, Lang\STARTUP_CLEAN_OLD_BEHAVIORS_TEXT, and writeLog().

Referenced by processWindow().

◆ cleanTmpFolders()

cleanTmpFolders ( )
private

Cleans temporary folders by removing unnecessary files.

Definition at line 479 of file class.action.startup.php.

480 {
482
483 $this->splash->setTextLoading( $bearsamppLang->getValue( Lang::STARTUP_CLEAN_TMP_TEXT ) );
484 $this->splash->incrProgressBar();
485
486 $this->writeLog( 'Clear tmp folders' );
487 Util::clearFolder( $bearsamppRoot->getTmpPath(), array('cachegrind', 'composer', 'openssl', 'mailpit', 'xlight', 'npm-cache', 'pip', 'opcache', '.gitignore') );
488 Util::clearFolder( $bearsamppCore->getTmpPath(), array('.gitignore') );
489
490 // Ensure opcache directory exists for persistent file cache
491 $opcachePath = $bearsamppRoot->getTmpPath() . DIRECTORY_SEPARATOR . 'opcache';
492
493 if (!is_dir($opcachePath)) {
494 $this->writeLog('Creating opcache directory: ' . $opcachePath);
495 if (!@mkdir($opcachePath, 0755, true) && !is_dir($opcachePath)) {
496 $this->writeLog('Failed to create opcache directory: ' . $opcachePath);
497 return;
498 }
499 }
500
501 if (!is_writable($opcachePath)) {
502 $this->writeLog('Opcache directory is not writable: ' . $opcachePath);
503 }
504 }
const STARTUP_CLEAN_TMP_TEXT
static clearFolder($path, $exclude=array())

References $bearsamppCore, $bearsamppLang, $bearsamppRoot, Util\clearFolder(), Lang\STARTUP_CLEAN_TMP_TEXT, and writeLog().

Referenced by processWindow().

◆ createSslCrts()

createSslCrts ( )
private

Creates SSL certificates if they do not already exist. Logs the creation process.

Definition at line 854 of file class.action.startup.php.

855 {
856 global $bearsamppLang, $bearsamppOpenSsl;
857
858 $this->splash->incrProgressBar();
859 if ( !$bearsamppOpenSsl->existsCrt( 'localhost' ) ) {
860 $this->splash->setTextLoading( sprintf( $bearsamppLang->getValue( Lang::STARTUP_GEN_SSL_CRT_TEXT ), 'localhost' ) );
861 $bearsamppOpenSsl->createCrt( 'localhost' );
862 }
863 }
const STARTUP_GEN_SSL_CRT_TEXT

References $bearsamppLang, and Lang\STARTUP_GEN_SSL_CRT_TEXT.

Referenced by processWindow().

◆ installServices()

installServices ( )
private

Installs and starts services for the application. Checks if services are already installed and updates them if necessary. Logs the installation process and any errors encountered.

Uses optimized service checking and starting methods.

Definition at line 873 of file class.action.startup.php.

874 {
876
877 Util::logTrace('Starting installServices method');
878
879 if (!$this->restart) {
880 Util::logTrace('Normal startup mode - processing services');
881
882 // Service Installation
884 } else {
885 Util::logTrace('Restart mode - skipping service installation');
886 $this->splash->incrProgressBar(self::GAUGE_SERVICES * count($bearsamppBins->getServices()));
887 }
888
889 Util::logTrace('Completed installServices method');
890 }
installServicesSequential($bearsamppBins, $bearsamppLang)

References $bearsamppBins, $bearsamppLang, $bearsamppRoot, installServicesSequential(), and Util\logTrace().

Referenced by processWindow().

◆ installServicesSequential()

installServicesSequential ( $bearsamppBins,
$bearsamppLang )
private

Service Installation Installs and starts services sequentially with proper progress tracking. Ensures exactly GAUGE_SERVICES (5) progress steps per service.

Parameters
object$bearsamppBinsThe bins object
object$bearsamppLangThe language object

Definition at line 900 of file class.action.startup.php.

901 {
902 Util::logTrace('Starting sequential service installation');
903 $installStartTime = Util::getMicrotime();
904
905 // Step 1: Check and prepare all services
906 $servicesToStart = [];
907 $serviceErrors = [];
908
909 $totalServiceCount = count($bearsamppBins->getServices());
910 $currentServiceIndex = 0;
911
912 foreach ($bearsamppBins->getServices() as $sName => $service) {
913 $currentServiceIndex++;
914
915 Util::logTrace('Preparing service: ' . $sName);
916
917 // prepareService() increments 1 step
918 $serviceInfo = $this->prepareService($sName, $service, $bearsamppBins, $bearsamppLang, $currentServiceIndex, $totalServiceCount);
919
920 if ($serviceInfo['restart']) {
921 $this->writeLog('Need restart: installService ' . $serviceInfo['bin']->getName());
922 Util::logTrace('Restart required for service: ' . $serviceInfo['bin']->getName());
923 $this->restart = true;
924 // prepareService used 1 step, need 4 more to reach GAUGE_SERVICES (5 total)
925 $this->splash->incrProgressBar(self::GAUGE_SERVICES - 1);
926 continue;
927 }
928
929 if (!empty($serviceInfo['error'])) {
930 $serviceErrors[$sName] = $serviceInfo;
931 // prepareService used 1 step, need 4 more to reach GAUGE_SERVICES (5 total)
932 $this->splash->incrProgressBar(self::GAUGE_SERVICES - 1);
933 continue;
934 }
935
936 if ($serviceInfo['needsStart']) {
937 $servicesToStart[$sName] = $serviceInfo;
938 } else {
939 // Service already running or doesn't need to start
940 // prepareService used 1 step, need 4 more to reach GAUGE_SERVICES (5 total)
941 $this->splash->incrProgressBar(self::GAUGE_SERVICES - 1);
942 }
943 }
944
945 // Step 2: Start all services sequentially with progress updates
946 if (!empty($servicesToStart)) {
947 Util::logTrace('Starting ' . count($servicesToStart) . ' services sequentially');
948
949 $serviceCount = 0;
950 $totalServices = count($servicesToStart);
951
952 foreach ($servicesToStart as $sName => $serviceInfo) {
953 $serviceCount++;
954 $name = $serviceInfo['name'];
955 $service = $serviceInfo['service'];
956
957 // Update splash before starting (1 step - 2nd of 5)
958 $this->splash->setTextLoading('Starting ' . $name . ' (' . $serviceCount . '/' . $totalServices . ')');
959 $this->splash->incrProgressBar();
960
961 Util::logTrace('Starting service: ' . $sName);
962 $serviceStartTime = Util::getMicrotime();
963
964 // Start the service
965 $success = $service->start();
966
967 $duration = round(Util::getMicrotime() - $serviceStartTime, 3);
968
969 if ($success) {
970 $this->writeLog($name . ' service started in ' . $duration . 's');
971 Util::logTrace('Service ' . $name . ' started successfully in ' . $duration . ' seconds');
972
973 // Update splash after successful start
974 $this->splash->setTextLoading($name . ' started successfully');
975 } else {
976 $error = $service->getError();
977 if (empty($error)) {
978 $error = 'Failed to start service';
979 }
980
981 $serviceErrors[$sName] = $serviceInfo;
982 $serviceErrors[$sName]['error'] = $error;
983 Util::logTrace('Service ' . $name . ' failed to start: ' . $error);
984
985 // Run syntax check if available
986 if (!empty($serviceInfo['syntaxCheckCmd'])) {
987 try {
988 $cmdSyntaxCheck = $serviceInfo['bin']->getCmdLineOutput($serviceInfo['syntaxCheckCmd']);
989 if (!$cmdSyntaxCheck['syntaxOk']) {
990 $serviceErrors[$sName]['error'] .= PHP_EOL . 'Syntax error: ' . $cmdSyntaxCheck['content'];
991 }
992 } catch (\Exception $e) {
993 // Ignore syntax check errors
994 }
995 }
996 }
997
998 // Complete remaining steps: prepareService=1, pre-start=1, now add 3 more = 5 total
999 $this->splash->incrProgressBar(self::GAUGE_SERVICES - 2);
1000 }
1001 }
1002
1003 // Step 3: Report any errors
1004 foreach ($serviceErrors as $sName => $serviceInfo) {
1005 if (!empty($serviceInfo['error'])) {
1006 Util::logTrace('Service error occurred for ' . $sName . ': ' . $serviceInfo['error']);
1007 if (!empty($this->error)) {
1008 $this->error .= PHP_EOL . PHP_EOL;
1009 }
1010 $this->error .= sprintf($bearsamppLang->getValue(Lang::STARTUP_SERVICE_ERROR), $serviceInfo['name']) . PHP_EOL . $serviceInfo['error'];
1011 }
1012 }
1013
1014 $installDuration = round(Util::getMicrotime() - $installStartTime, 3);
1015 $this->writeLog('Service installation completed in ' . $installDuration . 's');
1016 Util::logTrace('Service installation completed in ' . $installDuration . ' seconds');
1017 }
prepareService($sName, $service, $bearsamppBins, $bearsamppLang, $currentIndex=0, $totalCount=0)
const STARTUP_SERVICE_ERROR

References $bearsamppBins, $bearsamppLang, $error, Util\getMicrotime(), Util\logTrace(), prepareService(), Lang\STARTUP_SERVICE_ERROR, and writeLog().

Referenced by installServices().

◆ killOldInstances()

killOldInstances ( )
private

Kills old instances of Bearsampp processes.

Definition at line 529 of file class.action.startup.php.

530 {
531 global $bearsamppLang;
532
533 $this->splash->setTextLoading( $bearsamppLang->getValue( Lang::STARTUP_KILL_OLD_PROCS_TEXT ) );
534 $this->splash->incrProgressBar();
535
536 // Stop services
537 /*foreach ($bearsamppBins->getServices() as $sName => $service) {
538 $serviceInfos = $service->infos();
539 if ($serviceInfos === false) {
540 continue;
541 }
542 $service->stop();
543 }*/
544
545 // Stop third party procs
546 $procsKilled = Win32Ps::killBins();
547 if ( !empty( $procsKilled ) ) {
548 $this->writeLog( 'Procs killed:' );
549 $procsKilledSort = array();
550 foreach ( $procsKilled as $proc ) {
552 $procsKilledSort[] = '-> ' . basename( $unixExePath ) . ' (PID ' . $proc[Win32Ps::PROCESS_ID] . ') in ' . $unixExePath;
553 }
554 sort( $procsKilledSort );
555 foreach ( $procsKilledSort as $proc ) {
556 $this->writeLog( $proc );
557 }
558 }
559 }
$proc
Definition ajax.php:61
const STARTUP_KILL_OLD_PROCS_TEXT
static formatUnixPath($path)
static killBins($refreshProcs=false)
const EXECUTABLE_PATH
const PROCESS_ID

References $bearsamppLang, $proc, Win32Ps\EXECUTABLE_PATH, Util\formatUnixPath(), Win32Ps\killBins(), Win32Ps\PROCESS_ID, Lang\STARTUP_KILL_OLD_PROCS_TEXT, and writeLog().

Referenced by processWindow().

◆ prepareService()

prepareService ( $sName,
$service,
$bearsamppBins,
$bearsamppLang,
$currentIndex = 0,
$totalCount = 0 )
private

Prepares a service for startup (check, install if needed, but don't start yet)

Parameters
string$sNameService name
object$serviceService object
object$bearsamppBinsBins object
object$bearsamppLangLanguage object
int$currentIndexCurrent service index
int$totalCountTotal service count
Returns
array Service information array

Definition at line 1030 of file class.action.startup.php.

1031 {
1032 $serviceInfo = [
1033 'sName' => $sName,
1034 'service' => $service,
1035 'bin' => null,
1036 'name' => '',
1037 'port' => 0,
1038 'syntaxCheckCmd' => null,
1039 'error' => '',
1040 'restart' => false,
1041 'needsStart' => false,
1042 'startTime' => Util::getMicrotime()
1043 ];
1044
1045 // Identify service type and get bin
1046 $syntaxCheckCmd = null;
1047 $bin = null;
1048 $port = 0;
1049
1050 if ($sName == BinMailpit::SERVICE_NAME) {
1051 $bin = $bearsamppBins->getMailpit();
1052 $port = $bearsamppBins->getMailpit()->getSmtpPort();
1053 } elseif ($sName == BinMemcached::SERVICE_NAME) {
1054 $bin = $bearsamppBins->getMemcached();
1055 $port = $bearsamppBins->getMemcached()->getPort();
1056 } elseif ($sName == BinApache::SERVICE_NAME) {
1057 $bin = $bearsamppBins->getApache();
1058 $port = $bearsamppBins->getApache()->getPort();
1059 $syntaxCheckCmd = BinApache::CMD_SYNTAX_CHECK;
1060 } elseif ($sName == BinMysql::SERVICE_NAME) {
1061 $bin = $bearsamppBins->getMysql();
1062 $port = $bearsamppBins->getMysql()->getPort();
1063 $syntaxCheckCmd = BinMysql::CMD_SYNTAX_CHECK;
1064
1065 // Pre-initialize MySQL data if needed
1066 if (!file_exists($bin->getDataDir()) || count(glob($bin->getDataDir() . '/*')) === 0) {
1067 Util::logTrace('Pre-initializing MySQL data directory');
1068 $bin->initData();
1069 }
1070 } elseif ($sName == BinMariadb::SERVICE_NAME) {
1071 $bin = $bearsamppBins->getMariadb();
1072 $port = $bearsamppBins->getMariadb()->getPort();
1073 $syntaxCheckCmd = BinMariadb::CMD_SYNTAX_CHECK;
1074 } elseif ($sName == BinPostgresql::SERVICE_NAME) {
1075 $bin = $bearsamppBins->getPostgresql();
1076 $port = $bearsamppBins->getPostgresql()->getPort();
1077 } elseif ($sName == BinXlight::SERVICE_NAME) {
1078 $bin = $bearsamppBins->getXlight();
1079 $port = $bearsamppBins->getXlight()->getPort();
1080 }
1081
1082 $name = $bin->getName() . ' ' . $bin->getVersion() . ' (' . $service->getName() . ')';
1083
1084 $serviceInfo['bin'] = $bin;
1085 $serviceInfo['name'] = $name;
1086 $serviceInfo['port'] = $port;
1087 $serviceInfo['syntaxCheckCmd'] = $syntaxCheckCmd;
1088
1089 // Update splash with current service being checked (1 step)
1090 if ($currentIndex > 0 && $totalCount > 0) {
1091 $this->splash->setTextLoading('Checking ' . $bin->getName() . ' service (' . $currentIndex . '/' . $totalCount . ')');
1092 }
1093 $this->splash->incrProgressBar();
1094
1095 // Check if service is already installed
1096 $serviceAlreadyInstalled = false;
1097 $serviceToRemove = false;
1098
1099 if ($sName == BinApache::SERVICE_NAME) {
1100 $serviceInfos = $this->checkApacheServiceWithTimeout($service);
1101 } else if ($sName == BinMysql::SERVICE_NAME) {
1102 $serviceInfos = $this->checkMySQLServiceWithTimeout($service, $bin);
1103 if ($serviceInfos === false && $service->isInstalled()) {
1104 Util::logTrace('MySQL service appears to be hanging, forcing restart');
1105 Win32Ps::killBins(['mysqld.exe']);
1106 $service->delete();
1107 $serviceToRemove = true;
1108 }
1109 } else {
1110 try {
1111 $serviceInfos = $service->infos();
1112 } catch (\Exception $e) {
1113 Util::logTrace("Exception during service check: " . $e->getMessage());
1114 $serviceInfos = false;
1115 } catch (\Throwable $e) {
1116 Util::logTrace("Throwable during service check: " . $e->getMessage());
1117 $serviceInfos = false;
1118 }
1119 }
1120
1121 if ($serviceInfos !== false) {
1122 $serviceAlreadyInstalled = true;
1123 $this->writeLog($name . ' service already installed');
1124
1125 // Check if service needs to be removed and reinstalled
1126 if ($sName == BinPostgresql::SERVICE_NAME) {
1127 $serviceGenPathName = trim(str_replace('"', '', $service->getBinPath()));
1128 $installedPathParts = explode(' ', $serviceInfos[Win32Service::VBS_PATH_NAME], 2);
1129 $serviceVbsPathName = trim(str_replace('"', '', $installedPathParts[0]));
1130 } else {
1131 $serviceGenPathName = trim(str_replace('"', '', $service->getBinPath() . ($service->getParams() ? ' ' . $service->getParams() : '')));
1132 $serviceVbsPathName = trim(str_replace('"', '', $serviceInfos[Win32Service::VBS_PATH_NAME]));
1133 }
1134
1135 $normalizedGenPath = preg_replace('/\s+/', ' ', $serviceGenPathName);
1136 $normalizedVbsPath = preg_replace('/\s+/', ' ', $serviceVbsPathName);
1137
1138 if ($normalizedGenPath !== $normalizedVbsPath && $serviceGenPathName != $serviceVbsPathName) {
1139 $serviceToRemove = true;
1140 $this->writeLog($name . ' service has to be removed');
1141 }
1142 }
1143
1144 // Remove service if needed (no progress increment - part of check phase)
1145 if ($serviceToRemove) {
1146 if (!$service->delete()) {
1147 $serviceInfo['restart'] = true;
1148 return $serviceInfo;
1149 }
1150 }
1151
1152 // Check port availability (no progress increment - part of check phase)
1153 $isPortInUse = Util::isPortInUse($port);
1154 if ($isPortInUse !== false) {
1155 // Port is in use - check if it's our service that's already running
1156 if ($service->isRunning()) {
1157 // Service is already running and owns the port - this is OK
1158 $this->writeLog($name . ' service already running on port ' . $port);
1159 Util::logTrace('Service ' . $name . ' already running - no need to start');
1160 $serviceInfo['needsStart'] = false;
1161 return $serviceInfo;
1162 }
1163
1164 // Port is in use by something else - this is an error
1165 $serviceInfo['error'] = sprintf($bearsamppLang->getValue(Lang::STARTUP_SERVICE_PORT_ERROR), $port, $isPortInUse);
1166 return $serviceInfo;
1167 }
1168
1169 // Install service if needed (no progress increment - part of check phase)
1170 if (!$serviceAlreadyInstalled || $serviceToRemove) {
1171 if (!$service->create()) {
1172 $serviceInfo['error'] = sprintf($bearsamppLang->getValue(Lang::STARTUP_SERVICE_CREATE_ERROR), $service->getError());
1173 return $serviceInfo;
1174 }
1175 }
1176
1177 $serviceInfo['needsStart'] = true;
1178 return $serviceInfo;
1179 }
$port
checkMySQLServiceWithTimeout($service, $bin)
checkApacheServiceWithTimeout($service)
const CMD_SYNTAX_CHECK
const SERVICE_NAME
const CMD_SYNTAX_CHECK
const STARTUP_SERVICE_CREATE_ERROR
const STARTUP_SERVICE_PORT_ERROR
static isPortInUse($port)

References $bearsamppBins, $bearsamppLang, $port, checkApacheServiceWithTimeout(), checkMySQLServiceWithTimeout(), BinApache\CMD_SYNTAX_CHECK, BinMariadb\CMD_SYNTAX_CHECK, BinMysql\CMD_SYNTAX_CHECK, Util\getMicrotime(), Util\isPortInUse(), Win32Ps\killBins(), Util\logTrace(), BinApache\SERVICE_NAME, BinMailpit\SERVICE_NAME, BinMariadb\SERVICE_NAME, BinMemcached\SERVICE_NAME, BinMysql\SERVICE_NAME, BinPostgresql\SERVICE_NAME, BinXlight\SERVICE_NAME, Lang\STARTUP_SERVICE_CREATE_ERROR, Lang\STARTUP_SERVICE_PORT_ERROR, Win32Service\VBS_PATH_NAME, and writeLog().

Referenced by installServicesSequential().

◆ processWindow()

processWindow ( $window,
$id,
$ctrl,
$param1,
$param2 )

Processes the main window events during startup.

Parameters
mixed$windowThe window handle.
int$idThe event ID.
mixed$ctrlThe control that triggered the event.
mixed$param1Additional parameter 1.
mixed$param2Additional parameter 2.

Definition at line 73 of file class.action.startup.php.

74 {
75 global $bearsamppRoot, $bearsamppCore, $bearsamppLang, $bearsamppBins, $bearsamppTools, $bearsamppApps, $bearsamppWinbinder;
76
77 Util::logTrace('Starting processWindow method');
78
79 // Rotation logs
80 Util::logTrace('Performing log rotation');
81 $this->rotationLogs();
82
83 // Clean
84 Util::logTrace('Starting cleanup operations');
85 $this->cleanTmpFolders();
86 $this->cleanOldBehaviors();
87
88 // List procs
89 Util::logTrace('Listing running processes');
90 if ($bearsamppRoot->getProcs() !== false) {
91 $this->writeLog('List procs:');
92 $listProcs = array();
93 foreach ($bearsamppRoot->getProcs() as $proc) {
95 $listProcs[] = '-> ' . basename($unixExePath) . ' (PID ' . $proc[Win32Ps::PROCESS_ID] . ') in ' . $unixExePath;
96 }
97 sort($listProcs);
98 foreach ($listProcs as $proc) {
99 $this->writeLog($proc);
100 }
101 Util::logTrace('Found ' . count($listProcs) . ' running processes');
102 } else {
103 Util::logTrace('No processes found or unable to retrieve process list');
104 }
105
106 // List modules
107 Util::logTrace('Listing bins modules');
108 $this->writeLog('List bins modules:');
109 foreach ($bearsamppBins->getAll() as $module) {
110 if (!$module->isEnable()) {
111 $this->writeLog('-> ' . $module->getName() . ': ' . $bearsamppLang->getValue(Lang::DISABLED));
112 Util::logTrace('Bin module ' . $module->getName() . ' is disabled');
113 } else {
114 $this->writeLog('-> ' . $module->getName() . ': ' . $module->getVersion() . ' (' . $module->getRelease() . ')');
115 Util::logTrace('Bin module ' . $module->getName() . ': ' . $module->getVersion() . ' (' . $module->getRelease() . ')');
116 }
117 }
118
119 Util::logTrace('Listing tools modules');
120 $this->writeLog('List tools modules:');
121 foreach ($bearsamppTools->getAll() as $module) {
122 if (!$module->isEnable()) {
123 $this->writeLog('-> ' . $module->getName() . ': ' . $bearsamppLang->getValue(Lang::DISABLED));
124 Util::logTrace('Tool module ' . $module->getName() . ' is disabled');
125 } else {
126 $this->writeLog('-> ' . $module->getName() . ': ' . $module->getVersion() . ' (' . $module->getRelease() . ')');
127 Util::logTrace('Tool module ' . $module->getName() . ': ' . $module->getVersion() . ' (' . $module->getRelease() . ')');
128 }
129 }
130
131 Util::logTrace('Listing apps modules');
132 $this->writeLog('List apps modules:');
133 foreach ($bearsamppApps->getAll() as $module) {
134 if (!$module->isEnable()) {
135 $this->writeLog('-> ' . $module->getName() . ': ' . $bearsamppLang->getValue(Lang::DISABLED));
136 Util::logTrace('App module ' . $module->getName() . ' is disabled');
137 } else {
138 $this->writeLog('-> ' . $module->getName() . ': ' . $module->getVersion() . ' (' . $module->getRelease() . ')');
139 Util::logTrace('App module ' . $module->getName() . ': ' . $module->getVersion() . ' (' . $module->getRelease() . ')');
140 }
141 }
142
143 // Kill old instances
144 Util::logTrace('Killing old instances');
145 $this->killOldInstances();
146
147 // Prepare app
148 Util::logTrace('Preparing application - refreshing hostname');
149 $this->refreshHostname();
150
151 Util::logTrace('Checking launch startup settings');
152 $this->checkLaunchStartup();
153
154 Util::logTrace('Checking browser configuration');
155 $this->checkBrowser();
156
157 Util::logTrace('Gathering system information');
158 $this->sysInfos();
159
160 Util::logTrace('Refreshing aliases');
161 $this->refreshAliases();
162
163 Util::logTrace('Refreshing virtual hosts');
164 $this->refreshVhosts();
165
166 // Check app path
167 Util::logTrace('Checking application path');
168 $this->checkPath();
169
170 Util::logTrace('Scanning folders');
171 $this->scanFolders();
172
173 Util::logTrace('Changing paths in files');
174 $this->changePath();
175
176 Util::logTrace('Saving current path');
177 $this->savePath();
178
179 // Check BEARSAMPP_PATH, BEARSAMPP_BINS and System Path reg keys
180 Util::logTrace('Checking PATH registry key');
181 $this->checkPathRegKey();
182
183 Util::logTrace('Checking BINS registry key');
184 $this->checkBinsRegKey();
185
186 Util::logTrace('Checking System PATH registry key');
187 $this->checkSystemPathRegKey();
188
189 // Update config
190 Util::logTrace('Updating configuration');
191 $this->updateConfig();
192
193 // Create SSL certificates
194 Util::logTrace('Creating SSL certificates');
195 $this->createSslCrts();
196
197 // Install
198 Util::logTrace('Installing services');
199 $this->installServices();
200
201 // Actions if everything OK
202 if (!$this->restart && empty($this->error)) {
203 Util::logTrace('Startup completed successfully - refreshing Git repositories');
204 $this->refreshGitRepos();
205 $startupTime = round(Util::getMicrotime() - $this->startTime, 3);
206 $this->writeLog('Started in ' . $startupTime . 's');
207 Util::logTrace('Application started successfully in ' . $startupTime . ' seconds');
208 } else {
209 Util::logTrace('Startup issues detected - incrementing progress bar');
210 $this->splash->incrProgressBar(2);
211 }
212
213 if ($this->restart) {
214 Util::logTrace('Restart required - preparing to restart application');
215 $this->writeLog(APP_TITLE . ' has to be restarted');
216 $this->splash->setTextLoading(
217 sprintf(
219 APP_TITLE . ' ' . $bearsamppCore->getAppVersion()
220 )
221 );
222
223 Util::logTrace('Deleting all services before restart');
224 foreach ($bearsamppBins->getServices() as $sName => $service) {
225 Util::logTrace('Deleting service: ' . $sName);
226 $service->delete();
227 }
228
229 Util::logTrace('Setting execution action to RESTART');
231 }
232
233 if (!empty($this->error)) {
234 Util::logTrace('Errors occurred during startup: ' . $this->error);
235 $this->writeLog('Error: ' . $this->error);
236 $bearsamppWinbinder->messageBoxError($this->error, $bearsamppLang->getValue(Lang::STARTUP_ERROR_TITLE));
237 }
238
239 Util::logTrace('Starting loading screen');
241
242 // Give the loading window time to initialize before we terminate this process
243 Util::logTrace('Waiting for loading window to initialize');
244 usleep(500000); // 500ms delay to allow loading window to start
245
246 Util::logTrace('Loading process started');
247
248 // Closing cli to finish startup
249 Util::logTrace('Finishing startup process');
250
251 // Safely reset WinBinder and destroy the splash window
252 $bearsamppWinbinder->destroyWindow($window);
253 $bearsamppWinbinder->reset();
254
255 // Exit this startup process cleanly - the loading window will continue running
256 Util::logTrace('Exiting startup process cleanly');
257 exit(0);
258
259 }
const DISABLED
const STARTUP_PREPARE_RESTART_TEXT
const STARTUP_ERROR_TITLE
static startLoading()

References $bearsamppBins, $bearsamppCore, $bearsamppLang, $bearsamppRoot, $proc, APP_TITLE, changePath(), checkBinsRegKey(), checkBrowser(), checkLaunchStartup(), checkPath(), checkPathRegKey(), checkSystemPathRegKey(), cleanOldBehaviors(), cleanTmpFolders(), createSslCrts(), Lang\DISABLED, Win32Ps\EXECUTABLE_PATH, exit, Util\formatUnixPath(), Util\getMicrotime(), installServices(), killOldInstances(), Util\logTrace(), Win32Ps\PROCESS_ID, refreshAliases(), refreshGitRepos(), refreshHostname(), refreshVhosts(), ActionExec\RESTART, rotationLogs(), savePath(), scanFolders(), Util\startLoading(), Lang\STARTUP_ERROR_TITLE, Lang\STARTUP_PREPARE_RESTART_TEXT, sysInfos(), updateConfig(), and writeLog().

◆ refreshAliases()

refreshAliases ( )
private

Refreshes the aliases in the Apache configuration.

Definition at line 626 of file class.action.startup.php.

627 {
629
630 $this->splash->setTextLoading( $bearsamppLang->getValue( Lang::STARTUP_REFRESH_ALIAS_TEXT ) );
631 $this->splash->incrProgressBar();
632 $this->writeLog( 'Refresh aliases' );
633
634 $bearsamppBins->getApache()->refreshAlias( $bearsamppConfig->isOnline() );
635 }
const STARTUP_REFRESH_ALIAS_TEXT

References $bearsamppBins, $bearsamppConfig, $bearsamppLang, Lang\STARTUP_REFRESH_ALIAS_TEXT, and writeLog().

Referenced by processWindow().

◆ refreshGitRepos()

refreshGitRepos ( )
private

Refreshes Git repositories if the scan on startup is enabled. Logs the number of repositories found.

Definition at line 1185 of file class.action.startup.php.

1186 {
1187 global $bearsamppLang, $bearsamppTools;
1188
1189 $this->splash->incrProgressBar();
1190 if ( $bearsamppTools->getGit()->isScanStartup() ) {
1191 $this->splash->setTextLoading( $bearsamppLang->getValue( Lang::STARTUP_REFRESH_GIT_REPOS_TEXT ) );
1192
1193 $repos = $bearsamppTools->getGit()->findRepos( false );
1194 $this->writeLog( 'Update GIT repos: ' . count( $repos ) . ' found' );
1195 }
1196 }
const STARTUP_REFRESH_GIT_REPOS_TEXT

References $bearsamppLang, Lang\STARTUP_REFRESH_GIT_REPOS_TEXT, and writeLog().

Referenced by processWindow().

◆ refreshHostname()

refreshHostname ( )
private

Refreshes the hostname in the configuration.

Definition at line 564 of file class.action.startup.php.

565 {
567
568 $this->splash->setTextLoading( $bearsamppLang->getValue( Lang::STARTUP_REFRESH_HOSTNAME_TEXT ) );
569 $this->splash->incrProgressBar();
570 $this->writeLog( 'Refresh hostname' );
571
572 $bearsamppConfig->replace( Config::CFG_HOSTNAME, gethostname() );
573 }
const CFG_HOSTNAME
const STARTUP_REFRESH_HOSTNAME_TEXT

References $bearsamppConfig, $bearsamppLang, Config\CFG_HOSTNAME, Lang\STARTUP_REFRESH_HOSTNAME_TEXT, and writeLog().

Referenced by processWindow().

◆ refreshVhosts()

refreshVhosts ( )
private

Refreshes the virtual hosts in the Apache configuration.

Definition at line 640 of file class.action.startup.php.

641 {
643
644 $this->splash->setTextLoading( $bearsamppLang->getValue( Lang::STARTUP_REFRESH_VHOSTS_TEXT ) );
645 $this->splash->incrProgressBar();
646 $this->writeLog( 'Refresh vhosts' );
647
648 $bearsamppBins->getApache()->refreshVhosts( $bearsamppConfig->isOnline() );
649 }
const STARTUP_REFRESH_VHOSTS_TEXT

References $bearsamppBins, $bearsamppConfig, $bearsamppLang, Lang\STARTUP_REFRESH_VHOSTS_TEXT, and writeLog().

Referenced by processWindow().

◆ rotationLogs()

rotationLogs ( )
private

Rotates the logs by archiving old logs and purging old archives. Enhanced with file lock checking to prevent permission denied errors.

Definition at line 265 of file class.action.startup.php.

266 {
268
269 Util::logTrace("Starting log rotation process");
270 $this->splash->setTextLoading($bearsamppLang->getValue(Lang::STARTUP_ROTATION_LOGS_TEXT));
271 $this->splash->incrProgressBar();
272
273 $archivesPath = $bearsamppRoot->getLogsPath() . '/archives';
274 if (!is_dir($archivesPath)) {
275 Util::logTrace("Creating archives directory: " . $archivesPath);
276 mkdir($archivesPath, 0777, true);
277 return;
278 }
279
280 $date = date('Y-m-d-His', time());
281 $archiveLogsPath = $archivesPath . '/' . $date;
282 $archiveScriptsPath = $archiveLogsPath . '/scripts';
283
284 // Create archive folders
285 Util::logTrace("Creating archive directories for current rotation");
286 if (!is_dir($archiveLogsPath)) {
287 Util::logTrace("Creating logs archive directory: " . $archiveLogsPath);
288 mkdir($archiveLogsPath, 0777, true);
289 } else {
290 Util::logTrace("Logs archive directory already exists: " . $archiveLogsPath);
291 }
292
293 if (!is_dir($archiveScriptsPath)) {
294 Util::logTrace("Creating scripts archive directory: " . $archiveScriptsPath);
295 mkdir($archiveScriptsPath, 0777, true);
296 } else {
297 Util::logTrace("Scripts archive directory already exists: " . $archiveScriptsPath);
298 }
299
300 // Count archives
301 Util::logTrace("Counting existing archives");
302 $archives = array();
303 $handle = @opendir($archivesPath);
304 if (!$handle) {
305 Util::logTrace("Failed to open archives directory: " . $archivesPath);
306 return;
307 }
308
309 while (false !== ($file = readdir($handle))) {
310 if ($file == '.' || $file == '..') {
311 continue;
312 }
313 $archives[] = $archivesPath . '/' . $file;
314 }
315 closedir($handle);
316 sort($archives);
317 Util::logTrace("Found " . count($archives) . " existing archives");
318
319 // Remove old archives
320 if (count($archives) > $bearsamppConfig->getMaxLogsArchives()) {
321 $total = count($archives) - $bearsamppConfig->getMaxLogsArchives();
322 Util::logTrace("Removing " . $total . " old archives");
323 for ($i = 0; $i < $total; $i++) {
324 Util::logTrace("Deleting old archive: " . $archives[$i]);
325 Util::deleteFolder($archives[$i]);
326 }
327 }
328
329 // Helper function to check if a file is locked
330 $isFileLocked = function($filePath) {
331 if (!file_exists($filePath)) {
332 return false;
333 }
334
335 $handle = @fopen($filePath, 'r+');
336 if ($handle === false) {
337 Util::logTrace("File appears to be locked: " . $filePath);
338 return true; // File is locked
339 }
340
341 fclose($handle);
342 return false; // File is not locked
343 };
344
345 // Logs
346 Util::logTrace("Archiving log files");
347 $srcPath = $bearsamppRoot->getLogsPath();
348 $handle = @opendir($srcPath);
349 if (!$handle) {
350 Util::logTrace("Failed to open logs directory: " . $srcPath);
351 return;
352 }
353
354 $logsCopied = 0;
355 $logsSkipped = 0;
356
357 while (false !== ($file = readdir($handle))) {
358 if ($file == '.' || $file == '..' || is_dir($srcPath . '/' . $file)) {
359 continue;
360 }
361
362 $sourceFile = $srcPath . '/' . $file;
363 $destFile = $archiveLogsPath . '/' . $file;
364
365 // Check if file is locked before attempting to copy
366 if ($isFileLocked($sourceFile)) {
367 Util::logTrace("Skipping locked log file: " . $file);
368 $logsSkipped++;
369 continue;
370 }
371
372 try {
373 if (copy($sourceFile, $destFile)) {
374 $logsCopied++;
375 Util::logTrace("Archived log file: " . $file);
376 } else {
377 $logsSkipped++;
378 Util::logTrace("Failed to copy log file: " . $file);
379 }
380 } catch (Exception $e) {
381 $logsSkipped++;
382 Util::logTrace("Exception copying log file " . $file . ": " . $e->getMessage());
383 }
384 }
385 closedir($handle);
386 Util::logTrace("Logs archived: " . $logsCopied . " copied, " . $logsSkipped . " skipped");
387
388 // Scripts
389 Util::logTrace("Archiving script files");
390 $srcPath = $bearsamppCore->getTmpPath();
391 $handle = @opendir($srcPath);
392 if (!$handle) {
393 Util::logTrace("Failed to open tmp directory: " . $srcPath);
394 return;
395 }
396
397 $scriptsCopied = 0;
398 $scriptsSkipped = 0;
399
400 while (false !== ($file = readdir($handle))) {
401 if ($file == '.' || $file == '..' || is_dir($srcPath . '/' . $file)) {
402 continue;
403 }
404
405 $sourceFile = $srcPath . '/' . $file;
406 $destFile = $archiveScriptsPath . '/' . $file;
407
408 // Check if file is locked before attempting to copy
409 if ($isFileLocked($sourceFile)) {
410 Util::logTrace("Skipping locked script file: " . $file);
411 $scriptsSkipped++;
412 continue;
413 }
414
415 try {
416 if (copy($sourceFile, $destFile)) {
417 $scriptsCopied++;
418 Util::logTrace("Archived script file: " . $file);
419 } else {
420 $scriptsSkipped++;
421 Util::logTrace("Failed to copy script file: " . $file);
422 }
423 } catch (Exception $e) {
424 $scriptsSkipped++;
425 Util::logTrace("Exception copying script file " . $file . ": " . $e->getMessage());
426 }
427 }
428 closedir($handle);
429 Util::logTrace("Scripts archived: " . $scriptsCopied . " copied, " . $scriptsSkipped . " skipped");
430
431 // Purge logs - only delete files that aren't locked
432 Util::logTrace("Purging log files");
433 $logsPath = $bearsamppRoot->getLogsPath();
434 $handle = @opendir($logsPath);
435 if (!$handle) {
436 Util::logTrace("Failed to open logs directory for purging: " . $logsPath);
437 return;
438 }
439
440 $logsDeleted = 0;
441 $logsPurgeSkipped = 0;
442
443 while (false !== ($file = readdir($handle))) {
444 if ($file == '.' || $file == '..' || $file == 'archives' || $file == '.gitignore' || is_dir($logsPath . '/' . $file)) {
445 continue;
446 }
447
448 $filePath = $logsPath . '/' . $file;
449
450 // Check if file is locked before attempting to delete
451 if ($isFileLocked($filePath)) {
452 Util::logTrace("Skipping locked log file during purge: " . $file);
453 $logsPurgeSkipped++;
454 continue;
455 }
456
457 try {
458 if (file_exists($filePath) && unlink($filePath)) {
459 $logsDeleted++;
460 Util::logTrace("Purged log file: " . $file);
461 } else {
462 $logsPurgeSkipped++;
463 Util::logTrace("Failed to purge log file: " . $file);
464 }
465 } catch (Exception $e) {
466 $logsPurgeSkipped++;
467 Util::logTrace("Exception purging log file " . $file . ": " . $e->getMessage());
468 }
469 }
470 closedir($handle);
471 Util::logTrace("Logs purged: " . $logsDeleted . " deleted, " . $logsPurgeSkipped . " skipped");
472
473 Util::logTrace("Log rotation completed");
474 }
const STARTUP_ROTATION_LOGS_TEXT
static deleteFolder($path)

References $bearsamppBins, $bearsamppConfig, $bearsamppCore, $bearsamppLang, $bearsamppRoot, Util\deleteFolder(), Util\logTrace(), and Lang\STARTUP_ROTATION_LOGS_TEXT.

Referenced by processWindow().

◆ savePath()

savePath ( )
private

Saves the current application path.

Definition at line 721 of file class.action.startup.php.

722 {
723 global $bearsamppCore;
724
725 file_put_contents( $bearsamppCore->getLastPath(), $this->rootPath );
726 $this->writeLog( 'Save current path: ' . $this->rootPath );
727 }

References $bearsamppCore, and writeLog().

Referenced by processWindow().

◆ scanFolders()

scanFolders ( )
private

Scans folders and logs the number of files to scan. Performance optimization: Skips expensive file scan when path hasn't changed. This saves 3-8 seconds on typical startups (95% of cases).

Definition at line 669 of file class.action.startup.php.

670 {
672
673 $this->splash->setTextLoading( $bearsamppLang->getValue( Lang::STARTUP_SCAN_FOLDERS_TEXT ) );
674 $this->splash->incrProgressBar();
675
676 $lastPath = $bearsamppCore->getLastPathContent();
677 $currentPath = $this->rootPath;
678
679 // Performance optimization: Skip scan if path hasn't changed
680 if ($lastPath === $currentPath) {
681 Util::logDebug('Path unchanged, skipping file scan (performance optimization)');
682 Util::logTrace('Last path: "' . $lastPath . '" matches current path: "' . $currentPath . '"');
683 $this->filesToScan = [];
684 $this->writeLog('Files to scan: 0 (path unchanged - scan skipped)');
685
686 // Log performance benefit
687 $this->writeLog('Performance: File scan skipped, saving 3-8 seconds');
688 return;
689 }
690
691 // Path changed, perform full scan
692 Util::logDebug('Path changed, performing full file scan');
693 Util::logTrace('Last path: "' . $lastPath . '" differs from current path: "' . $currentPath . '"');
694 $this->writeLog('Path changed detected - performing full scan');
695
696 $scanStartTime = Util::getMicrotime();
697 $this->filesToScan = Util::getFilesToScan();
698 $scanDuration = round(Util::getMicrotime() - $scanStartTime, 3);
699
700 $this->writeLog('Files to scan: ' . count($this->filesToScan) . ' (scanned in ' . $scanDuration . 's)');
701 }
const STARTUP_SCAN_FOLDERS_TEXT
static logDebug($data, $file=null)
static getFilesToScan($path=null, $useCache=true, $forceRefresh=false)

References $bearsamppCore, $bearsamppLang, $rootPath, Util\getFilesToScan(), Util\getMicrotime(), Util\logDebug(), Util\logTrace(), Lang\STARTUP_SCAN_FOLDERS_TEXT, and writeLog().

Referenced by processWindow().

◆ sysInfos()

sysInfos ( )
private

Logs system information.

Definition at line 612 of file class.action.startup.php.

613 {
614 global $bearsamppLang;
615
616 $this->splash->setTextLoading( $bearsamppLang->getValue( Lang::STARTUP_SYS_INFOS ) );
617 $this->splash->incrProgressBar();
618
619 $os = Batch::getOsInfo();
620 $this->writeLog( sprintf( 'OS: %s', $os ) );
621 }
static getOsInfo()
const STARTUP_SYS_INFOS

References $bearsamppLang, Batch\getOsInfo(), Lang\STARTUP_SYS_INFOS, and writeLog().

Referenced by processWindow().

◆ updateConfig()

updateConfig ( )
private

Updates the configuration for bins, tools, and apps. Logs the update process.

Definition at line 837 of file class.action.startup.php.

838 {
839 global $bearsamppLang, $bearsamppBins, $bearsamppTools, $bearsamppApps;
840
841 $this->splash->setTextLoading( $bearsamppLang->getValue( Lang::STARTUP_UPDATE_CONFIG_TEXT ) );
842 $this->splash->incrProgressBar();
843 $this->writeLog( 'Update config' );
844
845 $bearsamppBins->update();
846 $bearsamppTools->update();
847 $bearsamppApps->update();
848 }
const STARTUP_UPDATE_CONFIG_TEXT

References $bearsamppBins, $bearsamppLang, Lang\STARTUP_UPDATE_CONFIG_TEXT, and writeLog().

Referenced by processWindow().

◆ writeLog()

writeLog ( $log)
private

Field Documentation

◆ $error

$error
private

Definition at line 21 of file class.action.startup.php.

Referenced by installServicesSequential().

◆ $filesToScan

$filesToScan
private

Definition at line 24 of file class.action.startup.php.

◆ $restart

$restart
private

Definition at line 19 of file class.action.startup.php.

◆ $rootPath

$rootPath
private

Definition at line 23 of file class.action.startup.php.

Referenced by scanFolders().

◆ $splash

$splash
private

Definition at line 18 of file class.action.startup.php.

◆ $startTime

$startTime
private

Definition at line 20 of file class.action.startup.php.

Referenced by checkApacheServiceWithTimeout().

◆ GAUGE_OTHERS

const GAUGE_OTHERS = 19

Definition at line 27 of file class.action.startup.php.

◆ GAUGE_SERVICES

const GAUGE_SERVICES = 5

Definition at line 26 of file class.action.startup.php.


The documentation for this class was generated from the following file: