Files
Bookshelf/bd-bookshelf/single-book.php
2026-10-18 19:01:01 -07:00

224 lines
8.2 KiB
PHP

<?php
// Copyright 2026 Umbra Tools (umbratools.com)
// SPDX-License-Identifier: Apache-2.0
/**
* Template Name: Book Detail
*
* Individual book page that pulls data from BD Bookshelf plugin database.
*
* @package BD_Murphy
*/
get_header();
// Get the book slug from the URL
$book_slug = get_query_var('book_slug');
if (empty($book_slug)) {
// Fallback: try to get from query var set by rewrite rule
global $wp_query;
$book_slug = $wp_query->get('book_slug');
}
if (empty($book_slug)) {
// Try to get from the current page slug
$book_slug = get_post_field('post_name', get_the_ID());
}
// Try to load book from plugin database
$book = null;
if (class_exists('BDM_Book_Manager') && !empty($book_slug)) {
$book = BDM_Book_Manager::get_book_by_slug($book_slug);
}
if (!$book) {
// Show a message if book not found
?>
<div class="book-page-container">
<div style="text-align: center; padding: 60px 20px;">
<h1><?php esc_html_e('Book Not Found', 'bd-bookshelf'); ?></h1>
<p><?php esc_html_e('The book you are looking for could not be found.', 'bd-bookshelf'); ?></p>
<a href="<?php echo esc_url(home_url('/books/')); ?>" class="btn-primary"><?php esc_html_e('Browse All Books', 'bd-bookshelf'); ?></a>
</div>
</div>
<?php
get_footer();
return;
}
// Get book data
$title = esc_html($book->title);
$description = wp_kses_post($book->description);
$cover_url = esc_url($book->cover_image);
// Get authors
$author_names = [];
foreach ($book->authors as $ba) {
$author_names[] = esc_html($ba->author_name);
}
$author_string = !empty($author_names) ? implode(', ', $author_names) : 'B.D. Murphy';
// Get series info
$series = null;
if ($book->series_id > 0 && class_exists('BDM_Series')) {
$series = BDM_Series::get_series($book->series_id);
}
// Get retail links grouped by format
$retail_links = [];
if (!empty($book->retail_links)) {
foreach ($book->retail_links as $link) {
$format = $link->format;
if (!isset($retail_links[$format])) {
$retail_links[$format] = [];
}
$retail_links[$format][] = $link;
}
}
// Get rating display
$rating_html = '';
if ($book->rating_amazon > 0 || $book->rating_goodreads > 0) {
$rating_html .= '<div class="book-ratings">';
if ($book->rating_amazon > 0) {
$rating_html .= '<span class="rating amazon">' . number_format($book->rating_amazon, 1) . '/5 (Amazon)</span>';
}
if ($book->rating_goodreads > 0) {
$rating_html .= '<span class="rating goodreads">' . number_format($book->rating_goodreads, 1) . '/5 (Goodreads)</span>';
}
$rating_html .= '</div>';
}
// Social share URL
$share_url = home_url('/book/' . urlencode($book->slug) . '/');
?>
<div class="book-page-container">
<div class="book-page-layout">
<!-- Left Column: Cover + Purchase Links -->
<div class="book-page-left">
<div class="book-page-cover">
<?php if ($cover_url) : ?>
<img src="<?php echo $cover_url; ?>" alt="<?php echo $title; ?>">
<?php else : ?>
<div class="book-page-cover-placeholder"><?php echo $title; ?></div>
<?php endif; ?>
</div>
<div class="book-purchase-section">
<!-- Format Toggle -->
<?php if (!empty($retail_links)) : ?>
<div class="book-format-toggle" role="tablist" aria-label="<?php esc_attr_e('Format selection', 'bd-bookshelf'); ?>">
<?php
$formats = ['ebook' => __('eBook', 'bd-bookshelf'), 'paperback' => __('Paperback', 'bd-bookshelf'), 'hardcover' => __('Hardback', 'bd-bookshelf'), 'audio' => __('Audio', 'bd-bookshelf')];
$active_format = 'ebook';
$has_format = [];
foreach (array_keys($retail_links) as $f) {
$has_format[$f] = true;
}
$first_format = key($retail_links);
$active_format = $first_format;
?>
<?php foreach ($formats as $fmt => $label) : ?>
<?php if (isset($has_format[$fmt])) : ?>
<button class="format-btn<?php echo ($fmt === $active_format) ? ' active' : ''; ?>"
data-format="<?php echo esc_attr($fmt); ?>"
role="tab"
aria-selected="<?php echo ($fmt === $active_format) ? 'true' : 'false'; ?>"
onclick="showFormat('<?php echo esc_attr($fmt); ?>')">
<?php echo $label; ?>
</button>
<?php endif; ?>
<?php endforeach; ?>
</div>
<!-- Retail Links by Format -->
<div class="book-retailer-links">
<?php foreach ($retail_links as $format => $links) : ?>
<div class="format-links" id="links-<?php echo esc_attr($format); ?>" style="<?php echo ($format === $active_format) ? '' : 'display:none'; ?>">
<?php foreach ($links as $link) : ?>
<a href="<?php echo esc_url($link->url); ?>" class="retailer-link" target="_blank" rel="noopener noreferrer">
<?php echo esc_html($link->site_name); ?>
</a>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
<!-- Center Column: Book Details -->
<div class="book-page-center">
<div class="book-page-header">
<div class="book-title-section">
<h1 class="book-title"><?php echo $title; ?></h1>
<p class="book-pen-name"><?php echo $author_string; ?></p>
<?php if ($series) : ?>
<p class="book-series-info">
<?php
printf(
esc_html__('Part of the %s series', 'bd-bookshelf'),
esc_html($series->name)
);
?>
</p>
<?php endif; ?>
</div>
</div>
<?php echo $rating_html; ?>
<?php if ($description) : ?>
<div class="book-blurb">
<div class="blurb-text"><?php echo $description; ?></div>
</div>
<?php endif; ?>
<div class="book-share-section">
<div class="social-share-buttons">
<?php get_template_part('template-parts/social-share'); ?>
</div>
</div>
</div>
<!-- Right Column: Sidebar -->
<aside class="book-page-sidebar">
<?php if (is_active_sidebar('book-detail-sidebar')) : ?>
<div class="book-sidebar-widgets">
<?php dynamic_sidebar('book-detail-sidebar'); ?>
</div>
<?php endif; ?>
</aside>
</div>
</div>
<script>
function showFormat(format) {
// Hide all format links
document.querySelectorAll('.format-links').forEach(function(el) {
el.style.display = 'none';
});
// Show selected format links
var target = document.getElementById('links-' + format);
if (target) {
target.style.display = '';
}
// Update active button
document.querySelectorAll('.format-btn').forEach(function(btn) {
btn.classList.remove('active');
btn.setAttribute('aria-selected', 'false');
});
var activeBtn = document.querySelector('.format-btn[data-format="' + format + '"]');
if (activeBtn) {
activeBtn.classList.add('active');
activeBtn.setAttribute('aria-selected', 'true');
}
}
</script>
<?php
get_footer();