Files
Bookshelf/umbra-bookshelf/docs/KNOWN-ISSUES.md
bdm dec732931c Consolidate three plugins into Umbra Bookshelf
Merge BD Bookshelf (0.1.0), BD BookShelfHelper (2.0.0) and BD SimpleEmail
(2.0.0) into a single plugin released as Umbra Bookshelf 1.0.0, with the
BD Bookshelf theme left as a separate, unrenamed artifact.

Modules
  includes/books/    catalogue, ISBN/ASIN, series, retail, ratings, shortcodes,
                     SEO, GDPR, scrapers, admin, CSV/post import
  includes/library/  book post type + series taxonomy, pen names, data entry,
                     shortlinks, reviews, migrate
  includes/email/    subscribers, newsletters, composition, sending

Renamed: plugin headers, text domains (all three -> umbra-bookshelf), classes
(BD_*/BDM_* -> Umbra_*), constants (-> UMBRA_BOOKSHELF_*), asset handles, JS
globals and admin slugs.

Deliberately not renamed -- persisted contract with live installs and with
published post content: table names, option keys, post meta keys, transients,
nonce actions, cron hooks, AJAX actions, shortcodes ([bd-book], [bd-books],
[bdm_signup]), post type `book`, taxonomy `series`, cookies and CSS classes.
BD_BookShelfHelper survives only as a class_alias for the unmodified theme.

Collisions resolved
  * class-umbra-theme-compatibility.php declared BD_BookShelfHelper, the same
    name as the library module's helper. Latent while the plugins were
    separate (only fired when both were active), but an unconditional fatal
    once merged. Renamed to Umbra_Theme_Compatibility with a class_alias.
  * All three modules called add_menu_page. One top-level menu is now
    registered by the bootstrap at admin_menu priority 9.
  * BD Bookshelf and BookShelfHelper both claimed bd-bookshelf-settings, leaving
    one Settings screen unreachable -> umbra-bookshelf-settings and
    umbra-bookshelf-library-settings.
  * Catalogue and library both enqueued bd-bookshelf-admin; the second enqueue
    was silently discarded -> unique handles per module.
  * Umbra_Admin and Umbra_Migration both registered bd_bookshelf_import_csv, so
    one handler silently replaced the other. The import page now lives only in
    Umbra_Admin (the variant wired to the admin JS); Umbra_Migration keeps only
    the preview/run endpoints it uniquely provides.
  * Modules were constructed from an init callback, so their own init
    registrations raced the hook being dispatched. Now constructed on
    plugins_loaded behind a re-entrancy guard.

