Question

I am trying to create a dynamic block and I followed the steps described in the documentation, but for some reason the content that is being returned from /wp-json/wp/v2/block-renderer/plugin-blocks/frontpage-releases?context=edit&_locale=user is Error loading block: No route was found matching the URL and request method with a JSON response that says {"code":"rest_no_route","message":"No route was found matching the URL and request method","data":{"status":404}} and not an actual block. Here is my code for your review, please let me know if I am missing something. Thanks!

Notes On The Implementation:

  • All of the blocks are compiled down through React via laravel-mix with Webpack into assets/js/blocks.js

Debugging Results So Far:

  • The showBlock() method is being called when I save the page, but not when I add it to the content of the page in the editor, nor from the page itself.
  • Currently testing if either the taxonomies or custom block groups are causing it.
  • Changed the code to not use ob_start()/ob_get_clean() and appending it to the $value variable, to see if that was causing an issue.
  • Added and later removed monolog/monolog to use in addition to xdebug helper extension with PhpStorm debugging, and see that it is calling the handle() method, but not the showBlock() method except when saving.

BlockFactory.php:

namespace LibraryPlugin\Entities\Blocks;

use LibraryPlugin\Entities\Blocks\Dynamic\FrontpageReleases;
use LibraryPlugin\Traits\Helpers\LocationHelperTrait;

/**
 * Class BlockFactory
 *
 * Loads all of the blocks into the editor, so that we can use them.
 * This is called from the plugin file, within the main plugin file,
 * if we are in the admin panel.
 *
 * @package LibraryPlugin\Entities\Blocks
 */
class BlockFactory
{
    use LocationHelperTrait;

    /**
     * BlockFactory constructor.
     *
     * This is run as soon as the plugin is being loaded and allows
     * the plugin to add all of the blocks to the `init` action, before
     * the other stages.
     *
     * @throws \Exception
     */
    public function __construct()
    {
        $blocks = [
            ..., // Other non-dynamic blocks that work
            FrontpageReleases::class,
        ];

        add_filter(
            'block_categories',
            function ($categories, $post) {
                return array_merge(
                    [
                        [
                            'slug' => 'plugin-templates',
                            'title' => 'Plugin Page Templates'
                        ],
                        [
                            'slug'  => 'plugin-blocks',
                            'title' => 'Plugin Blocks',
                        ],
                    ],
                    $categories
                );
            },
            1,
            2
        );

        add_action('init', function () {
            wp_register_script(
                'plugin-blocks',
                $this->webAsset('js/blocks.js'),
                ['wp-blocks', 'wp-i18n', 'wp-element', 'wp-editor', 'lodash', 'wp-components'],
                PLUGIN_VERSION
            );

            // Ensure we have the location of any assets in plugin
            wp_localize_script('plugin-blocks', 'PLUGIN', [
                'pluginUrl' => PLUGIN_URI,
            ]);

            wp_register_style(
                'plugin-blocks',
                $this->webAsset('css/blocks.css'),
                [],
                PLUGIN_VERSION
            );
        });

        foreach ($blocks as $block) {
            add_action('init', [$block, 'handle']);
        }
    }
}

FrontpageReleases.php:

namespace LibraryPlugin\Entities\Blocks\Dynamic;

use LibraryPlugin\Traits\Helpers\LocationHelperTrait;

/**
 * Class FrontpageReleases
 *
 * This class is called during `init` action. Uses `plugin-blocks` JS
 * and CSS declared in `BlockFactory.php`. Passes a render callback to
 * make it a dynamic block.
 *
 * @package LibraryPlugin\Entities\Blocks
 */
class FrontpageReleases
{
    use LocationHelperTrait;

    /**
     * Register the release note blocks
     *
     * @return void
     */
    public static function handle(): void
    {
        register_block_type(
            'plugin-blocks/frontpage-releases',
            [
                'render_callback' => [__CLASS__, 'showBlock']
            ]
        );
    }

    /**
     * Render the value of the releases
     *
     * @param mixed $attributes
     *
     * @return mixed
     */
    public static function showBlock($attributes = null)
    {
        $classCount = 0;
        $value = '';
        try {
            $allReleases = new \WP_Query([
                'post_type' => 'page',
                'posts_per_page' => 3,
                'tax_query' => [
                    'relation' => 'AND',
                    [
                        'taxonomy' => 'release',
                        'field' => 'term_id',
                        'terms' => get_terms('release', ['fields' => 'ids'])
                    ],
                    [
                        'taxonomy' => 'solutions',
                        'field' => 'term_id',
                        'terms' => get_terms('solutions', ['fields' => 'ids']),
                        'operator' => 'NOT IN'
                    ]
                ],
                'order'          => 'DESC',
                'orderby'        => 'release', // Sort by custom taxonomy
            ]);

            if ($allReleases->have_posts()) {
                while ($allReleases->have_posts()) {
                    $allReleases->the_post();
                    $isReleased = function_exists('types_render_field')
                        ? types_render_field('is-released')
                        : get_post_meta(get_the_ID(), 'wpcf-is-released');
                    $value .= '<div class="release-version"><a href="' . get_the_permalink() . '" title="'
                        . get_the_title() . '"><h2>' . get_the_title() . '</h2><p>';
                    if (!$isReleased && $count === 0) {
                        $value .= 'Upcoming Release';
                    }
                    if ($isReleased && $count === 0) {
                        $value .= 'Current Release';
                        $count++;
                    } elseif ($isReleased && $count > 0) {
                        $value .= 'Previous Release';
                        $count++;
                    }
                    $count++;
                    $value .= '</p></a></div>';
                }
            }

            $value .= '<div class="solution-resources">
                <a href="/resources/">
                    <h2>Helpful Information</h2>
                    <p>Recommended Browser, Product Timeline, Maintentance Changes, Cloud Report,
                        Training Videos, etc.</p>
                </a>
            </div>';
        } catch (\Exception $e) {
            // TODO: Figure out how to handle any exceptions
        }

        return $value;
    }
}

frontpage-releases.jsx gets compiled into blocks.js:

import { PluginIcon } from './plugin-icon';
const { ServerSideRender } = window.wp.components;
const { registerBlockType } = window.wp.blocks;
const { __ } = window.wp.i18n;

registerBlockType('plugin-blocks/frontpage-releases', {
  title: __('Frontpage Releases', 'library-plugin'),

  icon: PluginIcon,

  category: 'plugin-blocks',

  edit: function ({ attributes }) {
    return (
      <ServerSideRender
        block="plugin-blocks/frontpage-releases"
        attributes={attributes}
      />
    );
  },

  save() {
    return null;
  },
});
Était-ce utile?

La solution

The handle() method is being called by an add_action('enqueue_block_editor_assets, [$block, 'handle']) method along with all the other blocks.

Here lies the problem. The register_block_type is being called too late. Try to call the function inside the init action hook.

You can see an example in the shortcode block of the core.

Licencié sous: CC-BY-SA avec attribution
Non affilié à wordpress.stackexchange
scroll top