Files
igny8/plugins/wordpress/source/igny8-wp-bridge/includes/template-functions.php
2026-01-10 03:58:02 +00:00

355 lines
9.8 KiB
PHP

<?php
/**
* Template Helper Functions
*
* Helper functions for IGNY8 content template
*
* @package Igny8Bridge
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
/**
* Parse content HTML into intro and H2 sections
*
* @param string $content HTML content
* @return array ['intro' => 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 = '<div>' . $content . '</div>';
$dom->loadHTML('<?xml encoding="UTF-8">' . $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;
}
/**
* 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
*
* @param string $heading Section heading text
* @param int $post_id Post ID
* @return array Array of badges with 'text' and 'type' keys
*/
function igny8_get_section_badges($heading, $post_id) {
$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 ($primary_kw && stripos($heading_lower, strtolower($primary_kw)) !== false) {
$badges[] = ['text' => $primary_kw, 'type' => 'primary'];
}
// Priority 2: Tags
if ($tags && !is_wp_error($tags) && count($badges) < 2) {
foreach ($tags as $tag) {
if (stripos($heading_lower, strtolower($tag->name)) !== false) {
$badges[] = ['text' => $tag->name, 'type' => 'tag'];
if (count($badges) >= 2) break;
}
}
}
// Priority 3: Categories
if ($categories && !is_wp_error($categories) && count($badges) < 2) {
foreach ($categories as $cat) {
if (stripos($heading_lower, strtolower($cat->name)) !== false) {
$badges[] = ['text' => $cat->name, 'type' => 'category'];
if (count($badges) >= 2) break;
}
}
}
// Priority 4: Secondary keywords
if ($secondary_kws && count($badges) < 2) {
$kw_array = is_array($secondary_kws) ? $secondary_kws : explode(',', $secondary_kws);
foreach ($kw_array as $kw) {
$kw = trim($kw);
if (!empty($kw) && stripos($heading_lower, strtolower($kw)) !== false) {
$badges[] = ['text' => $kw, 'type' => 'keyword'];
if (count($badges) >= 2) break;
}
}
}
return $badges;
}
/**
* 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, '<table') !== false);
}
/**
* Get image aspect ratio from position
*
* @param int $position Image position (0-3)
* @return string 'square' or 'landscape'
*/
function igny8_get_image_aspect($position) {
// Even positions (0, 2) = square
// Odd positions (1, 3) = landscape
return ($position % 2 === 0) ? 'square' : 'landscape';
}
/**
* Determine if image description should be shown
*
* @param int $section_index Section index (0-based)
* @return bool True if should show description
*/
function igny8_show_image_description($section_index) {
// First 4 sections (0-3) show descriptions
return ($section_index < 4);
}
/**
* Generate table of contents from content
*
* @param string $content HTML content
* @return array Array of TOC items with 'number', 'text', and 'id' keys
*/
function igny8_generate_table_of_contents($content) {
$toc_items = [];
// Parse content for H2 headings
preg_match_all('/<h2[^>]*>(.*?)<\/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;
?>
<div class="<?php echo esc_attr($placeholder_class); ?>"
data-widget-position="<?php echo esc_attr($position); ?>"
data-section-index="<?php echo esc_attr($section_index); ?>">
<?php
/**
* Action hook for widget placeholder content
*
* @param string $position Widget position (left/right)
* @param int $section_index Section index
*/
do_action('igny8_widget_placeholder', $position, $section_index);
?>
</div>
<?php
}