Changeset 3416925
- Timestamp:
- 12/11/2025 03:38:55 AM (4 months ago)
- Location:
- post-formats-for-block-themes/trunk
- Files:
-
- 6 edited
-
build/index.asset.php (modified) (1 diff)
-
build/index.js (modified) (1 diff)
-
includes/class-format-detector.php (modified) (1 diff)
-
includes/class-format-styles.php (modified) (9 diffs)
-
post-formats-for-block-themes.php (modified) (3 diffs)
-
readme.txt (modified) (2 diffs)
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-e dit-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 75 75 */ 76 76 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 ); 79 80 } 80 81 -
post-formats-for-block-themes/trunk/includes/class-format-styles.php
r3413728 r3416925 35 35 add_filter( 'get_block_templates', array( __CLASS__, 'add_block_templates' ), 10, 3 ); 36 36 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 ); 39 42 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 ); 40 44 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 47 52 * @param WP_Post $post Inserted or updated post object. 48 53 * @param WP_REST_Request $request Request object. 49 54 * @param bool $creating True when creating a post, false when updating. 50 55 */ 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 */ 51 81 public static function rest_assign_template( $post, $request, $creating ) { 52 82 // Only handle posts … … 55 85 } 56 86 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 62 97 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 } 85 155 } 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 } 89 186 } 90 187 } … … 144 241 145 242 /** 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 152 316 * @param WP_REST_Response $response The response object. 153 317 * @param WP_Block_Template $template The template object. 154 318 * @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. 156 320 */ 157 321 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 } 158 331 // 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}" ); 168 343 } 169 344 … … 248 423 } 249 424 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 250 432 // Ensure theme's single template is available for posts 251 433 // The theme's single template often doesn't have post_types set, so it gets filtered out … … 255 437 if ( 'single' === $template->slug ) { 256 438 $single_found = true; 439 error_log( "PFBT: Found 'single' template in results" ); 257 440 // Ensure it's assigned to post type 258 441 if ( ! isset( $template->post_types ) || ! is_array( $template->post_types ) ) { … … 261 444 if ( ! in_array( 'post', $template->post_types, true ) ) { 262 445 $template->post_types[] = 'post'; 446 error_log( "PFBT: Added 'post' to single template post_types" ); 263 447 } 264 448 break; … … 268 452 // If single template wasn't in the filtered results, fetch it and add it 269 453 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 ); 271 459 $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 272 464 foreach ( $all_templates as $template ) { 273 465 if ( 'single' === $template->slug ) { … … 282 474 // Add it to the beginning of results so it's the default 283 475 array_unshift( $query_result, $single_template ); 476 $single_found = true; // Mark as found 477 error_log( "PFBT: Successfully added 'single' template to results" ); 284 478 break; 285 479 } 286 480 } 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 289 522 $templates = array( 290 523 'single-format-aside' => __( 'Aside Format', 'post-formats-for-block-themes' ), … … 342 575 } 343 576 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 344 581 return $query_result; 345 582 } -
post-formats-for-block-themes/trunk/post-formats-for-block-themes.php
r3416861 r3416925 4 4 * Plugin URI: https://wordpress.org/plugins/post-formats-for-block-themes/ 5 5 * Description: Modernizes WordPress post formats for block themes with format-specific patterns, auto-detection, and enhanced editor experience. 6 * Version: 1.1. 16 * Version: 1.1.2 7 7 * Requires at least: 6.8 8 8 * Tested up to: 6.9 … … 39 39 * Plugin constants 40 40 */ 41 define( 'PFBT_VERSION', '1.1. 1' );41 define( 'PFBT_VERSION', '1.1.2' ); 42 42 define( 'PFBT_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 43 43 define( 'PFBT_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); … … 80 80 * Hide format templates from template chooser dropdown 81 81 * 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 */ 124 89 125 90 /** -
post-formats-for-block-themes/trunk/readme.txt
r3416861 r3416925 6 6 Tested up to: 6.9 7 7 Requires PHP: 7.4 8 Stable tag: 1.1. 18 Stable tag: 1.1.2 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 347 347 348 348 == 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 349 378 350 379 = 1.1.1 - 2025-12-09 =
Note: See TracChangeset
for help on using the changeset viewer.