Plugin Directory

Changeset 3416925


Ignore:
Timestamp:
12/11/2025 03:38:55 AM (4 months ago)
Author:
courane01
Message:

Release v1.1.2: Editor UI improvements and template fixes

New Features:

  • Add 'Default' template option in template chooser
  • Add comprehensive logging for debugging

Improvements:

  • Remove duplicate format dropdown from sidebar
  • Move status counter to editor notice
  • Clarify 'Standard (Single Template)' option
  • Ensure 'Single' template appears in chooser
  • Fix REST API template value responses

Bug Fixes:

  • Fix standard posts showing incorrect format templates
  • Fix template chooser displaying all available templates
  • Fix editor showing stale template values
Location:
post-formats-for-block-themes/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • post-formats-for-block-themes/trunk/build/index.asset.php

    r3413728 r3416925  
    1 <?php return array('dependencies' => array('react', 'wp-a11y', 'wp-blocks', 'wp-components', 'wp-data', 'wp-edit-post', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins'), 'version' => 'd71d97bec109e533dfa5');
     1<?php return array('dependencies' => array('react', 'wp-a11y', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins'), 'version' => 'aee0db3c8e30a508c90e');
  • post-formats-for-block-themes/trunk/build/index.js

    r3413728 r3416925  
    1 (()=>{"use strict";const t=window.React,e=window.wp.plugins,n=(window.wp.editPost,window.wp.components),a=window.wp.data,r=window.wp.element,o=window.wp.i18n,s=window.wp.a11y,i=window.wp.hooks,p=window.wp.blocks,m=()=>{const[e,i]=(0,r.useState)(!1),[m,c]=(0,r.useState)(!1),{isNewPost:d,currentFormat:l,postType:f}=(0,a.useSelect)(t=>{const e=t("core/editor"),n=e.getCurrentPost();return{isNewPost:!n.id||"auto-draft"===n.status,currentFormat:e.getEditedPostAttribute("format")||"standard",postType:n.type}},[]),{editPost:u}=(0,a.useDispatch)("core/editor"),{insertBlocks:w}=(0,a.useDispatch)("core/block-editor");(0,r.useEffect)(()=>{d&&"post"===f&&!m&&window.pfbtData&&setTimeout(()=>{i(!0),c(!0)},500)},[d,f,m]);if(!e||!window.pfbtData)return null;const g=window.pfbtData.formats,h=Object.entries(g).sort((t,e)=>"standard"===t[0]?-1:"standard"===e[0]?1:t[1].name.localeCompare(e[1].name));return(0,t.createElement)(n.Modal,{title:(0,o.__)("Choose Post Format","post-formats-for-block-themes"),onRequestClose:()=>i(!1),className:"pfpu-format-modal"},(0,t.createElement)("div",{className:"pfpu-format-grid"},h.map(([e,a])=>(0,t.createElement)(n.Card,{key:e,className:"pfpu-format-card"},(0,t.createElement)(n.CardBody,null,(0,t.createElement)(n.Button,{onClick:()=>(t=>{if(u({format:t}),"standard"!==t&&window.pfbtData.formats[t]){const e=window.pfbtData.formats[t];((t,e)=>{if(!window.pfbtData.patterns||!window.pfbtData.patterns[t])return;const n=window.pfbtData.patterns[t],a=(0,p.parse)(n);a.length>0&&e(a,0,void 0,!1)})(t,w),(0,s.speak)((0,o.sprintf)(/* translators: %s: Format name */ /* translators: %s: Format name */
    2 (0,o.__)("Selected %s format. Pattern inserted.","post-formats-for-block-themes"),e.name),"polite")}i(!1)})(e),className:"pfpu-format-button",variant:"standard"===e?"primary":"secondary"},(0,t.createElement)("span",{className:`dashicons dashicons-${a.icon}`,"aria-hidden":"true"}),(0,t.createElement)("span",{className:"pfpu-format-name"},a.name)),(0,t.createElement)("p",{className:"pfpu-format-description"},a.description))))))};if((0,e.registerPlugin)("post-formats-for-block-themes",{render:()=>(0,t.createElement)(t.Fragment,null,(0,t.createElement)(m,null))}),(0,i.addFilter)("editor.BlockEdit","pfpu/status-paragraph-counter",e=>n=>{const{name:a,attributes:r,setAttributes:s}=n;if("core/paragraph"!==a||!r.className?.includes("status-paragraph"))return(0,t.createElement)(e,{...n});const i=280-(r.content||"").replace(/<[^>]*>/g,"").length,p=i<0;return(0,t.createElement)("div",{className:"pfpu-status-paragraph-wrapper"},(0,t.createElement)(e,{...n}),(0,t.createElement)("div",{className:`pfpu-char-counter ${p?"is-over-limit":""} ${i<=20?"is-warning":""}`,"aria-live":"polite","aria-atomic":"true"},(0,t.createElement)("span",null,(0,o.sprintf)(/* translators: %d: Remaining characters */ /* translators: %d: Remaining characters */
    3 (0,o.__)("%d characters remaining","post-formats-for-block-themes"),i))))}),"undefined"!=typeof document){const t=document.createElement("style");t.textContent="\n\t.pfpu-format-modal {\n\t\tmax-width: 800px;\n\t}\n\n\t.pfpu-format-grid {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n\t\tgap: 1rem;\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-format-card {\n\t\ttext-align: center;\n\t}\n\n\t.pfpu-format-button {\n\t\twidth: 100%;\n\t\theight: auto;\n\t\tpadding: 1rem;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tgap: 0.5rem;\n\t}\n\n\t.pfpu-format-button .dashicons {\n\t\tfont-size: 2rem;\n\t\twidth: 2rem;\n\t\theight: 2rem;\n\t}\n\n\t.pfpu-format-name {\n\t\tfont-weight: 600;\n\t}\n\n\t.pfpu-format-description {\n\t\tfont-size: 0.875rem;\n\t\tcolor: #757575;\n\t\tmargin-top: 0.5rem;\n\t}\n\n\t.pfpu-format-change-actions {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: 0.5rem;\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-status-validator {\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-status-paragraph-wrapper {\n\t\tposition: relative;\n\t}\n\n\t.pfpu-char-counter {\n\t\tposition: absolute;\n\t\tbottom: -30px;\n\t\tright: 0;\n\t\tfont-size: 0.875rem;\n\t\tcolor: #757575;\n\t}\n\n\t.pfpu-char-counter.is-warning {\n\t\tcolor: #f0b849;\n\t\tfont-weight: 600;\n\t}\n\n\t.pfpu-char-counter.is-over-limit {\n\t\tcolor: #d63638;\n\t\tfont-weight: 600;\n\t}\n",document.head.appendChild(t)}})();
     1(()=>{"use strict";const t=window.React,e=window.wp.plugins,a=window.wp.components,n=window.wp.data,r=window.wp.element,o=window.wp.i18n,s=window.wp.a11y,i=window.wp.hooks,p=window.wp.blocks,l=()=>{const[e,i]=(0,r.useState)(!1),[l,m]=(0,r.useState)(!1),{isNewPost:c,currentFormat:d,postType:u}=(0,n.useSelect)(t=>{const e=t("core/editor"),a=e.getCurrentPost();return{isNewPost:!a.id||"auto-draft"===a.status,currentFormat:e.getEditedPostAttribute("format")||"standard",postType:a.type}},[]),{editPost:f}=(0,n.useDispatch)("core/editor"),{insertBlocks:b}=(0,n.useDispatch)("core/block-editor");(0,r.useEffect)(()=>{c&&"post"===u&&!l&&window.pfbtData&&setTimeout(()=>{i(!0),m(!0)},500)},[c,u,l]);if(!e||!window.pfbtData)return null;const h=window.pfbtData.formats,g=Object.entries(h).map(([t,e])=>"standard"===t?[t,{...e,name:(0,o.__)("Standard (Single Template)","post-formats-for-block-themes"),description:(0,o.__)("Default post format using the Single template","post-formats-for-block-themes")}]:[t,e]).sort((t,e)=>"standard"===t[0]?-1:"standard"===e[0]?1:t[1].name.localeCompare(e[1].name));return(0,t.createElement)(a.Modal,{title:(0,o.__)("Choose Post Format","post-formats-for-block-themes"),onRequestClose:()=>i(!1),className:"pfpu-format-modal"},(0,t.createElement)("div",{className:"pfpu-format-grid"},g.map(([e,n])=>(0,t.createElement)(a.Card,{key:e,className:"pfpu-format-card"},(0,t.createElement)(a.CardBody,null,(0,t.createElement)(a.Button,{onClick:()=>(t=>{if(f({format:t,template:"standard"===t?"":`single-format-${t}`}),"standard"!==t&&window.pfbtData.formats[t]){const e=window.pfbtData.formats[t];((t,e)=>{if(!window.pfbtData.patterns||!window.pfbtData.patterns[t])return;const a=window.pfbtData.patterns[t],n=(0,p.parse)(a);n.length>0&&e(n,0,void 0,!1)})(t,b),(0,s.speak)(sprintf(/* translators: %s: Format name */ /* translators: %s: Format name */
     2(0,o.__)("Selected %s format. Pattern inserted.","post-formats-for-block-themes"),e.name),"polite")}i(!1)})(e),className:"pfpu-format-button",variant:"standard"===e?"primary":"secondary"},(0,t.createElement)("span",{className:`dashicons dashicons-${n.icon}`,"aria-hidden":"true"}),(0,t.createElement)("span",{className:"pfpu-format-name"},n.name)),(0,t.createElement)("p",{className:"pfpu-format-description"},n.description))))))},m=()=>{const{createNotice:t,removeNotice:e}=(0,n.useDispatch)("core/notices"),{currentFormat:a,blocks:s}=(0,n.useSelect)(t=>{const e=t("core/editor"),a=t("core/block-editor");return{currentFormat:e.getEditedPostAttribute("format")||"standard",blocks:a.getBlocks()}},[]);return(0,r.useEffect)(()=>{if("status"!==a)return void e("pfbt-status-char-count");const n=s.find(t=>"core/paragraph"===t.name&&t.attributes.className?.includes("status-paragraph"));if(!n)return void e("pfbt-status-char-count");const r=(n.attributes.content||"").replace(/<[^>]*>/g,"").length;r>280?t("error",sprintf(/* translators: %d: Current character count */ /* translators: %d: Current character count */
     3(0,o.__)("%d / 280 characters - Status updates should be 280 characters or less","post-formats-for-block-themes"),r),{id:"pfbt-status-char-count",isDismissible:!1}):r>=260?t("warning",sprintf(/* translators: %d: Current character count */ /* translators: %d: Current character count */
     4(0,o.__)("%d / 280 characters - Approaching limit","post-formats-for-block-themes"),r),{id:"pfbt-status-char-count",isDismissible:!1}):e("pfbt-status-char-count")},[a,s,t,e]),null};if((0,e.registerPlugin)("post-formats-for-block-themes",{render:()=>(0,t.createElement)(t.Fragment,null,(0,t.createElement)(l,null),(0,t.createElement)(m,null))}),(0,i.addFilter)("editor.BlockEdit","pfpu/status-paragraph-counter",e=>a=>{const{name:n,attributes:r,setAttributes:s}=a;if("core/paragraph"!==n||!r.className?.includes("status-paragraph"))return(0,t.createElement)(e,{...a});const i=280-(r.content||"").replace(/<[^>]*>/g,"").length,p=i<0;return(0,t.createElement)("div",{className:"pfpu-status-paragraph-wrapper"},(0,t.createElement)(e,{...a}),(0,t.createElement)("div",{className:`pfpu-char-counter ${p?"is-over-limit":""} ${i<=20?"is-warning":""}`,"aria-live":"polite","aria-atomic":"true"},(0,t.createElement)("span",null,sprintf(/* translators: %d: Remaining characters */ /* translators: %d: Remaining characters */
     5(0,o.__)("%d characters remaining","post-formats-for-block-themes"),i))))}),"undefined"!=typeof document){const t=document.createElement("style");t.textContent='\n\t.pfpu-format-modal {\n\t\tmax-width: 800px;\n\t}\n\n\t.pfpu-format-grid {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n\t\tgap: 1rem;\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-format-card {\n\t\ttext-align: center;\n\t}\n\n\t.pfpu-format-button {\n\t\twidth: 100%;\n\t\theight: auto;\n\t\tpadding: 1rem;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tgap: 0.5rem;\n\t}\n\n\t.pfpu-format-button .dashicons {\n\t\tfont-size: 2rem;\n\t\twidth: 2rem;\n\t\theight: 2rem;\n\t}\n\n\t.pfpu-format-name {\n\t\tfont-weight: 600;\n\t}\n\n\t.pfpu-format-description {\n\t\tfont-size: 0.875rem;\n\t\tcolor: #757575;\n\t\tmargin-top: 0.5rem;\n\t}\n\n\t.pfpu-format-change-actions {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: 0.5rem;\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-status-validator {\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-status-paragraph-wrapper {\n\t\tposition: relative;\n\t}\n\n\t.pfpu-char-counter {\n\t\tposition: absolute;\n\t\tbottom: -30px;\n\t\tright: 0;\n\t\tfont-size: 0.875rem;\n\t\tcolor: #757575;\n\t}\n\n\t.pfpu-char-counter.is-warning {\n\t\tcolor: #f0b849;\n\t\tfont-weight: 600;\n\t}\n\n\t.pfpu-char-counter.is-over-limit {\n\t\tcolor: #d63638;\n\t\tfont-weight: 600;\n\t}\n\n\t/* Template Modal - Visual Separation for Format Templates */\n\n\t/* Target template items in the template selection modal */\n\t/* Format templates have "Format" in their title (e.g., "Gallery Format", "Aside Format") */\n\n\t/* Template card styling - targets the button/card elements */\n\t.edit-post-template__panel .components-panel__body button[aria-label*="Format"],\n\t.edit-site-template-card button[aria-label*="Format"],\n\t.block-editor-block-card button[aria-label*="Format"] {\n\t\tborder-left: 4px solid var(--wp-admin-theme-color, #2271b1) !important;\n\t\tpadding-left: 12px !important;\n\t\tbackground: rgba(34, 113, 177, 0.05) !important;\n\t\tposition: relative;\n\t}\n\n\t/* Add emoji badge to format templates */\n\t.edit-post-template__panel .components-panel__body button[aria-label*="Format"]::before,\n\t.edit-site-template-card button[aria-label*="Format"]::before,\n\t.block-editor-block-card button[aria-label*="Format"]::before {\n\t\tcontent: "🎨 ";\n\t\tmargin-right: 4px;\n\t\tfont-size: 14px;\n\t}\n\n\t/* Template dropdown/modal items */\n\t.edit-post-template-dropdown__content button[aria-label*="Format"],\n\t.components-dropdown-menu__menu button[aria-label*="Format"] {\n\t\tborder-left: 4px solid var(--wp-admin-theme-color, #2271b1);\n\t\tpadding-left: 12px;\n\t\tbackground: rgba(34, 113, 177, 0.05);\n\t}\n\n\t/* Add visual indicator to currently selected format template */\n\t.edit-post-template__panel .components-panel__body .is-selected[aria-label*="Format"],\n\tbutton[aria-checked="true"][aria-label*="Format"] {\n\t\tbackground: rgba(34, 113, 177, 0.1) !important;\n\t\tfont-weight: 600;\n\t}\n\n\t/* Template name in sidebar - show when auto-applied */\n\t.edit-post-template__panel .components-panel__body .components-base-control__help {\n\t\tfont-style: italic;\n\t\tcolor: #757575;\n\t}\n',document.head.appendChild(t)}})();
  • post-formats-for-block-themes/trunk/includes/class-format-detector.php

    r3407389 r3416925  
    7575     */
    7676    private function __construct() {
    77         add_action( 'save_post', array( $this, 'detect_and_set_format' ), 10, 3 );
    78         add_action( 'rest_after_insert_post', array( $this, 'detect_format_rest' ), 10, 2 );
     77        // TEMPORARILY DISABLED - causing format override issues
     78        // add_action( 'save_post', array( $this, 'detect_and_set_format' ), 10, 3 );
     79        // add_action( 'rest_after_insert_post', array( $this, 'detect_format_rest' ), 10, 2 );
    7980    }
    8081
  • post-formats-for-block-themes/trunk/includes/class-format-styles.php

    r3413728 r3416925  
    3535        add_filter( 'get_block_templates', array( __CLASS__, 'add_block_templates' ), 10, 3 );
    3636        add_filter( 'pre_get_block_file_template', array( __CLASS__, 'get_block_file_template' ), 10, 3 );
    37         add_action( 'set_object_terms', array( __CLASS__, 'on_format_change' ), 10, 6 );
    38         add_action( 'rest_after_insert_post', array( __CLASS__, 'rest_assign_template' ), 10, 3 );
     37        // Taxonomy handler disabled - causes conflicts with REST API handler
     38        // add_action( 'set_object_terms', array( __CLASS__, 'on_format_change' ), 10, 6 );
     39        add_action( 'rest_after_insert_post', array( __CLASS__, 'rest_assign_template' ), 999, 3 );
     40        add_action( 'rest_insert_post', array( __CLASS__, 'rest_assign_template_early' ), 1, 3 );
     41        add_filter( 'rest_wp_template_query', array( __CLASS__, 'filter_rest_template_query' ), 10, 2 );
    3942        add_filter( 'rest_prepare_wp_template', array( __CLASS__, 'hide_format_templates_from_rest' ), 10, 3 );
     43        add_filter( 'rest_prepare_post', array( __CLASS__, 'filter_post_rest_response' ), 10, 3 );
    4044        add_filter( 'default_page_template_title', array( __CLASS__, 'fix_template_display_name' ), 10, 3 );
    41     }
    42 
    43     /**
    44      * Assign template via REST API (block editor)
    45      *
    46      * @since 1.0.0
     45        add_action( 'updated_post_meta', array( __CLASS__, 'watch_template_meta_changes' ), 10, 4 );
     46    }
     47
     48    /**
     49     * Early template handler - runs BEFORE anything else can set template
     50     *
     51     * @since 1.1.1
    4752     * @param WP_Post         $post     Inserted or updated post object.
    4853     * @param WP_REST_Request $request  Request object.
    4954     * @param bool            $creating True when creating a post, false when updating.
    5055     */
     56    public static function rest_assign_template_early( $post, $request, $creating ) {
     57        if ( 'post' !== $post->post_type ) {
     58            return;
     59        }
     60
     61        // If format param is in request and it's being set to standard/empty
     62        if ( $request->has_param( 'format' ) ) {
     63            $format = $request->get_param( 'format' );
     64            // Standard format (false, empty, or 'standard' string)
     65            if ( empty( $format ) || 'standard' === $format || false === $format ) {
     66                // Force delete any format template immediately
     67                delete_post_meta( $post->ID, '_wp_page_template' );
     68                error_log( "PFBT EARLY: Cleared template for post {$post->ID} due to standard format in request" );
     69            }
     70        }
     71    }
     72
     73    /**
     74     * Assign template via REST API (block editor)
     75     *
     76     * @since 1.0.0
     77     * @param WP_Post         $post     Inserted or updated post object.
     78     * @param WP_REST_Request $request  Request object.
     79     * @param bool            $creating True when creating a post, false when updating.
     80     */
    5181    public static function rest_assign_template( $post, $request, $creating ) {
    5282        // Only handle posts
     
    5585        }
    5686
    57         // Check if user manually selected a template
    58         $manual_template = $request->get_param( 'template' );
    59         if ( ! empty( $manual_template ) ) {
    60             // If it's empty string, clear template
    61             if ( '' === $manual_template ) {
     87        error_log( "PFBT REST: === START rest_assign_template for post {$post->ID} ===" );
     88        error_log( "PFBT REST: Request has 'format' param: " . ( $request->has_param( 'format' ) ? 'YES (' . $request->get_param( 'format' ) . ')' : 'NO' ) );
     89        error_log( "PFBT REST: Request has 'template' param: " . ( $request->has_param( 'template' ) ? 'YES (' . $request->get_param( 'template' ) . ')' : 'NO' ) );
     90
     91        // Check if user manually selected a template in this request
     92        if ( $request->has_param( 'template' ) ) {
     93            $manual_template = $request->get_param( 'template' );
     94
     95            if ( '' === $manual_template || 'default' === $manual_template ) {
     96                // User selected "Default" or cleared the template
    6297                delete_post_meta( $post->ID, '_wp_page_template' );
    63                 return;
    64             }
    65             // Otherwise it's a regular template, let WordPress handle it
    66             return;
    67         }
    68 
    69         // Auto-assign based on format
    70         $format = $request->get_param( 'format' );
    71 
    72         // If no format in request, get from post
    73         if ( empty( $format ) ) {
    74             $format = get_post_format( $post->ID );
    75         }
    76 
    77         // Default to standard if still empty
    78         if ( empty( $format ) || false === $format ) {
    79             $format = 'standard';
    80         }
    81 
    82         // Assign template based on format
    83         if ( 'standard' === $format ) {
    84             delete_post_meta( $post->ID, '_wp_page_template' );
     98                delete_post_meta( $post->ID, '_pfbt_manual_template' );
     99                delete_post_meta( $post->ID, '_pfbt_manual_template_slug' );
     100                error_log( "PFBT REST: User selected 'Default' template for post {$post->ID}, cleared template assignment and override flags" );
     101            } else {
     102                // User manually selected a specific template
     103                update_post_meta( $post->ID, '_pfbt_manual_template', true );
     104                update_post_meta( $post->ID, '_pfbt_manual_template_slug', $manual_template );
     105                error_log( "PFBT REST: User manually selected template '{$manual_template}' for post {$post->ID}, set override flag" );
     106
     107                // Set the template meta (WordPress doesn't do this automatically for custom template values)
     108                update_post_meta( $post->ID, '_wp_page_template', $manual_template );
     109            }
     110
     111            error_log( "PFBT REST: === END (manual template in request) ===" );
     112            return;
     113        }
     114
     115        // Check if user has manual override active
     116        $has_manual_override = get_post_meta( $post->ID, '_pfbt_manual_template', true );
     117
     118        if ( $has_manual_override ) {
     119            // User has taken control, don't auto-assign
     120            $manual_template_slug = get_post_meta( $post->ID, '_pfbt_manual_template_slug', true );
     121            error_log( "PFBT REST: Manual override active for post {$post->ID}, keeping template: {$manual_template_slug}" );
     122            error_log( "PFBT REST: === END (manual override active) ===" );
     123            return;
     124        }
     125
     126        // Get the ACTUAL current format from the post (after WordPress has processed it)
     127        $current_format = get_post_format( $post->ID );
     128        $raw_format_value = $current_format;
     129
     130        // Normalize - WordPress stores standard as false/empty
     131        $current_format = empty( $current_format ) || false === $current_format ? 'standard' : $current_format;
     132
     133        error_log( "PFBT REST: get_post_format() returned: " . var_export( $raw_format_value, true ) );
     134        error_log( "PFBT REST: Normalized format: {$current_format}" );
     135
     136        // Get current template assignment
     137        $current_template = get_post_meta( $post->ID, '_wp_page_template', true );
     138        error_log( "PFBT REST: Current template meta: " . ( $current_template ? $current_template : 'EMPTY' ) );
     139
     140        // Auto-assign template based on format (no manual override)
     141        if ( 'standard' === $current_format ) {
     142            // Standard format should NEVER have a format template
     143            if ( $current_template && strpos( $current_template, 'single-format-' ) === 0 ) {
     144                delete_post_meta( $post->ID, '_wp_page_template' );
     145                error_log( "PFBT REST: ❌ CLEARED format template for standard post {$post->ID}, was: {$current_template}" );
     146
     147                // Verify it was actually deleted
     148                $verify = get_post_meta( $post->ID, '_wp_page_template', true );
     149                error_log( "PFBT REST: After delete, template meta is now: " . ( $verify ? $verify : 'EMPTY' ) );
     150            } elseif ( $current_template && strpos( $current_template, 'single-format-' ) !== 0 ) {
     151                error_log( "PFBT REST: ⚠️ Standard post {$post->ID} has non-format template: {$current_template} (leaving as-is)" );
     152            } else {
     153                error_log( "PFBT REST: ✅ Post {$post->ID} is standard and has no template (correct)" );
     154            }
    85155        } else {
    86             $template_slug = 'single-format-' . $format;
    87             // Store just the slug (not full ID) so WordPress editor can match it
    88             update_post_meta( $post->ID, '_wp_page_template', $template_slug );
     156            // Format post should have matching format template
     157            $expected_template = 'single-format-' . $current_format;
     158            if ( $current_template !== $expected_template ) {
     159                update_post_meta( $post->ID, '_wp_page_template', $expected_template );
     160                error_log( "PFBT REST: ✅ Auto-assigned template {$expected_template} for post {$post->ID} (format: {$current_format})" );
     161            } else {
     162                error_log( "PFBT REST: ✅ Post {$post->ID} already has correct template: {$expected_template}" );
     163            }
     164        }
     165
     166        error_log( "PFBT REST: === END rest_assign_template ===" );
     167    }
     168
     169    /**
     170     * Watch for template meta changes to debug what's setting it
     171     *
     172     * @since 1.1.1
     173     * @param int    $meta_id    ID of updated metadata entry.
     174     * @param int    $object_id  Post ID.
     175     * @param string $meta_key   Meta key.
     176     * @param mixed  $meta_value Meta value.
     177     */
     178    public static function watch_template_meta_changes( $meta_id, $object_id, $meta_key, $meta_value ) {
     179        if ( '_wp_page_template' === $meta_key ) {
     180            $post = get_post( $object_id );
     181            if ( $post && 'post' === $post->post_type ) {
     182                $backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 5 );
     183                $caller = isset( $backtrace[3] ) ? $backtrace[3]['function'] : 'unknown';
     184                error_log( "PFBT WATCH: Template meta updated for post {$object_id} to '{$meta_value}' by {$caller}" );
     185            }
    89186        }
    90187    }
     
    144241
    145242    /**
    146      * Hide format templates from REST API template list
    147      *
    148      * Format templates are assigned automatically based on post format,
    149      * so they shouldn't appear in the template dropdown in the editor.
    150      *
    151      * @since 1.0.0
     243     * Filter post REST API response to fix template display
     244     *
     245     * Ensures the template field correctly shows 'default' when no template is assigned.
     246     *
     247     * @since 1.1.1
     248     * @param WP_REST_Response $response The response object.
     249     * @param WP_Post          $post     Post object.
     250     * @param WP_REST_Request  $request  Request object.
     251     * @return WP_REST_Response Modified response.
     252     */
     253    public static function filter_post_rest_response( $response, $post, $request ) {
     254        // Only handle posts
     255        if ( 'post' !== $post->post_type ) {
     256            return $response;
     257        }
     258
     259        $template_meta = get_post_meta( $post->ID, '_wp_page_template', true );
     260        $template_in_response = $response->data['template'] ?? '';
     261
     262        error_log( "PFBT POST REST: Post {$post->ID} - Meta: " . ( $template_meta ?: '[EMPTY]' ) . " | Response: " . ( $template_in_response ?: '[EMPTY]' ) );
     263
     264        // If template meta is empty but response has a template, fix it
     265        if ( empty( $template_meta ) && ! empty( $template_in_response ) ) {
     266            error_log( "PFBT POST REST: ⚠️ Fixing template - meta is empty but response shows '{$template_in_response}'" );
     267            $response->data['template'] = 'default';
     268        }
     269        // If template meta is empty, ensure response shows 'default'
     270        elseif ( empty( $template_meta ) ) {
     271            $response->data['template'] = 'default';
     272            error_log( "PFBT POST REST: ✅ Set template to 'default' for post {$post->ID}" );
     273        }
     274
     275        return $response;
     276    }
     277
     278    /**
     279     * Filter REST API template query parameters
     280     *
     281     * Ensures the 'single' template is included when querying templates for posts.
     282     *
     283     * @since 1.1.1
     284     * @param array           $args    Query parameters.
     285     * @param WP_REST_Request $request REST request object.
     286     * @return array Modified query parameters.
     287     */
     288    public static function filter_rest_template_query( $args, $request ) {
     289        error_log( "PFBT REST QUERY: Template query args: " . print_r( $args, true ) );
     290
     291        // If querying for post templates, ensure 'single' is explicitly included
     292        if ( isset( $args['post_type'] ) && 'post' === $args['post_type'] ) {
     293            // If slug__in is set and doesn't include 'single', add it
     294            if ( isset( $args['slug__in'] ) && is_array( $args['slug__in'] ) ) {
     295                if ( ! in_array( 'single', $args['slug__in'], true ) ) {
     296                    $args['slug__in'][] = 'single';
     297                    error_log( "PFBT REST QUERY: Added 'single' to slug__in array" );
     298                }
     299            } else {
     300                // No slug__in set, create one with single
     301                $args['slug__in'] = array( 'single' );
     302                error_log( "PFBT REST QUERY: Created slug__in array with 'single'" );
     303            }
     304        }
     305
     306        return $args;
     307    }
     308
     309    /**
     310     * Add metadata to format templates in REST API response
     311     *
     312     * Adds classification metadata to help visually separate format templates
     313     * from theme templates in the editor UI.
     314     *
     315     * @since 1.1.1
    152316     * @param WP_REST_Response $response The response object.
    153317     * @param WP_Block_Template $template The template object.
    154318     * @param WP_REST_Request $request The request object.
    155      * @return WP_REST_Response|null Modified response or null to hide.
     319     * @return WP_REST_Response Modified response with template metadata.
    156320     */
    157321    public static function hide_format_templates_from_rest( $response, $template, $request ) {
     322        // Log ALL templates going through REST API
     323        error_log( "PFBT REST FILTER: Processing template '{$template->slug}' for REST response" );
     324
     325        // Check if this is the "Default" pseudo-template
     326        if ( 'default' === $template->slug ) {
     327            $response->data['pfbt_template_type'] = 'default';
     328            $response->data['pfbt_is_default_option'] = true;
     329            error_log( "PFBT REST: Marked as Default template option" );
     330        }
    158331        // Check if this is a format template
    159         if ( strpos( $template->slug, 'single-format-' ) === 0 ) {
    160             // Check if this request is for the editor (not Site Editor)
    161             $context = $request->get_param( 'context' );
    162 
    163             // Hide from editor context (template dropdown)
    164             // but allow in Site Editor context (for customization)
    165             if ( 'edit' === $context ) {
    166                 return null; // Return null to exclude from response
    167             }
     332        elseif ( strpos( $template->slug, 'single-format-' ) === 0 ) {
     333            // Add classification metadata for visual separation
     334            $response->data['pfbt_template_type'] = 'format';
     335            $response->data['pfbt_format_name'] = str_replace( 'single-format-', '', $template->slug );
     336            $response->data['pfbt_auto_applicable'] = true;
     337
     338            error_log( "PFBT REST: Added metadata to format template {$template->slug}" );
     339        } else {
     340            // Theme template
     341            $response->data['pfbt_template_type'] = 'theme';
     342            error_log( "PFBT REST: Marked as theme template: {$template->slug}" );
    168343        }
    169344
     
    248423        }
    249424
     425        error_log( "PFBT: add_block_templates called with " . count( $query_result ) . " templates" );
     426        error_log( "PFBT: Query params: " . print_r( $query, true ) );
     427
     428        // Log what templates we currently have
     429        $template_slugs = array_map( function( $t ) { return $t->slug; }, $query_result );
     430        error_log( "PFBT: Current templates: " . implode( ', ', $template_slugs ) );
     431
    250432        // Ensure theme's single template is available for posts
    251433        // The theme's single template often doesn't have post_types set, so it gets filtered out
     
    255437            if ( 'single' === $template->slug ) {
    256438                $single_found = true;
     439                error_log( "PFBT: Found 'single' template in results" );
    257440                // Ensure it's assigned to post type
    258441                if ( ! isset( $template->post_types ) || ! is_array( $template->post_types ) ) {
     
    261444                if ( ! in_array( 'post', $template->post_types, true ) ) {
    262445                    $template->post_types[] = 'post';
     446                    error_log( "PFBT: Added 'post' to single template post_types" );
    263447                }
    264448                break;
     
    268452        // If single template wasn't in the filtered results, fetch it and add it
    269453        if ( ! $single_found ) {
    270             // Get all templates without post_type filter
     454            error_log( "PFBT: Single template NOT found, attempting to fetch and add it" );
     455
     456            // Try to get the single template directly from the theme
     457            // Avoid recursion by using remove_filter temporarily
     458            remove_filter( 'get_block_templates', array( __CLASS__, 'add_block_templates' ), 10 );
    271459            $all_templates = get_block_templates( array(), $template_type );
     460            add_filter( 'get_block_templates', array( __CLASS__, 'add_block_templates' ), 10, 3 );
     461
     462            error_log( "PFBT: Fetched " . count( $all_templates ) . " templates without filter" );
     463
    272464            foreach ( $all_templates as $template ) {
    273465                if ( 'single' === $template->slug ) {
     
    282474                    // Add it to the beginning of results so it's the default
    283475                    array_unshift( $query_result, $single_template );
     476                    $single_found = true; // Mark as found
     477                    error_log( "PFBT: Successfully added 'single' template to results" );
    284478                    break;
    285479                }
    286480            }
    287         }
    288 
     481
     482            if ( ! $single_found ) {
     483                error_log( "PFBT: WARNING - Could not find 'single' template even after fetching all templates" );
     484            }
     485        }
     486
     487        // Add "Default" pseudo-template option
     488        // This allows users to explicitly clear template assignment
     489        // Add it to all queries - WordPress will filter by post_types if needed
     490        $default_exists = false;
     491        foreach ( $query_result as $existing_template ) {
     492            if ( 'default' === $existing_template->slug ) {
     493                $default_exists = true;
     494                break;
     495            }
     496        }
     497
     498        if ( ! $default_exists ) {
     499            $default_template              = new WP_Block_Template();
     500            $default_template->slug        = 'default';
     501            $default_template->id          = get_stylesheet() . '//default';
     502            $default_template->theme       = get_stylesheet();
     503            $default_template->content     = '';
     504            $default_template->source      = 'plugin';
     505            $default_template->type        = 'wp_template';
     506            $default_template->title       = __( 'Default', 'post-formats-for-block-themes' );
     507            $default_template->description = __( 'Use default template hierarchy (no specific template)', 'post-formats-for-block-themes' );
     508            $default_template->status      = 'publish';
     509            $default_template->has_theme_file = false;
     510            $default_template->is_custom   = false;
     511            $default_template->post_types  = array( 'post' );
     512            $default_template->author      = null;
     513            $default_template->origin      = 'plugin';
     514
     515            // Add at the very beginning so it's the first option
     516            array_unshift( $query_result, $default_template );
     517            error_log( "PFBT: Added 'Default' template option to results" );
     518        }
     519
     520        // Add format templates to BOTH post editor and site editor
     521        // Visual separation will be handled by CSS styling
    289522        $templates = array(
    290523            'single-format-aside'   => __( 'Aside Format', 'post-formats-for-block-themes' ),
     
    342575        }
    343576
     577        // Log final templates being returned
     578        $final_slugs = array_map( function( $t ) { return $t->slug; }, $query_result );
     579        error_log( "PFBT: Returning " . count( $query_result ) . " templates: " . implode( ', ', $final_slugs ) );
     580
    344581        return $query_result;
    345582    }
  • post-formats-for-block-themes/trunk/post-formats-for-block-themes.php

    r3416861 r3416925  
    44 * Plugin URI: https://wordpress.org/plugins/post-formats-for-block-themes/
    55 * Description: Modernizes WordPress post formats for block themes with format-specific patterns, auto-detection, and enhanced editor experience.
    6  * Version: 1.1.1
     6 * Version: 1.1.2
    77 * Requires at least: 6.8
    88 * Tested up to: 6.9
     
    3939 * Plugin constants
    4040 */
    41 define( 'PFBT_VERSION', '1.1.1' );
     41define( 'PFBT_VERSION', '1.1.2' );
    4242define( 'PFBT_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
    4343define( 'PFBT_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
     
    8080 * Hide format templates from template chooser dropdown
    8181 *
    82  * Format templates should apply automatically via template hierarchy,
    83  * not appear as selectable options in the Template dropdown.
    84  * This prevents them from hiding/replacing the theme's templates.
    85  *
    86  * @since 1.0.4
    87  * @param array $query_result Array of block template objects
    88  * @param array $query Block templates query parameters
    89  * @param string $template_type wp_template or wp_template_part
    90  * @return array Filtered array of block templates
    91  */
    92 function pfbt_filter_format_templates_from_chooser( $query_result, $query, $template_type ) {
    93     // Only filter templates (not template parts) in the post editor
    94     if ( 'wp_template' !== $template_type ) {
    95         return $query_result;
    96     }
    97 
    98     // Don't filter if we're in the site editor or template admin
    99     if ( is_admin() && isset( $_GET['page'] ) && 'gutenberg-edit-site' === $_GET['page'] ) {
    100         return $query_result;
    101     }
    102 
    103     // Filter out format templates from the chooser
    104     $format_template_slugs = array(
    105         'single-format-aside',
    106         'single-format-gallery',
    107         'single-format-link',
    108         'single-format-image',
    109         'single-format-quote',
    110         'single-format-status',
    111         'single-format-video',
    112         'single-format-audio',
    113         'single-format-chat',
    114     );
    115 
    116     return array_filter(
    117         $query_result,
    118         function( $template ) use ( $format_template_slugs ) {
    119             return ! in_array( $template->slug, $format_template_slugs, true );
    120         }
    121     );
    122 }
    123 add_filter( 'get_block_templates', 'pfbt_filter_format_templates_from_chooser', 10, 3 );
     82 * NOTE: This filtering is handled by the rest_prepare_wp_template filter
     83 * in includes/class-format-styles.php for block themes.
     84 * The theme_post_templates filter is only for classic themes and causes
     85 * conflicts with block theme template handling.
     86 *
     87 * @since 1.1.1
     88 */
    12489
    12590/**
  • post-formats-for-block-themes/trunk/readme.txt

    r3416861 r3416925  
    66Tested up to: 6.9
    77Requires PHP: 7.4
    8 Stable tag: 1.1.1
     8Stable tag: 1.1.2
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    347347
    348348== Changelog ==
     349
     350= 1.1.2 - 2025-12-11 =
     351
     352**New Features**
     353
     354* **Added:** "Default" template option in template chooser that explicitly clears template assignment and uses default template hierarchy
     355* **Added:** Comprehensive logging system for tracking template assignment and REST API behavior for easier debugging
     356
     357**Improvements**
     358
     359* **Improved:** Simplified editor UI by removing duplicate "Post Format" dropdown from sidebar - now uses WordPress's built-in format selector in Status & visibility panel
     360* **Improved:** Status format character counter moved from sidebar panel to editor notice for cleaner UI
     361* **Improved:** Format selection modal now clearly shows "Standard (Single Template)" option with descriptive text
     362* **Improved:** "Single" template from theme now properly appears in template chooser for posts
     363* **Improved:** REST API now correctly returns 'default' template value when no template is assigned, fixing display issues
     364
     365**Bug Fixes**
     366
     367* **Fixed:** Standard format posts no longer incorrectly show format templates (like "Aside Format") when no template should be assigned
     368* **Fixed:** Template chooser modal now correctly displays all available templates including theme's default "Single" template
     369* **Fixed:** Editor now properly reflects actual database state for template assignments instead of showing cached/stale values
     370
     371**Technical Changes**
     372
     373* **Changed:** Removed `FormatSwitcherPanel` component to eliminate duplicate UI controls
     374* **Changed:** Removed `PluginDocumentSettingPanel` wrapper for cleaner sidebar
     375* **Changed:** "Default" template now added to all template queries for consistent availability
     376* **Changed:** Added `rest_prepare_post` filter to ensure correct template values in editor
     377* **Changed:** Template assignment logic now properly handles "default" template selection
    349378
    350379= 1.1.1 - 2025-12-09 =
Note: See TracChangeset for help on using the changeset viewer.