Post Export: Preparred_Post

Greyd\\Preparred_Post is a data abstraction for WordPress posts that you can reliably export from one site and import into another. The class wraps a post’s core fields and augments them with everything needed for a safe round-trip: post meta, taxonomy terms, nested references found inside content or meta, attached media, language metadata, and optional menu resolution. It is used by Post Export and Global Content.

The class accepts a WP_Post, a post ID, or a plain array. During construction, it gathers and normalizes all required data. It also rewrites references to nested posts and terms in the block content into stable placeholders, so you can restore those references on import even if IDs differ across sites.

Architecture and flow

You instantiate Preparred_Post with a post (ID/object/array) and optional export_arguments. The constructor coerces the input into a WP_Post and then populates the public properties. The preparation sequence runs in a fixed order:

  • Nested posts: It scans post_content using patterns from get_nested_post_patterns(). For each referenced post (by ID or slug/type), it collects minimal info and replaces the in-content reference with a placeholder {{<post_id>}}. This covers templates, forms, attachments, and other embedded resources.
  • Nested terms: It registers temporary dynamic taxonomies and scans post_content for taxonomy references (including JSON structures such as taxQuery and advancedFilter). It replaces found term IDs with placeholders like {{t_<term_id>}} and stores the referenced terms for later restoration.
  • Dynamic strings: It runs Post_Export_Helper::replace_dynamic_strings() over post_content to normalize environment-dependent strings.
  • Post meta: It pulls all post meta, skips blacklisted or “maybe skip” keys, unserializes values, lets filters adjust values, and stores the result in meta. During export/import, this ensures consistent treatment of complex meta.
  • Terms: It fetches all assigned terms per taxonomy using a low-level helper (Helper::get_post_taxonomy_terms) to avoid language-related filter side effects. If the post represents a dynamic taxonomy (via posttype_settings meta), it limits preparation to that taxonomy’s terms.
  • Media: If the post is an attachment, it records filename, absolute path, and URL, so importers can move the file or relink it.
  • Language: If a translation tool is detected, it records the language code, tool metadata, and—when export_arguments['translations'] is enabled—the IDs of available translations for the post.
  • Menus (optional): When export_arguments['resolve_menus'] is true, it rewrites wp:navigation-link blocks to custom links by expanding id based references into plain URLs, removing tool-specific attributes that won’t survive across sites.

Throughout the process, the class logs progress using do_action( 'greyd_post_export_log', ... ) hooks, and exposes several filters to alter meta and content during preparation.

Import and conflict behavior flags

Two properties describe what should happen later during import:

  • conflict_action controls how to react if a post with the same post_name and post_type already exists on the target site:
    • keep (default): keep the existing post and insert the new one with a new ID.
    • replace: replace the existing post with the new one.
    • skip: skip importing this post.
  • import_action communicates the desired final state after import:
    • insert (default): insert the post (or update if the process supports it).
    • draft: set post status to draft.
    • trash: move to trash.
    • delete: delete permanently.

Note: Preparred_Post does not execute import logic by itself. It only prepares data and signals intent via the properties above. Your importer applies these flags.

Placeholder strategy

The placeholder strategy is central to portability. IDs in content or JSON attributes are converted into {{<id>}} (posts) and {{t_<term_id>}} (terms). On import, you resolve placeholders to target-site IDs based on slugs, types, or other lookup rules, then replace placeholders back to concrete IDs.

Limitations and notes

The class avoids opinionated import behavior. It focuses on consistent extraction and marking of dependencies. Because it skips blacklisted meta and may normalize strings, always check filters and helper callbacks if you rely on site-specific meta. Menu resolution only runs when explicitly enabled. Translation handling depends on the active translation tool and helper functions in Post_Export_Helper.

Developer reference

Below is a reference of the public properties and methods you’ll interact with when preparing and transporting posts.

Public properties

  • ID (int): The source post ID.
  • post_name (string): Post slug.
  • post_title (string): Post title.
  • post_type (string, default post): Post type.
  • post_date (string Y-m-d H:i:s): Local publish time.
  • post_date_gmt (string Y-m-d H:i:s): GMT publish time.
  • post_content (string): Post content, after placeholder replacement and optional menu resolution.
  • guid (string): GUID as stored with the post.
  • post_author (int): Author user ID.
  • post_excerpt (string): Excerpt.
  • post_status (string, default publish): Status.
  • comment_status (string, default open): Comments open/closed.
  • ping_status (string, default open): Pings open/closed.
  • post_password (string): Post password in plain text.
  • to_ping (string): URLs queued to be pinged.
  • pinged (string): URLs already pinged.
  • post_modified (string Y-m-d H:i:s): Local modified time.
  • post_modified_gmt (string Y-m-d H:i:s): GMT modified time.
  • post_content_filtered (string): Utility field for content filters.
  • post_parent (int): Parent ID.
  • menu_order (int): Menu order.
  • post_mime_type (string): Attachment MIME type.
  • comment_count (int): Cached count.
  • filter (string|null): Internal WordPress filter marker.
  • meta (array): All prepared post meta. Keys are meta keys; values are arrays of values (unserialized and filtered). Blacklisted and skipped meta are excluded.
  • terms (array): Assigned terms grouped by taxonomy. Each taxonomy key maps to a list of term arrays carrying the minimal importable details (IDs, slugs, hierarchy included via get_term_parents()).
  • nested (array): Referenced posts discovered in post_content. Keys are post IDs. Values contain: ID, post_name, post_type, front_url.
  • nested_terms (array): Referenced terms discovered in post_content. Keys are term IDs; values are WP_Term objects or null if missing.
  • media (array): Only for attachments; contains: name, path, url.
  • language (array): Language metadata if a translation tool is active: code, tool, post_ids, args.
  • export_arguments (array): Export options; constructor merges passed defaults with any values already set on the instance.
  • conflict_action (string, one of keep|replace|skip, default keep): Desired conflict handling on import.
  • import_action (string, one of insert|draft|trash|delete, default insert): Desired action after import.

