post_content, 'kofront_dashboard' ) || has_shortcode( $post->post_content, 'kofront_editor' ) ) ) { // Enqueue the native WordPress Media Uploader wp_enqueue_media(); wp_localize_script( 'kofront-script', 'kofrontAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'kofront_ajax_nonce' ) ) ); } } // --------------------------------------------------------- // 1.1. Prevent Caching on Portal Pages (Pre-render hook). // --------------------------------------------------------- add_action( 'template_redirect', 'kofront_disable_caching' ); function kofront_disable_caching() { global $post; // Trigger if the page has the dashboard or editor shortcode. if ( is_a( $post, 'WP_Post' ) && ( has_shortcode( $post->post_content, 'kofront_dashboard' ) || has_shortcode( $post->post_content, 'kofront_editor' ) ) ) { if ( ! defined( 'DONOTCACHEPAGE' ) ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound define( 'DONOTCACHEPAGE', true ); } // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound do_action( 'litespeed_control_set_nocache', 'kofront-portal' ); nocache_headers(); } } // --------------------------------------------------------- // 2. AJAX listener for instant category deletion. // --------------------------------------------------------- add_action( 'wp_ajax_kofront_delete_category', 'kofront_ajax_delete_category' ); function kofront_ajax_delete_category() { check_ajax_referer( 'kofront_ajax_nonce', 'security' ); if ( ! current_user_can( 'edit_others_posts' ) ) { wp_send_json_error( array( 'message' => 'Permission denied.' ) ); } $cat_id = isset( $_POST['cat_id'] ) ? intval( wp_unslash( $_POST['cat_id'] ) ) : 0; if ( $cat_id > 0 ) { $del_result = wp_delete_term( $cat_id, 'category' ); if ( is_wp_error( $del_result ) ) { wp_send_json_error( array( 'message' => $del_result->get_error_message() ) ); } else { wp_send_json_success( array( 'message' => 'Category deleted.' ) ); } } wp_send_json_error( array( 'message' => 'Invalid category ID.' ) ); } // --------------------------------------------------------- // 3. Dashboard shortcode. // --------------------------------------------------------- add_shortcode( 'kofront_dashboard', 'kofront_render_dashboard' ); function kofront_render_dashboard( $atts ) { $parsed_atts = shortcode_atts( array( 'editor_url' => get_permalink() ), $atts ); $editor_url = esc_url( $parsed_atts['editor_url'] ); if ( ! is_user_logged_in() ) { $login_url = wp_login_url( get_permalink() ); /* translators: %s: Login URL */ return '

' . sprintf( __( 'You must be logged in to access the portal. Please log in here.', 'kofront-frontend-posts' ), esc_url( $login_url ) ) . '

'; } $current_user_id = get_current_user_id(); $current_url = get_permalink(); $message = ''; // Handle post deletion. if ( isset( $_GET['kofront_action'] ) && sanitize_text_field( wp_unslash( $_GET['kofront_action'] ) ) === 'delete' && isset( $_GET['kofront_post_id'] ) ) { $del_post_id = intval( wp_unslash( $_GET['kofront_post_id'] ) ); if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'kofront_delete_post_' . $del_post_id ) ) { $del_post = get_post( $del_post_id ); if ( $del_post && ( $del_post->post_author == $current_user_id || current_user_can( 'edit_others_posts' ) ) ) { wp_trash_post( $del_post_id ); $message .= '
Post successfully moved to trash.
'; } else { $message .= '
Permission denied.
'; } } } // Handle post save success (PRG pattern redirect target). if ( isset( $_GET['kofront_success'] ) && isset( $_GET['kofront_saved_id'] ) ) { $success_type = sanitize_text_field( wp_unslash( $_GET['kofront_success'] ) ); $action_msg = ( $success_type === 'updated' ) ? 'Post updated successfully.' : 'New post created successfully.'; $message .= '
'; $message .= '
' . esc_html( $action_msg ) . '
'; $saved_id = intval( wp_unslash( $_GET['kofront_saved_id'] ) ); $saved_post = get_post( $saved_id ); if ( $saved_post && ( $saved_post->post_author == $current_user_id || current_user_can( 'edit_others_posts' ) ) ) { $btn_text = ( $saved_post->post_status === 'publish' ) ? 'View Live Post' : 'Preview Draft'; $btn_link = ( $saved_post->post_status === 'publish' ) ? get_permalink( $saved_id ) : get_preview_post_link( $saved_id ); $message .= '👁 ' . esc_html( $btn_text ) . ''; } $message .= '
'; } $query_args = array( 'post_type' => 'post', 'post_status' => array('publish', 'pending', 'draft'), 'posts_per_page' => -1 ); if ( ! current_user_can( 'edit_others_posts' ) ) { $query_args['author'] = $current_user_id; } $user_posts = get_posts( $query_args ); ob_start(); ?>

Post Management

You haven't created any posts yet.

ID ); $edit_link = add_query_arg( 'kofront_edit_id', $p->ID, $editor_url ); $delete_url = wp_nonce_url( add_query_arg( array( 'kofront_action' => 'delete', 'kofront_post_id' => $p->ID ), $current_url ), 'kofront_delete_post_' . $p->ID ); $display_title = !empty($p->post_title) ? $p->post_title : '(Untitled)'; ?>
Title Status Date Action
post_status) ); ?> ID ) ); ?> post_status === 'publish' ) : ?> View Edit Delete
get_permalink() ), $atts ); $dashboard_url = esc_url( $parsed_atts['dashboard_url'] ); if ( ! is_user_logged_in() ) { $login_url = wp_login_url( get_permalink() ); /* translators: %s: Login URL */ return '

' . sprintf( __( 'You must be logged in to access the portal. Please log in here.', 'kofront-frontend-posts' ), esc_url( $login_url ) ) . '

'; } $current_user_id = get_current_user_id(); $message = ''; $edit_id = isset( $_GET['kofront_edit_id'] ) ? intval( wp_unslash( $_GET['kofront_edit_id'] ) ) : 0; // Handle form submission. if ( isset( $_POST['kofront_is_submission'] ) && sanitize_text_field( wp_unslash( $_POST['kofront_is_submission'] ) ) === '1' ) { if ( ! isset( $_POST['kofront_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['kofront_nonce'] ) ), 'kofront_submit_action' ) ) { $message .= '
Security check failed. Please try again.
'; } else { $post_id_to_edit = isset( $_POST['kofront_post_id'] ) ? intval( wp_unslash( $_POST['kofront_post_id'] ) ) : 0; $post_title = isset( $_POST['kofront_title'] ) ? sanitize_text_field( wp_unslash( $_POST['kofront_title'] ) ) : ''; $post_excerpt = isset( $_POST['kofront_excerpt'] ) ? sanitize_textarea_field( wp_unslash( $_POST['kofront_excerpt'] ) ) : ''; if ( isset( $_POST['kofront_save_draft'] ) ) { $final_status = 'draft'; } else { $final_status = 'publish'; } $layout_style = isset( $_POST['kofront_layout_style'] ) ? sanitize_text_field( wp_unslash( $_POST['kofront_layout_style'] ) ) : '1-col'; $selected_cats = isset( $_POST['kofront_categories'] ) && is_array( $_POST['kofront_categories'] ) ? array_map( 'intval', wp_unslash( $_POST['kofront_categories'] ) ) : array(); if ( ! empty( $_POST['kofront_new_category'] ) ) { $new_cat_name = sanitize_text_field( wp_unslash( $_POST['kofront_new_category'] ) ); $term_info = term_exists( $new_cat_name, 'category' ); if ( ! $term_info ) { $term_info = wp_insert_term( $new_cat_name, 'category' ); } if ( ! is_wp_error( $term_info ) ) { $selected_cats[] = intval( $term_info['term_id'] ); } } $gutenberg_content = ''; $order = isset( $_POST['kofront_order'] ) && is_array( $_POST['kofront_order'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['kofront_order'] ) ) : array(); $headings = isset( $_POST['kofront_heading'] ) && is_array( $_POST['kofront_heading'] ) ? array_map( 'wp_kses_post', wp_unslash( $_POST['kofront_heading'] ) ) : array(); $heading_levels = isset( $_POST['kofront_heading_level'] ) && is_array( $_POST['kofront_heading_level'] ) ? array_map( 'intval', wp_unslash( $_POST['kofront_heading_level'] ) ) : array(); $heading_aligns = isset( $_POST['kofront_heading_align'] ) && is_array( $_POST['kofront_heading_align'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['kofront_heading_align'] ) ) : array(); $paragraphs = isset( $_POST['kofront_paragraph'] ) && is_array( $_POST['kofront_paragraph'] ) ? array_map( 'wp_kses_post', wp_unslash( $_POST['kofront_paragraph'] ) ) : array(); $toc_titles = isset( $_POST['kofront_toc_title'] ) && is_array( $_POST['kofront_toc_title'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['kofront_toc_title'] ) ) : array(); $toc_levels_arr = isset( $_POST['kofront_toc_levels'] ) && is_array( $_POST['kofront_toc_levels'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['kofront_toc_levels'] ) ) : array(); $toc_spans_arr = isset( $_POST['kofront_toc_span'] ) && is_array( $_POST['kofront_toc_span'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['kofront_toc_span'] ) ) : array(); $shortcodes = isset( $_POST['kofront_shortcode'] ) && is_array( $_POST['kofront_shortcode'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['kofront_shortcode'] ) ) : array(); $raw_blocks = isset( $_POST['kofront_raw_block'] ) && is_array( $_POST['kofront_raw_block'] ) ? array_map( 'wp_kses_post', wp_unslash( $_POST['kofront_raw_block'] ) ) : array(); $block_image_ids = array(); $blocks_array = array(); // Collect blocks for native column generation. $used_anchors = array(); // Track heading anchor IDs to prevent duplicates. $toc_items = array(); // Store headings to populate TOC blocks after loop. $toc_configs = array(); // Store TOC placeholders and titles. $toc_counter = 0; foreach ( $order as $block_type ) { $block_html = ''; if ( $block_type === 'heading' ) { $text = trim( str_replace( array( '
', '
', '
', "\r", "\n" ), ' ', kofront_sanitize_inline_html( (string) array_shift( $headings ) ) ) ); $plain_text = trim( wp_strip_all_tags( $text ) ); $level = ! empty( $heading_levels ) ? intval( array_shift( $heading_levels ) ) : 2; if ( $level < 1 || $level > 6 ) { $level = 2; } $align = ! empty( $heading_aligns ) ? (string) array_shift( $heading_aligns ) : 'left'; $align_class = ( $align === 'center' ) ? ' has-text-align-center' : ''; $class_attr = trim( 'kofront-span-all' . $align_class ); if ( $plain_text !== '' ) { $base_anchor = sanitize_title( $plain_text ); if ( '' === $base_anchor ) { $base_anchor = 'section'; } $anchor_id = $base_anchor; $suffix = 2; while ( in_array( $anchor_id, $used_anchors, true ) ) { $anchor_id = $base_anchor . '-' . $suffix; $suffix++; } $used_anchors[] = $anchor_id; $toc_items[] = array( 'level' => $level, 'text' => $plain_text, 'id' => $anchor_id, ); $level_json = ( 2 !== $level ) ? '"level":' . $level . ',' : ''; $block_html .= '' . $text . ''; } } elseif ( $block_type === 'toc' ) { $toc_counter++; $raw_toc_title = ! empty( $toc_titles ) ? (string) array_shift( $toc_titles ) : ''; $toc_title = ( '' !== trim( $raw_toc_title ) ) ? $raw_toc_title : __( 'Table of Contents', 'kofront-frontend-posts' ); $raw_toc_levels = ! empty( $toc_levels_arr ) ? (string) array_shift( $toc_levels_arr ) : '1,2,3,4,5,6'; $raw_toc_span = ! empty( $toc_spans_arr ) ? (string) array_shift( $toc_spans_arr ) : '0'; $placeholder = ''; $toc_configs[ $placeholder ] = array( 'title' => $toc_title, 'levels' => $raw_toc_levels, 'span' => ( '1' === $raw_toc_span ) ? '1' : '0', ); $block_html = $placeholder; } elseif ( $block_type === 'paragraph' ) { $text = trim( kofront_sanitize_inline_html( (string) array_shift( $paragraphs ) ) ); if ( trim( wp_strip_all_tags( $text ) ) !== '' ) { $text = preg_replace( "/\r\n|\r|\n/", '
', $text ); $block_html .= '

' . $text . '

'; } } elseif ( $block_type === 'shortcode' ) { $sc_text = ! empty( $shortcodes ) ? trim( wp_strip_all_tags( (string) array_shift( $shortcodes ) ) ) : ''; if ( $sc_text !== '' ) { $block_html .= '' . $sc_text . ''; } } elseif ( $block_type === 'raw_block' ) { $raw_b = ! empty( $raw_blocks ) ? trim( (string) array_shift( $raw_blocks ) ) : ''; if ( $raw_b !== '' ) { $block_html .= $raw_b; } } elseif ( strpos( $block_type, 'image_' ) === 0 ) { $size_key = 'kofront_image_size_' . str_replace( 'image_', '', $block_type ); $img_size = isset( $_POST[ $size_key ] ) ? sanitize_text_field( wp_unslash( $_POST[ $size_key ] ) ) : 'large'; $existing_img_key = 'kofront_existing_' . $block_type; $current_img_id = isset( $_POST[ $existing_img_key ] ) ? intval( wp_unslash( $_POST[ $existing_img_key ] ) ) : 0; $span_img_key = 'kofront_span_' . $block_type; $is_span = ! empty( $_POST[ $span_img_key ] ) ? ' kofront-span-all' : ''; if ( $current_img_id > 0 ) { $img_url = wp_get_attachment_url( $current_img_id ); $block_html .= ''; $block_html .= '
'; $block_html .= ''; $block_image_ids[ $block_type ] = $current_img_id; } } elseif ( strpos( $block_type, 'gallery_' ) === 0 ) { $layout_key = 'kofront_gallery_layout_' . str_replace( 'gallery_', '', $block_type ); $gallery_layout = isset( $_POST[ $layout_key ] ) ? sanitize_text_field( wp_unslash( $_POST[ $layout_key ] ) ) : 'grid'; $gallery_img_ids = array(); $existing_key = 'kofront_existing_' . $block_type; if ( isset( $_POST[ $existing_key ] ) && is_array( $_POST[ $existing_key ] ) ) { $gallery_img_ids = array_map( 'intval', wp_unslash( $_POST[ $existing_key ] ) ); } $span_gal_key = 'kofront_span_' . $block_type; $is_span = ! empty( $_POST[ $span_gal_key ] ) ? ' kofront-span-all' : ''; if ( ! empty( $gallery_img_ids ) ) { $img_count = count( $gallery_img_ids ); $count_class = ' kofront-gallery-count-' . ( $img_count >= 3 ? '3-plus' : $img_count ); $class_addition = $count_class . $is_span; if ( $gallery_layout === 'masonry' ) { $class_addition .= ' kofront-masonry-gallery'; } elseif ( $gallery_layout === 'slider' ) { $class_addition .= ' kofront-slider-gallery'; } $block_html .= ''; $block_html .= ''; $block_html .= ''; } } if ( $block_html !== '' ) { $blocks_array[] = $block_html; } } // Populate any Table of Contents blocks using collected headings. if ( ! empty( $toc_configs ) ) { foreach ( $blocks_array as $idx => $blk_content ) { if ( isset( $toc_configs[ $blk_content ] ) ) { $t_cfg = $toc_configs[ $blk_content ]; $t_title = $t_cfg['title']; $t_levels_str = $t_cfg['levels']; $t_span = $t_cfg['span']; $allowed_levels = array_map( 'intval', array_filter( explode( ',', $t_levels_str ) ) ); $span_class = ( '1' === $t_span ) ? ' kofront-span-all' : ''; $filtered_items = array(); foreach ( $toc_items as $item ) { if ( in_array( intval( $item['level'] ), $allowed_levels, true ) ) { $filtered_items[] = $item; } } $toc_html = ''; $blocks_array[ $idx ] = $toc_html; } } } // Store pure Gutenberg blocks for full backend editor compatibility (2-col wrapper is applied via the_content filter). $gutenberg_content = implode( '', $blocks_array ); $post_args = array( 'post_title' => $post_title, 'post_content' => $gutenberg_content, 'post_excerpt' => $post_excerpt, 'post_status' => $final_status, 'post_type' => 'post', 'post_category' => $selected_cats, ); // Execute insert/update. $action_type = 'created'; if ( $post_id_to_edit > 0 ) { $existing_post = get_post( $post_id_to_edit ); if ( $existing_post && ( $existing_post->post_author == $current_user_id || current_user_can( 'edit_others_posts' ) ) ) { $post_args['ID'] = $post_id_to_edit; $post_id = wp_update_post( $post_args ); $action_type = 'updated'; } else { $post_id = new WP_Error( 'auth', 'Permission denied.' ); } } else { $post_args['post_author'] = $current_user_id; $post_id = wp_insert_post( $post_args ); } if ( ! is_wp_error( $post_id ) ) { update_post_meta( $post_id, '_kofront_layout_style', $layout_style ); if ( isset( $_POST['kofront_tags'] ) ) { wp_set_post_tags( $post_id, sanitize_text_field( wp_unslash( $_POST['kofront_tags'] ) ), false ); } $featured_block_key = isset( $_POST['kofront_featured_image_block'] ) ? sanitize_text_field( wp_unslash( $_POST['kofront_featured_image_block'] ) ) : ''; $clear_featured_flag = isset( $_POST['kofront_clear_featured'] ) ? intval( wp_unslash( $_POST['kofront_clear_featured'] ) ) : 0; if ( $featured_block_key && isset( $block_image_ids[ $featured_block_key ] ) ) { set_post_thumbnail( $post_id, $block_image_ids[ $featured_block_key ] ); } elseif ( ! empty( $_POST['kofront_existing_thumbnail'] ) ) { set_post_thumbnail( $post_id, intval( wp_unslash( $_POST['kofront_existing_thumbnail'] ) ) ); } elseif ( $clear_featured_flag === 1 ) { delete_post_thumbnail( $post_id ); } /// Redirect cleanly back to the dashboard URL via data attribute handled by kofront.js. $redirect_url = add_query_arg( array( 'kofront_success' => $action_type, 'kofront_saved_id' => $post_id, ), $dashboard_url ); return '

' . esc_html__( 'Saving and redirecting...', 'kofront-frontend-posts' ) . '

'; } else { $message .= '
Error: ' . esc_html( $post_id->get_error_message() ) . '
'; } } } // Prepare data for the form. $f_title = ''; $f_excerpt = ''; $f_cats = array(); $f_tags_str = ''; $f_status = 'publish'; $f_layout = '1-col'; $existing_blocks_html = ''; if ( $edit_id > 0 ) { $existing_post = get_post($edit_id); if ( $existing_post && ( $existing_post->post_author == $current_user_id || current_user_can( 'edit_others_posts' ) ) ) { $f_title = $existing_post->post_title; $f_excerpt = $existing_post->post_excerpt; $f_status = $existing_post->post_status; $f_cats = wp_get_post_categories($edit_id); $f_layout = get_post_meta($edit_id, '_kofront_layout_style', true) ?: '1-col'; $current_featured_id = get_post_thumbnail_id($edit_id); $tags = wp_get_post_tags($edit_id); if ($tags) { $tag_names = array(); foreach($tags as $t) { $tag_names[] = $t->name; } $f_tags_str = implode(', ', $tag_names); } $raw_html = $existing_post->post_content; $clean_html = preg_replace( '/^\s*
(.*)<\/div>\s*$/is', '$1', $raw_html ); $parsed_blks = parse_blocks( $clean_html ); $img_counter = 1000; foreach ( $parsed_blks as $p_block ) { if ( empty( $p_block['blockName'] ) ) { if ( '' !== trim( $p_block['innerHTML'] ) ) { $raw_val = esc_textarea( trim( $p_block['innerHTML'] ) ); $existing_blocks_html .= "
Custom HTML Block
(Backend HTML content preserved. You can reorder or delete it here, or edit it in the WordPress backend editor.)
"; } continue; } $b = preg_replace( '/^

0 ) ? 'Edit Post' : 'New Post'; ?>

