-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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 user preference api #1948
Add user preference api #1948
Conversation
Simple API to get and set user preferences.
lib/api.php
Outdated
* @param string $request The parameter key for the value being validated. | ||
* @return bool If the preference name is valid. | ||
*/ | ||
function gutenberg_validate_preference_name( $preference_name, $request, $key ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to wrap all of this logic in functions? Why not just a single static class
that also contains a register_routes
method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to, but merging these and the Gutenberg_User_Preferences would couple it to the API, as it would become dependent on the API request. But perhaps that's not a problem, I'm still getting used to our coding styles and usually I'd have a class that handled the preferences and could be reused outside of the API. I'll change this round.
lib/preferences.php
Outdated
* @return bool If the preference name is valid preference. | ||
*/ | ||
public static function is_valid_preference_name( $preference_name ) { | ||
return in_array( $preference_name, self::VALID_PREFERENCES ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can add a filter here to allow plugins to register their own user preferences. Not something that needs to be done for this PR.
lib/api.php
Outdated
function gutenburg_register_routes() { | ||
register_rest_route( 'gutenburg/v1', '/user-preferences', array( | ||
'methods' => WP_REST_Server::READABLE, | ||
'callback' => 'gutenburg_get_user_preferences', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will want a permission_callback
here and with other endpoints to make sure the user is authenticated (and has whatever capability we deem necessary to use the Gutenberg interface, probably edit_posts
). We should be able to re-use the same permission callback for all of these routes..
lib/api.php
Outdated
'validate_callback' => 'gutenberg_validate_preference_name', | ||
), | ||
), | ||
) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's combine these two endpoints using the same route ('/user-preferences/(?P<preference>[a-z_]+)'
) into a single register_rest_route
call. See: https://core.trac.wordpress.org/browser/tags/4.8/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php#L90
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, now that I think about it, I don't think there are many use cases for getting a single preference. Setting a single preference and setting multiple preferences can be done the same way:
POST /gutenberg/v1/user-preferences
{
"pref1": "value1",
"pref2: "value2" // if needed, and so on
}
or the value can be set to null
to delete them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Will change this.
Merged the api routes and functions into the preferences class, fixed a load of lint issues and issues with older PHP versions, and added API tests. Will squash this up once we're happy. |
Couldn't we just use the Instead of using the REST API for this, we should think about leveraging the user settings WordPress already has. See The We can simply update the cookie on the client side using |
The existing user settings functions may work fine; I don't think we knew about them, but we should try that first. |
$user_id = get_current_user_id(); | ||
$preferences = array(); | ||
foreach ( self::$valid_preferences as $preference_name ) { | ||
$preferences[ $preference_name ] = get_user_meta( $user_id, 'gutenberg_' . $preference_name ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens when a preference is unset? It should be excluded from this array.
} | ||
|
||
foreach ( $params['preferences'] as $preference_name => $value ) { | ||
update_user_meta( $user_id, 'gutenberg_' . $preference_name, $value ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If null
is passed here, then the preference should be deleted instead.
This code looks nice and clean, the only thing I see that's missing is handling of unset preferences and deleting preferences. Let's hold off on adding those, though, we may not need this at all. Sorry about the potential waste of effort 😞 |
In the end this wasn't required, but before I close and delete the branch, @nylen what was the alternative to this? |
@notnownikki #2140 used the existing user settings functionality I mentioned earlier. |
I'm not quite sure what this would look like using setUserSetting... we'll want to keep track of how often the user uses blocks, so on first load, the user sees their most frequently used blocks. It doesn't look like it's possible to have a user setting that contains more than simple values, so we'd have to have a setting per block type with the number of uses? |
You can totally store arrays etc. with it. No need for per-block-type-settings |
Ah brilliant! Thanks, docs on it were a bit difficult to find, codex. and developer. returned nothing when I searched for it. |
@swissspidy so I've been trying this, and can't get it to work with anything but strings.
results in this:
I still can't find docs on this, but reading the code, it converts the value to a string just by calling |
I had the same issue when using |
Closing in anticipation of @youknowriad's PR that will take care of serialization |
Reopening. Turns out we've been looking at this from different perspectives. There's a need for local storage that persists on the client side (e.g. recently used blocks, session preferences) and storing data that persists across session and browser (e.g. block usage stats so we can determine what blocks a user frequently uses, across all their posts). This PR lets us fulfil the latter, and there is currently no way of doing this. So, reopening in case js-core discussions don't result in something usable for us. |
Codecov Report
@@ Coverage Diff @@
## master #1948 +/- ##
========================================
Coverage ? 27.2%
========================================
Files ? 160
Lines ? 4914
Branches ? 819
========================================
Hits ? 1337
Misses ? 3030
Partials ? 547 Continue to review full report at Codecov.
|
I think we should use |
It looks like #1455 is closed. I'm closing this one as it is very old. Feel free to reopen if this one is still necessary. Thanks :) |
Fixes #1455