Files
website/scripts/whmcs-migrate/migrate.php
Claude Dev b4ef90465c feat: complete pre-launch audit — frontend polish, churn prevention, login history, financial reports, configurable checkout
Includes all work from phases 6-9+ and frontend polish rounds 1 & 2:

- Login history with device trust, new device notifications, session management
- Churn prevention: cancellation surveys, winback campaigns with email sequences
- Financial reports: revenue, P&L, tax, aging, refund, subscription reports with PDF/CSV/JSON export
- Configurable checkout: plan config groups/options, build-your-own VPS
- Frontend polish: fix broken legal links, add SEO meta tags, favicon, font display=swap,
  Head titles on all 14 marketing pages, mobile responsive fixes, AuthLayout legal footer,
  remove false 24/7 claims, hide empty stats, correct uptime SLA to 99.9%,
  GameServers notify buttons linked to /contact, 301 redirects for /terms and /privacy
- WHMCS migration scripts
- Update legal page effective dates to March 16, 2026

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:39:25 -04:00

223 lines
7.2 KiB
PHP

<?php
declare(strict_types=1);
/**
* WHMCS to EZSCALE Migration Script
*
* Usage:
* php migrate.php Run all phases (fetches from WHMCS API)
* php migrate.php --phase=1 Run only phase 1
* php migrate.php --dry-run Run without writing to the database
* php migrate.php --export-only Export all WHMCS data to JSONL files (no DB writes)
* php migrate.php --from-export Import from previously exported JSONL files (no API calls)
* php migrate.php --status Show current migration progress
* php migrate.php --export-status Show exported JSONL file summary
* php migrate.php --validate-only Test connectivity without migrating
* php migrate.php --reset Reset all migration state
* php migrate.php --reset-exports Delete all exported JSONL files
* php migrate.php --help Show this help message
*/
require_once __DIR__ . '/vendor/autoload.php';
use WhmcsMigrate\MigrationRunner;
// ---------------------------------------------------------------------------
// Banner
// ---------------------------------------------------------------------------
const VERSION = '2.0.0';
$banner = <<<BANNER
╔═══════════════════════════════════════════════════╗
║ WHMCS → EZSCALE Migration Tool v%s ║
║ %s ║
╚═══════════════════════════════════════════════════╝
BANNER;
fprintf(STDOUT, $banner, VERSION, date('Y-m-d H:i:s'));
// ---------------------------------------------------------------------------
// CLI argument parsing
// ---------------------------------------------------------------------------
$options = getopt('', [
'dry-run',
'export-only',
'from-export',
'phase:',
'reset',
'reset-exports',
'status',
'export-status',
'validate-only',
'help',
]);
if (isset($options['help'])) {
printUsage();
exit(0);
}
// ---------------------------------------------------------------------------
// Resolve base path (directory containing this script)
// ---------------------------------------------------------------------------
$basePath = __DIR__;
// ---------------------------------------------------------------------------
// Apply CLI overrides before constructing the runner
// ---------------------------------------------------------------------------
if (isset($options['dry-run'])) {
putenv('DRY_RUN=true');
$_ENV['DRY_RUN'] = 'true';
$_SERVER['DRY_RUN'] = 'true';
}
if (isset($options['export-only'])) {
putenv('EXPORT_ONLY=true');
$_ENV['EXPORT_ONLY'] = 'true';
$_SERVER['EXPORT_ONLY'] = 'true';
}
if (isset($options['from-export'])) {
putenv('FROM_EXPORT=true');
$_ENV['FROM_EXPORT'] = 'true';
$_SERVER['FROM_EXPORT'] = 'true';
}
// ---------------------------------------------------------------------------
// Execute
// ---------------------------------------------------------------------------
try {
$runner = new MigrationRunner($basePath);
if (isset($options['reset'])) {
$runner->reset();
exit(0);
}
if (isset($options['reset-exports'])) {
$runner->resetExports();
exit(0);
}
if (isset($options['status'])) {
$runner->showStatus();
exit(0);
}
if (isset($options['export-status'])) {
$runner->showExportSummary();
exit(0);
}
if (isset($options['validate-only'])) {
$runner->validateOnly();
exit(0);
}
$phaseNumber = isset($options['phase']) ? (int) $options['phase'] : null;
$runner->run($phaseNumber);
exit(0);
} catch (Throwable $e) {
fprintf(STDERR, "\nFATAL ERROR: %s\n", $e->getMessage());
fprintf(STDERR, " File: %s:%d\n", $e->getFile(), $e->getLine());
fprintf(STDERR, " Trace:\n%s\n", $e->getTraceAsString());
exit(1);
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function printUsage(): void
{
$usage = <<<USAGE
Usage: php migrate.php [OPTIONS]
Options:
--dry-run Run the migration without writing to the database.
All operations are logged but no INSERT/UPDATE queries
are executed.
--export-only Export all WHMCS data to JSONL files without touching
the database. Each entity type gets its own .jsonl file
in the exports/ directory. This is fast for re-imports.
--from-export Import from previously exported JSONL files instead of
hitting the WHMCS API. Much faster for subsequent runs
since there are no API calls or rate-limit waits.
Requires --export-only to have been run first.
--phase=N Run only the specified phase number (1-7).
Phases:
1 Clients → Users + UserProfiles
2 Products → Plans + PlanPrices
3 Services → Subscriptions + Services
4 Invoices → Invoices + InvoiceItems
5 Transactions → PaymentTransactions
6 Promotions → Coupons
7 Orders → Orders
--status Display the current progress of all phases and exit.
--export-status Display a summary of all exported JSONL files.
--validate-only Test WHMCS API and EZSCALE database connectivity
without performing any migration.
--reset Delete all migration state (ID mappings and progress)
so the migration can be re-run from scratch.
--reset-exports Delete all exported JSONL files from the exports/
directory.
--help Show this help message and exit.
Configuration:
Copy .env.example to .env and fill in:
- WHMCS API credentials (WHMCS_API_URL, WHMCS_API_IDENTIFIER, WHMCS_API_SECRET)
- EZSCALE database credentials (EZSCALE_DB_*)
- Laravel APP_KEY (LARAVEL_APP_KEY) for encrypting sensitive data
- BATCH_SIZE (default: 250, WHMCS API supports up to 250)
Optional plan mapping:
Edit plan_mapping.json to map WHMCS product IDs to existing EZSCALE
plan slugs. Unmapped products will be auto-created as new plans.
Workflow:
1. Export all data: php migrate.php --export-only
2. Review exports: php migrate.php --export-status
3. Test import: php migrate.php --from-export --dry-run
4. Run import: php migrate.php --from-export
5. Check status: php migrate.php --status
For a direct migration (no export step):
php migrate.php
State:
Migration progress and ID mappings are saved to the state/ directory.
If the migration is interrupted, re-running will resume from the last
checkpoint. Use --reset to clear all state.
Exports:
JSONL files are saved to the exports/ directory. Each line is one JSON
record. Use --reset-exports to delete all export files.
Logs:
Detailed logs are written to logs/migration.log.
USAGE;
echo $usage;
}