# XShop – Architecture (v1.0.0) ## 1. Overview ``` repo/ docs/ # product specs & ADRs xshop-theme/ # presentation layer xshop-core/ # companion plugin release/ # built zips (not committed) tools/ # build / QA scripts ``` Two installable artifacts: theme (`xshop`) + plugin (`xshop-core`). Theme never stores business logic that outlives theme activation (wishlist/compare/Q&A/banners live in plugin). ## 2. Theme – `xshop-theme` ### 2.1 File map (M3) ``` xshop-theme/ style.css / functions.php / rtl.css / header.php / footer.php / index.php etc inc/ setup/assets.php — tokens→base→layout→components→woo→utilities→style.css + theme.js + search.js (front-end only where data-xshop-search exists, documented) woocommerce/setup.php — loop_start/end, toolbar, gallery remove, related 4/4, product.js conditional assets/ css/woo.css — + search dropdown (.xshop-search, _dropdown, _results, _item, responsive fixed @640) js/search.js — debounce 250ms, AbortController, stale seq, keyboard, a11y template-parts/components/ ajax-search.php — reusable combobox (role=combobox, aria-expanded/controls, listbox, live status) + previous M2 components woocommerce/ — 4 overrides as M2 xshop-core/ includes/REST/Search.php — xshop/v1/search endpoint includes/Core/Plugin.php — loads REST/Search.php ``` ### 2.2 Bootstrap `functions.php` is a thin loader: ```php require_once __DIR__ . '/inc/setup/theme-support.php'; require_once __DIR__ . '/inc/setup/menus.php'; // ... each file exposes a single setup function hooked appropriately ``` No giant `functions.php`. Each `inc/*` file is namespaced or prefixed `xshop_`. ### 2.3 Namespacing & Prefixing - Text domain: `xshop` - PHP functions/options/actions/meta: `xshop_` prefix. - Classes: `XShop\Theme\...` and `XShop\Core\...` (PSR-4 style even if manual require). ### 2.4 Hook Strategy - Use `after_setup_theme` for theme support, `init` for CPT/taxonomy (only banners/Q&A). - Use `wp_enqueue_scripts` with conditional loading. - Use WC hooks for pricing, badges, loops – avoid overriding templates unless necessary. ## 3. Plugin – `xshop-core` ``` xshop-core/ xshop-core.php # plugin header + loader includes/ Core/ # plugin bootstrap, constants Modules/ Wishlist/ Compare/ QA/ Search/ Filter/ Banners/ Badges/ DemoImport/ SetupWizard/ SystemStatus/ Widgets/ Admin/ # menu, dashboard, settings pages REST/ # REST endpoints (search/filter/wishlist/compare/QA) Compatibility/ assets/ css/ js/ languages/ templates/ # wishlist, compare, banners front-end fragments ``` Plugin owns persistence for wishlist/compare/Q&A/banners. Theme only renders. ## 4. Data Ownership - **WC**: products, variations, orders, customers, coupons, shipping, payment, taxes, cart, checkout. - **WP**: users, posts, pages, media, menus, comments. - **Custom**: banners (CPT `xshop_banner`), Q&A (CPT or comments extension – see DATABASE-MODEL.md), wishlist/compare (user meta + cookie + transient for guests), theme settings (single option `xshop_settings` + mods). Avoid custom tables in v1; revisit via ADR if scale demands. ## 5. Design System (M2) Tokens: `tokens.css` unchanged — adds WC tokens `--xshop-wc-badge-sale/--xshop-wc-price` etc. Layering `tokens→base→layout→components→woo→utilities→style.css` (woo.css 159 lines, tokens for shop/product/cart). Dark mode semantic swap covers `bg/surface/card/text/muted/border/input/focus/link/notice` — verified on shop/card/gallery/tabs/cart/checkout. Logical props only, zero `left/right`. ## 6. Asset Strategy (M2) - Vanilla JS: `theme.js` (deferred) + `product.js` (enqueued only on `is_product()` via `xshop_wc_single_setup` guard). No gallery framework, 40 lines, keyboard Arrow/Home/End. - Enqueue: `tokens→base→layout→components→woo→utilities→style.css` chain in `inc/setup/assets.php:1` (`woo.css` **intentionally global** 12KB — replaces Woo's 3 stylesheets, avoids FOUC on shop/product/cart/account; documented, tiny vs conditional complexity). WC styles dequeued (`woocommerce_enqueue_styles → __return_empty_array`). `product.js` conditional, `comment-reply` conditional. - Localized `xshopData` on `xshop` handle. No jQuery for theme code; Woo's jQuery remains for variations/add-to-cart. - Build: `tools/build-release.ps1` now includes top-level folder `xshop/` wrapper (fixed in M1.1). ## 7. AJAX / REST (M3: Search) - **Search**: `GET /wp-json/xshop/v1/search?search=&limit=` via `xshop-core/includes/REST/Search.php:1` (`register_rest_route xshop/v1/search`). Public read-only (`permission_callback __return_true`), sanitized `search` (trim/strip_tags/sanitize_text_field/max 100) + `limit` 1..20, min length 2 returns empty without DB, `WP_Query` s + `_sku` LIKE, `post_status publish`, `no_found_rows`, `fields ids` deduped to `limit` (default 6), response `{items:[{id,title,url,image,price_html,type,in_stock}], total}` + `Cache-Control: public, max-age=60`. No private data, no N+1, no draft, no customer/order, `wc_get_product` only for returned IDs. - Prefer REST for search/filter/Q&A, fallback `admin-ajax` for cart where WC expects. ## 8. Security Model See `SECURITY.md`. TL;DR: sanitize in, escape out, nonces, capability checks, prepared statements, no `unserialize`, no open redirects. ## 9. Performance Model See `PERFORMANCE.md`. Conditional assets, lazy-load, transients for expensive queries, no N+1, `wp_cache`. ## 10. i18n / RTL - All strings via `__()`, `_e()`, `esc_html__()` with text domain `xshop`. - Logical CSS, `dir` attribute toggling, `is_rtl()` branching only where logical props insufficient. - Persian typography tokens, `lang="fa"` support, mixed LTR numbers handled via `unicode-bidi` where needed. ## 11. Templating (M2) `header.php` → `site-header` + breadcrumbs; `footer.php` → `site-footer`. Content templates use Loop + `get_template_part`. Reusable: `product-card.php:1` (WC_Product badges/price/rating, hook `xshop_product_card_after_actions`), `product-grid.php:1`, `product-gallery.php:1` (featured+thumbs, keyboard). `front-page.php` section-based via `xshop_front_hero_args`. **Woo overrides (4, all minimal, versioned):** - `woocommerce/content-product.php` (3.6.0) — Why: grid/token alignment; Hooks/CSS insufficient (li.product markup). Minimal: single `
  • ` + `get_template_part product-card`. Risk: Woo 3.6 → bump → re-check `wc_product_class`. - `woocommerce/archive-product.php` (3.4.0) — Why: XShop header (category title/desc/count) + toolbar + empty-state CTA. Hooks could do header but empty-state needs override. Minimal. - `woocommerce/content-single-product.php` (3.6.0) — Why: grid layout `.xshop-product` gallery+summary + custom gallery component. Hooks alone can't provide grid wrapper without CSS hacks. Minimal: wraps hooks, replaces `woocommerce_show_product_images`. - `woocommerce/single-product.php` (1.6.4) — Delegator to `content-single-product.php`; kept for explicitness, could be removed (Woo default works) but retained for clarity. All keep Woo hooks (`woocommerce_before_single_product`, `woocommerce_single_product_summary`, `woocommerce_after_single_product_summary` etc.) — no business logic rewrite. `inc/woocommerce/setup.php:1` handles `loop_start/end` filter (`xshop-products`), toolbar `woocommerce_before_shop_loop` 9/35, remove gallery, related args `posts_per_page 4 columns 4`. ## 12. Decision Records ADRs in `docs/ADR/` – one per major decision (e.g., “No custom tables for Q&A in v1”). ## 13. Release `release/xshop.zip` + `release/xshop-core.zip` built via `tools/build-release.ps1`. Excludes `.git`, `node_modules`, `.env`, logs, temp. ## 14. Versioning SemVer 1.0.0. `CHANGELOG.md` follows Keep a Changelog. ## 15. Risks & Mitigations - WC API churn → pin tested versions, monitor template versions, use hooks not overrides. - RTL regressions → logical props + visual regression checklist. - Demo import timeouts → chunked importer with resume.