Skip to content
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

Bulk Migration Support via WP CLI #70

Merged
merged 13 commits into from
Jul 8, 2022
52 changes: 42 additions & 10 deletions assets/js/editor/editor.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
import ClassicBlockTransformer from './transform/ClassicBlockTransformer';
import MigrationClient from './transform/MigrationClient';

let loaded = false;

/**
* ConnectToBlocksSupport connects the JS implementation of
* Connect to Blocks to Gutenberg JS.
* ConvertToBlocksSupport connects the JS implementation of
* Convert to Blocks to Gutenberg JS.
*/
class ConnectToBlocksEditorSupport {
class ConvertToBlocksEditorSupport {
/**
* Returns the singleton instance of ConnectToBlocksEditorSupport.
* Returns the singleton instance of ConvertToBlocksEditorSupport.
*
* @returns {ConnectToBlocksEditorSupport}
* @returns {ConvertToBlocksEditorSupport}
*/
static getInstance() {
if (!this.instance) {
this.instance = new ConnectToBlocksEditorSupport();
this.instance = new ConvertToBlocksEditorSupport();
}

return this.instance;
}

/**
* Activates the ConnectToBlocksEditorSupport
* Activates the ConvertToBlocksEditorSupport
*/
enable() {
document.addEventListener('DOMContentLoaded', this.didBlockEditorLoad.bind(this));
Expand All @@ -38,14 +41,43 @@ class ConnectToBlocksEditorSupport {

registerPlugin('convert-to-blocks', {
render: () => {
transformer.execute();
// Don't render more than once, to avoid triggering multiple migrations
if (loaded) {
return null;
}

loaded = true;

// This delay allows Gutenberg to initialize legacy content into freeform blocks
setTimeout(() => {
const result = transformer.execute();
const config = window.convert_to_blocks_agent || false;

// if no migration config, then ignore this request
if (!config) {
return null;
}

const client = new MigrationClient(config);

// if no blocks transformed, then we can jump to the next post
if (!result) {
client.next();
return null;
}

client.save();

return null;
}, 500);
faisal-alvi marked this conversation as resolved.
Show resolved Hide resolved

return null;
},
});
}
}

const support = ConnectToBlocksEditorSupport.getInstance();
const support = ConvertToBlocksEditorSupport.getInstance();
support.enable();

export default ConnectToBlocksEditorSupport;
export default ConvertToBlocksEditorSupport;
7 changes: 7 additions & 0 deletions assets/js/editor/transform/ClassicBlockTransformer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ class ClassicBlockTransformer {
*/
constructor() {
this.wp = window.wp;
this.didTransform = false;
}

/**
* Runs the Classic to Gutenberg Block transform on the current document.
*
* @returns {boolean} The result of the transformation.
*/
execute() {
const coreEditor = this.wp.data.select('core/block-editor');
Expand All @@ -23,6 +26,8 @@ class ClassicBlockTransformer {
/* Currently set to do 3 levels of recursion */
this.convertBlocks(blocks, 1, 3);
}

return this.didTransform;
}

/**
Expand Down Expand Up @@ -65,6 +70,8 @@ class ClassicBlockTransformer {
this.wp.data
.dispatch('core/block-editor')
.replaceBlocks(block.clientId, this.blockHandler(block));

this.didTransform = true;
} else if (block.innerBlocks && block.innerBlocks.length > 0) {
this.convertBlocks(block.innerBlocks);
}
Expand Down
104 changes: 104 additions & 0 deletions assets/js/editor/transform/MigrationClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
const { wp, location } = window;

/**
* MigrationClient provides the client-side support for the BE MigrationAgent.
*/
class MigrationClient {
/**
* Initializes the client with the specified config settings.
*
* @param {object} config The convert to blocks config
*/
constructor(config) {
this.config = config;
this.saved = false;
this.didNext = false;
}

/**
* Saves the curent post by manually dispatching savePost.
*/
save() {
// don't rerun after save
if (this.saved) {
return;
}

this.saved = true;

const { dispatch, subscribe } = wp.data;
const editor = dispatch('core/editor');

subscribe(this.didSave.bind(this));
editor.savePost();
}

/**
* On Post save, runs the next post migration.
*/
didSave() {
const { select } = wp.data;
const isSavingPost = select('core/editor').isSavingPost();
const isAutosavingPost = select('core/editor').isAutosavingPost();

if (isAutosavingPost && !isSavingPost) {
return;
}

if (this.hasNext()) {
this.next();
}
}

/**
* Checks if there is a post in the queue.
*
* @returns {boolean} True or false if next is present.
*/
hasNext() {
if (this.didNext) {
return false;
}

if (!this.hasNextConfig()) {
return false;
}

return this.config.agent.next;
}

/**
* Navigates to the next post to migrate.
*/
next() {
if (!this.hasNextConfig()) {
return;
}

this.didNext = true;
location.href = this.config.agent.next;
}

/**
* Checks if the next migration post data is present in config.
*
* @returns {boolean} True or false if next config is present
*/
hasNextConfig() {
if (!this.config) {
return false;
}

if (!this.config.agent) {
return false;
}

if (!this.config.agent.next) {
return false;
}

return true;
}
}

export default MigrationClient;
Loading