=== WP Site Sync Pro ===
Version: 4.9.13
Purpose: Push or pull DB + media + themes + plugins between two WordPress sites over REST.

== What it does ==
- Both sites need the plugin installed and a shared Migration Key (URL + secret).
- Push = this site packages data → uploads chunks → destination assembles & imports.
- Pull = destination packages → this site downloads chunks → this site imports.
- Sync is job-locked (one active job), time-sliced (many short AJAX/REST requests) so PHP timeouts do not kill large transfers.
- This plugin folder is never included in plugin zips (self-exclude).

== Architecture (roles) ==
Source browser (admin.js)
  → local AJAX (class-sync-ajax.php / class-sync-handler.php)
  → remote REST (class-api.php on the other site)

UI layer
  - assets/admin.js + admin.css + custom-dialog.js
  - class-admin.php: settings page, Migration Key, enqueue assets
  - Leave-page warning while sync runs; Stop button confirms cancel

Core classes (inc/)
  - class-helpers.php     Shared dirs, zip/unzip shell helpers, secrets, maintenance/safe mode
  - class-logger.php      File logs → wp-content/wp-site-sync/logs/sync-YYYY-MM-DD.log
  - class-job-manager.php Job lock, status %, slice timeouts (default 20s / zip 45s)
  - class-sync-handler.php Local packaging: SQL dump, zip themes/plugins/uploads; AJAX entry
  - class-sync-ajax.php   Chunk upload/download HTTP (cURL multipart), cancel, lock, status
  - class-api.php         REST: handshake, upload-chunk, process-push, download-package, cancel, secure-login
  - class-push-assembler.php Destination: stitch push_*.part files into final packages (sliced)
  - class-import-slice.php   Destination/local import: DB SQL slices + zip extract slices
  - class-remote-import.php  Path delete helpers, URL/prefix finalize pieces
  - class-pull-export.php    Remote prepare packages for pull

Data on disk (wp-content/wp-site-sync/)
  - exports/  Built packages (sql.gz, zips)
  - temp/     Incoming chunks / assembled packages during import
  - logs/     Daily verbose sync logs (auto-clean after 30 days)

== Push flow (typical) ==
1. Acquire lock → job_id
2. prepare_push: dump DB, zip media/themes/plugins (active and/or inactive as selected)
3. send_chunk × N:  ~2–12 MB chunks (Safe Mode = 2 MB, concurrency 1; else up to ~12 MB, concurrency 3)
4. process-push iterations on destination:
   0 = assemble parts → packages
   1 = plugins zip
   2 = themes zip
   3 = media (uploads) zip
   4 = database import + finalize (prefix/URL replace)
   5 = cleanup / complete
5. Release lock / cancel cleans remote + local temp

== Pull flow (typical) ==
1. Lock → remote prepare packages
2. Download packages in chunks
3. Import locally with same sliced import path
4. Finalize + optional one-time secure login link (session may die after DB pull)

== Import method (plugins / themes / media) ==
Default: merge/overwrite in place (extract over existing files).
Optional delete-first: Settings → "Delete Before Extract" (option `wp_site_sync_delete_before_extract`),
or filter `wp_site_sync_delete_before_extract`. Deletes matching root folders before extract
(slower on large plugins like Elementor). Must be enabled on the importing site.

Extract preference:
1. Shell `unzip -o` when available (fast)
2. Else PHP ZipArchive, entry-by-entry, time-sliced (slow on large plugin trees)

Media: overwrite_roots always false (merge into uploads).

== Key options / filters ==
- wp_site_sync_remote_url, wp_site_sync_secret_key
- wp_site_sync_safe_mode (smaller chunks, no parallel uploads)
- wp_site_sync_delete_before_extract (delete plugin/theme folders before extract)
- wp_site_sync_delete_data_on_uninstall
- Filters: wp_site_sync_zip_slice_timeout, wp_site_sync_db_slice_timeout,
  wp_site_sync_slice_timeout, wp_site_sync_delete_before_extract,
  wp_site_sync_shell_unzip_max_bytes

== Performance notes (from real syncs) ==
- Biggest cost is usually the plugins package (size on wire) + destination extract if shell unzip is missing.
- Status polling (~3s) and chunk round-trips add wall time; destination PHP max_execution_time can cap each slice (~45s on some hosts).
- Always check logs on BOTH sites when debugging; destination writes its own log during process-push.

== Files map ==
wp-site-sync-pro.php     Bootstrap, activation, updater
inc/*.php                Server logic (see Architecture)
assets/*                 Admin UI
uninstall.php            Optional data wipe
vendor/gl-plugin-updater Auto-update helper
