8.2 KiB
8.2 KiB
Changelog
All notable changes to XShop follow Keep a Changelog and SemVer.
[1.0.0] – Unreleased
Added
- Phase 0: product spec, architecture, feature matrix, roadmap, UI spec, database model, security, performance, testing, compatibility docs + ADRs.
- M1 — Theme Foundation:
- Templates:
header.php,footer.php,index.php,front-page.php(section-based hero/category/product/promo/latest),single.php,page.php,archive.php,search.php,404.php,sidebar.php,comments.php(threaded, paginated, accessible). - Components:
template-parts/components/site-header.php,site-footer.php,breadcrumbs.php(Woo-aware, filterable),pagination.php(RTL-safe),search-form.php,post-card.php,empty-state.php,loading.php,section-heading.php,hero.php,promo-banner.php. - Design system: finalized
assets/css/tokens.css(full palette/typography/spacing/radius/shadow/z/transition + dark mode semantic swap),base.css,layout.css,components.css,utilities.css— logical properties, zeroleft/right. - JS:
assets/js/theme.jsextended with accessible mobile nav (aria-expanded, focus trap, Esc, click-outside) + dark-mode toggle. - PHP:
inc/helpers/template.php(xshop_has_woocommerce, xshop_is_woocommerce_page, branding fallback),inc/setup/body-classes.php,inc/setup/assets.php(layered enqueue + Woo style dequeue),inc/woocommerce/setup.php(wrappers). - Docs: updated
docs/ARCHITECTURE.md,docs/UI-SPEC.md,docs/TESTING.mdfor M1.
- Templates:
- M1.1 — Runtime QA:
- Local XAMPP WP 7.1 + WC 11.1.0 + PHP 8.2.12 — 29 tests all PASS, 2 bugs fixed (
.htaccess+ ZIP wrapper),docs/RUNTIME-QA.md+.gitignoreupdate,tools/build-release.ps1fix.
- Local XAMPP WP 7.1 + WC 11.1.0 + PHP 8.2.12 — 29 tests all PASS, 2 bugs fixed (
- M2 — WooCommerce Storefront Foundation:
assets/css/woo.css(shop toolbar, product grid 4/3/2/1, card badges/price/rating, single gallery/thumbs/tabs/related, cart responsive table, mini-cart, account 220|1fr, checkout col2-set — logical props, token-based, dark-mode via semantic tokens).- Components:
product-card.php(WC_Product sale%/outofstock/featured/no-image/long titles, hookxshop_product_card_after_actions),product-grid.php,product-gallery.php(keyboard Arrow/Home/End,is-active),mini-cart.php(count/items/subtotal/remove/empty). - Woo integration:
inc/woocommerce/setup.php(loop_start/endxshop-products, toolbar, remove gallery, related 4/4,product.jsconditional onis_product()),inc/setup/assets.php(woo.css global intentional, documented). - Templates:
woocommerce/content-product.php:3.6.0,archive-product.php:3.4.0,content-single-product.php:3.6.0,single-product.php:1.6.4(all minimal, versioned, hooks preserved). - JS:
assets/js/product.js(gallery thumbs, 40 lines, vanilla). - Data: variable product 24 with 3 real variations (S 120k instock 10 / M 150→130k outofstock / L 180k) — attribute
SizeS/M/L,data-product_variationsJSON,reset_variations. - Runtime: shop/category/empty, simple/sale/no-image/outofstock/variable, gallery, cart quantity/coupon/totals/empty, account, checkout, RTL/LTR, dark, mobile — 18 tests PASS, 2 bugs fixed (coming-soon +
global $product: Typeparse error),debug.logclean, ZIP rebuild + manual install PASS. - Docs:
ARCHITECTURE.md,UI-SPEC.md,TESTING.md,COMPATIBILITY.md,RUNTIME-QA.mdupdated.
- M3 — WooCommerce AJAX Product Search (REST-first):
- Endpoint
GET /wp-json/xshop/v1/search(xshop-core/includes/REST/Search.php:1,Core/Plugin.php) — public__return_true, sanitizedsearch(strip_tags/sanitize_text_field/max 100) +limit1..20, min 2 → empty,WP_Query s+_skuLIKE,publishonly,no_found_rowsfields idsdeduped to limit default 6, response{items:[id,title,url,image,price_html,type,in_stock],total}+Cache-Control: public, max-age=60, no private/draft/customer/order, SKU + title/content search, HPOS-safe. - UI:
template-parts/components/ajax-search.php:1reusable combobox (role=comboboxaria-expanded/controls/autocompletelistboxaria-livedata-*, view-all?s=&post_type=product, hiddenpost_typewhen Woo active, RTL via logical, dark via tokens). - JS:
assets/js/search.js:1vanilla debounce 250ms,AbortController, staleseq, dedupelastQuery,fetch, loading/empty/error/view-all, keyboardArrowUp/Down/Enter/Escape,click outside,aria-activedescendant, noconsole.log. - Style:
assets/css/woo.css:1dropdownabsolute→fixed@640max 60vhtokensearch item grid48px 1fr+ price/stock. - Asset:
inc/setup/assets.php:1enqueuesearch.jsonly wheredata-xshop-search(header front-end, init guard), versioned. - Security: strict sanitization/validation, bounded limit/length, no private data, escaped output, abuse note in
SECURITY.md(rate limit via proxy). - Performance: debounce, bounded, stale cancel, dedupe,
Cache-Control, minimal payload, documented inPERFORMANCE.md. - Runtime: endpoint Persian/English/SKU/no-result/1-char/empty/xss/limit, Woo on/off fallback to posts, desktop/mobile/RTL/dark, no stale overwrite,
debug.logclean. - Docs:
ARCHITECTURE.md:7UI-SPEC.md:3,8SECURITY.md:11PERFORMANCE.md:8TESTING.md:M3RUNTIME-QA.md:M3.
- Endpoint
- M4 — WooCommerce AJAX Product Filtering (REST-first, shared ProductQuery):
- Query:
xshop-core/includes/Query/ProductQuery.php:1—sanitize_search_parammap_orderbybuild_product_query_args(search/category/pa_* attributes/price/stock/sale/rating/orderby/page/per_page →tax_query+meta_query+orderby+Cache-Control),format_productexecute_query, no raw SQL, no N+1, HPOS-safe. - Endpoint
GET /wp-json/xshop/v1/products(REST/Products.php:1,Core/Plugin.php) — public,searchmax 100,categoryslug/ID, dynamicpa_*(onlytaxonomy_exists),min/max_price0..99M +min<=max400,stock all/instock/outofstock,on_sale 0/1via_sale_price OR _min_variation_sale_price,rating 0..5,orderbyallow-list,page 1..100per_page 1..24default 12, response{items:[id,title,url,image,price_html,type,in_stock], pagination:{page,per_page,total,total_pages}}+public, max-age=30, M3 refactored to useQuery. - UI:
template-parts/components/product-filters.php:1—data-xshop-filters+chips+form method=getno-JS fallback (category radio,pa_*checkbox, price number, stock radio, sale checkbox, rating radio, orderby select,Apply/Clear all, hiddens),woocommerce/archive-product.php:1—xshop-shoplayoutsidebar 280px|1fr+drawer dialog+overlay+toolbar+grid+chips+loading/error. - JS:
assets/js/filter.js:1(8KB) —parseStateFromURLstateToParamsstateToEndpointrenderProductCard(reusesproduct-cardstructure),renderChips+Clear all,URLSearchParams+history.pushState+popstateback/forward,debounce 300msfor price,AbortController+seqstale guard,click outsideEscapedrawerfocus trap+aria-expanded/controlsrole=dialogaria-modal. - Style:
assets/css/woo.css:1—.xshop-shop__layoutresponsive,.xshop-chip,.xshop-filtercard,.xshop-drawerfixed, RTL viainset-inline, dark via tokens. - Asset:
inc/setup/assets.php:1—filter.jsfront-end with DOM guard (data-xshop-filters), versioned,woo.cssglobal intentional. - Server fallback:
inc/woocommerce/setup.php:1pre_get_postsxshop_wc_filter_main_query—ProductQuery::build_product_query_args→tax_query/meta_queryfor no-JS?stock=instocketc. - Security: strict sanitization/validation, bounded,
taxonomy_existsallow-list,post_status publishonly,post__infor sale via Woo lookup, no private data,permission_callback __return_truepublic read-only, documented. - Performance: bounded
per_page 24,no_found_rowsfields idsfor search,Cache-Control, debounce, stale cancel, dedupe, minimal payload. - Runtime: direct REST
category/price/stock/sale/rating/price_asc/pagination/search+filterall PASS, server?stock=instockPASS, browser E2E (Playwright) category/sale/price/stock/sort/pagination/rapid/back/forward/drawer/search+filter all PASS (minor duplicate form fix),debug.logclean.
- Query: