如何指定哪些Gutenberg块在页面模板的编辑器中可用

时间:2020-02-13 作者:UntitledGraphic

使用此处给出的示例:enter link description here 我已经成功地限制了全局可用的块类型或按帖子类型(例如:page)使用的块类型。但我真正想做的是通过页面模板限制块类型。我试过使用if ( is_page_template(\'page-home.php\') ) {...} 但是没有快乐。从下面的代码中可以明显看出,但我使用的是ACF自定义块。砌块本身工作正常。因此,目前我的函数中有以下内容。php文件:

function my_allowed_block_types( $allowed_blocks, $post ) {
// works on all content
$allowed_blocks = array(
    \'core/image\',
    \'core/paragraph\',
    \'core/heading\',
    \'core/list\'
);
// works for all pages but too general for what I want to do
if( $post->post_type === \'page\' ) {
    $allowed_blocks= array( 
        \'acf/homepage\'
    );
}
// Intended to restrict to just one block on my homepage template but does not
if ( is_page_template(\'page-home.php\') ) {
    $allowed_blocks= array( 
        \'acf/homepage\'
    );
}

3 个回复
SO网友:Will

It\'s theoretically possible 但需要重新加载页面,因为在最初加载内容进行编辑后,可以更改页面模板;与post类型不同。

(可能尝试使用UpdateSettings 尽管如此documentation is scarce.

SO网友:Myles Hyson

嘿,所以有可能做到这一点,我写了一篇文章。您需要使用Gutenberg的data module api.

下面的代码将为您启动并运行此程序。

/** main.js **/
import BlockRestrictor from \'./BlockRestrictor\'

/*
 * Add a mapping of block names and what templates they are
 * restricted to.
 */
const blockTemplateRestrictions = {
    \'core/code\': [
        \'template-super-cool.php\',
    ],
}

wp.domReady(() => {
    const restrictor = new BlockRestrictor(blockTemplateRestrictions)
    const templateWhitelister = new TemplateWhitelister(blockTemplateRestrictions)

    restrictor.run()
    templateWhitelister.run()
})
const { data } = window.wp
const { select, dispatch, subscribe } = data
const { getEditedPostAttribute } = select(\'core/editor\')
const { isTyping } = select(\'core/block-editor\')
const { getBlockType } = select(\'core/blocks\')
const { addBlockTypes, removeBlockTypes } = dispatch(\'core/blocks\')

class BlockRestrictor {
    /**
     * Currently selected template.
     * @type {string}
     */
    currentTemplate = \'\'

    /**
     * Map block names to the actual block object.
     *
     * @type {object}
     */
    unregisteredBlocks = {}

    constructor(blockTemplateRestrictions) {
        this.blockTemplateRestrictions = blockTemplateRestrictions
    }

    /**
     * Initiates listening to the redux store for when a restricted block is either
     * added or removed.
     */
    run() {
        this.currentTemplate = getEditedPostAttribute(\'template\') || \'default\'

        this.restrictBlocksToTemplate()

        /**
         * subscribe fires whenever the redux store in gutenberg updates
         */
        subscribe(() => {
            /**
             * ensure we don\'t run our logic when the user is typing.
             */
            if (isTyping() === true) {
                return false
            }

            const newTemplate = getEditedPostAttribute(\'template\') || \'default\'

            if (this.currentTemplate !== newTemplate) {
                this.currentTemplate = newTemplate
                this.restrictBlocksToTemplate()
            }
        })
    }

    /**
     * Helps decide which blocks we actually want to add or remove from
     * the store.
     */
    templateBlockRegistry() {
        let blocksToAdd = []
        let blocksToRemove = []

        Object.keys(this.blockTemplateRestrictions).forEach((blockName) => {
            if (this.blockTemplateRestrictions[blockName].includes(this.currentTemplate)) {
                blocksToAdd.push(blockName)
            } else {
                blocksToRemove.push(blockName)
            }
        })

        return {
            blocksToAdd,
            blocksToRemove,
        }
    }

    /**
     * Either removes or adds blocks to the store based on what the current
     * template is.
     */
    restrictBlocksToTemplate() {
        const { blocksToAdd, blocksToRemove } = this.templateBlockRegistry()

        if (blocksToRemove.length) {
            blocksToRemove.forEach((blockName) => {
                const blockExists = getBlockType(blockName)
                const isRegistered = typeof this.unregisteredBlocks[blockName] === \'undefined\'
                if (blockExists && isRegistered) {
                    this.unregisteredBlocks[blockName] = getBlockType(blockName)
                }
            })
            removeBlockTypes(Object.keys(this.unregisteredBlocks))
        }

        if (blocksToAdd.length) {
            let registeredBlocks = []
            blocksToAdd.forEach(blockName => {
                const blockExists = typeof getBlockType(blockName) === \'undefined\'
                const isUnregistered = typeof this.unregisteredBlocks[blockName] !== \'undefined\'

                if (blockExists && isUnregistered) {
                    registeredBlocks.push(this.unregisteredBlocks[blockName])
                    delete this.unregisteredBlocks[blockName]
                }
            })
            addBlockTypes(registeredBlocks)
        }
    }

}

export default BlockRestrictor
这里有一个链接,指向详细介绍如何基于页面模板限制块的文章。How to Restrict Blocks to Specific Page Templates in the WordPress Gutenberg Editor

SO网友:Joshua Ellis

在此扩展一些现有技术。您需要从js/editor方面处理模板切换。下面是我用来解决这个问题的一个简短片段。

Key Idea:检查模板匹配,删除所有不在白名单中的块,强制取消注册。在注销之前,必须从编辑器中删除所有不允许的块,以防止出现一系列错误。这里的反弹可能会推得更高。

import domReady from \'@wordpress/dom-ready\';
import { dispatch, subscribe, select } from \'@wordpress/data\';
import { getBlockTypes, unregisterBlockType } from \'@wordpress/blocks\'
import { debounce } from \'lodash\';

/**
 * Template Updating.
 */
domReady(() => {
  // Get current block list func.
  const getBlockList = () => select(\'core/block-editor\').getBlocks();

  subscribe(
    debounce(() => {
      // Get Blocks.
      const currentBlockList = getBlockList();

      // Get Template.
      const template = select(\'core/editor\').getEditedPostAttribute(
        \'template\',
      );

      // Set allowed.
      const allowedBlocks = [
        \'core/paragraph\',
      ];
      
      // Check whatever template.
      if (template === \'template-chapters.php\') {
        // Compare current blocks with allowed
        if (currentBlockList.length > 0) {

          // Array of allowed blocks.
          const tmp = currentBlockList.filter(block => {
            return -1 !== allowedBlocks.indexOf(block.name);
          });


          if (tmp.length !== currentBlockList.length && currentBlockList.length > 1) {
            // Remove all offending blocks.
            dispatch(\'core/block-editor\').resetBlocks(tmp);
            return;
          }
        }

        // Proceed to unregister.
        getBlockTypes().forEach( function ( blockType ) {
            if ( allowedBlocks.indexOf( blockType.name ) === -1 ) {
              unregisterBlockType( blockType.name );
            }
        } );
      }
    }, 100)
  );
});

相关推荐

初学者问题:通过管理Web界面访问Functions.php以导入自定义帖子类型?

是否可以访问这些功能。php文件仅仅使用管理web界面?我正在尝试访问以前创建的(手动编码的)自定义帖子类型,我不得不跳过很多障碍,因为我无法访问函数中的代码。php文件。我已经浏览了很多帮助页面,但建议的步骤似乎总是涉及到函数。php文件(我无法访问)或使用插件中的导入/导出工具,该插件首先创建了自定义帖子类型(据我所知,没有使用任何插件)。这似乎是一个非常基本的问题,但我一辈子都想不出来。任何帮助都将不胜感激!