Allow `recover-module` endpoint to recover multiple modules at once.
See original GitHub issueFeature Description
In #4823 a few issues have come up that encourages multiple or batched module recovery operation. This is also a common case that should be handled in the API level so we do not need to make multiple requests to the endpoint to recover more than one module.
#5297 introduces a barbaric way to recover multiple modules. It still makes multiple API calls, obviously, but it updates the recoverable module lists after all module recovery requests are settled. Once the API supports multiple module module recovery, we can refactor the recoverModules action and potentially get rid of recoverModule action altogether.
This, along with #5287 can reduce number of API calls and make the experience of module recovery more consistent.
Do not alter or remove anything below. The following sections will be managed by moderators only.
Acceptance criteria
- The
recover-moduleREST endpoint should be renamed torecover-modules, and updated to allow multiple modules to be recovered in a single request.- The error handling should be updated to reflect the batched nature of the request, so a single module recovery failure doesn’t result in the failure of the entire request, and individual module error statuses are returned to be handled by the client.
- The HTTP status code should generally be a 200 even if some modules fail to recover, unless there is an unexpected error.
- The response should be updated to contain a map of module slugs to error statuses.
- Assuming it a) still exists and b) is not being used the
recoverModuleaction should be removed. - The
recoverModulesaction should be updated to make use of the renamed & updatedrecover-modulesendpoint, making a single request to recover all specified modules.
Implementation Brief
- In
includes/Core/Modules/Modules.php:- In the
get_rest_routes()method, locate the route definition forcore/modules/data/recover-module:- Re-define the route to be
recover-modules(plural). - Re-structure the
callbackfunction:- It should accept
slugsinstead ofslugin$request['data'].$request['data']['slugs']will be an array of module slugs that need to be recovered. - Create an array and assign it to a variable named
$response. This array should have two nested empty arrays with the keys:successanderror. - Loop through the
$request['data']['slugs']array and for each of the slug, do the following:- Execute all the checks and the module settings update that we currently perform for recovering a single module.
- If everything was successful, add an element to the
$response['success']array with the current slug as the key, andtrue(boolean) as the value. - If an error was encountered:
- Add an element to the
$response['success']array with the current slug as the key, andfalse(boolean) as the value. - Add an element to the
$response['error']array with the current slug as the key, and the error (WP_Error) as the value.
- Add an element to the
- Return a
WP_REST_Responsewith the$responsearray passed to it.
- It should accept
- Re-define the route to be
- In the
- In
assets/js/googlesitekit/modules/datastore/modules.js:- Update the
fetchRecoverModuleStorefunction:- Rename it to
fetchRecoverModulesStore(plural). - Change
baseNametorecoverModules. - Update the
controlCallbackproperty function:- Replace
recover-modulewithrecover-modules(plural). - Replace all instances of
slugwithslugs(plural).
- Replace
- Update the
argsToParamsandvalidateParamsproperty functions to replace all instances ofslugwithslugs.
- Rename it to
- Update the
recoverModulesaction:- Re-structure the second parameter function of the
createValidatedActionfunction:- Using the
yieldkeyword, call thefetchRecoverModulesStore.actions.fetchRecoverModules()action withslugspassed to it and access theresponseproperty from the object returned by it (by destructuring it). - Destructure the
responseobject and accesssuccessanderrorfrom it. - For each module slug (key) in the
successobject which has the value oftrue(i.e. successful recoveries), reload its module settings by dispatchingfetchGetSettingsfrom the respective module store. The module store name can be obtained using thegetModuleStoreNameselector from thecore/modulesstore. - If the
successobject is not an empty object:- Using the
yieldkeyword, call thefetchGetModulesStore.actions.fetchGetModules()action. - Using the
yieldkeyword, refresh the list of recoverable modules by dispatching theinvalidateResolutionaction from thecore/modulesstore, passing the stringgetRecoverableModulesand and an empty array as parameters. - Using the
yieldkeyword, refresh user capabilities from the server by dispatching therefreshCapabilitiesaction from thecore/userstore.
- Using the
- At last, return an object containing
response.
- Using the
- Re-structure the second parameter function of the
- In the
storevariable assignment, inside theData.combineStores()call, reflect this change offetchRecoverModuleStoretofetchRecoverModulesStore(plural).
- Update the
- In
assets/js/components/dashboard-sharing/ModuleRecoveryAlert/index.js:- Update the
getRecoveryErrorvariable assignment to call thegetErrorForActionselector withrecoverModules(plural) passed as the parameter, instead ofrecoverModule. - Update the
clearErrorsdispatch to userecoverModules(plural) as the parameter, instead ofrecoverModule.
- Update the
- In
assets/js/components/dashboard-sharing/ModuleRecoveryAlert/index.stories.js:- Replace all instances of
recover-modulewithrecover-modules. - Ensure that the stories work as expected. If not, make necessary changes.
- Replace all instances of
Test Coverage
- In
tests/phpunit/integration/Core/Modules/ModulesTest.php:- Replace all instances of
recover-modulewithrecover-modules. - Update all
WP_REST_Request()calls to the refactored endpoint to reflect the new request and response structure. - Fix any other failing test.
- Replace all instances of
- In
assets/js/googlesitekit/modules/datastore/modules.test.js:- Replace all instances of
recover-modulewithrecover-modules. - Update all
fetchMockcalls and relevantexpectcalls to reflect the new request and response structure. - Fix any other failing test.
- Replace all instances of
QA Brief
- This doesn’t include any visual change.
- Ensure that the
dashboardSharingfeature flag is enabled in the tester plugin. - Set up Site Kit with a few/all modules.
- Using the Dashboard Sharing settings modal, share access to those modules with other administrators.
- Sign up into Site Kit with a different administrator user.
- Disconnect Site Kit from the first administrator user so that the modules become recoverable.
- As the second administrator user, try to recover the modules.
- Verify that the module recovery occurs smoothly.
- In the
Networktab of the browser developer tools, verify that only one request is made to the/google-site-kit/v1/core/modules/data/recover-modulesendpoint to recover all modules, instead of multiple requests to/google-site-kit/v1/core/modules/data/recover-module, one for each module. - If an error is encountered, verify that it is displayed correctly.
Changelog entry
- Add multi-module support to module recovery API endpoint.
Issue Analytics
- State:
- Created a year ago
- Comments:7

Top Related StackOverflow Question
QA Update: ✅
Verified:
/google-site-kit/v1/core/modules/data/recover-modulesendpoint to recover all modules.Thank you very much for the feedback, @techanvil!