Add WordPress export (WXR/.xml) import support#4046
Open
wojtekn wants to merge 7 commits into
Open
Conversation
Support importing a WordPress export file directly in Studio's import/export screen and the Add-Site "Import from a backup" flow, matching the WordPress dashboard's Tools → Import → WordPress. The content is imported via the bundled wordpress-importer plugin so it works offline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fetch the wordpress-importer plugin via a postinstall download script into the gitignored wp-files/ bundle, matching how PHP, WP server files, and agent skills are handled. Keeps the ~2.2 MB third-party plugin out of the repo while the runtime import stays fully offline (the plugin ships in the built bundle). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Register the wordpress-importer plugin as an entry in the existing FILES_TO_DOWNLOAD registry instead of a standalone script, reusing the shared fetch/extract/retry plumbing. No behavior change; the plugin still downloads into wp-files/ at install time and ships in the CLI bundle. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collaborator
📊 Performance Test ResultsComparing f1dbbf0 vs trunk app-size
site-editor
site-startup
Results are median values from multiple test runs. Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff) |
Build the expected path with path.join instead of a hardcoded forward-slash string, so the assertion matches on Windows CI where path.join uses backslash. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The comment referenced a standalone download-wordpress-importer.ts script that was folded into download-wp-server-files.ts and never committed. Point it at the FILES_TO_DOWNLOAD registry instead. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The plugin is downloaded at build time and shipped in the CLI bundle, not vendored in the repo. Align the comment with that. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
updateSiteUrl only rewrites the target site's own URL and returns early when it is unchanged — which is always the case for a WXR merge (the DB keeps the target URL, and the importer has no knowledge of the source URL). The call did nothing but implied a capability it lacks. Replace it with a comment explaining why internal links keep pointing at the source, matching the dashboard importer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related issues
How AI was used in this PR
Authored with Claude Code: codebase exploration, the importer/handler/validator implementation, the PHP driver, tests, and this description. All changes were reviewed by the author, and the flows were manually tested in the app (see Testing Instructions).
Proposed Changes
Studio's Import/Export screen previously accepted full-site backups (Jetpack, Local, Playground,
.wpress) and raw.sqldatabases, but not a WordPress export file — the.xml(WXR) produced by Tools → Export. That importer is a first-class option in the WordPress dashboard, and users reasonably expect it in Studio too.This adds
.xmlas a supported import format in both the Import/Export tab (existing site) and the Add-Site → Import from a backup flow (new site). The content — posts, pages, terms, authors, and media — is imported the same way the dashboard does it: via the officialwordpress-importerplugin. The plugin is installed into the target site before the import runs, so the import works offline with no wordpress.org fetch at runtime.WXR import differs from the other formats in that it merges content into an existing WordPress install rather than replacing files/database. A few things the reviewer should know about:
.xmlspecifically, the new site is now created and started once (installing WordPress) before the import runs, sowp-config.phpand the database exist when the importer needs them. Other backup types keep their existing skip-start behavior..wp.localURLs resolve only via the OS hosts file + Studio's proxy and serve a self-signed cert, none of which the import runtime has, so posts import but images keep pointing at the source site. This is documented in the PHP driver and left as a possible follow-up.wordpress-importerplugin is not vendored in the repo. It's downloaded at install time (pinned version) via the existingFILES_TO_DOWNLOADregistry inscripts/download-wp-server-files.ts, alongside WP core, SQLite, WP-CLI, etc., and ships in the CLI bundle underwp-files/. The runtime install into the site is a local copy — no network needed at import time. CI must runpostinstall(or the download step) before packaging so the plugin is present in the bundle; the sibling downloads already rely on this.Testing Instructions
.xml(WXR) file. Prefer a public source site if you want to verify media import..xml. Confirm the progress bar completes, then open the site and verify posts/pages imported. With a public source, media appears in the Media Library..xml. Confirm the new site is created and the content imported.wordpress-importerplugin installs from the bundled copy). Media that must be fetched from origin will be missing offline, which is expected.npm run cli:build && npm test -- apps/cli/lib/import-export(adds validator, backup-handler-factory, and importer-selection tests).Pre-merge Checklist