UNPKG

@woocommerce/data

Version:
152 lines (151 loc) 5.44 kB
/** * External dependencies */ import { mapValues } from 'lodash'; import { useDispatch, useSelect } from '@wordpress/data'; /** * Internal dependencies */ import { STORE_NAME } from './constants'; /** * Retrieve and decode the user's WooCommerce meta values. * * @param {Object} user WP User object. * @return {Object} User's WooCommerce preferences. */ const getWooCommerceMeta = (user) => { const wooMeta = user.woocommerce_meta || {}; const userData = mapValues(wooMeta, (data, key) => { if (!data || data.length === 0) { return ''; } try { return JSON.parse(data); } catch (e) { if (e instanceof Error) { /* eslint-disable no-console */ console.error(`Error parsing value '${data}' for ${key}`, e.message); /* eslint-enable no-console */ } else { /* eslint-disable no-console */ console.error(`Unexpected Error parsing value '${data}' for ${key} ${e}`); /* eslint-enable no-console */ } return ''; } }); return userData; }; // Create wrapper for updating user's `woocommerce_meta`. async function updateUserPrefs(receiveCurrentUser, user, saveUser, getLastEntitySaveError, userPrefs) { // @todo Handle unresolved getCurrentUser() here. // Prep fields for update. const metaData = mapValues(userPrefs, JSON.stringify); if (Object.keys(metaData).length === 0) { return { error: new Error('Invalid woocommerce_meta data for update.'), updatedUser: undefined, }; } // Optimistically propagate new woocommerce_meta to the store for instant update. receiveCurrentUser({ ...user, woocommerce_meta: { ...user.woocommerce_meta, ...metaData, }, }); // Use saveUser() to update WooCommerce meta values. const updatedUser = await saveUser({ id: user.id, woocommerce_meta: metaData, }); if (undefined === updatedUser) { // Return the encountered error to the caller. const error = getLastEntitySaveError('root', 'user', user.id); return { error, updatedUser, }; } // Decode the WooCommerce meta after save. const updatedUserResponse = { ...updatedUser, woocommerce_meta: getWooCommerceMeta(updatedUser), }; return { updatedUser: updatedUserResponse, }; } /** * Custom react hook for retrieving thecurrent user's WooCommerce preferences. * * This is a wrapper around @wordpress/core-data's getCurrentUser() and saveUser(). */ export const useUserPreferences = () => { // Get our dispatch methods now - this can't happen inside the callback below. const dispatch = useDispatch(STORE_NAME); const { addEntities, receiveCurrentUser, saveEntityRecord } = dispatch; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore let { saveUser } = dispatch; const userData = useSelect((select) => { const { getCurrentUser, getEntity, getEntityRecord, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore getLastEntitySaveError, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore hasStartedResolution, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore hasFinishedResolution, } = select(STORE_NAME); return { isRequesting: hasStartedResolution('getCurrentUser') && !hasFinishedResolution('getCurrentUser'), user: getCurrentUser(), getCurrentUser, getEntity, getEntityRecord, getLastEntitySaveError, }; }); const updateUserPreferences = (userPrefs) => { // WP 5.3.x doesn't have the User entity defined. if (typeof saveUser !== 'function') { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore saveUser = async (userToSave) => { const entityDefined = Boolean(userData.getEntity('root', 'user')); if (!entityDefined) { // Add the User entity so saveEntityRecord works. await addEntities([ { name: 'user', kind: 'root', baseURL: '/wp/v2/users', plural: 'users', }, ]); } // Fire off the save action. await saveEntityRecord('root', 'user', userToSave); // Respond with the updated user. return userData.getEntityRecord('root', 'user', userToSave.id); }; } // Get most recent user before update. const currentUser = userData.getCurrentUser(); return updateUserPrefs(receiveCurrentUser, currentUser, saveUser, userData.getLastEntitySaveError, userPrefs); }; const userPreferences = userData.user ? getWooCommerceMeta(userData.user) : {}; return { isRequesting: userData.isRequesting, ...userPreferences, updateUserPreferences, }; };