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;