diff --git a/docs/developer/blocks/README.md b/docs/developer/blocks/README.md new file mode 100644 index 000000000..f626e2f7d --- /dev/null +++ b/docs/developer/blocks/README.md @@ -0,0 +1,6 @@ +# Blocks in GatherPress + +1. All blocks in general (LINK to /docs/user/...) +2. [Hookable patterns for events & venues](./hookable-patterns/) + - Add to or Remove blocks from the post type block templates +3. [Slots & fills in GatherPress Admin UI](./slot-fills/) diff --git a/docs/developer/blocks/hookable-patterns/README.md b/docs/developer/blocks/hookable-patterns/README.md new file mode 100644 index 000000000..2d8f11b4f --- /dev/null +++ b/docs/developer/blocks/hookable-patterns/README.md @@ -0,0 +1,42 @@ +# Hookable patterns for events & venues + +GatherPress registers multiple invisible block-patterns, that are used as template properties of the main post types. + +Patterns allow to be filtered by the (upgraded since WordPress 6.5) Block Hooks API. Making use of this API brings some advantages, which are at least: + +- GatherPress' blocks can be easily moved, modified or removed by extenders via standardized core code +- GatherPress provides central entry points for plugin developers to hook in own blocks, to extend GatherPress +- GatherPress' blocks will provide their hooking code themself, which keeps concerns separate and code clean + +For example when you create a new event post, it gets pre-poulated with a set of blocks, curated within a block-pattern named `gatherpress/event-template`. + +GatherPress combines four of such block-patterns to curate the creation of: + +- [New Events](#new-event) +- [New Venues](#new-venue) +- [New Event Queries within any post](#new-event-queries-within-any-post) +- [Venue Details within any post](#venue-details-within-any-post) + +## New Event + +GatherPress adds the following blocks by default into a new created event: + +- A block-pattern named `gatherpress/event-template`. + + +## New Venue + +A new created venue will have the following blocks prepared by default: + +- A block-pattern named `gatherpress/venue-template` + - A block-pattern named `gatherpress/venue-details`, which keeps detailed information about a selected venue in the shape of blocks + +## New Event Queries within any post + +## Venue Details within any post + +### Resources + +- [@wordpress/hooks - Block Editor Handbook | Developer.WordPress.org](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-hooks/) +- [#devnote - Introducing Block Hooks for dynamic blocks - Make WordPress Core](https://make.wordpress.org/core/2023/10/15/introducing-block-hooks-for-dynamic-blocks/) +- [Exploring the Block Hooks API in WordPress 6.5 - WordPress Developer Blog](https://developer.wordpress.org/news/2024/03/25/exploring-the-block-hooks-api-in-wordpress-6-5/) diff --git a/docs/developer/blocks/slot-fills/README.md b/docs/developer/blocks/slot-fills/README.md new file mode 100644 index 000000000..5b52e5628 --- /dev/null +++ b/docs/developer/blocks/slot-fills/README.md @@ -0,0 +1,42 @@ +# Slots & fills in GatherPress Admin UI + +Similar to the central entry points for blocks – GatherPress' [hookable-patterns](./../hookable-patterns/), the plugin provides central administrative entry-points within the post- and site-editor for all block settings. + +GatherPress keeps relevant post data about the currently edited venue or event post within slot inside the `InseptorControls` panel, specific for each post type. These open slots are used by GatherPress itself and can be filled externally. + +Every slot belongs to one of each post type. Additionally the venue-slot will be added to the event-slot automatically. + +Every GatherPress block with own administrative sidebar-elements registers a fill for either the venue- or the events-slot. Plugin developers should provide their additions to GatherPress within the slots as well, which will help keeping the overall admin interface clean & consistent. + +## Available Slots + +- `EventPluginDocumentSettings` A slot that has all settings related to an event. +- `VenuePluginDocumentSettings` A slot that has all settings related to a venue. + +All slots will be rendered into the `PluginDocumentSettingPanel` imported from the `@wordpress/editor` package. This panel is shown in the document sidebar for the event and venue post types [in both the post and site editor][devnote]. + +## Fills by GatherPress + +- `VenuePluginFill` loads the `VenuePluginDocumentSettings` slot into the `EventPluginDocumentSettings` slot, so that venue changes can be made from within an event context. + + +## Add or remove UI elements + +```js +export default function GatherPressAwesomeFill() { + return ( + <> + +

A note that will be seen in the document sidebar under "Event settings".

