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.
463 lines
13 KiB
PHP
463 lines
13 KiB
PHP
<?php
|
|
// Copyright 2026 Umbra Tools (umbratools.com)
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
/**
|
|
* BDMurphy Bookshelf Theme Functions
|
|
*
|
|
* @package BD_Murphy
|
|
* @since 2.0.0
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Theme version
|
|
*/
|
|
define('BDM_VERSION', '2.2.10');
|
|
define('BDM_DIR', get_template_directory());
|
|
define('BDM_URI', get_template_directory_uri());
|
|
|
|
/**
|
|
* Includes
|
|
*/
|
|
require_once BDM_DIR . '/inc/setup.php';
|
|
require_once BDM_DIR . '/inc/book-helpers.php';
|
|
require_once BDM_DIR . '/inc/customizer.php';
|
|
require_once BDM_DIR . '/inc/theme-options.php';
|
|
require_once BDM_DIR . '/inc/template-tags.php';
|
|
require_once BDM_DIR . '/inc/widgets.php';
|
|
require_once BDM_DIR . '/inc/nav-menu.php';
|
|
require_once BDM_DIR . '/inc/ajax-handlers.php';
|
|
require_once BDM_DIR . '/inc/short-urls.php';
|
|
require_once BDM_DIR . '/inc/theme-admin.php';
|
|
|
|
/**
|
|
* Setup
|
|
*/
|
|
function bdm_setup() {
|
|
load_theme_textdomain('bd-bookshelf', BDM_DIR . '/languages');
|
|
|
|
add_theme_support('title-tag');
|
|
add_theme_support('post-thumbnails');
|
|
add_theme_support('html5', array(
|
|
'search-form',
|
|
'comment-form',
|
|
'comment-list',
|
|
'gallery',
|
|
'caption',
|
|
'script',
|
|
'style',
|
|
));
|
|
add_theme_support('automatic-feed-links');
|
|
add_theme_support('wp-block-styles');
|
|
add_theme_support('responsive-embeds');
|
|
add_theme_support('align-wide');
|
|
add_theme_support('editor-styles');
|
|
|
|
add_filter('query_vars', function($vars) {
|
|
$vars[] = 'short_link_slug';
|
|
$vars[] = 'book_slug';
|
|
return $vars;
|
|
});
|
|
add_editor_style('assets/css/editor-style.css');
|
|
|
|
add_theme_support('custom-logo', array(
|
|
'width' => 200,
|
|
'height' => 200,
|
|
'flex-width' => true,
|
|
'flex-height' => true,
|
|
));
|
|
|
|
add_theme_support('custom-header', array(
|
|
'default-image' => BDM_URI . '/assets/images/banner.jpg',
|
|
'width' => 1538,
|
|
'height' => 250,
|
|
'flex-height' => false,
|
|
'header-text' => false,
|
|
'default-text-color' => '000000',
|
|
));
|
|
|
|
add_theme_support('custom-background', array(
|
|
'default-color' => 'F5F0E8',
|
|
));
|
|
|
|
// Image sizes
|
|
add_image_size('shelf-thumb', 44, 62, true);
|
|
add_image_size('blog-thumb', 100, 68, true);
|
|
add_image_size('rev-thumb', 52, 74, true);
|
|
add_image_size('book-cover', 130, 185, true);
|
|
add_image_size('book-page-cover', 220, 310, true);
|
|
add_image_size('series-card', 400, 280, true);
|
|
add_image_size('series-header', 1200, 300, true);
|
|
|
|
// Navigation menus
|
|
register_nav_menus(array(
|
|
'primary' => esc_html__('Primary Menu', 'bd-bookshelf'),
|
|
'footer' => esc_html__('Footer Menu', 'bd-bookshelf'),
|
|
));
|
|
|
|
// Widget areas
|
|
register_sidebar(array(
|
|
'name' => esc_html__('Home Sidebar', 'bd-bookshelf'),
|
|
'id' => 'home-sidebar',
|
|
'description' => esc_html__('Widget area for the book shelf on the home page', 'bd-bookshelf'),
|
|
'before_widget' => '<div id="%1$s" class="widget %2$s">',
|
|
'after_widget' => '</div>',
|
|
'before_title' => '<h3 class="widget-title">',
|
|
'after_title' => '</h3>',
|
|
));
|
|
|
|
register_sidebar(array(
|
|
'name' => esc_html__('Footer Left', 'bd-bookshelf'),
|
|
'id' => 'footer-left',
|
|
'before_widget' => '<div id="%1$s" class="widget %2$s">',
|
|
'after_widget' => '</div>',
|
|
'before_title' => '<h3 class="widget-title">',
|
|
'after_title' => '</h3>',
|
|
));
|
|
|
|
register_sidebar(array(
|
|
'name' => esc_html__('Footer Right', 'bd-bookshelf'),
|
|
'id' => 'footer-right',
|
|
'description' => esc_html__('Widget area for the footer right section', 'bd-bookshelf'),
|
|
'before_widget' => '<div id="%1$s" class="widget %2$s">',
|
|
'after_widget' => '</div>',
|
|
'before_title' => '<h3 class="widget-title">',
|
|
'after_title' => '</h3>',
|
|
));
|
|
|
|
register_sidebar(array(
|
|
'name' => esc_html__('Book Detail Sidebar', 'bd-bookshelf'),
|
|
'id' => 'book-detail-sidebar',
|
|
'description' => esc_html__('Widget area for the book detail page sidebar', 'bd-bookshelf'),
|
|
'before_widget' => '<div id="%1$s" class="widget %2$s">',
|
|
'after_widget' => '</div>',
|
|
'before_title' => '<h3 class="widget-title">',
|
|
'after_title' => '</h3>',
|
|
));
|
|
}
|
|
add_action('after_setup_theme', 'bdm_setup');
|
|
|
|
/**
|
|
* Enqueue scripts and styles
|
|
*/
|
|
function bdm_enqueue_scripts() {
|
|
// Inline script for no-js to js class swap
|
|
wp_enqueue_script(
|
|
'bd-bookshelf-no-js',
|
|
'',
|
|
array(),
|
|
null,
|
|
true
|
|
);
|
|
wp_add_inline_script('bd-bookshelf-no-js', '
|
|
(function() {
|
|
var html = document.documentElement;
|
|
if (html.className.indexOf("no-js") !== -1) {
|
|
html.className = html.className.replace(/\\bno-js\\b/, "") + " js";
|
|
}
|
|
})();
|
|
');
|
|
|
|
// Root stylesheet (theme info)
|
|
wp_enqueue_style(
|
|
'bd-murphy-root-style',
|
|
get_stylesheet_uri(),
|
|
array(),
|
|
BDM_VERSION
|
|
);
|
|
|
|
// Main stylesheet
|
|
wp_enqueue_style(
|
|
'bd-murphy-style',
|
|
BDM_URI . '/assets/css/style.css',
|
|
array('bd-murphy-root-style'),
|
|
BDM_VERSION
|
|
);
|
|
|
|
// Local fonts (bundled Google Fonts)
|
|
wp_enqueue_style(
|
|
'bd-murphy-google-fonts',
|
|
BDM_URI . '/assets/fonts/fonts.css',
|
|
array(),
|
|
null
|
|
);
|
|
|
|
// Navigation script
|
|
wp_enqueue_script(
|
|
'bd-murphy-navigation',
|
|
BDM_URI . '/assets/js/navigation.js',
|
|
array(),
|
|
BDM_VERSION,
|
|
true
|
|
);
|
|
|
|
// Social share script
|
|
wp_enqueue_script(
|
|
'bd-murphy-social-share',
|
|
BDM_URI . '/assets/js/social-share.js',
|
|
array(),
|
|
BDM_VERSION,
|
|
true
|
|
);
|
|
|
|
// Localize navigation script
|
|
wp_localize_script(
|
|
'bd-murphy-navigation',
|
|
'bdMurphyScreenReaderText',
|
|
array(
|
|
'expand' => esc_html__('Expand child menu', 'bd-bookshelf'),
|
|
'collapse' => esc_html__('Collapse child menu', 'bd-bookshelf'),
|
|
)
|
|
);
|
|
|
|
// Comment reply script
|
|
if (is_singular() && comments_open()) {
|
|
wp_enqueue_script('comment-reply');
|
|
}
|
|
}
|
|
add_action('wp_enqueue_scripts', 'bdm_enqueue_scripts');
|
|
|
|
/**
|
|
* Enqueue admin styles
|
|
*/
|
|
function bdm_enqueue_admin_styles($hook) {
|
|
wp_enqueue_style(
|
|
'bd-murphy-admin-style',
|
|
BDM_URI . '/assets/css/admin-style.css',
|
|
array(),
|
|
BDM_VERSION
|
|
);
|
|
}
|
|
add_action('admin_enqueue_scripts', 'bdm_enqueue_admin_styles');
|
|
|
|
/**
|
|
* Output Customizer CSS
|
|
*/
|
|
function bdm_output_customizer_css() {
|
|
$primary_color = get_theme_mod('primary_color', '#1B3A6B');
|
|
$accent_color = get_theme_mod('accent_color', '#C8A96E');
|
|
$cream_color = get_theme_mod('background_color', 'F5F0E8');
|
|
$heading_font = get_theme_mod('heading_font', 'Playfair Display');
|
|
$body_font = get_theme_mod('body_font', 'Lato');
|
|
|
|
// Calculate derived colors
|
|
$slate_blue = bdm_adjust_color($primary_color, 30);
|
|
$sky_blue = bdm_adjust_color($primary_color, 80);
|
|
|
|
printf(
|
|
'<style id="bdm-customizer-styles" type="text/css">%s</style>',
|
|
":root {
|
|
--bdm-navy: {$primary_color};
|
|
--bdm-slate: {$slate_blue};
|
|
--bdm-sky: {$sky_blue};
|
|
--bdm-gold: {$accent_color};
|
|
--bdm-cream: #{$cream_color};
|
|
--bdm-parchment: #EDE4D0;
|
|
--bdm-body-text: #2C2C2C;
|
|
--bdm-mid-grey: #555555;
|
|
--bdm-light-grey: #888888;
|
|
--bdm-active-green: #2D6A4F;
|
|
--bdm-heading-font: {$heading_font}, Georgia, serif;
|
|
--bdm-body-font: {$body_font}, Calibri, sans-serif;
|
|
}" . "\n"
|
|
);
|
|
}
|
|
add_action('wp_head', 'bdm_output_customizer_css', 99);
|
|
|
|
/**
|
|
* Adjust color brightness
|
|
*
|
|
* @param string $hex Hex color code.
|
|
* @param int $percent Percent to adjust (-255 to 255).
|
|
* @return string
|
|
*/
|
|
function bdm_adjust_color($hex, $percent) {
|
|
$hex = ltrim($hex, '#');
|
|
|
|
if (strlen($hex) === 3) {
|
|
$hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
|
|
}
|
|
|
|
$r = hexdec(substr($hex, 0, 2));
|
|
$g = hexdec(substr($hex, 2, 2));
|
|
$b = hexdec(substr($hex, 4, 2));
|
|
|
|
$r = min(255, max(0, $r + $percent));
|
|
$g = min(255, max(0, $g + $percent));
|
|
$b = min(255, max(0, $b + $percent));
|
|
|
|
return sprintf('#%02x%02x%02x', $r, $g, $b);
|
|
}
|
|
|
|
/**
|
|
* Fire bdm_post_published action on publish
|
|
*
|
|
* @param int $post_id Post ID.
|
|
*/
|
|
function bdm_publish_hook($post_id) {
|
|
do_action('bdm_post_published', $post_id);
|
|
}
|
|
add_action('publish_post', 'bdm_publish_hook');
|
|
|
|
/**
|
|
* RSS feed link in head
|
|
*/
|
|
function bdm_rss_feed_link() {
|
|
printf(
|
|
'<link rel="alternate" type="application/rss+xml" title="%s RSS Feed" href="%s">' . "\n",
|
|
esc_attr(get_bloginfo('name')),
|
|
esc_url(get_bloginfo('rss2_url'))
|
|
);
|
|
}
|
|
add_action('wp_head', 'bdm_rss_feed_link');
|
|
|
|
/**
|
|
* Add custom body classes
|
|
*
|
|
* @param array $classes Body classes.
|
|
* @return array
|
|
*/
|
|
function bdm_body_classes($classes) {
|
|
// Adds class for sticky nav
|
|
if (get_theme_mod('sticky_nav', true)) {
|
|
$classes[] = 'has-sticky-nav';
|
|
}
|
|
|
|
return $classes;
|
|
}
|
|
add_filter('body_class', 'bdm_body_classes');
|
|
|
|
/**
|
|
* Content width
|
|
*/
|
|
if (!isset($content_width)) {
|
|
$content_width = 1200;
|
|
}
|
|
|
|
/**
|
|
* Set default Goodreads widget in home sidebar
|
|
*/
|
|
function bdm_default_home_sidebar_widgets() {
|
|
if (!is_admin()) {
|
|
return;
|
|
}
|
|
|
|
$sidebar_id = 'home-sidebar';
|
|
|
|
// Check if sidebar has any widgets
|
|
if (is_active_sidebar($sidebar_id)) {
|
|
return;
|
|
}
|
|
|
|
// Get the Goodreads widget settings
|
|
$widget_options = get_option('widget_bdm_goodreads_books', array());
|
|
|
|
// Find an available widget instance number
|
|
$instance_num = 1;
|
|
while (isset($widget_options[$instance_num])) {
|
|
$instance_num++;
|
|
}
|
|
|
|
// Create the widget instance
|
|
$widget_options[$instance_num] = array(
|
|
'title' => '',
|
|
);
|
|
|
|
// Update the option
|
|
update_option('widget_bdm_goodreads_books', $widget_options);
|
|
|
|
// Get current sidebars option
|
|
$sidebars = get_option('sidebars_widgets', array());
|
|
|
|
// Add widget to home sidebar
|
|
$widget_id = 'bdm_goodreads_books-' . $instance_num;
|
|
if (!isset($sidebars[$sidebar_id]) || !is_array($sidebars[$sidebar_id])) {
|
|
$sidebars[$sidebar_id] = array();
|
|
}
|
|
|
|
// Only add if not already present
|
|
if (!in_array($widget_id, $sidebars[$sidebar_id])) {
|
|
array_unshift($sidebars[$sidebar_id], $widget_id);
|
|
}
|
|
|
|
// Update sidebars
|
|
update_option('sidebars_widgets', $sidebars);
|
|
}
|
|
add_action('after_switch_theme', 'bdm_default_home_sidebar_widgets');
|
|
|
|
/**
|
|
* Register block styles
|
|
*/
|
|
function bdm_register_block_styles() {
|
|
register_block_style('core/image', array(
|
|
'name' => 'bd-bookshelf-rounded',
|
|
'label' => esc_html__('Rounded', 'bd-bookshelf'),
|
|
));
|
|
register_block_style('core/quote', array(
|
|
'name' => 'bd-bookshelf-pull-quote',
|
|
'label' => esc_html__('Pull Quote', 'bd-bookshelf'),
|
|
));
|
|
}
|
|
add_action('init', 'bdm_register_block_styles');
|
|
|
|
/**
|
|
* Register block patterns
|
|
*/
|
|
function bdm_register_block_patterns() {
|
|
register_block_pattern_category('bd-bookshelf', array(
|
|
'label' => esc_html__('BD Bookshelf', 'bd-bookshelf'),
|
|
));
|
|
}
|
|
add_action('init', 'bdm_register_block_patterns');
|
|
|
|
/**
|
|
* Add avatar support to comments
|
|
*
|
|
* @param array $args Comment form args.
|
|
* @return array
|
|
*/
|
|
function bdm_comment_form_defaults($args) {
|
|
$args['comment_field'] = '<p class="comment-form-comment"><label for="comment">' . esc_html__('Comment', 'bd-bookshelf') . ' <span class="required">*</span></label><textarea id="comment" name="comment" cols="45" rows="8" aria-describedby="form-allowed-tags" aria-required="true" required></textarea></p>';
|
|
return $args;
|
|
}
|
|
add_filter('comment_form_defaults', 'bdm_comment_form_defaults');
|
|
|
|
/**
|
|
* Add rewrite rules for book detail pages
|
|
*/
|
|
function bdm_rewrite_rules() {
|
|
add_rewrite_rule(
|
|
'^book/([^/]+)/?$',
|
|
'index.php?book_slug=$matches[1]',
|
|
'top'
|
|
);
|
|
}
|
|
add_action('init', 'bdm_rewrite_rules');
|
|
|
|
/**
|
|
* Load book detail template for book_slug query var
|
|
*/
|
|
function bdm_template_include_book($template) {
|
|
if (get_query_var('book_slug')) {
|
|
$book_template = get_template_directory() . '/single-book.php';
|
|
if (file_exists($book_template)) {
|
|
return $book_template;
|
|
}
|
|
}
|
|
return $template;
|
|
}
|
|
add_filter('template_include', 'bdm_template_include_book');
|
|
|
|
/**
|
|
* Flush rewrite rules on theme activation
|
|
*/
|
|
function bdm_rewrite_flush() {
|
|
bdm_rewrite_rules();
|
|
flush_rewrite_rules();
|
|
}
|
|
add_action('after_switch_theme', 'bdm_rewrite_flush');
|