Skip to content
122 changes: 121 additions & 1 deletion packages/data/src/plugins/persistence/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ export function migrateThirdPartyFeaturePreferencesToPreferencesStore(
continue;
}

// Skip this scope if there are no features to migrates
// Skip this scope if there are no features to migrate.
const featuresToMigrate = interfaceScopes[ scope ];
if ( ! featuresToMigrate ) {
continue;
Expand Down Expand Up @@ -458,6 +458,125 @@ export function migrateThirdPartyFeaturePreferencesToPreferencesStore(
}
}

/**
* Migrates interface 'enableItems' data to the preferences store.
*
* The interface package stores this data in this format:
* ```js
* {
* enableItems: {
* singleEnableItems: {
* complementaryArea: {
* 'core/edit-post': 'edit-post/document',
* 'core/edit-site': 'edit-site/global-styles',
* }
* },
* multipleEnableItems: {
* pinnedItems: {
* 'core/edit-post': {
* 'plugin-1': true,
* },
* 'core/edit-site': {
* 'plugin-2': true,
* },
* },
* }
* }
* }
* ```
* and it should be migrated it to:
* ```js
* {
* 'core/edit-post': {
* complementaryArea: 'edit-post/document',
* pinnedItems: {
* 'plugin-1': true,
* },
* },
* 'core/edit-site': {
* complementaryArea: 'edit-site/global-styles',
* pinnedItems: {
* 'plugin-2': true,
* },
* },
* }
* ```
*
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the clear documentation 🎉

* @param {Object} persistence The persistence interface.
*/
export function migrateInterfaceEnableItemsToPreferencesStore( persistence ) {
const interfaceStoreName = 'core/interface';
const preferencesStoreName = 'core/preferences';
const state = persistence.get();
const sourceEnableItems = state[ interfaceStoreName ]?.enableItems;

// There's nothing to migrate, exit early.
if ( ! sourceEnableItems ) {
return;
}

const allPreferences = state[ preferencesStoreName ]?.preferences ?? {};

// First convert complementaryAreas into the right format.
// Use the existing preferences as the accumulator so that the data is
// merged.
const sourceComplementaryAreas =
sourceEnableItems?.singleEnableItems?.complementaryArea ?? {};

const convertedComplementaryAreas = Object.keys(
sourceComplementaryAreas
).reduce( ( accumulator, scope ) => {
const data = sourceComplementaryAreas[ scope ];

// Don't overwrite any existing data in the preferences store.
if ( accumulator[ scope ]?.complementaryArea ) {
return accumulator;
}

return {
...accumulator,
[ scope ]: {
...accumulator[ scope ],
complementaryArea: data,
},
};
}, allPreferences );

// Next feed the converted complementary areas back into a reducer that
// converts the pinned items, resulting in the fully migrated data.
const sourcePinnedItems =
sourceEnableItems?.multipleEnableItems?.pinnedItems ?? {};
const allConvertedData = Object.keys( sourcePinnedItems ).reduce(
( accumulator, scope ) => {
const data = sourcePinnedItems[ scope ];
// Don't overwrite any existing data in the preferences store.
if ( accumulator[ scope ]?.pinnedItems ) {
return accumulator;
}

return {
...accumulator,
[ scope ]: {
...accumulator[ scope ],
pinnedItems: data,
},
};
},
convertedComplementaryAreas
);

persistence.set( preferencesStoreName, {
preferences: allConvertedData,
} );

// Remove migrated preferences.
const otherInterfaceItems = state[ interfaceStoreName ];
persistence.set( interfaceStoreName, {
...otherInterfaceItems,
enableItems: undefined,
} );
}

persistencePlugin.__unstableMigrate = ( pluginOptions ) => {
const persistence = createPersistenceInterface( pluginOptions );

Expand Down Expand Up @@ -507,6 +626,7 @@ persistencePlugin.__unstableMigrate = ( pluginOptions ) => {
'core/edit-site',
'editorMode'
);
migrateInterfaceEnableItemsToPreferencesStore( persistence );
};

export default persistencePlugin;
120 changes: 120 additions & 0 deletions packages/data/src/plugins/persistence/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import plugin, {
migrateThirdPartyFeaturePreferencesToPreferencesStore,
migrateIndividualPreferenceToPreferencesStore,
convertEditPostPanels,
migrateInterfaceEnableItemsToPreferencesStore,
} from '../';
import objectStorage from '../storage/object';
import { createRegistry } from '../../../';
Expand Down Expand Up @@ -967,3 +968,122 @@ describe( 'convertEditPostPanels', () => {
} );
} );
} );

describe( 'migrateInterfaceEnableItemsToPreferencesStore', () => {
it( 'migrates enableItems to the preferences store', () => {
const persistenceInterface = createPersistenceInterface( {
storageKey: 'test-username',
} );

persistenceInterface.set( 'core/interface', {
enableItems: {
singleEnableItems: {
complementaryArea: {
'core/edit-post': 'edit-post/document',
'core/edit-site': 'edit-site/global-styles',
},
},
multipleEnableItems: {
pinnedItems: {
'core/edit-post': {
'plugin-1': true,
},
'core/edit-site': {
'plugin-2': true,
},
},
},
},
} );

migrateInterfaceEnableItemsToPreferencesStore( persistenceInterface );

expect( persistenceInterface.get() ).toEqual( {
'core/preferences': {
preferences: {
'core/edit-post': {
complementaryArea: 'edit-post/document',
pinnedItems: {
'plugin-1': true,
},
},
'core/edit-site': {
complementaryArea: 'edit-site/global-styles',
pinnedItems: {
'plugin-2': true,
},
},
},
},
'core/interface': {
enableItems: undefined,
},
} );
} );

it( 'merges pinnedItems and complementaryAreas with existing preferences store data', () => {
const persistenceInterface = createPersistenceInterface( {
storageKey: 'test-username',
} );

persistenceInterface.set( 'core/interface', {
enableItems: {
singleEnableItems: {
complementaryArea: {
'core/edit-post': 'edit-post/document',
'core/edit-site': 'edit-site/global-styles',
},
},
multipleEnableItems: {
pinnedItems: {
'core/edit-post': {
'plugin-1': true,
},
'core/edit-site': {
'plugin-2': true,
},
},
},
},
} );

persistenceInterface.set( 'core/preferences', {
preferences: {
'core/edit-post': {
preferenceA: 1,
preferenceB: 2,
},
'core/edit-site': {
preferenceC: true,
},
},
} );

migrateInterfaceEnableItemsToPreferencesStore( persistenceInterface );

expect( persistenceInterface.get() ).toEqual( {
'core/preferences': {
preferences: {
'core/edit-post': {
preferenceA: 1,
preferenceB: 2,
complementaryArea: 'edit-post/document',
pinnedItems: {
'plugin-1': true,
},
},
'core/edit-site': {
preferenceC: true,
complementaryArea: 'edit-site/global-styles',
pinnedItems: {
'plugin-2': true,
},
},
},
},
'core/interface': {
enableItems: undefined,
},
} );
} );
} );
Loading