WP Manifestindependent plugin directory
manifest / content / tie-books-manager

TIE Books Manager

TIE Books Manager - WordPress plugin: Books CPT with login-restricted viewing and AJAX-filterable [books_list] shortcode

by Sarojinee Tarale · github.com/sarojinee/tie-books-manager · website

0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/sarojinee/tie-books-manager/archive/refs/heads/main.zip

Readme

TIE Books Manager

A WordPress plugin that adds a Books custom post type and displays a collection of books that is restricted to logged-in users only. Built as a developer assignment with a focus on functionality, WordPress coding standards, and proper use of hooks, filters, and APIs.


Features

  • Custom Post Type Books with custom fields:
    • Title (default WordPress field)
    • Author (text)
    • Genre (dropdown: Fiction, Non-Fiction, Sci-Fi, Biography, Fantasy)
    • Published Date (date picker)
    • Description (WYSIWYG editor via wp_editor)
  • Access restriction so only logged-in users can view single book pages and the books listing.
  • Custom single-book template showing title, author, genre, published date, and description.
  • [books_list] shortcode that lists all books with title (linked), author, and genre.
  • Pagination — 5 books per page.
  • Bonus implemented: AJAX filtering (no page reload) by Genre and Author.
  • Input sanitization, output escaping, and nonce verification throughout.
  • Responsive CSS for desktop and mobile.

Requirements

  • WordPress 5.8 or higher (uses wp_editor, block-ready CPT registration).
  • PHP 7.4 or higher.

Installation & Setup

  1. Download or clone this repository.
  2. Copy the tie-books-manager folder into your WordPress installation under:
    wp-content/plugins/tie-books-manager
  3. In the WordPress admin, go to Plugins and Activate "TIE Books Manager".
    • On activation the plugin registers the CPT and flushes rewrite rules automatically, so single-book permalinks work immediately.
  4. (If single book URLs ever return 404) go to Settings → Permalinks and click Save Changes once to refresh rewrite rules.

Usage

Adding Books

  1. In the admin sidebar, open Books → Add New.
  2. Enter the Title, then fill in the Book Details meta box: Author, Genre, Published Date, and Description.
  3. Publish.

Displaying the Books List

  1. Create a new Page (e.g. "Library").
  2. Add the shortcode into the content:
    [books_list]
  3. Publish and view the page.
    • Logged-in users see the filterable, paginated list.
    • Logged-out users see the restricted-access message.

Viewing a Single Book

Click a book title in the list (or visit /books/your-book-slug/). The custom single template renders the full details.


Testing Checklist

  1. Logged-in user
    • Visit the page containing [books_list] → list of books appears, 5 per page.
    • Use the Filter By Genre dropdown → list updates via AJAX without reloading.
    • Type in Filter By Author → list updates via AJAX (debounced).
    • Click a pagination link → next 5 books load via AJAX.
    • Click a book title → single book page shows all fields.
  2. Logged-out user (open an incognito window)
    • Visit a single book URL → restricted message is shown.
    • Visit the books archive (/books/) → restricted message is shown.
    • Visit the [books_list] page → restricted message is shown instead of the list.

How Access Restriction Was Implemented

Access control is enforced in three complementary layers, so there is no single point of bypass:

  1. Front-end pages — template_redirect hook (includes/access-control.php) On every request, the plugin checks is_singular( 'books' ) and is_post_type_archive( 'books' ). If the request targets a single book or the books archive and is_user_logged_in() returns false, the request is halted with wp_die() showing:

    "You must be logged in to view this content. Please log in or register." Using template_redirect stops execution before any book content is rendered, so restricted content is never sent to the browser.

  2. Shortcode output — [books_list] (includes/shortcode.php) The shortcode callback first checks is_user_logged_in(). If the visitor is not logged in, it returns the restricted-access message instead of rendering the list markup. This protects the listing even when the shortcode is embedded on an otherwise-public page.

  3. AJAX endpoint (includes/ajax-filter.php) The AJAX handler verifies a nonce with check_ajax_referer() and then re-checks is_user_logged_in(), returning wp_send_json_error() for guests. The wp_ajax_nopriv_* hook is intentionally not registered, so logged-out visitors cannot pull book data directly from admin-ajax.php.


Security Notes

  • All meta input is sanitized: sanitize_text_field() for text/date/genre, wp_kses_post() for the rich-text description.
  • All output is escaped: esc_html(), esc_attr(), esc_url(), wp_kses_post().
  • Meta saving is guarded by a nonce (tie_books_save_meta), an autosave check, and a current_user_can( 'edit_post', $post_id ) capability check.
  • The AJAX request is protected by a nonce created with wp_create_nonce() and passed via wp_localize_script().

File Structure

tie-books-manager/
├── tie-books-manager.php        # Main plugin file: constants, includes, asset enqueue, activation hooks
├── README.md
├── assets/
│   ├── css/books.css            # Responsive styles
│   └── js/books.js              # AJAX filtering & pagination
├── includes/
│   ├── cpt.php                  # Registers the Books custom post type
│   ├── metaboxes.php            # Book Details meta box + save logic
│   ├── access-control.php       # template_redirect login restriction
│   ├── shortcode.php            # [books_list] shortcode + filter UI
│   ├── ajax-filter.php          # AJAX handler for genre/author filtering & pagination
│   └── template-loader.php      # Loads the custom single-book template
└── templates/
    └── single-book.php          # Single book front-end template

Notes on Design Choices

  • The book Description is stored as post meta (rendered with wp_editor in admin and wp_kses_post on the front end) rather than the default content editor, keeping all book fields grouped in one meta box. The CPT therefore only declares title support.
  • Pagination uses a hash-based base (#page=%#%) so that page links are handled entirely client-side by AJAX, avoiding full page reloads.
  • Author filtering uses a LIKE comparison for partial-match convenience; genre uses an exact = match against the predefined values.

Author

Sarojinee Tarale

Read the full README on GitHub →