Cancel

Post Content

Post Settings

term_id, $f_cats ) ? 'checked' : ''; ?>
Cancel / Discard
post_content, 'kofront_dashboard' ) || has_shortcode( $post->post_content, 'kofront_editor' ) ) ) { ?>

kofront User Guide

Welcome to kofront! This portal allows you to easily create, edit, and manage your website posts directly from the frontend.

1. Creating a Post: Click "+ Create New Post" at the top to open the editor. Enter your main title and use the content builder buttons to insert headings, text paragraphs, or body images.

2. Organizing Content: Use the up (↑) and down (↓) arrows on any content block to rearrange your article layout. Click "X" to remove a block.

3. Images & Sizing: Click "Choose Image" to securely access your media library, upload new files, or select existing ones. You can also select the radio button beneath an image to use it as the main Cover/Featured Image for your post.

4. Categories & Tags: Select existing categories or type a new one into the input box. For tags, write multiple tags separated by commas (e.g., design, tech, updates).

5. Saving Options: You can choose to publish your post immediately, save it as a draft for later review, or click "Cancel" to close the editor without saving.

array( 'href' => true, 'target' => true, 'rel' => true, 'title' => true, ), 'strong' => array(), 'b' => array(), 'em' => array(), 'i' => array(), 'u' => array(), 's' => array(), 'strike' => array(), 'del' => array(), 'code' => array(), 'mark' => array(), 'sub' => array(), 'sup' => array(), 'br' => array(), ); } function kofront_sanitize_inline_html( $html ) { return wp_kses( (string) $html, kofront_get_allowed_inline_html() ); } function kofront_get_richtext_toolbar_html( $context = 'paragraph' ) { $extra_btns = ''; if ( 'paragraph' === $context ) { $extra_btns = ""; } return "
{$extra_btns}
"; } function kofront_get_allowed_builder_html() { return array_merge( kofront_get_allowed_inline_html(), array( 'div' => array( 'class' => true, 'id' => true, 'style' => true, 'contenteditable' => true, 'data-placeholder' => true, ), 'strong' => array( 'class' => true, ), 'span' => array( 'class' => true, 'style' => true, ), 'em' => array(), 'label' => array( 'class' => true, 'style' => true, ), 'button' => array( 'type' => true, 'class' => true, 'title' => true, 'style' => true, 'data-target-type' => true, 'data-input-id' => true, 'data-counter' => true, 'data-cmd' => true, ), 'input' => array( 'type' => true, 'name' => true, 'id' => true, 'class' => true, 'value' => true, 'required' => true, 'checked' => true, 'disabled' => true, 'placeholder' => true, 'readonly' => true, ), 'select' => array( 'name' => true, 'class' => true, 'style' => true, ), 'option' => array( 'value' => true, 'selected' => true, ), 'textarea' => array( 'name' => true, 'class' => true, 'rows' => true, 'required' => true, 'placeholder' => true, 'readonly' => true, ), 'img' => array( 'src' => true, 'class' => true, 'alt' => true, ), ) ); } // --------------------------------------------------------- // 8. Register with Rank Math SEO as a Table of Contents provider. // --------------------------------------------------------- add_filter( 'rank_math/researches/toc_plugins', 'kofront_register_rank_math_toc' ); function kofront_register_rank_math_toc( $toc_plugins ) { $toc_plugins['kofront-frontend-posts/kofront-frontend-posts.php'] = 'kofront frontend posts'; return $toc_plugins; } // --------------------------------------------------------- // 9. Dynamically sync TOC and apply 2-column layout on frontend render. // --------------------------------------------------------- add_filter( 'the_content', 'kofront_filter_frontend_post_content', 20 ); function kofront_filter_frontend_post_content( $content ) { if ( ! is_singular( 'post' ) || ! in_the_loop() || ! is_main_query() ) { return $content; } $post_id = get_the_ID(); if ( ! $post_id ) { return $content; } // 1. If post contains a kofront TOC block, dynamically ensure all headings have IDs and sync the TOC list (supports backend edits). if ( strpos( $content, 'data-kofront-toc="1"' ) !== false ) { $used_ids = array(); $toc_items = array(); $content = preg_replace_callback( '/]*)>(.*?)<\/h\1>/is', function ( $matches ) use ( &$used_ids, &$toc_items ) { $level = intval( $matches[1] ); $attrs = $matches[2]; $inner_html = $matches[3]; $plain_text = trim( wp_strip_all_tags( $inner_html ) ); if ( '' === $plain_text ) { return $matches[0]; } if ( preg_match( '/\bid=["\']([^"\']+)["\']/i', $attrs, $id_match ) ) { $anchor_id = $id_match[1]; } else { $base_anchor = sanitize_title( $plain_text ); if ( '' === $base_anchor ) { $base_anchor = 'section'; } $anchor_id = $base_anchor; $suffix = 2; while ( in_array( $anchor_id, $used_ids, true ) ) { $anchor_id = $base_anchor . '-' . $suffix; $suffix++; } $attrs .= ' id="' . esc_attr( $anchor_id ) . '"'; } $used_ids[] = $anchor_id; $toc_items[] = array( 'level' => $level, 'text' => $plain_text, 'id' => $anchor_id, ); return '' . $inner_html . ''; }, $content ); $content = preg_replace_callback( '/]*\bdata-kofront-toc="1"[^>]*>.*?<\/nav>/is', function ( $nav_match ) use ( $toc_items ) { $nav_html = $nav_match[0]; $toc_title = __( 'Table of Contents', 'kofront-frontend-posts' ); if ( preg_match( '/data-toc-title="([^"]*)"/i', $nav_html, $t_match ) ) { $toc_title = wp_strip_all_tags( $t_match[1] ); } $toc_levels_str = '1,2,3,4,5,6'; if ( preg_match( '/data-toc-levels="([^"]*)"/i', $nav_html, $l_match ) ) { $toc_levels_str = preg_replace( '/[^0-9,]/', '', $l_match[1] ); } $allowed_levels = array_map( 'intval', array_filter( explode( ',', $toc_levels_str ) ) ); $toc_span = ( strpos( $nav_html, 'data-toc-span="1"' ) !== false || strpos( $nav_html, 'kofront-span-all' ) !== false ) ? '1' : '0'; $span_class = ( '1' === $toc_span ) ? ' kofront-span-all' : ''; $filtered_items = array(); foreach ( $toc_items as $item ) { if ( in_array( intval( $item['level'] ), $allowed_levels, true ) ) { $filtered_items[] = $item; } } $rebuilt = ''; return $rebuilt; }, $content ); } // 2. Apply the 2-column newspaper wrapper dynamically if enabled and not already present. $layout_style = get_post_meta( $post_id, '_kofront_layout_style', true ); if ( '2-col' === $layout_style && strpos( $content, 'kofront-newspaper-columns' ) === false ) { $content = '
' . $content . '
'; } return $content; }