+
+ + ); +} +``` + + +### Resources + +- [Unified Extensibility APIs in 6.6][devnote] + +[devnote]: https://make.wordpress.org/core/2024/06/18/editor-unified-extensibility-apis-in-6-6/ "#devnote - Editor: Unified Extensibility APIs in 6.6 – Make WordPress Core" diff --git a/gatherpress.php b/gatherpress.php index 3ff5c9704..b391c2daf 100644 --- a/gatherpress.php +++ b/gatherpress.php @@ -7,7 +7,7 @@ * Author URI: https://gatherpress.org/ * Version: 0.31.0-alpha * Requires PHP: 7.4 - * Requires at least: 6.4 + * Requires at least: 6.6 * Text Domain: gatherpress * Domain Path: /languages * License: GNU General Public License v2.0 or later diff --git a/includes/core/classes/class-block.php b/includes/core/classes/class-block.php index a20b606cf..d2a0ce44e 100644 --- a/includes/core/classes/class-block.php +++ b/includes/core/classes/class-block.php @@ -49,6 +49,7 @@ protected function __construct() { * @return void */ protected function setup_hooks(): void { + add_action( 'init', array( $this, 'register_block_patterns' ) ); // Priority 11 needed for block.json translations of title and description. add_action( 'init', array( $this, 'register_blocks' ), 11 ); } @@ -72,4 +73,73 @@ public function register_blocks(): void { ); } } + + + /** + * Register block patterns. + * + * This method registers multiple different block-patterns for GatherPress. + * + * @since 1.0.0 + * @see https://developer.wordpress.org/reference/functions/register_block_pattern/ + * + * @return void + */ + public function register_block_patterns(): void { + + /** + * Made to be used with the 'template' parameter + * when registering the 'gatherpress_event' post type + * and will not be visible to the editor at any point. + */ + register_block_pattern( + 'gatherpress/event-template', + array( + 'title' => __( 'Invisible Event Template Block Pattern', 'gatherpress' ), + // Even this paragraph seems useless, it's not. + // It is the entry point for all our hooked blocks + // and as such absolutely important! + 'content' => '', // Other blocks are hooked-in here. + 'inserter' => false, + 'source' => 'plugin', + ) + ); + + /** + * Made to be used with the 'template' parameter + * when registering the 'gatherpress_venue' post type + * and will not be visible to the editor at any point. + */ + register_block_pattern( + 'gatherpress/venue-template', + array( + 'title' => __( 'Invisible Venue Template Block Pattern', 'gatherpress' ), + // Even this paragraph seems useless, it's not. + // It is the entry point for all our hooked blocks + // and as such absolutely important! + 'content' => '

', // Other blocks are hooked-in here. + 'inserter' => false, + 'source' => 'plugin', + ) + ); + + /** + * Mainly for use with the 'venue-details' block, + * which is a group block under the hood + * and uses this pattern as innerBlocks template, + * it will not be visible to the editor at any point. + */ + register_block_pattern( + 'gatherpress/venue-details', + array( + 'title' => __( 'Invisible Venue Details Block Pattern', 'gatherpress' ), + // Even this post-title seems useless, it's not. + // It is the entry point for all our hooked blocks + // and as such absolutely important! + 'content' => '', // Other blocks are hooked-in here. + 'inserter' => false, + 'source' => 'plugin', + ) + ); + } } diff --git a/includes/core/classes/class-event-setup.php b/includes/core/classes/class-event-setup.php index 0a94f3448..9f550060b 100644 --- a/includes/core/classes/class-event-setup.php +++ b/includes/core/classes/class-event-setup.php @@ -128,6 +128,7 @@ public function register_post_type(): void { ), ), array( 'gatherpress/rsvp-response' ), + // The future! // array( 'core/pattern', array( 'slug' => 'gatherpress/event-template' ) ), // phpcs:ignore Squiz.PHP.CommentedOutCode.Found ! ), 'menu_position' => 4, 'supports' => array( diff --git a/includes/core/classes/class-venue.php b/includes/core/classes/class-venue.php index cf45b0553..d8f348188 100644 --- a/includes/core/classes/class-venue.php +++ b/includes/core/classes/class-venue.php @@ -132,6 +132,7 @@ public function register_post_type(): void { 'menu_icon' => 'dashicons-location', 'template' => array( array( 'gatherpress/venue' ), + // The future! // array( 'core/pattern', array( 'slug' => 'gatherpress/venue-template' ) ), // phpcs:ignore Squiz.PHP.CommentedOutCode.Found ! ), 'has_archive' => true, 'rewrite' => array( @@ -230,6 +231,8 @@ public function register_taxonomy(): void { 'show_in_rest' => true, ) ); + // It is necessary to make this taxonomy visible on event posts, within REST responses. + register_taxonomy_for_object_type( self::TAXONOMY, Event::POST_TYPE ); } /** diff --git a/src/panels/event-settings/index.js b/src/panels/event-settings/index.js index 3f487965c..dfe9482c2 100644 --- a/src/panels/event-settings/index.js +++ b/src/panels/event-settings/index.js @@ -8,7 +8,7 @@ import { __experimentalVStack as VStack, } from '@wordpress/components'; import { registerPlugin } from '@wordpress/plugins'; -import { PluginDocumentSettingPanel } from '@wordpress/edit-post'; +import { PluginDocumentSettingPanel } from '@wordpress/editor'; /** * Internal dependencies. @@ -22,6 +22,7 @@ import MaxAttendanceLimitPanel from './max-attendance-limit'; import NotifyMembersPanel from './notify-members'; import OnlineEventLinkPanel from './online-link'; import VenueSelectorPanel from './venue-selector'; +import { EventPluginDocumentSettings } from './slot'; /** * A settings panel for event-specific settings in the block editor. @@ -44,6 +45,9 @@ const EventSettings = () => { initialOpen={true} className="gatherpress-event-settings" > + {/* Extendable entry point for "Event Settings" panel. */} + + diff --git a/src/panels/event-settings/slot.js b/src/panels/event-settings/slot.js new file mode 100644 index 000000000..0c0285cca --- /dev/null +++ b/src/panels/event-settings/slot.js @@ -0,0 +1,17 @@ +/** + * Defines an extensibility slot for the "Event Settings" panel. + */ + +/** + * WordPress dependencies + */ +import { createSlotFill, PanelRow } from '@wordpress/components'; + +export const { Fill, Slot } = createSlotFill('EventPluginDocumentSettings'); +export const EventPluginDocumentSettings = ({ children, className }) => ( + + {children} + +); + +EventPluginDocumentSettings.Slot = Slot; diff --git a/src/panels/venue-settings/fill.js b/src/panels/venue-settings/fill.js new file mode 100644 index 000000000..eaa3ab457 --- /dev/null +++ b/src/panels/venue-settings/fill.js @@ -0,0 +1,24 @@ +/** + * Fill the "Venue Settings" slot into the "Event Settings" slot by default, + * so that venue changes can be made from within an event context. + */ + +/** + * WordPress dependencies + */ +import { Fill } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import { VenuePluginDocumentSettings } from './slot'; + +export default function VenuePluginFill() { + return ( + <> + + + + + ); +} diff --git a/src/panels/venue-settings/index.js b/src/panels/venue-settings/index.js index a18c55fd0..bbdbc5b1e 100644 --- a/src/panels/venue-settings/index.js +++ b/src/panels/venue-settings/index.js @@ -8,13 +8,15 @@ import { __experimentalVStack as VStack, } from '@wordpress/components'; import { registerPlugin } from '@wordpress/plugins'; -import { PluginDocumentSettingPanel } from '@wordpress/edit-post'; +import { PluginDocumentSettingPanel } from '@wordpress/editor'; /** * Internal dependencies. */ import { isVenuePostType } from '../../helpers/venue'; import VenueInformationPanel from './venue-information'; +import { VenuePluginDocumentSettings } from './slot'; +import VenuePluginFill from './fill'; /** * VenueSettings Component @@ -35,6 +37,9 @@ const VenueSettings = () => { initialOpen={true} className="gatherpress-venue-settings" > + {/* Extendable entry point for "Venue Settings" panel. */} + + @@ -56,6 +61,10 @@ registerPlugin('gatherpress-venue-settings', { render: VenueSettings, }); +registerPlugin('gatherpress-venue-settings-at-events', { + render: VenuePluginFill, +}); + /** * Toggle Venue Settings Panel * diff --git a/src/panels/venue-settings/slot.js b/src/panels/venue-settings/slot.js new file mode 100644 index 000000000..4f92d6efb --- /dev/null +++ b/src/panels/venue-settings/slot.js @@ -0,0 +1,17 @@ +/** + * Defines as extensibility slot for the "Venue Settings" panel. + */ + +/** + * WordPress dependencies + */ +import { createSlotFill, PanelRow } from '@wordpress/components'; + +export const { Fill, Slot } = createSlotFill('VenuePluginDocumentSettings'); +export const VenuePluginDocumentSettings = ({ children, className }) => ( + + {children} + +); + +VenuePluginDocumentSettings.Slot = Slot;