Skip to content

Commit

Permalink
[Data Liberation] "Fetch from a different URL" button for failed medi…
Browse files Browse the repository at this point in the history
…a downloads, Interactivity API support (#2040)

## Description

Ships user-driven import error handling and makes the import UI more
useful by automatically refreshing the progress details.

### User-driven error handling

When a remote asset cannot be downloaded, most importers either stop or
ignore the error. This PR adds a user interaction to make an explicit
decision about what should happen next – do we ignore the missing asset?
Do we use another file instead?


https://github.com/user-attachments/assets/cea48258-b644-434c-9fb2-1b890c4d86d7


### Auto-Refreshing Import Status

This PR also re-expresses the entire data liberation wp-admin page using
the interactivity API, and auto-refreshes the progress:


https://github.com/user-attachments/assets/e093268b-5deb-4bc2-a1d2-e2bb1148e153

A part of #1894

## Technical overview

### User-driven error handling

During the frontloading stage, the `WP_Stream_Importer` exposes all the
frontloaded entities to the API consumer. The consumer then creates a
post of type `frontloading_placeholder` with an initial status
`awaiting_download` for each asset, and updates it with progress
information and status (success, failure, skipped) as the import
progresses.

The frontloading stage is not finished until all the frontloaded assets
have been processed with a non-error outcome. There's a few ways to
recover from errors:

* Retry the download – `WP_Stream_Importer` now retries the failed
assets URL (via `WP_Retry_Frontloading_Iterator`) before moving on to
entities provided by the usual entity source such as a WXR file.
* Changing the downloaded URL – done by the user on the wp-admin page
* Choosing to skip the download – done by the user on the wp-admin page

Sometimes we don't want to require user interactions, e.g. when running
the `importWxr` Blueprint step. In those scenarios, we could choose a
default error outcome, e.g. "skip failed downloads".

### Auto-refreshing admin page

Two `fetch()` requests running in an infinite loop are:

* Updating the JavaScript interactivity store with the latest import
state from the server
* Running the next import step

### Other changes

* Adds `php_userstreamop_read` to the Asyncify list – it crashed the
importer in `@wp-playground/cli` running in bun.

## Follow-up work

* Pretty UI transitions. Right now it's all sudden and jerky. We need
progress bars, smooth animations, clear visual causality.
* Prevent running the same import in two concurrent requests. This is a
serial importer not designed for parallelization.
* Run each import step in a transaction – either it all worked and we
can commit the changes and an updated cursor, or it didn't work and we
roll back the last step. Ideally we'll never see a scenario where an
entity was processed, but a crash happened before storing the updated
cursor and the next run reprocesses the same entity.

## Testing instructions

* Go to the data liberation admin page
* Upload a WXR export file
* Confirm the import processes automatically and doesn't error out
  • Loading branch information
adamziel authored Dec 4, 2024
1 parent 955be03 commit 6ebd956
Show file tree
Hide file tree
Showing 20 changed files with 1,772 additions and 765 deletions.
14 changes: 6 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,36 @@ All notable changes to this project are documented in this file by a CI job
that runs on every NPM release. The file follows the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
format.

## [v1.0.14] (2024-12-02)
## [v1.0.14] (2024-12-02)

### Blueprints

- Resolve the latest WordPress version from the API instead of assuming it's the same as the last minified build. ([#2027](https://github.com/WordPress/wordpress-playground/pull/2027))
- Resolve the latest WordPress version from the API instead of assuming it's the same as the last minified build. ([#2027](https://github.com/WordPress/wordpress-playground/pull/2027))

### Tools


#### Blueprints Builder

- Add installPlugin support for single plugin files. ([#2033](https://github.com/WordPress/wordpress-playground/pull/2033))
- Add installPlugin support for single plugin files. ([#2033](https://github.com/WordPress/wordpress-playground/pull/2033))

### PHP WebAssembly

- Networking: Preserve the content-type header when fetch()-ing. ([#2028](https://github.com/WordPress/wordpress-playground/pull/2028))
- Networking: Preserve the content-type header when fetch()-ing. ([#2028](https://github.com/WordPress/wordpress-playground/pull/2028))

### Website

- [Web] Re-enable wp-cron. ([#2039](https://github.com/WordPress/wordpress-playground/pull/2039))
- [Web] Re-enable wp-cron. ([#2039](https://github.com/WordPress/wordpress-playground/pull/2039))

### Various

- [Data Liberation] WP_Stream_Importer: User-driven incremental import. ([#2013](https://github.com/WordPress/wordpress-playground/pull/2013))
- [Data Liberation] WP_Stream_Importer: User-driven incremental import. ([#2013](https://github.com/WordPress/wordpress-playground/pull/2013))

### Contributors

The following contributors merged PRs in this release:

@adamziel @brandonpayton


## [v1.0.13] (2024-11-25)

### Enhancements
Expand Down
14 changes: 6 additions & 8 deletions packages/docs/site/docs/main/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,36 @@ All notable changes to this project are documented in this file by a CI job
that runs on every NPM release. The file follows the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
format.

## [v1.0.14] (2024-12-02)
## [v1.0.14] (2024-12-02)

### Blueprints

- Resolve the latest WordPress version from the API instead of assuming it's the same as the last minified build. ([#2027](https://github.com/WordPress/wordpress-playground/pull/2027))
- Resolve the latest WordPress version from the API instead of assuming it's the same as the last minified build. ([#2027](https://github.com/WordPress/wordpress-playground/pull/2027))

### Tools


#### Blueprints Builder

- Add installPlugin support for single plugin files. ([#2033](https://github.com/WordPress/wordpress-playground/pull/2033))
- Add installPlugin support for single plugin files. ([#2033](https://github.com/WordPress/wordpress-playground/pull/2033))

### PHP WebAssembly

- Networking: Preserve the content-type header when fetch()-ing. ([#2028](https://github.com/WordPress/wordpress-playground/pull/2028))
- Networking: Preserve the content-type header when fetch()-ing. ([#2028](https://github.com/WordPress/wordpress-playground/pull/2028))

### Website

- [Web] Re-enable wp-cron. ([#2039](https://github.com/WordPress/wordpress-playground/pull/2039))
- [Web] Re-enable wp-cron. ([#2039](https://github.com/WordPress/wordpress-playground/pull/2039))

### Various

- [Data Liberation] WP_Stream_Importer: User-driven incremental import. ([#2013](https://github.com/WordPress/wordpress-playground/pull/2013))
- [Data Liberation] WP_Stream_Importer: User-driven incremental import. ([#2013](https://github.com/WordPress/wordpress-playground/pull/2013))

### Contributors

The following contributors merged PRs in this release:

@adamziel @brandonpayton


## [v1.0.13] (2024-11-25)

### Enhancements
Expand Down
1 change: 1 addition & 0 deletions packages/php-wasm/compile/php/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@ export ASYNCIFY_ONLY=$'"rc_dtor_func",\
"_php_stream_fill_read_buffer",\
"_php_stream_read",\
"php_stream_read_to_str",\
"php_userstreamop_read",\
"zif_fread",\
"wasm_read",\
"php_stdiop_read",\
Expand Down
Binary file modified packages/php-wasm/node/asyncify/8_3_0/php_8_3.wasm
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/php-wasm/node/asyncify/php_8_3.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const dependencyFilename = __dirname + '/8_3_0/php_8_3.wasm';
export { dependencyFilename };
export const dependenciesTotalSize = 15083501;
export const dependenciesTotalSize = 15085661;
export function init(RuntimeName, PHPLoader) {
/**
* Overrides Emscripten's default ExitStatus object which gets
Expand Down
76 changes: 39 additions & 37 deletions packages/playground/data-liberation/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,25 @@
require_once __DIR__ . '/src/byte-readers/WP_Remote_File_Reader.php';
require_once __DIR__ . '/src/byte-readers/WP_Remote_File_Ranged_Reader.php';

if(!class_exists('WP_HTML_Tag_Processor')) {
require_once __DIR__ . "/src/wordpress-core-html-api/class-wp-html-token.php";
require_once __DIR__ . "/src/wordpress-core-html-api/class-wp-html-span.php";
require_once __DIR__ . "/src/wordpress-core-html-api/class-wp-html-text-replacement.php";
require_once __DIR__ . "/src/wordpress-core-html-api/class-wp-html-decoder.php";
require_once __DIR__ . "/src/wordpress-core-html-api/class-wp-html-attribute-token.php";

require_once __DIR__ . "/src/wordpress-core-html-api/class-wp-html-decoder.php";
require_once __DIR__ . "/src/wordpress-core-html-api/class-wp-html-tag-processor.php";
require_once __DIR__ . "/src/wordpress-core-html-api/class-wp-html-open-elements.php";
require_once __DIR__ . "/src/wordpress-core-html-api/class-wp-token-map.php";
require_once __DIR__ . "/src/wordpress-core-html-api/html5-named-character-references.php";
require_once __DIR__ . "/src/wordpress-core-html-api/class-wp-html-active-formatting-elements.php";
require_once __DIR__ . "/src/wordpress-core-html-api/class-wp-html-processor-state.php";
require_once __DIR__ . "/src/wordpress-core-html-api/class-wp-html-unsupported-exception.php";
require_once __DIR__ . "/src/wordpress-core-html-api/class-wp-html-processor.php";
if ( ! class_exists( 'WP_HTML_Tag_Processor' ) ) {
require_once __DIR__ . '/src/wordpress-core-html-api/class-wp-html-token.php';
require_once __DIR__ . '/src/wordpress-core-html-api/class-wp-html-span.php';
require_once __DIR__ . '/src/wordpress-core-html-api/class-wp-html-text-replacement.php';
require_once __DIR__ . '/src/wordpress-core-html-api/class-wp-html-decoder.php';
require_once __DIR__ . '/src/wordpress-core-html-api/class-wp-html-attribute-token.php';

require_once __DIR__ . '/src/wordpress-core-html-api/class-wp-html-decoder.php';
require_once __DIR__ . '/src/wordpress-core-html-api/class-wp-html-tag-processor.php';
require_once __DIR__ . '/src/wordpress-core-html-api/class-wp-html-open-elements.php';
require_once __DIR__ . '/src/wordpress-core-html-api/class-wp-token-map.php';
require_once __DIR__ . '/src/wordpress-core-html-api/html5-named-character-references.php';
require_once __DIR__ . '/src/wordpress-core-html-api/class-wp-html-active-formatting-elements.php';
require_once __DIR__ . '/src/wordpress-core-html-api/class-wp-html-processor-state.php';
require_once __DIR__ . '/src/wordpress-core-html-api/class-wp-html-unsupported-exception.php';
require_once __DIR__ . '/src/wordpress-core-html-api/class-wp-html-processor.php';
}
if (!isset($html5_named_character_references)) {
require_once __DIR__ . "/src/wordpress-core-html-api/html5-named-character-references.php";
if ( ! isset( $html5_named_character_references ) ) {
require_once __DIR__ . '/src/wordpress-core-html-api/html5-named-character-references.php';
}

require_once __DIR__ . '/src/block-markup/WP_Block_Markup_Processor.php';
Expand All @@ -56,6 +56,8 @@
require_once __DIR__ . '/src/import/WP_Import_Session.php';
require_once __DIR__ . '/src/import/WP_Stream_Importer.php';
require_once __DIR__ . '/src/import/WP_Markdown_Importer.php';
require_once __DIR__ . '/src/import/WP_Entity_Iterator_Chain.php';
require_once __DIR__ . '/src/import/WP_Retry_Frontloading_Iterator.php';

require_once __DIR__ . '/src/utf8_decoder.php';

Expand All @@ -65,50 +67,50 @@
require_once __DIR__ . '/vendor/autoload.php';

// Polyfill WordPress core functions
if (!function_exists('_doing_it_wrong')) {
$GLOBALS['_doing_it_wrong_messages'] = [];
function _doing_it_wrong($method, $message, $version) {
if ( ! function_exists( '_doing_it_wrong' ) ) {
$GLOBALS['_doing_it_wrong_messages'] = array();
function _doing_it_wrong( $method, $message, $version ) {
$GLOBALS['_doing_it_wrong_messages'][] = $message;
}
}

if(!function_exists('wp_kses_uri_attributes')) {
if ( ! function_exists( 'wp_kses_uri_attributes' ) ) {
function wp_kses_uri_attributes() {
return [];
return array();
}
}

if (!function_exists('__')) {
function __($input) {
if ( ! function_exists( '__' ) ) {
function __( $input ) {
return $input;
}
}

if (!function_exists('esc_attr')) {
function esc_attr($input) {
return htmlspecialchars($input);
if ( ! function_exists( 'esc_attr' ) ) {
function esc_attr( $input ) {
return htmlspecialchars( $input );
}
}

if (!function_exists('esc_html')) {
function esc_html($input) {
return htmlspecialchars($input);
if ( ! function_exists( 'esc_html' ) ) {
function esc_html( $input ) {
return htmlspecialchars( $input );
}
}

if (!function_exists('esc_url')) {
function esc_url($url) {
return htmlspecialchars($url);
if ( ! function_exists( 'esc_url' ) ) {
function esc_url( $url ) {
return htmlspecialchars( $url );
}
}

if (!function_exists('wp_kses_uri_attributes')) {
if ( ! function_exists( 'wp_kses_uri_attributes' ) ) {
function wp_kses_uri_attributes() {
return array();
}
}

if (!function_exists('mbstring_binary_safe_encoding')) {
if ( ! function_exists( 'mbstring_binary_safe_encoding' ) ) {
function mbstring_binary_safe_encoding( $reset = false ) {
static $encodings = array();
static $overloaded = null;
Expand Down Expand Up @@ -140,7 +142,7 @@ function mbstring_binary_safe_encoding( $reset = false ) {
}
}

if (!function_exists('reset_mbstring_encoding')) {
if ( ! function_exists( 'reset_mbstring_encoding' ) ) {
function reset_mbstring_encoding() {
mbstring_binary_safe_encoding( true );
}
Expand Down
Loading

0 comments on commit 6ebd956

Please sign in to comment.