Continues the Bookshelf history. The three plugins tracked there are consolidated into umbra-bookshelf/ and this repository becomes the canonical home for the plugin and the theme. bd-bookshelf/ -> theme/ separate artifact, name unchanged (root specs) -> umbra-bookshelf/spec/ aligned to Umbra Bookshelf old plugin zips -> archive/pre-umbra-releases/ Adds a repository README and drops the Bookshelf closure notice.
176 lines
6.6 KiB
PHP
176 lines
6.6 KiB
PHP
<?php
|
|
// Copyright 2026 Umbra Tools (umbratools.com)
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
/**
|
|
* Template Name: Books
|
|
*
|
|
* Grid layout of all books from BD Bookshelf plugin database.
|
|
* Shows plugin books if available, otherwise shows default examples.
|
|
*
|
|
* @package BD_Murphy
|
|
*/
|
|
|
|
get_header();
|
|
|
|
// Check if BD Bookshelf plugin is active and has books
|
|
$has_plugin_books = class_exists('BD_Bookshelf') && class_exists('BDM_Book_Manager');
|
|
$plugin_books = [];
|
|
|
|
if ($has_plugin_books) {
|
|
$plugin_books = BDM_Book_Manager::get_books(['number' => 100, 'orderby' => 'title', 'order' => 'ASC']);
|
|
}
|
|
|
|
// Default books from authorbdmurphy.com (used when BD Bookshelf plugin is not active)
|
|
$uploads = wp_upload_dir();
|
|
$cover_dir = $uploads['baseurl'] . '/book-covers';
|
|
|
|
$default_books = array(
|
|
array(
|
|
'title' => 'Pandemic Hacker',
|
|
'cover' => $cover_dir . '/pandemic-hacker.jpg',
|
|
'author' => 'B.D. Murphy',
|
|
'rating' => '4.4',
|
|
'url' => 'https://books2read.com/u/ml8z0W',
|
|
),
|
|
array(
|
|
'title' => 'Pandemic Hacker 2',
|
|
'cover' => $cover_dir . '/pandemic-hacker-2.jpg',
|
|
'author' => 'B.D. Murphy',
|
|
'rating' => '4.9',
|
|
'url' => 'https://books2read.com/u/4jjzvD',
|
|
),
|
|
array(
|
|
'title' => 'The Last Dwarf',
|
|
'cover' => $cover_dir . '/the-last-dwarf.jpg',
|
|
'author' => 'B.D. Murphy',
|
|
'rating' => '3.6',
|
|
'url' => 'https://books2read.com/u/bPAD27',
|
|
),
|
|
array(
|
|
'title' => 'Deal Hunter',
|
|
'cover' => $cover_dir . '/deal-hunter.jpg',
|
|
'author' => 'B.D. Murphy',
|
|
'rating' => '5.0',
|
|
'url' => 'https://books2read.com/u/3LxrVN',
|
|
),
|
|
array(
|
|
'title' => 'Nanite Evolution',
|
|
'cover' => $cover_dir . '/nanite-evolution.jpg',
|
|
'author' => 'B.D. Murphy',
|
|
'rating' => '5.0',
|
|
'url' => 'https://books2read.com/u/4E08e0',
|
|
),
|
|
array(
|
|
'title' => 'Sidney and Watson: Time Detectives',
|
|
'cover' => $cover_dir . '/sidney-watson.jpg',
|
|
'author' => 'B.D. Murphy',
|
|
'rating' => '5.0',
|
|
'url' => 'https://books2read.com/u/3kXXEW',
|
|
),
|
|
);
|
|
?>
|
|
|
|
<div class="books-page-container">
|
|
<header class="page-header">
|
|
<h1 class="page-title"><?php esc_html_e('Books', 'bd-bookshelf'); ?></h1>
|
|
</header>
|
|
|
|
<div class="books-grid">
|
|
<?php
|
|
if (!empty($plugin_books)) :
|
|
foreach ($plugin_books as $book) :
|
|
$title = esc_html($book->title);
|
|
$cover_url = esc_url($book->cover_image);
|
|
$book_url = home_url('/book/' . urlencode($book->slug) . '/');
|
|
$author_name = '';
|
|
|
|
// Get primary author name
|
|
if (!empty($book->authors)) {
|
|
foreach ($book->authors as $ba) {
|
|
if ($ba->is_primary) {
|
|
$author_name = esc_html($ba->author_name);
|
|
break;
|
|
}
|
|
}
|
|
if (empty($author_name) && isset($book->authors[0])) {
|
|
$author_name = esc_html($book->authors[0]->author_name);
|
|
}
|
|
}
|
|
if (empty($author_name)) {
|
|
$author_name = 'B.D. Murphy';
|
|
}
|
|
|
|
// Rating display
|
|
$rating_display = '';
|
|
if ($book->rating_amazon > 0 || $book->rating_goodreads > 0) {
|
|
$parts = [];
|
|
if ($book->rating_amazon > 0) {
|
|
$parts[] = 'Amazon: ' . number_format($book->rating_amazon, 1);
|
|
}
|
|
if ($book->rating_goodreads > 0) {
|
|
$parts[] = 'Goodreads: ' . number_format($book->rating_goodreads, 1);
|
|
}
|
|
$rating_display = implode(' | ', $parts);
|
|
}
|
|
|
|
// Series info
|
|
$series_info = '';
|
|
if ($book->series_id > 0 && class_exists('BDM_Series')) {
|
|
$series = BDM_Series::get_series($book->series_id);
|
|
if ($series) {
|
|
$series_info = $series->name;
|
|
}
|
|
}
|
|
|
|
// Description (truncated)
|
|
$description = '';
|
|
if (!empty($book->description)) {
|
|
$description = wp_trim_words(wp_strip_all_tags($book->description), 30);
|
|
}
|
|
?>
|
|
<article class="book-grid-item">
|
|
<a href="<?php echo esc_url($book_url); ?>" class="book-grid-cover">
|
|
<?php if ($cover_url) : ?>
|
|
<img src="<?php echo $cover_url; ?>" alt="<?php echo $title; ?>" loading="lazy">
|
|
<?php else : ?>
|
|
<div class="book-grid-cover-placeholder"><?php echo $title; ?></div>
|
|
<?php endif; ?>
|
|
</a>
|
|
<div class="book-grid-info">
|
|
<h2 class="book-grid-title"><a href="<?php echo esc_url($book_url); ?>"><?php echo $title; ?></a></h2>
|
|
<p class="book-grid-author"><?php echo $author_name; ?></p>
|
|
<?php if ($series_info) : ?>
|
|
<p class="book-grid-series"><?php echo esc_html($series_info); ?></p>
|
|
<?php endif; ?>
|
|
<?php if ($rating_display) : ?>
|
|
<div class="book-grid-rating"><?php echo esc_html($rating_display); ?></div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</article>
|
|
<?php
|
|
endforeach;
|
|
else :
|
|
// Show default example books
|
|
foreach ($default_books as $book) :
|
|
?>
|
|
<article class="book-grid-item">
|
|
<div class="book-grid-cover">
|
|
<img src="<?php echo esc_url($book['cover']); ?>" alt="<?php echo esc_attr($book['title']); ?>" loading="lazy">
|
|
</div>
|
|
<div class="book-grid-info">
|
|
<h2 class="book-grid-title"><?php echo esc_html($book['title']); ?></h2>
|
|
<p class="book-grid-author"><?php echo esc_html($book['author']); ?></p>
|
|
<div class="book-grid-rating"><?php echo esc_html($book['rating']); ?>/5</div>
|
|
</div>
|
|
</article>
|
|
<?php
|
|
endforeach;
|
|
endif;
|
|
?>
|
|
</div>
|
|
</div>
|
|
|
|
<?php
|
|
get_footer();
|