string, 'sections' => array] */ function igny8_parse_content_sections($content) { if (empty($content)) { return ['intro' => '', 'sections' => []]; } // Use DOMDocument to parse HTML $dom = new DOMDocument('1.0', 'UTF-8'); libxml_use_internal_errors(true); // Wrap content in a div to ensure proper parsing $wrapped_content = '
' . $content . '
'; $dom->loadHTML('' . $wrapped_content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); libxml_clear_errors(); $intro_html = ''; $sections = []; $current_section = null; // Get the wrapper div $xpath = new DOMXPath($dom); $nodes = $xpath->query('//div/*'); if ($nodes->length === 0) { return ['intro' => $content, 'sections' => []]; } // Iterate through all child nodes foreach ($nodes as $node) { // Check if node is an H2 heading if ($node->nodeName === 'h2') { // Save previous section if exists if ($current_section !== null) { $sections[] = $current_section; } // Start new section $current_section = [ 'heading' => trim($node->textContent), 'content' => '', 'id' => sanitize_title($node->textContent) ]; } elseif ($current_section !== null) { // Add to current section $current_section['content'] .= $dom->saveHTML($node); } else { // Add to intro (before first H2) $intro_html .= $dom->saveHTML($node); } } // Save last section if ($current_section !== null) { $sections[] = $current_section; } return [ 'intro' => trim($intro_html), 'sections' => $sections ]; } /** * Get in-article images from imported images meta * * @param int $post_id Post ID * @return array Indexed array of image data by position */ function igny8_get_in_article_images($post_id) { $imported_images = get_post_meta($post_id, '_igny8_imported_images', true); if (empty($imported_images) || !is_array($imported_images)) { return []; } $in_article_images = []; foreach ($imported_images as $img) { // Skip featured images if (isset($img['is_featured']) && $img['is_featured']) { continue; } $position = isset($img['position']) ? (int)$img['position'] : count($in_article_images) + 1; $in_article_images[$position] = $img; } return $in_article_images; } /** * Get featured image prompt from imported images meta * * @param int $post_id Post ID * @return string|null Image prompt or null */ function igny8_get_featured_image_prompt($post_id) { $imported_images = get_post_meta($post_id, '_igny8_imported_images', true); if (empty($imported_images) || !is_array($imported_images)) { return null; } foreach ($imported_images as $img) { if (isset($img['is_featured']) && $img['is_featured'] && isset($img['prompt'])) { return $img['prompt']; } } return null; } /** * Get featured image caption from imported images meta * * @param int $post_id Post ID * @return string|null Image caption or null */ function igny8_get_featured_image_caption($post_id) { $imported_images = get_post_meta($post_id, '_igny8_imported_images', true); if (empty($imported_images) || !is_array($imported_images)) { return null; } foreach ($imported_images as $img) { if (isset($img['is_featured']) && $img['is_featured'] && isset($img['caption'])) { return $img['caption']; } } return null; } /** * Format status label for display * * @param string $status Post status * @return string Formatted label */ function igny8_format_status_label($status) { $labels = [ 'draft' => 'Draft', 'pending' => 'Pending Review', 'publish' => 'Published', 'private' => 'Private', 'future' => 'Scheduled', 'trash' => 'Trash' ]; return isset($labels[$status]) ? $labels[$status] : ucfirst($status); } /** * Get status CSS class * * @param string $status Post status * @return string CSS class */ function igny8_get_status_class($status) { $classes = [ 'draft' => 'igny8-status-draft', 'pending' => 'igny8-status-pending', 'publish' => 'igny8-status-publish', 'private' => 'igny8-status-private', 'future' => 'igny8-status-future' ]; return isset($classes[$status]) ? $classes[$status] : 'igny8-status-default'; } /** * Calculate word count from content * * @param string $content HTML content * @return int Word count */ function igny8_calculate_word_count($content) { if (empty($content)) { return 0; } // Strip HTML tags and count words $text = wp_strip_all_tags($content); return str_word_count($text); } /** * Parse secondary keywords from meta * * @param string $keywords Comma-separated keywords * @return array Array of keywords */ function igny8_parse_keywords($keywords) { if (empty($keywords)) { return []; } // Split by comma and trim each keyword $keywords_array = array_map('trim', explode(',', $keywords)); // Remove empty values return array_filter($keywords_array); } /** * Get section badges based on keyword/tag matching * Returns only ONE badge per section and tracks used keywords to avoid repeats * * @param string $heading Section heading text * @param int $post_id Post ID * @param array &$used_keywords Reference to array tracking already-used keywords * @return array Array of badges with 'text' and 'type' keys (max 1) */ function igny8_get_section_badges($heading, $post_id, &$used_keywords = null) { // Initialize static variable to track used keywords across calls if not passed static $static_used_keywords = []; if ($used_keywords === null) { $used_keywords = &$static_used_keywords; } $badges = []; $heading_lower = strtolower($heading); // Get post taxonomies and keywords $tags = get_the_tags($post_id); $categories = get_the_category($post_id); $primary_kw = get_post_meta($post_id, '_igny8_primary_keyword', true); $secondary_kws = get_post_meta($post_id, '_igny8_secondary_keywords', true); // Priority 1: Primary keyword (if not already used) if ($primary_kw && !in_array(strtolower($primary_kw), $used_keywords)) { if (stripos($heading_lower, strtolower($primary_kw)) !== false) { $badges[] = ['text' => $primary_kw, 'type' => 'primary']; $used_keywords[] = strtolower($primary_kw); return $badges; // Return only 1 } } // Priority 2: Tags (if not already used) if ($tags && !is_wp_error($tags) && count($badges) < 1) { foreach ($tags as $tag) { $tag_lower = strtolower($tag->name); if (!in_array($tag_lower, $used_keywords) && stripos($heading_lower, $tag_lower) !== false) { $badges[] = ['text' => $tag->name, 'type' => 'tag']; $used_keywords[] = $tag_lower; return $badges; // Return only 1 } } } // Priority 3: Categories (if not already used) if ($categories && !is_wp_error($categories) && count($badges) < 1) { foreach ($categories as $cat) { $cat_lower = strtolower($cat->name); if (!in_array($cat_lower, $used_keywords) && stripos($heading_lower, $cat_lower) !== false) { $badges[] = ['text' => $cat->name, 'type' => 'category']; $used_keywords[] = $cat_lower; return $badges; // Return only 1 } } } // Priority 4: Secondary keywords (if not already used) if ($secondary_kws && count($badges) < 1) { $kw_array = is_array($secondary_kws) ? $secondary_kws : explode(',', $secondary_kws); foreach ($kw_array as $kw) { $kw = trim($kw); $kw_lower = strtolower($kw); if (!empty($kw) && !in_array($kw_lower, $used_keywords) && stripos($heading_lower, $kw_lower) !== false) { $badges[] = ['text' => $kw, 'type' => 'keyword']; $used_keywords[] = $kw_lower; return $badges; // Return only 1 } } } return $badges; } /** * Reset the used keywords tracker (call at start of template) */ function igny8_reset_used_keywords() { // Reset the static variable by calling with empty reference $empty = []; igny8_get_section_badges('', 0, $empty); } /** * Check if section content contains a table * * @param string $section_html Section HTML content * @return bool True if contains table */ function igny8_section_has_table($section_html) { return (stripos($section_html, ']*>(.*?)<\/h2>/i', $content, $matches); if (!empty($matches[1])) { foreach ($matches[1] as $index => $heading) { $heading_text = strip_tags($heading); $slug = sanitize_title($heading_text); $toc_items[] = [ 'number' => $index + 1, 'text' => $heading_text, 'id' => $slug ]; } } return $toc_items; } /** * Render widget placeholder * * @param string $position 'left' or 'right' * @param int $section_index Section index * @return void */ function igny8_render_widget_placeholder($position, $section_index) { // Check if widgets are enabled in settings $widgets_enabled = get_option('igny8_widgets_enabled', false); if (!$widgets_enabled) { return; } $placeholder_class = 'igny8-widget-placeholder igny8-widgets-enabled'; $placeholder_class .= ' igny8-widget-' . $position; $placeholder_class .= ' igny8-widget-section-' . $section_index; ?>