Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new preferences persistence API, and save editor preferences in user meta #39795

Merged
merged 74 commits into from
Apr 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
74b5e25
Implement basic API
talldan Mar 28, 2022
48ea1d9
Add new local storage persistence package
talldan Mar 28, 2022
f4a04e0
Only call persistenceLayer.set if there is a persistence layer
talldan Mar 28, 2022
0061cae
Wire up dependencies
talldan Mar 28, 2022
bce05a5
Fix exporting create as default and get not being async
talldan Mar 28, 2022
d592cf3
Remove old persistence interface and configure new persistence layer …
talldan Mar 28, 2022
62a5e47
Use correct user id and storage key
talldan Mar 29, 2022
b7a8786
Move local storage persistence layer into the preferences package
talldan Mar 29, 2022
2d6e113
Try a wp-preferences package
talldan Mar 29, 2022
0cb6615
Use database persistence
talldan Mar 29, 2022
5be7bd5
Only set preference values with particular actions
talldan Mar 29, 2022
7d9a302
Remove component for now
talldan Mar 29, 2022
4477ca5
Make native initialize function async
talldan Mar 29, 2022
a4007a8
Revert changes to preferences package.json
talldan Mar 29, 2022
2af0bd0
Try using an inline script to configure preferences
talldan Mar 30, 2022
3f68f83
Use a filter to add the necessary script dependencies
talldan Mar 31, 2022
ee97cd7
Remove import and package.json dependency from edit-post in favor of …
talldan Mar 31, 2022
145c79d
Remove merging of state
talldan Mar 31, 2022
4e7a13a
Try abort controller for cancelling multiple in flight requests
talldan Mar 31, 2022
7d5ed02
Revert "Try abort controller for cancelling multiple in flight requests"
talldan Mar 31, 2022
37c0c6d
Try throttling API requests
talldan Mar 31, 2022
8835a59
Simplify dependencies
talldan Mar 31, 2022
8a65181
Test that preferences are not persisted in tests due to reload
talldan Apr 1, 2022
bbcf4d3
Reset all preferences in e2e test setup
talldan Apr 4, 2022
528540b
Try `keepalive`
talldan Apr 4, 2022
20f8b4e
Oh, this is actually a debounce, not a throttle
talldan Apr 4, 2022
628a810
Try a localstorage fallback
talldan Apr 5, 2022
997fba6
Avoid `null` value becoming preloaded state
talldan Apr 5, 2022
97c8640
Improve naming and docs
talldan Apr 5, 2022
7f3ca74
Revert "Test that preferences are not persisted in tests due to reload"
talldan Apr 5, 2022
fe8944c
Use a stable reference when storage is empty
talldan Apr 5, 2022
269589f
Migrate block editor insert usage to preferences store
talldan Mar 22, 2022
b6c847e
Also reset preferences after each test
talldan Apr 5, 2022
bcab787
Use beforeEach for clearing e2e test browser state
talldan Apr 5, 2022
48e3d56
Try avoiding beforeAll and afterAll in nonce test
talldan Apr 5, 2022
b09ac17
Revert "Use beforeEach for clearing e2e test browser state"
talldan Apr 6, 2022
0c611ce
Switch to using beforeEach and afterEach, as they also ensure correct…
talldan Apr 6, 2022
1cd7d43
Revert "Migrate block editor insert usage to preferences store"
talldan Apr 6, 2022
08413dd
Migrate basic preferences in from localstorage
talldan Apr 6, 2022
4192f71
Port the migrate-individual-preference function
talldan Apr 6, 2022
ca3fabc
Port the migrate-feature-preference function
talldan Apr 6, 2022
8289807
Copy convert-edit-post-panels function from persistence plugin
talldan Apr 7, 2022
32ba8c0
Add moveInterfaceEnableItems function and improve folder structure
talldan Apr 7, 2022
5fb2a6f
Tidy up migration code
talldan Apr 7, 2022
8d10fd3
Add a test for the whole migration and fix a bug the test found
talldan Apr 7, 2022
d234b8b
Improve comment
talldan Apr 7, 2022
21b66de
Fix some more migration issues
talldan Apr 7, 2022
315a4fe
Remove old migration code
talldan Apr 7, 2022
feedc80
Add some docs for setPersistenceLayer
talldan Apr 8, 2022
65d9de5
Update database persistence layer docs
talldan Apr 8, 2022
32ffcf2
Add preferences package changelog entries
talldan Apr 11, 2022
ccff85e
Remove unused local storage persistence folder
talldan Apr 11, 2022
b77d4bc
Remove unused local storage persistence layer
talldan Apr 11, 2022
9000901
Add unit tests to preferences store
talldan Apr 11, 2022
5ff88d5
Add tests for persistence layer
talldan Apr 11, 2022
62e7520
Handle equality when comparing timestamps
talldan Apr 11, 2022
a56ca83
Improve the preferences README further
talldan Apr 12, 2022
cde874f
Improve docs
talldan Apr 12, 2022
95c96e2
Move php code into wordpress-6.1 folder
talldan Apr 12, 2022
f81418a
Reset preferences when running playwright tests
talldan Apr 13, 2022
5d18fa7
Fix typo
talldan Apr 21, 2022
34c7c95
Always register user meta
talldan Apr 21, 2022
b985c1b
Use an IIFE for the inline script and and convert to old school JS
talldan Apr 21, 2022
9d7871b
Use edit context
talldan Apr 21, 2022
01ad8d7
Use ISO date for preferences and rename to modified (not a timestamp …
talldan Apr 21, 2022
287e667
Add clarifying comment about blog prefix
talldan Apr 21, 2022
769cbfa
Use only one underscore
talldan Apr 21, 2022
46471c2
Make asnync debounce more traditional
talldan Apr 22, 2022
8fb8b96
Write tests for debounce async function
talldan Apr 22, 2022
049da18
Fix timestamps in persistence layer tests
talldan Apr 22, 2022
1febe25
Use fake timers
talldan Apr 22, 2022
99b8f52
Split the PHP hooks in two
talldan Apr 26, 2022
e53a9dd
Minimize code in inline script
talldan Apr 26, 2022
389abbb
Rename database-persistence-layer to preferences-persistence
talldan Apr 26, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -1709,6 +1709,12 @@
"markdown_source": "../packages/postcss-themes/README.md",
"parent": "packages"
},
{
"title": "@wordpress/preferences-persistence",
"slug": "packages-preferences-persistence",
"markdown_source": "../packages/preferences-persistence/README.md",
"parent": "packages"
},
{
"title": "@wordpress/preferences",
"slug": "packages-preferences",
Expand Down
106 changes: 106 additions & 0 deletions lib/compat/wordpress-6.1/persisted-preferences.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php
/**
* Server-side requirements for database persisted preferences.
*
* @package gutenberg
*/

/**
* Register the user meta for persisted preferences.
*/
function gutenberg_register_persisted_preferences_meta() {
// Create a meta key that incorporates the blog prefix so that each site
// on a multisite can have distinct user preferences.
global $wpdb;
$meta_key = $wpdb->get_blog_prefix() . 'persisted_preferences';
talldan marked this conversation as resolved.
Show resolved Hide resolved

register_meta(
'user',
$meta_key,
array(
'type' => 'object',
'single' => true,
'show_in_rest' => array(
'name' => 'persisted_preferences',
'type' => 'object',
'context' => array( 'edit' ),
'schema' => array(
'type' => 'object',
talldan marked this conversation as resolved.
Show resolved Hide resolved
'properties' => array(
'_modified' => array(
'description' => __( 'The date and time the preferences were updated.', 'default' ),
'type' => 'string',
'format' => 'date-time',
'context' => array( 'edit' ),
'readonly' => true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is readonly right here? We're modifying it via REST API put requests, no? Possible that I misunderstand what readonly means in this context 😀

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I managed to miss this comment and I've already clicked merge. I'll make a separate PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All good—easier to iterate than lug this big PR around.

Let me know where you landed with #39795 (comment) too which is a comment that I forgot about 😀

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Github makes it too easy to miss these things.

You do get an uncaught promise error if the user is offline, or the REST API errors. It doesn't stop the editor from working or anything, so doesn't seem like a critical issue.

Local storage is there as a back up, so everything still works.

I'll work on a PR to see what the options are for handling this better.

),
),
'additionalProperties' => true,
),
),
)
);
}

add_action( 'init', 'gutenberg_register_persisted_preferences_meta' );

/**
* Configures the preferences package to use user meta persistence.
*/
function gutenberg_configure_persisted_preferences() {
$user_id = get_current_user_id();
if ( empty( $user_id ) ) {
return;
}

global $wpdb;
$meta_key = $wpdb->get_blog_prefix() . 'persisted_preferences';

$preload_data = get_user_meta( $user_id, $meta_key, true );

wp_add_inline_script(
'wp-preferences',
sprintf(
'( function() {
var serverData = %s;
var userId = "%s";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor and belated, but it seems safer to encode userId formally, in the same way as serverData, even if we know that the result

sprintf( 'userId = %s', wp_json_encode( $user_id ) );

would be identifical to the current form

sprintf( 'userId = "%s"', $user_id );

The former doesn't rely on our own mental type checking, and redundancy helps with safety — especially around code interpolation. :)

var persistenceLayer = wp.preferencesPersistence.__unstableCreatePersistenceLayer( serverData, userId );
var preferencesStore = wp.preferences.store;
wp.data.dispatch( preferencesStore ).setPersistenceLayer( persistenceLayer );
} ) ();',
wp_json_encode( $preload_data ),
$user_id
),
'after'
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion this feels like too much code for an inline script. Inline scripts have limitations: they aren't transpiled and they aren't cached by the browser. Consider putting the bulk of this logic into a function that's in @wordpress/database-persistence-layer and having the inline script merely call that.

wp.databasePersistence.initPersistenceLayer( serverData, userId );


}

