add_action( 'init', $this, 'register_block' ); $loader->add_filter( 'block_categories_all', $this, 'add_block_category', 10, 2 ); } public function register_block(): void { if ( ! function_exists( 'register_block_type' ) ) { return; } // Register a script handle with no file src so we can attach inline JS. wp_register_script( 'acc-block-publications', false, [ 'wp-blocks', 'wp-element', 'wp-server-side-render', 'wp-block-editor', 'wp-components', 'wp-i18n' ], ACADEMICCREW_VERSION, true ); wp_add_inline_script( 'acc-block-publications', $this->editor_script() ); register_block_type( 'academiccrew/publications', [ 'api_version' => 2, 'title' => __( 'AcademicCrew: Publications', 'academiccrew' ), 'description' => __( 'Publications list for a research group member.', 'academiccrew' ), 'category' => 'academiccrew', 'icon' => 'book-alt', 'supports' => [ 'html' => false, 'align' => [ 'wide', 'full' ] ], 'attributes' => [ 'member_id' => [ 'type' => 'string', 'default' => '' ], 'per_page' => [ 'type' => 'integer', 'default' => 10 ], 'type' => [ 'type' => 'string', 'default' => '' ], 'year' => [ 'type' => 'string', 'default' => '' ], ], 'render_callback' => [ $this, 'render_block' ], 'editor_script' => 'acc-block-publications', ] ); } public function render_block( array $atts ): string { return do_shortcode( sprintf( '[academiccrew_publications_list member_id="%s" per_page="%d" type="%s" year="%s"]', esc_attr( $atts['member_id'] ?? '' ), (int) ( $atts['per_page'] ?? 10 ), esc_attr( $atts['type'] ?? '' ), esc_attr( $atts['year'] ?? '' ) ) ); } /** * Add the 'academiccrew' category once; guard against duplicates. */ public function add_block_category( array $categories ): array { foreach ( $categories as $cat ) { if ( $cat['slug'] === 'academiccrew' ) { return $categories; } } array_unshift( $categories, [ 'slug' => 'academiccrew', 'title' => 'AcademicCrew', 'icon' => null, ] ); return $categories; } private function editor_script(): string { return <<<'JS' (function(blocks, el, SSR, blockEditor, components, i18n) { var __ = i18n.__; var InspectorControls = blockEditor.InspectorControls; var PanelBody = components.PanelBody; var TextControl = components.TextControl; var RangeControl = components.RangeControl; var SelectControl = components.SelectControl; blocks.registerBlockType('academiccrew/publications', { edit: function(props) { var attrs = props.attributes; var setA = props.setAttributes; return [ el(InspectorControls, { key: 'controls' }, el(PanelBody, { title: __('Publications settings', 'academiccrew'), initialOpen: true }, el(TextControl, { label: __('Member ID (leave blank for page member)', 'academiccrew'), value: attrs.member_id, onChange: function(v) { setA({ member_id: v }); } }), el(RangeControl, { label: __('Items per page', 'academiccrew'), value: attrs.per_page, min: 1, max: 100, onChange: function(v) { setA({ per_page: v }); } }), el(SelectControl, { label: __('Type', 'academiccrew'), value: attrs.type, options: [ { label: __('All', 'academiccrew'), value: '' }, { label: 'Journal article', value: 'journal-article' }, { label: 'Conference paper', value: 'conference-paper' }, { label: 'Book chapter', value: 'book-chapter' }, { label: 'Preprint', value: 'preprint' }, { label: 'Book', value: 'book' }, { label: 'Thesis', value: 'thesis' } ], onChange: function(v) { setA({ type: v }); } }), el(TextControl, { label: __('Year (e.g. 2023 or 2020-2024)', 'academiccrew'), value: attrs.year, onChange: function(v) { setA({ year: v }); } }) ) ), el(SSR, { key: 'preview', block: 'academiccrew/publications', attributes: attrs }) ]; }, save: function() { return null; } }); }(wp.blocks, wp.element.createElement, wp.serverSideRender, wp.blockEditor, wp.components, wp.i18n)); JS; } }