Wordpress - Add pre-publish conditions to the block editor
const { registerPlugin } = wp.plugins;
const { PluginPrePublishPanel } = wp.editPost;
const { select, dispatch } = wp.data;
const { count } = wp.wordcount;
const { serialize } = wp.blocks;
const { PanelBody } = wp.components;
const PrePublishCheckList = () => {
let lockPost = false;
// Get the WordCount
const blocks = select( 'core/block-editor' ).getBlocks();
const wordCount = count( serialize( blocks ), 'words' );
let wordCountMessage = `${wordCount}`;
if ( wordCount < 500 ) {
lockPost = true;
wordCountMessage += ` - Minimum of 500 required.`;
}
// Get the cats
const cats = select( 'core/editor' ).getEditedPostAttribute( 'categories' );
let catsMessage = 'Set';
if ( ! cats.length ) {
lockPost = true;
catsMessage = 'Missing';
} else {
// Check that the cat is not uncategorized - this assumes that the ID of Uncategorized is 1, which it would be for most installs.
if ( cats.length === 1 && cats[0] === 1 ) {
lockPost = true;
catsMessage = 'Cannot use Uncategorized';
}
}
// Get the tags
const tags = select( 'core/editor' ).getEditedPostAttribute( 'tags' );
let tagsMessage = 'Set';
if ( tags.length < 3 || tags.length > 5 ) {
lockPost = true;
tagsMessage = 'Required 3 - 5 tags';
}
// Get the featured image
const featuredImageID = select( 'core/editor' ).getEditedPostAttribute( 'featured_media' );
let featuredImage = 'Set';
if ( featuredImageID === 0 ) {
lockPost = true;
featuredImage = 'Not Set';
}
// Do we need to lock the post?
if ( lockPost === true ) {
dispatch( 'core/editor' ).lockPostSaving();
} else {
dispatch( 'core/editor' ).unlockPostSaving();
}
return (
<PluginPrePublishPanel title={ 'Publish Checklist' }>
<p><b>Word Count:</b> { wordCountMessage }</p>
<p><b>Categories:</b> { catsMessage }</p>
<p><b>Tags:</b> { tagsMessage }</p>
<p><b>Featured Image:</b> { featuredImage }</p>
</PluginPrePublishPanel>
)
};
registerPlugin( 'pre-publish-checklist', { render: PrePublishCheckList } );
Display:
The solution above addresses the requirements listed in the question. One thing that can be expanded on is the category checking, I am making some assumptions about the category ID.
I have kept all of the checks in the same component for the sake of brevity and readability here. I would recommend moving each portion into a separate component and potentially making them Higher Order Components ( i.e withWordCount ).
I have inline comments that explain what is being done but am happy to explain further if there are any questions.
EDIT: Here's how I'm enqueuing the script
function enqueue_block_editor_assets() {
wp_enqueue_script(
'my-custom-script', // Handle.
plugin_dir_url( __FILE__ ) . '/build/index.js',
array( 'wp-blocks', 'wp-i18n', 'wp-element', 'wp-editor', 'wp-edit-post', 'word-count' ) // Dependencies, defined above.
);
}
add_action( 'enqueue_block_editor_assets', 'enqueue_block_editor_assets' );
Adding some more details about the build process. I am using @wordpress/scripts and running the following scripts:
"scripts": {
"build": "wp-scripts build",
"start": "wp-scripts start"
},
Edit 2:
You can get the attachment data via:
wp.data.select('core').getMedia( ID )
Update 29.02.2020
You have to replace select( 'core/editor' ).getBlocks()
with select( 'core/block-editor' ).getBlocks()
in order for this to work
This worked for me:
path\to\theme\pre-publish-checklist\src\index.js
const { registerPlugin } = wp.plugins;
const { PluginPrePublishPanel } = wp.editPost;
const { select, dispatch } = wp.data;
const { count } = wp.wordcount;
const { serialize } = wp.blocks;
const { PanelBody } = wp.components;
const PrePublishCheckList = () => {
let lockPost = false;
// Get the WordCount
const blocks = select( 'core/block-editor' ).getBlocks();
const wordCount = count( serialize( blocks ), 'words' );
let wordCountMessage = `${wordCount}`;
if ( wordCount < 500 ) {
lockPost = true;
wordCountMessage += ` - Minimum of 500 required.`;
}
// Get the cats
const cats = select( 'core/editor' ).getEditedPostAttribute( 'categories' );
let catsMessage = 'Set';
if ( ! cats.length ) {
lockPost = true;
catsMessage = 'Missing';
} else {
// Check that the cat is not uncategorized - this assumes that the ID of Uncategorized is 1, which it would be for most installs.
if ( cats.length === 1 && cats[0] === 1 ) {
lockPost = true;
catsMessage = 'Cannot use Uncategorized';
}
}
// Get the tags
const tags = select( 'core/editor' ).getEditedPostAttribute( 'tags' );
let tagsMessage = 'Set';
if ( tags.length < 3 || tags.length > 5 ) {
lockPost = true;
tagsMessage = 'Required 3 - 5 tags';
}
// Get the featured image
const featuredImageID = select( 'core/editor' ).getEditedPostAttribute( 'featured_media' );
let featuredImage = 'Set';
if ( featuredImageID === 0 ) {
lockPost = true;
featuredImage = 'Not Set';
}
// Do we need to lock the post?
if ( lockPost === true ) {
dispatch( 'core/editor' ).lockPostSaving();
} else {
dispatch( 'core/editor' ).unlockPostSaving();
}
return (
<PluginPrePublishPanel title={ 'Publish Checklist' }>
<p><b>Word Count:</b> { wordCountMessage }</p>
<p><b>Categories:</b> { catsMessage }</p>
<p><b>Tags:</b> { tagsMessage }</p>
<p><b>Featured Image:</b> { featuredImage }</p>
</PluginPrePublishPanel>
)
};
registerPlugin( 'pre-publish-checklist', { render: PrePublishCheckList } );
Full steps to create the panel with @wordpress/scripts
- Create a folder
pre-publish-checklist
in your theme - Create inside the folder package.json file with
"scripts": {
"build": "wp-scripts build",
"check-engines": "wp-scripts check-engines",
"check-licenses": "wp-scripts check-licenses",
"format:js": "wp-scripts format-js",
"lint:css": "wp-scripts lint-style",
"lint:js": "wp-scripts lint-js",
"lint:md:docs": "wp-scripts lint-md-docs",
"lint:md:js": "wp-scripts lint-md-js",
"lint:pkg-json": "wp-scripts lint-pkg-json",
"packages-update": "wp-scripts packages-update",
"start": "wp-scripts start",
"test:e2e": "wp-scripts test-e2e",
"test:unit": "wp-scripts test-unit-js"
},
"dependencies": {
"@wordpress/scripts": "^7.1.2"
}
}
- create a file in the folder with the path 'src/index.js' and place the code in the file
yarn
yarn build
- Add this code to functions.php to enqueue the file
function enqueue_block_editor_assets() {
wp_enqueue_script(
'pre-publish-checklist', // Handle.
get_template_directory_uri(). '/pre-publish-checklist/build/index.js',
array( 'wp-blocks', 'wp-i18n', 'wp-element', 'wp-editor', 'wp-edit-post', 'word-count' ) // Dependencies, defined above.
);
}
add_action( 'enqueue_block_editor_assets', 'enqueue_block_editor_assets' );