# Help4 Migration and Cutover Tool

This plugin now includes an admin page:

- `Help4 Builder > Migration and Cutover`
- URL slug: `admin.php?page=h4bs-cutover`

## What it does

1. **Maintenance Splash**
- Toggle public maintenance mode (`HTTP 503`) during live cutover.
- Branded splash includes headline, message, and contact button.
- Admin users remain able to access wp-admin.
- When enabled, it also sets `blog_public=0` (discourage indexing).

2. **Export Migration Bundle**
- Downloads one JSON file containing:
- Pages (`page`)
- Global/theme templates (`h4_template`)
- Help4 post meta (`_h4_*`, `_wp_page_template`)
- Help4 feature flags and settings options
- Front-page and permalink options

3. **Import Migration Bundle**
- Uploads the JSON on destination site and upserts content/settings.
- Preserves slugs so URLs remain stable.
- Applies Help4 settings and design-token payloads before Builder layouts so imported pages can inherit color, font, spacing, button, and form-field presets.

## Recommended cutover flow (md -> live)

1. On **live**: enable Maintenance Splash.
2. On **md**: export migration bundle JSON.
3. On **live**: import migration bundle JSON.
4. Validate front page, header/footer templates, key service and package pages.
5. On **live**: disable Maintenance Splash.

## Migration design tokens

Include a `h4bs_global_design_tokens` option in the migration plan for the source brand before importing page layouts. Capture at least:

- Brand colors: primary, secondary, accent, surface, text, muted, button background/text, and form field background/text/border.
- Typography: heading family/weight, body family/weight, base font size, and any known heading/body stacks.
- Layout: content width, section spacing, button radius, field radius, and repeated card/container spacing.
- Component style names: button style, form field style, header treatment, and footer treatment when known.

Full-width and canvas pages can use HTML blocks for legacy rebuilds. HTML block wrappers are intentionally transparent and unpadded by default; use the block's Wrapper Background and Wrapper Padding controls only when the wrapper itself should be visible.

## Media source URL mapping

For Elementor or other source-site migrations, export a source URL map before swapping images. Store exact source URLs and final WordPress media URLs in the migration plan under `media_source_url_map`.

- Prefer exact `_h4bs_source_url` or source URL matches before using filename, dimensions, alt text, or visually similar replacements.
- Preserve uploaded-media URLs when the old asset has already been imported into the destination media library.
- Keep a small audit list of any source URL that could not be mapped so a maintainer can decide whether to import, replace, or remove it.

## cPanel and WP-CLI temp directory hardening

Some cPanel/WP Toolkit installs resolve WordPress temp files to a vendor/toolkit path that WP-CLI cannot write. Before running media-heavy imports through WP-CLI, define a writable temp directory in `wp-config.php` or the command bootstrap:

### WP-CLI `eval-file` runner compatibility

Do not put `declare(strict_types=1);` or any other first-statement-only construct in PHP intended for `wp eval-file`. WP-CLI may prepend bootstrap code before evaluating the file, which means PHP no longer sees that declaration as the first statement and stops before the guarded work begins. This rule applies to seed, migration, launch, repair, audit, and recovery runners. Keep strict types in ordinary plugin source files, but omit the declaration from every standalone `eval-file` runner.

Before distributing any `wp eval-file` runner, verify all of the following:

- The file contains no `declare(strict_types=1);` or other first-statement assumption.
- Retain all existing host, path, version, capability, draft, noindex, no-publish, dry-run, and rollback guards; they must run before writes.
- A lint pass succeeds with `php -l runner.php`.
- A read-only harness confirms object counts, unique block IDs, parent references, and draft status.

```php
if (! defined('WP_TEMP_DIR')) {
    define('WP_TEMP_DIR', WP_CONTENT_DIR . '/uploads/h4bs-temp');
}
```

Create the directory first and verify the web/PHP user can write to it:

```sh
mkdir -p wp-content/uploads/h4bs-temp
```

Help4 Commerce media imports also create and use `wp-content/uploads/h4bs-temp` automatically when `WP_TEMP_DIR` is not already defined.

## Notes

- Staging (`md.help4wordpress.com`) should stay noindex.
- This tool is for Help4 structure/content migration and settings parity.
- Media library files should still be moved via clone/rsync/backup restore as part of full cutover.