Public methods

__construct( $post, $export_arguments = array() )

Accepts a post ID, WP_Post, object, or array and optional export arguments. Coerces input to a WP_Post, initializes core fields, merges export_arguments, and runs the preparation pipeline in order: prepare_nested_posts(), prepare_nested_terms(), prepare_strings(), prepare_meta(), prepare_terms(), prepare_media(), prepare_language(), prepare_menus().

Notes: If $post is invalid or missing an ID, the constructor returns early and the instance remains unprepared.

prepare_nested_posts(): void

Scans post_content for references to posts using patterns from get_nested_post_patterns( $this->ID, $this ). For each match, resolves the target by ID or by { post_name, post_type }, replaces content references with {{<ID>}}, and records minimal info in nested. Attachments get their front URL via wp_get_attachment_url(); other post types use get_permalink().

Logs: Emits granular debug lines via greyd_post_export_log.

prepare_nested_terms(): void

Registers dynamic taxonomies to stabilize parsing. Scans post_content for term references. It handles raw markup patterns as well as JSON fragments such as "taxQuery": {...} and "advancedFilter": [...]. It replaces each found term ID with {{t_<term_id>}} and records the term objects in nested_terms (or null if missing).

Why: This makes taxonomy-dependent content portable across sites with different term IDs.

prepare_strings(): void

Normalizes environment-dependent strings in post_content by delegating to Post_Export_Helper::replace_dynamic_strings( $content, $post_id ).

prepare_meta(): void

Loads all meta via get_post_meta( $this->ID ), skips blacklisted keys (Post_Export_Helper::blacklisted_meta()), applies “maybe skip” logic (Post_Export_Helper::maybe_skip_meta_option()), unserializes values, and exposes a filter for each meta key: apply_filters( 'greyd_export_post_meta-' . $meta_key, $value, $post_id, $export_arguments ). Adds each (possibly filtered) value to meta[ $meta_key ][].

prepare_terms(): void

Populates terms with assigned terms per taxonomy. When the post defines posttype_settings[is_taxonomy], it limits preparation to that taxonomy. Otherwise, it enumerates taxonomies and fetches terms using Helper::get_post_taxonomy_terms( $post_id, $taxonomy ) to avoid language filter interference. It resolves parent chains via get_term_parents() to preserve hierarchy.

get_term_parents( WP_Term $term, array $prepared ): WP_Term

Recursively resolves and rewrites a term’s parent to ensure parent terms are included and correctly referenced in terms. It prevents cycles with the $prepared list and logs each resolution step.

prepare_media(): void

If the current post is an attachment, it sets media with the file name, absolute path from get_attached_file( $ID ), and URL via wp_get_attachment_url( $ID ). This information allows importers to move or relink files.

prepare_language(): void

Initializes language with the detected translation tool (via Post_Export_Helper::get_translation_tool()). If a tool is active, it stores language details for the post and, when export_arguments['translations'] is true, collects translation post IDs via Post_Export_Helper::get_translated_post_ids( $this ).

prepare_menus(): void

Runs only when export_arguments['resolve_menus'] is truthy. It parses post_content for wp:navigation-link blocks and rewrites them to custom links by resolving referenced IDs to URLs, removing tool-specific attributes (type, id), and re-encoding the block with minimal attributes. Applies the filter greyd_post_export_resolve_menus to the final content.

Usage guidance

  • Build a Preparred_Post as the first step of any export. The instance contains everything you need to serialize it to JSON and ship it to another site.
  • On import, use post_name + post_type for lookups, then resolve placeholders in post_content and meta using your target-site IDs for posts and terms.
  • Respect conflict_action and import_action when applying changes to the target site.
  • If your content uses Navigation blocks and you want stable custom links on import, set resolve_menus in export_arguments.
  • If your project relies on translations, enable translations in export_arguments and integrate the language details during import.