add_action( 'admin_init', 'gutenberg_configure_persisted_preferences' );

/**
* Register dependencies for the inline script that configures the persistence layer.
*
* Note: When porting this to core update the code here:
* https://github.com/WordPress/wordpress-develop/blob/d2ab3d183740c3d1252cb921b18005495007e022/src/wp-includes/script-loader.php#L251-L258
*
* And make the same update to the gutenberg client assets file here:
* https://github.com/WordPress/gutenberg/blob/3f3c8df23c70a37b7ac4dddebc82030362133593/lib/client-assets.php#L242-L254
*
* The update should be adding a new case like this like this:
* ```
* case 'wp-preferences':
* array_push( $dependencies, 'wp-preferences-persistence' );
* break;
* ```
talldan marked this conversation as resolved.
Show resolved Hide resolved
*
* @param WP_Scripts $scripts An instance of WP_Scripts.
*/
function gutenberg_update_preferences_persistence_deps( $scripts ) {
$persistence_script = $scripts->query( 'wp-preferences', 'registered' );
if ( isset( $persistence_script->deps ) ) {
array_push( $persistence_script->deps, 'wp-preferences-persistence' );
}
}

add_action( 'wp_default_scripts', 'gutenberg_update_preferences_persistence_deps', 11 );
1 change: 1 addition & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ function gutenberg_is_experiment_enabled( $name ) {

// WordPress 6.1 compat.
require __DIR__ . '/compat/wordpress-6.1/blocks.php';
require __DIR__ . '/compat/wordpress-6.1/persisted-preferences.php';

// Experimental features.
require __DIR__ . '/experimental/block-editor-settings-mobile.php';
Expand Down
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"@wordpress/nux": "file:packages/nux",
"@wordpress/plugins": "file:packages/plugins",
"@wordpress/preferences": "file:packages/preferences",
"@wordpress/preferences-persistence": "file:packages/preferences-persistence",
"@wordpress/primitives": "file:packages/primitives",
"@wordpress/priority-queue": "file:packages/priority-queue",
"@wordpress/react-i18n": "file:packages/react-i18n",
Expand Down
Loading