将发布前条件添加到块编辑器

时间:2019-05-30 作者:Christine Cooper

介绍Block Editor 杀死所有提供发布条件的插件,如最少字数、特色图片要求等。

但是块编辑器确实引入了pre-publish checks:

Pre-publish checks

美丽的如何禁用Publish 按钮,直到满足设定数量的条件?

四种(非常)不同条件的示例:

最小字数(例如:500 单词)

  • 最小/最大标记(示例:3-5 标签)
  • 最小类别(不是uncategorized)
  • 特色图像已分配到我们目前所拥有的内容,正如预期的那样,文档不存在。但线索分散在网络上。

    在里面core/editor, 我们可以使用.lockPostSaving() 要禁用Publish 按钮,并通过.unlockPostSaving().

    我们可以通过以下方式将面板添加到预发布屏幕PluginPrePublishPanel. 示例(由MadMaardigan):

    var PluginPrePublishPanel = wp.editPost.PluginPrePublishPanel;
    var registerPlugin = wp.plugins.registerPlugin;
    
    function Component() {
        // lock post saving
        wp.data.dispatch(\'core/editor\').lockPostSaving()
    
        // unlock post saving
        // wp.data.dispatch(\'core/editor\').unlockPostSaving()
    
        return wp.element.createElement(
            PluginPrePublishPanel,
            {   
                className: \'my-plugin-publish-panel\',
                title: \'Panel title\',
                initialOpen: true,
            },  
            \'Panel content\'
        );  
    }
    
    registerPlugin( \'my-plugin\', {
      render: Component,
    });
    
    它的工作原理是:

    Custom pre-publish panel

    我们在GitHub上进行了很好的讨论:#7020, #7426, #13413, #15568, #10649...

  • 2 个回复
    最合适的回答,由SO网友:Welcher 整理而成

    EDIT Sept 2021:

    使用挂钩的答案的更新版本。

    此版本可以更好地跟踪编辑器中的更改。它还使用import 语句,而不是直接从wp 全球的此方法与@wordpress/scripts 在排队时,包将正确添加此文件的依赖项。访问wp 全局仍将工作,但您必须确保手动管理脚本依赖项。

    感谢评论中的所有人!

    import { useState, useEffect } from \'@wordpress/element\';
    import { registerPlugin } from \'@wordpress/plugins\';
    import { PluginPrePublishPanel } from \'@wordpress/edit-post\';
    import { useSelect, useDispatch } from \'@wordpress/data\';
    import { count } from \'@wordpress/wordcount\';
    import { serialize } from \'@wordpress/blocks\';
    
    const PrePublishCheckList = () => {
        // Manage the messaging in state.
        const [wordCountMessage, setWordCountMessage] = useState(\'\');
        const [catsMessage, setCatsMessage] = useState(\'\');
        const [tagsMessage, setTagsMessage] = useState(\'\');
        const [featuredImageMessage, setFeaturedImageMessage] = useState(\'\');
    
        // The useSelect hook is better for retrieving data from the store.
        const { blocks, cats, tags, featuredImageID } = useSelect((select) => {
            return {
                blocks: select(\'core/block-editor\').getBlocks(),
                cats: select(\'core/editor\').getEditedPostAttribute(\'categories\'),
                tags: select(\'core/editor\').getEditedPostAttribute(\'tags\'),
                featuredImageID:
                    select(\'core/editor\').getEditedPostAttribute(\'featured_media\'),
            };
        });
    
        // The useDispatch hook is better for dispatching actions.
        const { lockPostSaving, unlockPostSaving } = useDispatch(\'core/editor\');
    
        // Put all the logic in the useEffect hook.
        useEffect(() => {
            let lockPost = false;
            // Get the WordCount
            const wordCount = count(serialize(blocks), \'words\');
            if (wordCount < 500) {
                lockPost = true;
                setWordCountMessage(`${wordCount} - Minimum of 500 required.`);
            } else {
                setWordCountMessage(`${wordCount}`);
            }
    
            // Get the category count
            if (!cats.length || (cats.length === 1 && cats[0] === 1)) {
                lockPost = true;
                setCatsMessage(\'Missing\');
                // 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) {
                    setCatsMessage(\'Cannot use Uncategorized\');
                }
            } else {
                setCatsMessage(\'Set\');
            }
    
            // Get the tags
            if (tags.length < 3 || tags.length > 5) {
                lockPost = true;
                setTagsMessage(\'Required 3 - 5 tags\');
            } else {
                setTagsMessage(\'Set\');
            }
            // Get the featured image
            if (featuredImageID === 0) {
                lockPost = true;
                setFeaturedImageMessage(\'Not Set\');
            } else {
                setFeaturedImageMessage(\' Set\');
            }
    
            if (lockPost === true) {
                lockPostSaving();
            } else {
                unlockPostSaving();
            }
        }, [blocks, cats, tags, featuredImageID]);
    
        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> {featuredImageMessage}
                </p>
            </PluginPrePublishPanel>
        );
    };
    
    registerPlugin(\'pre-publish-checklist\', { render: PrePublishCheckList });
    
    Old Version:

    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 } );
    
    显示:

    enter image description here

    上述解决方案解决了问题中列出的要求。可以扩展的一件事是类别检查,我正在对类别ID进行一些假设。

    为了简洁易读,我将所有检查都保存在同一个组件中。我建议将每个部分移动到一个单独的组件中,并可能使它们成为更高阶的组件(即使用WordCount)。

    我有内联评论,解释正在做什么,但如果有任何问题,我很乐意进一步解释。

    编辑:下面是我将脚本排队的方式

    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\' );
    
    添加有关构建过程的更多详细信息。我正在使用@wordpress/scripts 并运行以下脚本:

    "scripts": {
        "build": "wp-scripts build",
        "start": "wp-scripts start"
      },
    
    编辑2:

    您可以通过以下方式获取附件数据:

    wp.data.select(\'core\').getMedia( ID )
    

    SO网友:BenB

    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

    1. Create a folder pre-publish-checklist in your theme
    2. 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"
     }
    }
    
    1. Create a file in the folder with the path \'src/index.js\' and place the code in the file
    2. yarn
    3. yarn build
    4. 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\' );
    

    相关推荐