<?php
|
namespace JVBase\blocks;
|
|
use JVBase\managers\CacheManager;
|
use JVBase\forms\TaxonomySelector;
|
use JVBase\meta\MetaManager;
|
use WP_Block;
|
use WP_Query;
|
|
class FAQBlock {
|
protected CacheManager $cache;
|
public function __construct()
|
{
|
$this->cache = CacheManager::for('faq_block', WEEK_IN_SECONDS);
|
add_action('init', [ $this, 'registerBlock' ]);
|
add_action('enqueue_block_editor_assets', [$this, 'localizeData']);
|
}
|
|
/**
|
* Register the FAQ block
|
*/
|
public function registerBlock() {
|
// Register the block
|
register_block_type(
|
JVB_DIR . '/build/faq',
|
[
|
'render_callback' => [$this, 'render'],
|
]
|
);
|
//
|
// // Localize script data for the editor
|
// add_action('enqueue_block_editor_assets', [$this, 'enqueue_editor_assets']);
|
//
|
// // Enqueue frontend scripts
|
// add_action('wp_enqueue_scripts', [$this, 'enqueue_frontend_assets']);
|
}
|
|
/**
|
* Enqueue editor assets
|
*/
|
public static function enqueue_editor_assets() {
|
// Pass section taxonomy name to JavaScript
|
wp_localize_script(
|
'jvb-faq-editor-script',
|
'jvbFaq',
|
[
|
'sectionTaxonomy' => BASE . 'section',
|
'faqPostType' => BASE . 'faq',
|
]
|
);
|
}
|
|
/**
|
* Enqueue frontend assets
|
*/
|
public static function enqueue_frontend_assets() {
|
// Check if block is being used on this page
|
if (has_block('jvb/faq')) {
|
wp_enqueue_script(
|
'jvb-faq-view',
|
JVB_URL . '/build/faq/view.js',
|
[],
|
filemtime(JVB_DIR . '/build/faq/view.js'),
|
true
|
);
|
}
|
}
|
|
/**
|
* Localize forms data for block editor
|
*/
|
public function localizeData(): void
|
{
|
// Get all sections
|
$section_taxonomy = BASE . 'section';
|
$sections_data = $this->cache->remember(
|
'sections',
|
function() {
|
$sections = get_terms([
|
'taxonomy' => BASE.'section',
|
'hide_empty' => false,
|
'orderby' => 'name',
|
'order' => 'ASC',
|
]);
|
|
// Format sections for JavaScript
|
$sections_data = [];
|
if (!is_wp_error($sections) && !empty($sections)) {
|
foreach ($sections as $term) {
|
$sections_data[] = [
|
'id' => $term->term_id,
|
'name' => $term->name,
|
'slug' => $term->slug,
|
];
|
}
|
}
|
return $sections_data;
|
}
|
);
|
|
|
// Pass section taxonomy name and sections to JavaScript
|
wp_localize_script(
|
'jvb-faq-editor-script',
|
'jvbFaq',
|
[
|
'sectionTaxonomy' => $section_taxonomy,
|
'faqPostType' => BASE . 'faq',
|
'sections' => $sections_data,
|
]
|
);
|
}
|
|
/**
|
* Render callback
|
*
|
* @param array $attributes Block attributes
|
* @param string $content Block content
|
* @param WP_Block $block Block instance
|
* @return string Rendered block HTML
|
*/
|
public function render($attributes, $content, $block)
|
{
|
ob_start();
|
?>
|
<?php
|
/**
|
* FAQ Block Template
|
*
|
* @param array $attributes Block attributes
|
* @param string $content Block content
|
* @param WP_Block $block Block instance
|
*/
|
// Get BASE constant
|
$base = defined('BASE') ? BASE : '';
|
$faq_post_type = $base . 'faq';
|
$section_taxonomy = $base . 'section';
|
|
// Get block attributes
|
$section_order = $attributes['sectionOrder'] ?? [];
|
$show_section_titles = $attributes['showSectionTitles'] ?? true;
|
$collapse_by_default = $attributes['collapseByDefault'] ?? false;
|
|
// Determine if we're on a taxonomy archive or main FAQ archive
|
$is_tax_archive = is_tax($section_taxonomy);
|
$current_term = null;
|
|
if ($is_tax_archive) {
|
$current_term = get_queried_object();
|
global $wp_query;
|
$faq_query = $wp_query;
|
} else {
|
// Build query args based on context
|
$query_args = [
|
'post_type' => $faq_post_type,
|
'posts_per_page' => -1,
|
'post_status' => 'publish',
|
'orderby' => 'menu_order title',
|
'order' => 'ASC',
|
];
|
// Get FAQs
|
$faq_query = new WP_Query($query_args);
|
}
|
|
|
if (!$faq_query->have_posts()) {
|
echo '<div class="faq-block faq-block--empty">';
|
echo '<p>' . esc_html__('No FAQs found.', 'jvb') . '</p>';
|
echo '</div>';
|
return;
|
}
|
|
// Organize FAQs by section
|
$faqs_by_section = [];
|
|
while ($faq_query->have_posts()) {
|
$faq_query->the_post();
|
$post_id = get_the_ID();
|
|
$terms = get_the_terms($post_id, $section_taxonomy);
|
|
if ($terms && !is_wp_error($terms)) {
|
foreach ($terms as $term) {
|
if (!isset($faqs_by_section[$term->term_id])) {
|
$faqs_by_section[$term->term_id] = [
|
'term' => $term,
|
'faqs' => [],
|
];
|
}
|
|
$faqs_by_section[$term->term_id]['faqs'][] = [
|
'id' => $post_id,
|
'title' => get_the_title(),
|
'content' => get_the_excerpt(),
|
'url' => get_the_permalink(),
|
];
|
}
|
} else {
|
// FAQ without section - add to "uncategorized"
|
if (!isset($faqs_by_section[0])) {
|
$faqs_by_section[0] = [
|
'term' => (object) [
|
'term_id' => 0,
|
'name' => __('General', 'jvb'),
|
'slug' => 'general',
|
],
|
'faqs' => [],
|
];
|
}
|
|
$faqs_by_section[0]['faqs'][] = [
|
'id' => $post_id,
|
'title' => get_the_title(),
|
'content' => get_the_excerpt(),
|
'url' => get_the_permalink(),
|
];
|
}
|
}
|
|
wp_reset_postdata();
|
|
// If on main FAQ archive and we have a custom order, apply it
|
if (!$is_tax_archive && !empty($section_order)) {
|
$ordered_sections = [];
|
|
// Add sections in custom order
|
foreach ($section_order as $term_id) {
|
if (isset($faqs_by_section[$term_id])) {
|
$ordered_sections[$term_id] = $faqs_by_section[$term_id];
|
}
|
}
|
|
// Add any sections not in the custom order at the end
|
foreach ($faqs_by_section as $term_id => $section_data) {
|
if (!isset($ordered_sections[$term_id])) {
|
$ordered_sections[$term_id] = $section_data;
|
}
|
}
|
|
$faqs_by_section = $ordered_sections;
|
}
|
|
// Generate unique IDs for accordion functionality
|
$block_id = 'faq-block-' . wp_unique_id();
|
|
// Render the block
|
$wrapper_attributes = get_block_wrapper_attributes([
|
'class' => 'faq-block',
|
'data-block-id' => $block_id,
|
]);
|
|
$nav = '';
|
if (!empty($section_order)) {
|
$nav = '<nav id="faq"><h2>Sections:</h2><ol>';
|
foreach ($section_order as $term_id) {
|
$term = get_term($term_id, $section_taxonomy);
|
if ($term && !is_wp_error($term)) {
|
$url = (!$is_tax_archive) ? "#{$term->slug}" : get_term_link($term);
|
$nav .= '<li><a href="'.$url.'">'.$term->name.'</a></li>';
|
}
|
}
|
$seeAll = ($is_tax_archive) ? '<p><a href="'.get_post_type_archive_link(BASE.'faq').'">'.__('See All FAQs', 'jvb').'</a></p>' : '';
|
$nav .= '</ol>'.$seeAll.'</nav>';
|
}
|
?>
|
|
<section <?php echo $wrapper_attributes; ?>>
|
<?= $nav ?>
|
<?php foreach ($faqs_by_section as $term_id => $section_data): ?>
|
<div id="<?= $section_data['term']->slug?>" class="faq-section" data-section-id="<?php echo esc_attr($term_id); ?>">
|
<?php if ($show_section_titles): ?>
|
<h2>
|
<?php echo esc_html($section_data['term']->name); ?>
|
</h2>
|
<?php endif; ?>
|
|
<div class="faq-list">
|
<?php foreach ($section_data['faqs'] as $index => $faq): ?>
|
<?php
|
$faq_id = $block_id . '-faq-' . $faq['id'];
|
$is_expanded = !$collapse_by_default;
|
?>
|
<details class="faq"<?= !$collapse_by_default ? ' open' : '' ?>>
|
<summary><h3><b>Q</b> <?= esc_html($faq['title']) ?></h3></summary>
|
<?= apply_filters('the_content', $faq['content']) ?>
|
<a class="button" href="<?= $faq['url'] ?>" title="Learn More about <?=$faq['title']?>">Learn More</a>
|
</details>
|
<?php endforeach; ?>
|
</div>
|
</div>
|
<?php endforeach; ?>
|
</section>
|
|
<?php
|
return ob_get_clean();
|
}
|
}
|