8.0 KiB
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:
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\...andXShop\Core\...(PSR-4 style even if manual require).
2.4 Hook Strategy
- Use
after_setup_themefor theme support,initfor CPT/taxonomy (only banners/Q&A). - Use
wp_enqueue_scriptswith 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 optionxshop_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 onis_product()viaxshop_wc_single_setupguard). No gallery framework, 40 lines, keyboard Arrow/Home/End. - Enqueue:
tokens→base→layout→components→woo→utilities→style.csschain ininc/setup/assets.php:1(woo.cssintentionally 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.jsconditional,comment-replyconditional. - Localized
xshopDataonxshophandle. No jQuery for theme code; Woo's jQuery remains for variations/add-to-cart. - Build:
tools/build-release.ps1now includes top-level folderxshop/wrapper (fixed in M1.1).
7. AJAX / REST (M3: Search)
- Search:
GET /wp-json/xshop/v1/search?search=&limit=viaxshop-core/includes/REST/Search.php:1(register_rest_route xshop/v1/search). Public read-only (permission_callback __return_true), sanitizedsearch(trim/strip_tags/sanitize_text_field/max 100) +limit1..20, min length 2 returns empty without DB,WP_Querys +_skuLIKE,post_status publish,no_found_rows,fields idsdeduped tolimit(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_productonly for returned IDs. - Prefer REST for search/filter/Q&A, fallback
admin-ajaxfor 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 domainxshop. - Logical CSS,
dirattribute toggling,is_rtl()branching only where logical props insufficient. - Persian typography tokens,
lang="fa"support, mixed LTR numbers handled viaunicode-bidiwhere 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<li>+get_template_part product-card. Risk: Woo 3.6 → bump → re-checkwc_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-productgallery+summary + custom gallery component. Hooks alone can't provide grid wrapper without CSS hacks. Minimal: wraps hooks, replaceswoocommerce_show_product_images.woocommerce/single-product.php(1.6.4) — Delegator tocontent-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.