|
# This is a custom script that automates the transition of a WordPress site |
|
# from Local by Flywheel to Laravel Herd for local development. |
|
# When placed in your user directory -> .config/herd/bin alongside a .bat file to run it, |
|
# you can run it from anywhere using the command "local-to-herd" in PowerShell. |
|
|
|
param( |
|
[string]$SiteName |
|
) |
|
|
|
# Function to check if a command exists |
|
function Test-Command { |
|
param([string]$Command) |
|
$null = Get-Command $Command -ErrorAction SilentlyContinue |
|
return $? |
|
} |
|
|
|
# Common variables |
|
$username = $env:USERNAME |
|
# Note: If this is in the system environment PATH, you can use just "mysql" instead of this full path. |
|
# Just check first that the alias is resolving to the correct MySQL instance using "Get-Command mysql". |
|
$herdMySQLPath = "C:\Users\$username\.config\herd\bin\services\mysql\8.0.36\bin\mysql.exe" |
|
|
|
Write-Host "`n=========== Local to Herd Site Setup Script ===========" -ForegroundColor Green |
|
Write-Host "Warnings:" -ForegroundColor Yellow |
|
Write-Host "`t - This script will close Local by Flywheel if it is running." -ForegroundColor Yellow |
|
Write-Host "`t - If you have used this before for this site, this script will overwrite the previous version of the database in Herd's MySQL server" -ForegroundColor Yellow |
|
Write-Host "`t - Ensure Herd and Local are running compatible versions of MySQL before proceeding, `n`t or you may have problems transferring the database back to Local `n`t and more importantly, to your live site if it is on Flywheel/WP Engine." -ForegroundColor Yellow |
|
Write-Host "This script assumes that:" |
|
Write-Host "`t - You have pulled down your site from Local and the database in the app/sql directory is the one you want to use" |
|
Write-Host "`t Note: To ensure this is the latest version, stop your site in Local before proceeding" |
|
Write-Host "`t - Your Local sites are located in C:\Users\$username\LocalSites\" |
|
Write-Host "`t Note: This script will not move any site files. `n`t This script configures Herd to serve your site from the same directory as Local." |
|
Write-Host "`t - Herd's MySQL service is running on port 3309 [NOT THE STANDARD 3306]" |
|
Write-Host "`t - You have set Laravel Herd to use .local as the TLD (if not, you will need to do a find and replace in the database)" |
|
Write-Host "`t - Your Herd MySQL username is 'root' and the password is empty" |
|
Write-Host "========================================================" -ForegroundColor Green |
|
|
|
try { |
|
# First, check prerequisites |
|
$prerequisites = @( |
|
"herd", |
|
$herdMySQLPath |
|
) |
|
foreach ($prerequisite in $prerequisites) { |
|
if (-not (Test-Command $prerequisite)) { |
|
throw "Error: Required command or executable path '$prerequisite' not found." |
|
} |
|
} |
|
|
|
# Make sure Local is not running |
|
$localProcess = Get-Process -Name "Local" -ErrorAction SilentlyContinue |
|
if ($localProcess) { |
|
Stop-Process -Name "Local" -Force |
|
} |
|
|
|
# Get site name from the user if not provided in the initial command |
|
if (-not $SiteName) { |
|
$SiteName = Read-Host "Enter the site name as it appears in Local (probably snake-case)" |
|
} |
|
if ( [string]::IsNullOrEmpty($SiteName)) { |
|
throw "Site name cannot be empty" |
|
} |
|
|
|
# Get Local database from app/sql |
|
$sqlFilePath = "C:\Users\$username\LocalSites\$SiteName\app\sql\local.sql" |
|
if (-not (Test-Path $sqlFilePath)) { |
|
throw "SQL file does not exist: $sqlFilePath" |
|
} |
|
|
|
# Import it into Herd's MySQL server |
|
$newDatabaseName = "$SiteName" + "_local" |
|
try { |
|
$createDbCommand = "CREATE DATABASE IF NOT EXISTS ``$newDatabaseName``;" |
|
$result = & $herdMySQLPath -u root -P 3309 -e $createDbCommand |
|
Write-Host "Database '$newDatabaseName' created successfully, or was already there." -ForegroundColor Green |
|
} |
|
catch { |
|
throw "Error creating database: $_" |
|
} |
|
try { |
|
Write-Host "Importing SQL file from Local into Herd database '$newDatabaseName'..." -ForegroundColor Cyan |
|
$mysqlImportArgs = @("-u", "root", "-P", "3309", $newDatabaseName) |
|
$importResult = Get-Content $sqlFilePath | & $herdMySQLPath $mysqlImportArgs |
|
if ($LASTEXITCODE -ne 0) { |
|
throw "Database import error: $importResult" |
|
} |
|
else { |
|
Write-Host $importResult -ForegroundColor Green |
|
} |
|
} |
|
catch { |
|
throw "Error importing SQL file: $_" |
|
} |
|
|
|
# Construct site path |
|
$sitePath = "C:\Users\$username\LocalSites\$SiteName\app\public" |
|
# Check if site directory exists |
|
if (-not (Test-Path $sitePath)) { |
|
throw "Site directory does not exist: $sitePath" |
|
} |
|
|
|
# Navigate to site directory |
|
Set-Location $sitePath |
|
|
|
# Run herd link |
|
$linkResult = & herd link $SiteName |
|
if ($LASTEXITCODE -ne 0) { |
|
throw $linkResult |
|
} |
|
else { |
|
Write-Host $linkResult -ForegroundColor Green |
|
} |
|
|
|
# Run herd secure |
|
$secureResult = & herd secure |
|
if ($LASTEXITCODE -ne 0) { |
|
Write-Warning "Herd secure command returned non-zero exit code: $secureResult" |
|
} |
|
else { |
|
Write-Host $secureResult |
|
} |
|
|
|
# Setup for wp-config-local.php |
|
$wpConfigPath = "C:\Users\$username\LocalSites\$SiteName\app\public" |
|
$wpConfigFile = Join-Path $wpConfigPath "wp-config-local.php" |
|
|
|
$getPrefixCommand = "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = '$newDatabaseName' AND TABLE_NAME LIKE '%_postmeta'" |
|
# Get the table prefix from the database by getting the postmeta table name |
|
$tablePrefixResult = & $herdMySQLPath -u root -P 3309 -D $newDatabaseName -e $getPrefixCommand |
|
if ($LASTEXITCODE -ne 0) { |
|
throw "Error retrieving table prefix: $tablePrefixResult" |
|
} |
|
# Extract the table prefix from the result and prepare it for the wp-config-local.php file |
|
$tablePrefix = $tablePrefixResult[1] |
|
$tablePrefix = $tablePrefix -replace 'postmeta$', '' # Remove postmeta from the result |
|
$tablePrefix = $tablePrefix.trim() # Trim any remaining whitespace |
|
$tablePrefix = "`$table_prefix = '$tablePrefix';" |
|
|
|
# Make a request to https://api.wordpress.org/secret-key/1.1/salt/ and put the returned keys in a variable |
|
$saltKeysUrl = "https://api.wordpress.org/secret-key/1.1/salt/" |
|
$saltKeys = Invoke-RestMethod -Uri $saltKeysUrl -UseBasicParsing |
|
if (-not $saltKeys) { |
|
throw "Failed to retrieve WordPress salt keys from $saltKeysUrl" |
|
} |
|
|
|
# Prepare the wp-config-local.php content |
|
$wpConfigContent = @" |
|
<?php |
|
/** |
|
* Local WordPress configuration |
|
* Generated by Herd Setup Script |
|
*/ |
|
|
|
// Database settings |
|
define('DB_NAME', '$newDatabaseName'); |
|
define('DB_USER', 'root'); |
|
define('DB_PASSWORD', ''); |
|
define('DB_HOST', '127.0.0.1:3309'); |
|
define('DB_CHARSET', 'utf8'); |
|
define('DB_COLLATE', ''); |
|
|
|
$saltKeys |
|
|
|
// Debug settings for local development |
|
define('WP_DEBUG', true); |
|
define('WP_DEBUG_LOG', true); |
|
define('WP_DEBUG_DISPLAY', false); |
|
define('WP_ENVIRONMENT_TYPE', 'local'); |
|
// Globally installed Composer packages - enables Symfony Vardumper if it's not installed in the project and you have installed it globally |
|
// If not, composer global require symfony/var-dumper |
|
require_once('C:\Users\$username\AppData\Roaming\Composer\vendor\autoload.php'); |
|
|
|
$tablePrefix |
|
|
|
/** Sets up WordPress vars and included files. */ |
|
require_once ABSPATH . 'wp-settings.php'; |
|
|
|
// Additional local configuration can be added here |
|
"@ |
|
|
|
# Write the content to wp-config-local.php |
|
try { |
|
Set-Content $wpConfigFile -Value $wpConfigContent -Encoding UTF8 |
|
Write-Host "wp-config-local.php created successfully at: $wpConfigFile" -ForegroundColor Green |
|
} |
|
catch { |
|
throw "Error creating wp-config-local.php: $_" |
|
} |
|
|
|
# Add redirect at the top of the existing wp-config.php file if it isn't already there |
|
$wpConfigFilePath = Join-Path $wpConfigPath "wp-config.php" |
|
if (Test-Path $wpConfigFilePath) { |
|
$redirectContent = @" |
|
<?php |
|
if (file_exists(__DIR__ . '/wp-config-local.php')) { |
|
require_once __DIR__ . '/wp-config-local.php'; |
|
} |
|
"@ |
|
try { |
|
# Read existing content |
|
$existingContent = Get-Content $wpConfigFilePath -Raw |
|
# Check if the redirect already exists |
|
if ($existingContent -match "require_once __DIR__ . '/wp-config-local.php';") { |
|
Write-Host "Redirect already exists in wp-config.php, skipping addition." -ForegroundColor Yellow |
|
} |
|
else { |
|
# If it doesn't exist, prepend the redirect content |
|
# Remove the first <?php tag if it exists, because we're adding it back in the redirect content |
|
if ($existingContent -match '^\s*<\?php') { |
|
$existingContent = $existingContent -replace '^\s*<\?php', '' |
|
} |
|
Set-Content $wpConfigFilePath -Value ($redirectContent + $existingContent) -Encoding UTF8 |
|
Write-Host "Local config redirect added to wp-config.php successfully." -ForegroundColor Green |
|
} |
|
} |
|
catch { |
|
throw "Error adding to wp-config.php: $_" |
|
} |
|
} |
|
# Summary |
|
Write-Host "" |
|
Write-Host "==================== Setup Complete ====================" -ForegroundColor Green |
|
Write-Host "URL: https://$SiteName.local" |
|
Write-Host "To export your database back to Local, run 'local-export-db'." |
|
Write-Host "========================================================" -ForegroundColor Green |
|
} |
|
catch { |
|
Write-Host "Error: $_" -ForegroundColor Red |
|
exit 1 |
|
} |
|
finally { |
|
Set-Location $sitePath |
|
} |