Skip to content

Commit

Permalink
Merge pull request #70 from 10up/feature/wp-cli-migration-agent
Browse files Browse the repository at this point in the history
Bulk Migration Support via WP CLI
  • Loading branch information
dkotter authored Jul 8, 2022
2 parents 6f167bf + b630da6 commit 2ffb5dc
Show file tree
Hide file tree
Showing 6 changed files with 518 additions and 10 deletions.
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);

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

0 comments on commit 2ffb5dc

Please sign in to comment.