WP Manifestindependent plugin directory
manifest / editor / gkd-post-include

GKD Post Include

WordPress Gutenberg block that embeds another post's content, picked via taxonomy → term → post

by AlwaysRichard · github.com/alwaysrichard/gkd-post-include

★ 0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/alwaysrichard/gkd-post-include/archive/refs/heads/master.zip

A WordPress Gutenberg block that embeds the full content of another post into the current post/page, picked via a taxonomy → term → post flow. It's a dynamic block — the included content is rendered on every page load, so edits to the source post stay in sync automatically.

Features

  • Taxonomy → Term → Post picker: pick any public, REST-exposed taxonomy, a term within it, and a post carrying that term — across every post type the taxonomy applies to.
  • Live sync: content is pulled from the source post at render time via the_content, not baked into the block on save.
  • Recursion guard: refuses to render if the source post is the current post, or if the source post (directly or transitively, up to 5 levels deep) includes the current post — skips with an HTML comment instead of looping.
  • Draft-friendly: source posts don't need to be published themselves — the page containing the block is what actually gates visibility. An "Include Drafts" switch controls whether draft posts show up in the picker.
  • Optional section heading: show the source post's title above the included content, in your choice of format (H1, H2, H3, Bold, Underline, Italic).
  • Optional featured image: show the source post's featured image, positioned above or below the title.

Requirements

  • WordPress 6.0+
  • PHP 8.0+
  • Node.js 18+ (for building — see Build)

Installation

  1. Clone/copy this plugin into wp-content/plugins/gkd-post-include
  2. Build it (see below)
  3. Activate GKD Post Include in WordPress Admin → Plugins

Build

This plugin uses @wordpress/scripts with a custom webpack.config.js (single-block entry, avoids the block.json auto-discovery filename collision documented in gkd_gallery/tools/WEBPACK_FIX.md).

npm install
npm run build    # Production build → blocks/PostInclude/build/
npm run start    # Development mode with live reloading

If your local machine's Node/npm is too old for @wordpress/scripts (this plugin was originally built against a dev box running Node 7 — a full generation behind), build on a server instead:

tools/push-to-server.sh   # rsyncs source to alwaysvw.net
ssh root@alwaysvw.net
cd /home/alwaysvw.net/public_html/wp-content/plugins/gkd-post-include
npm install && npm run build

tools/ is git-ignored — it's deploy tooling for this specific setup, not part of the plugin.

Block Usage

  1. Add the Post Include block to any post or page.
  2. Pick a Taxonomy, then a Term, then a Post — the post list is scoped to whatever post type(s) the taxonomy applies to, and excludes the post you're currently editing.
  3. Once a post is selected, the block shows a preview (title, status, excerpt) and a Change selection button to redo the picker.
  4. Three switches sit in the top-right of the block, next to the "Post Include" title:
    • Display Title — toggles whether the source post's title renders as a heading above the included content, and lets you pick its format (as dropdown: H1 / H2 / H3 / Bold / Underline / Italic).
    • Display Featured Image — toggles whether the source post's featured image renders, and lets you pick whether it goes Above or Below the title.
    • Include Drafts — widens the post picker to include draft posts (pending/private/future posts are always included; only draft is gated by this switch).

Block Attributes

Attribute Type Default Purpose
taxonomy string "" Taxonomy slug — retained so the editor can restore picker state.
termId integer 0 Selected term ID — same purpose.
postId integer 0 Selected post ID — the only attribute required at render time.
includeDrafts boolean false Whether the editor's post picker lists draft posts.
includeTitle boolean true Whether to render the source post's title as a heading.
titleFormat string "h2" h1 | h2 | h3 | bold | underline | italic.
displayFeaturedImage boolean false Whether to render the source post's featured image.
featuredImagePosition string "above" above | below (relative to the title).

taxonomy/termId aren't used at render time — they just let the editor UI restore the picker's "Selected post: Taxonomy → Term" context without re-deriving it.

Rendering Behavior

  • If postId is unset, or the source post can't be found, is trash, or is auto-draft, the block renders nothing but a discreet `` comment — never an error.
  • Otherwise: fetch the post, run post_content through apply_filters( 'the_content', ... ), and wrap it:
    <div class="gkd-post-include" data-gkd-post-include-source="123">
        <div class="gkd-post-include__featured-image">...</div>
        <h2 class="gkd-post-include__title">Source Post Title</h2>
        ...filtered content...
    </div>

    (the featured image only renders if the source post has one; its position swaps with the title's per featuredImagePosition)

  • Recursion guard: before rendering, the block checks whether the source post is the current post, and whether including the source post would create a cycle — i.e. whether the source post, directly or transitively (up to 5 levels of nested gkd/post-include blocks), includes the current post back. Either case skips rendering with an HTML comment rather than infinite-looping.

Architecture

gkd-post-include.php                # Plugin entry point — dynamic block registration via glob()
blocks/PostInclude/
  ├── block.json                    # Block metadata (Gutenberg Block API v3)
  ├── block_init.php                # PHP class autoloader
  ├── index.jsx                     # Block editor UI (React)
  ├── style.scss                    # Frontend styles
  ├── editor.scss                   # Editor-only styles
  ├── Renderer.php                  # WordPress render_callback interface
  ├── Engine.php                    # Thin adapter
  └── src/
      ├── main/Main.php             # Normalization, recursion guard, orchestration
      └── impl/
          ├── Queries.php           # Walks post content for nested gkd/post-include blocks
          └── HtmlBuilder.php       # Wrapper div + optional title heading + optional featured image

Rendering Flow

WordPress → Renderer::render()
         → Engine::run()
         → Main::run()
              → normalize attributes
              → self-reference / recursion checks
              → fetch + validate source post
              → apply_filters( 'the_content', ... )
              → HtmlBuilder::build()

Namespace

Everything lives under gkd_pi\ (gkd_pi\WP_Interface for Renderer/Engine, gkd_pi\Impl for Main/Queries/HtmlBuilder) — namespaced separately from gkd_gallery's gkd\ and gkd_tagcloud's gkd_tc\ so all three plugins can coexist on the same site without collisions.

License

GPL-2.0-or-later