Also
  * Missing assets created: assets/images/default-cover.png (referenced but
    never committed, so every cover-less book 404'd) and email/assets/js/
    admin.js (enqueued on every email admin page but never committed).
  * Library module's strpos($hook, 'bd-bookshelf') asset check matched every
    catalogue and email screen once slugs shared the umbra-bookshelf- prefix;
    now matched against its own slug list.
  * Consolidated uninstall deduplicates the double drop of bd_books/bd_series.
  * Specs aligned to the new name; pre-merge specs retained under
    spec/archive/ with provenance notes.
  * Tests added: tests/verify_structure.py (static) and tests/smoke_runtime.php
    (WordPress-stub runtime boot, front-end and admin contexts).

Deferred and recorded in docs/KNOWN-ISSUES.md: the catalogue and library
modules still create bd_books and bd_series with two incompatible schemas
(pre-existing, now unconditional), and Goodreads/Amazon scraping is still
implemented twice on shared cron hooks.
2026-10-18 19:55:36 -07:00

5.7 KiB
Raw Blame History

Known issues

Carried into the Umbra Bookshelf consolidation. Items 1–4 are pre-existing defects inherited from the three merged plugins; item 5 and the two repaired below are noted for traceability.


1. bd_books and bd_series have two incompatible schemas (DEFERRED — unresolved)

The books and library modules both create tables with identical names and different columns.

Umbra_Database::table() returns $wpdb->prefix . 'bd_' . $name, and the catalogue issues CREATE TABLE {prefix}bd_books with no IF NOT EXISTS guard:

catalogue  wp_bd_books   id, title, slug, description, isbn_*, amazon_asin,
                         goodreads_id, rating_*, created_at, ...
library    wp_bd_books   id, post_id, pen_name_id, series_id, volume_number,
                         asin, isbn, publish_date, sort_order, created_at

Same for wp_bd_series (catalogue: name, slug, description …; library: name, slug, cover_attachment_id, header_attachment_id, blurb, …).

Consequence. Whichever module is activated first wins; the second either no-ops (IF NOT EXISTS, library) or raises a database error (catalogue's unguarded CREATE TABLE). Whichever schema exists first is what the other module then reads and writes against, producing wrong results rather than an obvious failure.

Why deferred. Resolving it means choosing a canonical schema and migrating live data — a data-migration project, not a rename. Both datasets may hold rows that matter.

Options.

  1. Library schema becomes canonical; catalogue tables move to bd_bookshelf_* with an upgrade routine copying existing rows. Requires renaming DB keys, which this consolidation deliberately avoids.
  2. Catalogue schema becomes canonical; library relies on the book post type and postmeta instead of bd_books.
  3. Delete the catalogue duplicates and keep only the library model.

2. Goodreads and Amazon scraping is implemented twice

  • Catalogue: Umbra_Goodreads_Scraper, Umbra_Amazon_Scraper.
  • Library: Umbra_Bookshelf_Helper::refresh_goodreads_data(), ::scrape_amazon_ratings().

Both attach to the same cron hooks (bd_bookshelf_goodreads_refresh, bd_bookshelf_amazon_scrape), so each scheduled run performs duplicate requests to third-party APIs — wasted quota, faster rate limiting, and two places to fix a parsing bug. Needs a decision on which implementation survives.


3. assets/images/default-cover.png was missing

Umbra_Bookshelf_Helper returns assets/images/default-cover.png as the fallback cover, but the repository contained no images at all, so every cover-less book rendered a broken image.

Repaired during consolidation: a neutral 600×900 placeholder PNG was generated at that path. Replace it with real artwork before release.


4. email/assets/js/admin.js did not exist

Umbra_Simple_Email_Admin::enqueue_assets() enqueued it on every email admin page, but no such file was ever committed — a guaranteed 404.

Repaired during consolidation: an empty placeholder was created with a comment explaining the history. Add the intended behaviour, or drop the enqueue.


5. Umbra_SEO is never instantiated

Umbra_SEO registers its hooks from a constructor, but the bootstrap does not construct it — carried over unchanged from the original BD Bookshelf bootstrap. The class is loaded and its hooks never attach, so the module is inert.

Left as-is because enabling it changes behaviour. Either instantiate it in Umbra_Bookshelf::init_modules() or delete it.


6. Licence metadata is inconsistent (NOT CHANGED)

Plugin headers declared License: GPLv2 or later while the repository's LICENSE/NOTICE files (added in 85de97b) and every SPDX header state Apache-2.0. The consolidated header now says Apache-2.0 to match the SPDX headers and LICENSE, but this needs a deliberate decision — WordPress plugin-directory submissions require a GPL-compatible licence.


Fixed during consolidation

  • Cannot declare class fatal. class-bdm-theme-compatibility.php declared BD_BookShelfHelper, the same class name as the library plugin's own helper. Latent while the two were separate plugins (it only fired when both were active), but an unconditional fatal once merged. The shim is now Umbra_Theme_Compatibility, with a class_alias() preserving the legacy name for the unmodified theme.
  • Duplicate bd_bookshelf_import_csv AJAX handler. Both Umbra_Admin and Umbra_Migration registered it; the second silently replaced the first. The import page now lives solely in Umbra_Admin (it is the variant wired to admin/js/umbra-bookshelf-admin.js); Umbra_Migration keeps only the preview/run endpoints it uniquely provides.
  • Duplicate bd-bookshelf-settings submenu. Catalogue and library both claimed the slug, leaving one Settings screen unreachable. Now umbra-bookshelf-settings and umbra-bookshelf-library-settings.
  • Duplicate admin menu. All three modules called add_menu_page. Now one top-level menu registered by the bootstrap at priority 9.
  • Colliding asset handles. Catalogue and library both enqueued bd-bookshelf-admin; the second enqueue was silently discarded. Handles are now unique per module.
  • Modules could miss their own init callbacks. Constructing modules from inside an init callback means their init registrations race the hook currently being dispatched. Modules are now constructed on plugins_loaded, behind a re-entrancy guard.
  • Over-broad asset hook check. The library module's strpos($hook, 'bd-bookshelf') matched every catalogue and email screen once all slugs shared the umbra-bookshelf- prefix. Now matched against its own slug list.