Skip to content

Latest commit

 

History

History
101 lines (72 loc) · 5.61 KB

cbt-block-pattern-issue-rca.md

File metadata and controls

101 lines (72 loc) · 5.61 KB

Create Block Theme: Block Pattern Reference RCA

RCA

Confirmed: high-severity content-integrity bug in Create Block Theme 2.10.1.

Terminology: ordinary “unsynced patterns” are normally copied inline and do not retain database IDs. The broken references are usually instances of synced patterns that become dangling after their wp_block source is deleted.

Failure chain

  1. Save Patterns is enabled by default in src/editor-sidebar/save-panel.js:168-178.
  2. /save calls CBT_Theme_Patterns::add_patterns_to_theme() at includes/class-create-block-theme-api.php:395-400.
  3. Each wp_block is written to patterns/*.php.
  4. replace_local_pattern_references() only searches wp_template and wp_template_part at theme-patterns.php:132-150.
  5. It replaces references only in theme pattern/template files at theme-patterns.php:152-163.
  6. Ordinary posts, pages and CPTs retain <!-- wp:block {"ref":ID} /-->.
  7. The source is permanently deleted with wp_delete_post( $pattern->id, true ) at theme-patterns.php:248-249.
  8. Core subsequently calls get_post( ID ); if absent, core/block renders nothing and the editor reports “Block has been deleted or is unavailable.”

Root cause

The deletion boundary assumes every caller belongs to a theme template. That assumption is false: synced patterns can be inserted into any post type with block content.

The original implementation in PR #675 covered only template references. PR #790 later removed the sync-status distinction and made deletion unconditional for all patterns. No test asserts referential integrity in posts/pages; the existing integration test explicitly accepts source deletion.

Contributing defects

  • Exact str_replace() only handles canonical wp:block {"ref":ID} markup. It misses extra attributes, spacing and pattern overrides.
  • template-parts/*.html is hard-coded, while current WordPress returns parts/ from get_block_theme_folders().
  • Files are written and sources deleted incrementally; failures can leave a partial migration.
  • Filesystem writes and wp_delete_post() results are not checked.
  • sanitize_title_with_dashes() creates percent-encoded pattern slugs under the Finnish locale; the current site emits invalid-slug notices. This is adjacent but should be fixed before slug migration is trusted.

Current-site confirmation

The read-only audit found:

  • 5 broken references
  • 17 affected URLs
  • Includes draft page 34228, templates and template parts
  • Parent plugin: Create Block Theme 2.10.1, WordPress 7.0.2

No data was changed.

What this workaround does

wpcli-create-block-theme.php:

  • Records ID→theme-slug mappings before parent save deletes the rows.
  • Runs the parent save.
  • Scans every non-revision post afterward and changes ID references to core/pattern slug references.
  • Retains the mapping for interrupted-save repair.

This protects only saves performed through its WP-CLI command. The Site Editor’s native /save path remains vulnerable.

It should not be transplanted unchanged because it:

  • Runs after destructive deletion.
  • Uses the same fragile exact-string replacement.
  • Cannot preserve pattern override attributes.
  • Converts DB-synced patterns into theme patterns, changing their semantics and making post content dependent on the active theme.

Recommended native fix

The safest immediate upstream fix is not to delete DB-backed synced patterns until WordPress supports file-backed synced patterns (Gutenberg #59272).

  1. Restore wp_pattern_sync_status to the pattern model.
  2. Continue exporting files.
  3. Restrict existing ID→slug conversion to theme-owned files.
  4. Delete only genuinely unsynced patterns.
  5. Keep synced and partially-synced wp_block rows so post/page/CPT references and overrides remain valid.
  6. Replace the hard-coded template-parts path with get_block_theme_folders().
  7. Update the Save Patterns help text to explain that synced patterns remain database-backed.
  8. Add regression tests:
    • Synced pattern referenced by page remains renderable.
    • Draft/private/custom-post callers remain valid.
    • Partial-sync overrides survive.
    • Unsynced patterns still export and delete.
    • Template-part handling uses parts/.
    • Failed writes never delete source posts.

This is the smallest root-cause fix and preserves content semantics.

If maintainers explicitly want destructive conversion

To integrate the wrapper’s exact behavior natively:

  1. Put it in CBT_Theme_Patterns, not REST, CLI, or the proposed CBT_Theme_Save service, so every caller shares it.
  2. Build the complete ID→slug map before modifying anything.
  3. Write and validate all pattern files.
  4. Parse blocks recursively and migrate every non-revision post type using wp_update_post()—no raw str_replace().
  5. Reject references carrying content/overrides; retain their wp_block source because conversion would lose data.
  6. Migrate actual template directories returned by get_block_theme_folders().
  7. Verify no old references remain in database content or generated files.
  8. Only then delete source wp_block posts.
  9. Add page, post, CPT, nested-reference, multiple-reference, formatting and failure-path tests.
  10. Make the UI explicitly say this converts synced patterns into theme patterns.

Existing broken references cannot be repaired automatically because their ID→slug mapping is already gone. Keep the workaround’s explicit-map/backup recovery tooling separate from the prevention PR.

Implementation should be made against the upstream repository: ../create-block-theme is a v2.10.1 distribution directory whose Git root is the unrelated VVV site repository.