Files
mataba/shop/docs/DATABASE-MODEL.md
T

4.4 KiB
Raw Blame History

XShop – Database Model

1. Philosophy

Reuse WP/WC primitives. No custom tables in v1.0 – revisit via ADR if query scale warrants. Document every key.

2. WordPress-Owned

  • Users (wp_users, wp_usermeta): native. XShop adds: xshop_wishlist (array of product IDs), xshop_compare (array), xshop_recently_viewed (capped list).
  • Posts/Pages (wp_posts, wp_postmeta): native.
  • Media (wp_posts attachment): native.
  • Menus (wp_terms nav_menu): native.
  • Comments/Reviews: WC reviews = WP comments on product post type. XShop Q&A moderation hooks onto comment moderation flow where applicable – but primary store is custom (below).

3. WooCommerce-Owned

  • Products (wp_posts post_type product + wp_postmeta + wp_wc_* where HPOS enabled). Variations are product_variation children.
  • Orders/Customers/Coupons/Shipping/Payment/Taxes/Cart/Checkout: WC owned (HPOS tables if enabled). XShop never writes directly to WC order tables except via WC APIs.

4. XShop-Core Custom Data

4.1 Banners – CPT xshop_banner

  • post_type = xshop_banner (non-public, show_ui true under XShop menu).
  • Meta:
    • _xshop_banner_image (attachment ID, int)
    • _xshop_banner_mobile_image (attachment ID, int, nullable)
    • _xshop_banner_link (url, esc_url_raw)
    • _xshop_banner_cta (string)
    • _xshop_banner_position (enum: home_hero, home_strip, shop_top, product_sidebar, etc.)
    • _xshop_banner_active (1|0)
    • _xshop_banner_start / _xshop_banner_end (datetime Y-m-d H:i:s, UTC)
    • _xshop_banner_order (int)
  • Scheduling checked on render (skip if outside window or inactive).

4.2 Questions & Answers – CPT xshop_qa

Decision: CPT (not comments) for cleaner moderation + threading without polluting reviews.

  • post_type = xshop_qa, post_parent = product ID (or meta _xshop_qa_product_id for query flexibility – both stored, parent is canonical).
  • Post fields: post_title empty, post_content = question body, post_status = pending|publish|trash, post_author = asker.
  • Meta:
    • _xshop_qa_product_id (int, indexed via meta query)
    • _xshop_qa_answer (string, nullable – single answer for v1; extension to multiple answers uses child xshop_qa rows with post_parent = question ID in v1.1)
    • _xshop_qa_answered_by (int user ID)
    • _xshop_qa_answered_at (datetime)
  • Alternative for multiple answers (future): child posts post_type=xshop_qa, post_parent=question ID.
  • Spam: honeypot + nonce + rate limit (transient per IP/user, 60s).

4.3 Wishlist & Compare

  • Logged-in: wp_usermeta keys xshop_wishlist, xshop_compare (serialized array of ints, capped: wishlist 200, compare 4).
  • Guest: cookie xshop_wishlist / xshop_compare (JSON, HttpOnly false for JS count, SameSite Lax, 30 days) + optional transient xshop_guest_<token>.
  • On login: merge cookie → user meta (union, cap), clear cookie.
  • Counts exposed via REST and localized script data.

4.4 Recently Viewed

  • Cookie xshop_recently_viewed (JSON array of product IDs, capped 20, 30 days). No DB write for guests. Logged-in also stored in xshop_recently_viewed user meta for cross-device.

5. Options

  • Single option xshop_settings (array) – all Theme Options. Autoload yes. Individual mods also mirrored via theme_mod for Customizer preview where needed, but source of truth is xshop_settings.
  • Option xshop_settings_backup (for import/export).
  • Transient xshop_search_cache_<hash> (5 min) for AJAX search results.
  • Transient xshop_filter_counts_<hash> (5 min) for filter counts.

Do NOT scatter random options.

6. Indexes & Query Patterns

  • Banners: query by post_type + meta position+active+date range → meta query; small cardinality.
  • Q&A: WP_Query by post_type=xshop_qa + post_parent=product_id + post_status=publish (index on post_parent + post_type already exists).
  • Wishlist/Compare: user meta single-row lookup – O(1).
  • Search: WP_Query with s + post_type=product + tax_query for category, meta_query for SKU (_sku), limited to 8 suggestions, no_found_rows true, fields=ids then prime caches.

7. Migrations & Compatibility

  • HPOS: use wc_get_products() / CRUD, not direct wp_postmeta writes for product data.
  • On plugin deactivate: data retained (no destructive cleanup). Uninstall hook offered to purge (uninstall.php with confirmation).