Depending on whether a user is connecting to Site Kit or whether a user is returning to Site Kit after having already used a previous version of the plugin, the way they should be exposed to the new user input screen should behave differently. This issue is about implementing the necessary logic to determine the user's state regarding user input.
_Do not alter or remove anything below. The following sections will be managed by moderators only._
googlesitekit_user_input_state.admin_init, run a hook to check whether user input settings were previously completed (if the flag value is not already _“completed”_):googlesitekit-dashboard admin screen, check if the new user setting is currently _“required”_. If yes, redirect to the new googlesitekit-user-input screen from #2038.core/user store getUserInputState(). It should rely on a server-provided value via _googlesitekitUserData.userInputState.Note that this won't do anything user-facing via the above implementation, which is on purpose because the final pieces can only be implemented once everything is ready to be launched in production. For example, setting the new user setting to "required" or "dismissed" will happen later.
Core\Authentication\User_Input_State class that extends Core\Storage\User_Setting.OPTION constant with googlesitekit_user_input_state as its value.VALUE_REQUIRED with required value;VALUE_COMPLETED with completed value;VALUE_MISSING with missing value.set method to verify the incoming value is required, completed, missing, or empty. If the value is valid pass it to the parent method. If not, then just return false.In the Authentication class:
User_Input_State class as private property user_input_state;User_Input_Settings class as private property user_input_settings;register method in the register method of the Authentication class;admin_init action that calls the verify_user_input_settings method;verify_user_input_settings method that:user_input_settings->get_settings() functionuser_input_state setting to completed, otherwise missing.googlesitekit_user_data filter that adds userInputState property to the filtered data using value received from the user_input_state::get method.admin_init hook to redirect the user to the googlesitekit-user-input page if the current page is googlesitekit-dashboard and the user input state setting equals to required.In the core/user datastore (user-info.js file):
receiveUserInputState action that accepts user input state value and triggers appropriate action with the incoming value as a payload;userInputState property of the store state object.getUserInputState resolver that takes userInputState property from the _googlesitekitUserData object and yields receiveUserInputState action. It should behaive similar to getConnectURL resolvergetUserInputState to the core/user store which returns userInputState from the store state object.sync_with_proxy function - see #2036 for details. wp_googlesitekit_user_input_state option to required @felixarntz, IB is added. I know that you don't want to set the user input state to required yet, but I think it still makes sense to do it in the admin_init hook to prevent invoking user input settings endpoint on every page load. I have added it to IB.
@eugene-manuilov I think it's okay for the user input endpoint to be invoked because the results are cached. It would only fire a request once a week (or otherwise when the data expired). Whether the value is required or not shouldn't affect that at all, this check is only done for knowing whether the value should be set to completed or not (completed is _not_ the opposite of required here). Potentially we could explore using another flag value like missing (both missing and required would mean that the settings are not completed, with different nuance), that way we would only need to check the user input settings data if the value is empty. What do you think?
Regarding the IB specifically:
If yes, sets
user_input_statesetting tocompleted, otherwiserequired.
See above, this is not correct - only completed should be set, otherwise nothing, or if we introduce missing, then missing should be set. required is set once somebody with empty or missing starts the setup flow (should not happen here though).
VALUE_DISMISSEDwithdismissedvalue.
This should not be a possible value, dismissal is purely handled on the client. We might want to replace this with VALUE_MISSING though, see above, to only run the admin_init check for the one case where the setting is not initialized.
Step 4
- Update the
GoogleSitekitDashboardcomponent in theassets/js/googlesitekit-dashboard.jsfile to retrieveuserInputStatevalue using theuseSelecthook.- Check if
userInputStateequals torequiredand redirect the user to thegooglesitekit-user-inputscreen usinggetAdminURLselector from thecore/sitedatastore.
This redirect should happen server-side (e.g. in Screens class), we shouldn't need to first start loading JS, which might cause some flashing of the dashboard and would also easily allow avoiding the redirect via DevTools etc.
@felixarntz I have updated IB to address your feedback. As to the missing flag, I think we don't need it because it is the same thing as an empty value in the user input state setting.
This redirect should happen server-side (e.g. in Screens class), we shouldn't need to first start loading JS, which might cause some flashing of the dashboard and would also easily allow avoiding the redirect via DevTools etc.
Ok, updated IB to make the redirect in the Authentication class since it has everything required to do it.
@eugene-manuilov
As to the
missingflag, I think we don't need it because it is the same thing as an empty value in the user input state setting.
Right, it's kind of the same, the reason I brought it up for consideration is that it would allow us to not check user input settings if missing was set. Basically:
admin_init would only check user input settings if the flag is empty / not set. It then sets it to either missing or completed.missing otherwise means the same as empty / not set, it would allow the above logic to be skipped if not needed.We don't _need_ to add it, but may be worth it.
@felixarntz I think it is worth adding missing value because it will remove a need to send unnecessary requests to the proxy server. IB is updated.
@eugene-manuilov
Checks the current value of the user input state setting and returns if it equals to
completedormissing;
It should return if it's any non-empty value (just for the uninitialized state it should get user input settings to check it)
Sends a GET request to the
REST_Routes::REST_ROOT . '/core/user/data/user-input-settings'endpoint
Let's not send a REST request when we're already in PHP (even though we could do that internally). We should be able to use the User_Input_Settings class directly.
Add another
admin_inithook to redirect the user to thegooglesitekit-user-inputpage if the current page isgooglesitekit-dashboardand the user input state setting equals torequired.
Maybe we should do this in the initialization callback for the googlesitekit-dashboard screen, within Screens class?
It should return if it's any non-empty value (just for the uninitialized state it should get user input settings to check it)
Yep, makes sense, updated.
Let's not send a REST request when we're already in PHP (even though we could do that internally). We should be able to use the User_Input_Settings class directly.
Maybe we should do this in the initialization callback for the googlesitekit-dashboard screen, within Screens class?
I would avoid doing it because it requires re-instantiating User_Input_Settings and User_Input_State classes with their dependencies in Screens and Authentication classes. It'll make the codebase slightly more complicated and a bit more coupled which is worse than calling the rest_do_request function and adding another admin_init hook. If we had a dependency injection, we would easily do what you suggest because we could get User_Input_Settings and User_Input_State objects from a DI container without creating duplicates. But for now, I think it worth doing it as it states in the IB now.
Let me know what you think about it. If you still want to move it, I can update the IB.
@eugene-manuilov I think it would make sense to instantiate User_Input_Settings in the constructor of Authentication and assign it to a class property, similar to how most other general authentication-related classes are instantiated there. I'd prefer to avoid making an internal REST request, and with this approach, which is already established, we don't have to re-instantiate the classes.
Let's then keep the redirection in an admin_init hook within Authentication like you suggested, relying on $this->user_input_settings as well.
@felixarntz ok, updated.
IB âś…
I tested this a fair bit and found that everything works as expected. QA âś…
Regarding the constraint on possible values for googlesitekit_user_input_state, this seems to be better implemented using a sanitize callback (get_sanitize_callback in User_Input_State) rather than only in User_Input_State::set. That way the logic applies more globally, e.g. setting via REST or CLI as well.
This follows the IB and does work as expected so I can't say it's a QA failure but a suggested enhancement that would be quick to do. Thoughts @felixarntz ?
@aaemnnosttv Good catch! Let's open a follow-up issue for that.
@felixarntz I opened https://github.com/google/site-kit-wp/issues/2323 as a follow-up.
Moving this one forward to approval 👍