$val ) { if ( (string) $key === (string) $template_id ) { $block = $val; break; } } } if ( $block ) { $block = stripslashes_deep( $block ); // Prime transient for the "second refresh" speed. set_transient( 'addifect_site_template_' . $template_id, $block, MINUTE_IN_SECONDS ); return $block; } } return false; } /** * Get the active index for the current Kit/Design session. * * Logic: * 1. Try high-speed transient (addifect_index_{design_id}_{kit_id}) * 2. Fallback to Master Post Meta (_addifect_design_index) * 3. Re-prime transient if fallback was successful. * * @return array The index array (parts, all_keys, version, etc.) */ function addifect_get_active_index() { // Try the single active transient first. $index = get_transient( 'addifect_active_session_index' ); if ( false !== $index && is_array( $index ) ) { return $index; } // Fallback: Use the connection to pull directly from the Design Meta and re-prime the transient. $connection = get_option( 'addifect_active_connection' ); if ( ! empty( $connection['design_id'] ) ) { $master = get_post_meta( $connection['design_id'], '_addifect_design_index', true ); // If the master index exists and is an array, prime the transient and return it. if ( is_array( $master ) ) { set_transient( 'addifect_active_session_index', $master, 12 * HOUR_IN_SECONDS ); return $master; } } // Default empty state if nothing is found. return array( 'parts' => array(), 'all_keys' => array(), ); } /** * Get allowed HTML for Addifect rendering. * * @return array */ function addifect_get_allowed_html() { $allowed_tags = wp_kses_allowed_html( 'post' ); // Tags that should support style + tabindex. $interactive_tags = array( 'div', 'section', 'nav', 'a', 'span', 'img' ); foreach ( $interactive_tags as $tag ) { if ( isset( $allowed_tags[ $tag ] ) ) { $allowed_tags[ $tag ]['tabindex'] = true; $allowed_tags[ $tag ]['style'] = true; // ✅ CRITICAL } } // Extend anchor attributes. if ( isset( $allowed_tags['a'] ) ) { $allowed_tags['a'] = array_merge( $allowed_tags['a'], array( 'href' => true, 'target' => true, 'rel' => true, 'download' => true, ) ); } return $allowed_tags; } /** * Retrieve the HTML content of a template part (e.g., header or footer). * * This function fetches a template by its ID using `addifect_get_template()` * and returns the server-side rendered HTML (`ssr['html']`) if available. * If the template or its HTML does not exist, it returns an empty string. * * @since 1.0.2 * * @param string|int $template_id The unique identifier of the template part. * @return string The rendered HTML of the template part, or an empty string. */ function addifect_get_part_html( $template_id ) { $data = addifect_get_template( $template_id ); return ! empty( $data['ssr']['html'] ) ? $data['ssr']['html'] : ''; } /** * Extract header and footer HTML from template data. * * Safely reads template_parts and returns rendered HTML * for header and footer if available. * * @since 1.0.2 * * @param array $template Template data array. * @return array { * @type string $header Header HTML. * @type string $footer Footer HTML. * } */ function addifect_resolve_template_parts( $template ) { $result = array( 'header' => '', 'footer' => '', ); if ( empty( $template['globalParts'] ) || ! is_array( $template['globalParts'] ) ) { return $result; } $parts = $template['globalParts']; if ( ! empty( $parts['top'] ) ) { $result['header'] = addifect_get_part_html( $parts['top'] ); } if ( ! empty( $parts['bottom'] ) ) { $result['footer'] = addifect_get_part_html( $parts['bottom'] ); } return $result; } /** * Safely get SSR HTML from template data. * * @since 1.0.2 * * @param array $template Template array. * @return string */ function addifect_get_ssr_html( $template ) { if ( ! empty( $template['ssr'] ) && is_array( $template['ssr'] ) && ! empty( $template['ssr']['html'] ) ) { return $template['ssr']['html']; } return ''; } /** * Replaces Addifect data-binding variables (e.g., {{global.activePost.meta.title}}) * with actual WordPress database values in the SSR HTML string. * * @param string $html The raw SSR HTML string. * @return string The hydrated HTML string. */ function addifect_hydrate_ssr_html( $html ) { // 1. Unlocked: Process on ALL single post types (pages, posts, vault, guide, etc.) if ( ! is_singular() ) { return $html; } global $post; // 2. Fetch the featured image safely $featured_image = get_the_post_thumbnail_url( $post->ID, 'large' ); // 3. Define the raw mapping keys and their dynamic values $raw_map = array( 'global.activePost.meta.title' => esc_html( $post->post_title ), 'global.activePost.meta.slug' => esc_html( $post->post_name ), 'global.activePost.meta.date' => esc_html( get_the_date( '', $post ) ), 'global.activePost.meta.featuredImage' => $featured_image ? esc_url( $featured_image ) : '', 'global.activePost.content' => ! empty( $post->post_content ) ? $post->post_content : '', ); $replacements = array(); // 4. Build both Standard and URL-Encoded replacement tokens foreach ( $raw_map as $key => $value ) { $replacements[ '{{' . $key . '}}' ] = $value; } // 5. Execute a hyper-fast string replacement globally across the HTML return str_replace( array_keys( $replacements ), array_values( $replacements ), $html ); }