<# .SYNOPSIS AtomCMS Auto Installer for Windows (XAMPP / WampServer) .DESCRIPTION Automates the full installation of AtomCMS on Windows. Supports XAMPP and WampServer environments. #> $ErrorActionPreference = "Stop" $Host.UI.RawUI.WindowTitle = "AtomCMS Installer" $REPO_URL = "https://gitlab.epicnabbo.nl/RemcoEpic/atomcms-edit.git" $DB_NAME = "habbo" $DB_USER = "root" $DB_PASS = "" function Write-Logo { Write-Host "╔══════════════════════════════════════════╗" -ForegroundColor Magenta Write-Host "║ AtomCMS Auto Installer (Windows) ║" -ForegroundColor Magenta Write-Host "╚══════════════════════════════════════════╝" -ForegroundColor Magenta Write-Host "" } function Write-Step { param([string]$Message) Write-Host "[AtomCMS] $Message" -ForegroundColor Magenta } function Write-OK { param([string]$Message) Write-Host "[ OK ] $Message" -ForegroundColor Green } function Write-Info { param([string]$Message) Write-Host "[ INFO ] $Message" -ForegroundColor Cyan } function Write-Warn { param([string]$Message) Write-Host "[ WARN ] $Message" -ForegroundColor Yellow } function Write-Error { param([string]$Message) Write-Host "[FAILED] $Message" -ForegroundColor Red exit 1 } function Test-Admin { $identity = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object Security.Principal.WindowsPrincipal($identity) if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Warn "Not running as Administrator. Some operations may fail." $continue = Read-Host "Continue anyway? (y/N)" if ($continue -ne "y") { exit 1 } } } function Find-Xampp { $paths = @( "C:\xampp", "D:\xampp", "E:\xampp", "${env:ProgramFiles}\XAMPP", "${env:ProgramFiles(x86)}\XAMPP" ) foreach ($p in $paths) { if (Test-Path "$p\php\php.exe") { return $p } } return $null } function Find-Wamp { $paths = @( "C:\wamp64", "C:\wamp", "D:\wamp64", "D:\wamp" ) foreach ($p in $paths) { if (Test-Path "$p\bin\php\php8.?.?\php.exe") { return $p } if (Test-Path "$p\bin\php\php8.??\php.exe") { return $p } } return $null } function Find-PHP { $php = Get-Command "php.exe" -ErrorAction SilentlyContinue if ($php) { return Split-Path $php.Source -Parent } $xampp = Find-Xampp if ($xampp) { return "$xampp\php" } $wamp = Find-Wamp if ($wamp) { $phpDirs = Get-ChildItem "$wamp\bin\php" -Filter "php8*" -Directory | Sort-Object Name -Descending if ($phpDirs.Count -gt 0) { return $phpDirs[0].FullName } } return $null } function Find-MySQL { $mysql = Get-Command "mysql.exe" -ErrorAction SilentlyContinue if ($mysql) { return Split-Path $mysql.Source -Parent } $xampp = Find-Xampp if ($xampp -and (Test-Path "$xampp\mysql\bin\mysql.exe")) { return "$xampp\mysql\bin" } $wamp = Find-Wamp if ($wamp -and (Test-Path "$wamp\bin\mariadb\*\bin\mysql.exe")) { $dirs = Get-ChildItem "$wamp\bin\mariadb" -Directory | Sort-Object Name -Descending if ($dirs.Count -gt 0) { return "$($dirs[0].FullName)\bin" } } return $null } function Find-Apache { $xampp = Find-Xampp if ($xampp -and (Test-Path "$xampp\apache\bin\httpd.exe")) { return "$xampp\apache" } $wamp = Find-Wamp if ($wamp -and (Test-Path "$wamp\bin\apache\*\bin\httpd.exe")) { $dirs = Get-ChildItem "$wamp\bin\apache" -Directory | Sort-Object Name -Descending if ($dirs.Count -gt 0) { return $dirs[0].FullName } } return $null } function Ensure-Tool { param([string]$Name, [string]$CheckCommand, [string]$Url, [string]$InstallHint) $found = Get-Command $CheckCommand -ErrorAction SilentlyContinue if ($found) { Write-OK "$Name is installed" return $true } Write-Warn "$Name is not found." if ($Url) { Write-Info "Download from: $Url" } if ($InstallHint) { Write-Info "$InstallHint" } return $false } function Install-Composer { if (Get-Command "composer" -ErrorAction SilentlyContinue) { Write-OK "Composer already installed" return } Write-Step "Installing Composer..." $installer = "$env:TEMP\composer-setup.php" Invoke-WebRequest -Uri "https://getcomposer.org/installer" -OutFile $installer php $installer --quiet --install-dir="$env:USERPROFILE\bin" php -r "unlink('$installer');" $env:Path += ";$env:USERPROFILE\bin" [Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path", "User") + ";$env:USERPROFILE\bin", "User") Write-OK "Composer installed. You may need to restart your terminal." } function Clone-Project { param([string]$TargetDir) if (Test-Path "$TargetDir\artisan") { Write-OK "Project already cloned at $TargetDir" return $TargetDir } if (-not (Get-Command "git" -ErrorAction SilentlyContinue)) { Write-Error "Git is not installed. Install Git for Windows: https://git-scm.com/download/win" } Write-Step "Cloning project..." git clone $REPO_URL $TargetDir Write-OK "Project cloned to $TargetDir" return $TargetDir } function Configure-Env { param([string]$ProjectDir) Write-Step "Configuring environment..." $envFile = "$ProjectDir\.env" if (Test-Path $envFile) { Write-Info ".env already exists, skipping" return } Copy-Item "$ProjectDir\.env.example" $envFile $dbPass = Read-Host "Database password (leave empty for root without password)" (Get-Content $envFile) -replace 'DB_DATABASE=.*', "DB_DATABASE=$DB_NAME" | Set-Content $envFile (Get-Content $envFile) -replace 'DB_USERNAME=.*', "DB_USERNAME=$DB_USER" | Set-Content $envFile (Get-Content $envFile) -replace 'DB_PASSWORD=.*', "DB_PASSWORD=$dbPass" | Set-Content $envFile Push-Location $ProjectDir php artisan key:generate --quiet Pop-Location Write-OK ".env configured and APP_KEY generated" } function Create-Database { param([string]$MySQLDir) Write-Step "Creating database '$DB_NAME'..." $mysqlExe = if ($MySQLDir) { "$MySQLDir\mysql.exe" } else { "mysql.exe" } if ($DB_PASS) { & $mysqlExe -u $DB_USER -p$DB_PASS -e "CREATE DATABASE IF NOT EXISTS `$DB_NAME` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" 2>$null } else { & $mysqlExe -u $DB_USER -e "CREATE DATABASE IF NOT EXISTS `$DB_NAME` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" 2>$null } if ($LASTEXITCODE -eq 0) { Write-OK "Database '$DB_NAME' ready" } else { Write-Warn "Could not create database automatically." Write-Info "Open phpMyAdmin (http://localhost/phpmyadmin) and create a database named '$DB_NAME' with charset utf8mb4_unicode_ci." Read-Host "Press Enter after creating the database" } } function Run-Migrations { param([string]$ProjectDir) Write-Step "Running migrations and seeders..." Push-Location $ProjectDir php artisan migrate --seed --force Pop-Location Write-OK "Migrations and seeders complete" } function Build-Assets { param([string]$ProjectDir) Write-Step "Building frontend assets..." Push-Location $ProjectDir yarn build:all Pop-Location Write-OK "Frontend assets built" } function Set-Permissions { param([string]$ProjectDir) Write-Step "Setting permissions..." $folders = @("$ProjectDir\storage", "$ProjectDir\bootstrap\cache") foreach ($folder in $folders) { if (Test-Path $folder) { try { icacls $folder /grant "Everyone:F" /T /Q 2>$null } catch { Write-Warn "Could not set permissions on $folder. You may need to do this manually." } } } Write-OK "Permissions set" } function Configure-Apache { param([string]$ApacheDir, [string]$ProjectDir) Write-Step "Configuring Apache virtual host..." $domain = Read-Host "Enter your domain name (e.g. localhost)" $publicDir = "$ProjectDir\public".Replace("\", "/") $vhost = @" ServerName $domain DocumentRoot "$publicDir" Options Indexes FollowSymLinks AllowOverride All Require all granted ErrorLog logs/atomcms-error.log CustomLog logs/atomcms-access.log combined "@ if ($ApacheDir) { $confFile = "$ApacheDir\conf\extra\httpd-vhosts.conf" Add-Content -Path $confFile -Value "`n$vhost" -ErrorAction SilentlyContinue Write-OK "Virtual host added to $confFile" Write-Info "Make sure these lines are uncommented in httpd.conf:" Write-Info " Include conf/extra/httpd-vhosts.conf" Write-Info " LoadModule rewrite_module modules/mod_rewrite.so" } else { Write-Warn "Apache directory not found. Add this virtual host manually:" Write-Host $vhost -ForegroundColor Gray } } function Show-Summary { param([string]$Domain) Write-Host "" Write-Host "╔══════════════════════════════════════════════════════════════╗" -ForegroundColor Green Write-Host "║ AtomCMS is ready! ║" -ForegroundColor Green Write-Host "║ ║" -ForegroundColor Green Write-Host "║ Visit: http://$Domain ║" -ForegroundColor Green Write-Host "║ Admin: http://$Domain/admin ║" -ForegroundColor Green Write-Host "║ ║" -ForegroundColor Green Write-Host "║ Run the repair tool for extra checks: ║" -ForegroundColor Green Write-Host "║ php artisan atom:check --fix ║" -ForegroundColor Green Write-Host "╚══════════════════════════════════════════════════════════════╝" -ForegroundColor Green Write-Host "" } function Main { Write-Logo Test-Admin # Check environment $phpDir = Find-PHP $mysqlDir = Find-MySQL $apacheDir = Find-Apache if (-not $phpDir) { Write-Error "PHP not found. Install XAMPP (https://www.apachefriends.org/) or WampServer first." } # Add PHP and MySQL to PATH for this session if ($phpDir) { $env:Path = "$phpDir;$env:Path" } if ($mysqlDir) { $env:Path = "$mysqlDir;$env:Path" } Write-OK "PHP found: $((Get-Command php).Source)" if ($mysqlDir) { Write-OK "MySQL found: $mysqlDir" } if ($apacheDir) { Write-OK "Apache found: $apacheDir" } # Ensure required tools Ensure-Tool -Name "Node.js" -CheckCommand "node" -Url "https://nodejs.org/" -InstallHint "Install Node.js LTS" $hasYarn = Ensure-Tool -Name "Yarn" -CheckCommand "yarn" -Url "https://yarnpkg.com/getting-started/install" -InstallHint "Run: npm install -g yarn" Ensure-Tool -Name "Git" -CheckCommand "git" -Url "https://git-scm.com/download/win" -InstallHint "Install Git for Windows" if (-not $hasYarn) { Write-Step "Installing Yarn via npm..." npm install -g yarn Write-OK "Yarn installed" } Install-Composer # Where to install? $defaultDir = if (Find-Xampp) { "$(Find-Xampp)\htdocs\atomcms" } else { "$env:USERPROFILE\atomcms" } $projectDir = Read-Host "Installation directory [$defaultDir]" if (-not $projectDir) { $projectDir = $defaultDir } Clone-Project -TargetDir $projectDir Configure-Env -ProjectDir $projectDir # Install PHP deps Write-Step "Installing PHP dependencies..." Push-Location $projectDir composer install --no-interaction --optimize-autoloader --no-dev Pop-Location Write-OK "PHP dependencies installed" # Install Node deps Write-Step "Installing Node dependencies..." Push-Location $projectDir yarn install --frozen-lockfile Pop-Location Write-OK "Node dependencies installed" Create-Database -MySQLDir $mysqlDir Run-Migrations -ProjectDir $projectDir Build-Assets -ProjectDir $projectDir Set-Permissions -ProjectDir $projectDir $configureWeb = Read-Host "Configure Apache virtual host? (y/N)" if ($configureWeb -eq "y") { Configure-Apache -ApacheDir $apacheDir -ProjectDir $projectDir } # Finalize Write-Step "Finalizing..." Push-Location $projectDir php artisan storage:link --force 2>$null php artisan optimize:clear 2>$null Pop-Location $domain = Read-Host "Enter your domain/path to access the site (e.g. localhost/atomcms/public or your-domain.com)" Show-Summary -Domain $domain } Main