Files
mataba/shop/CHANGELOG.md
T

8.2 KiB
Raw Blame History

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, zero left/right.
    • JS: assets/js/theme.js extended 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.md for M1.
  • 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 + .gitignore update, tools/build-release.ps1 fix.
  • 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, hook xshop_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/end xshop-products, toolbar, remove gallery, related 4/4, product.js conditional on is_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 Size S/M/L, data-product_variations JSON, 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: Type parse error), debug.log clean, ZIP rebuild + manual install PASS.
    • Docs: ARCHITECTURE.md, UI-SPEC.md, TESTING.md, COMPATIBILITY.md, RUNTIME-QA.md updated.
  • 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, sanitized search (strip_tags/sanitize_text_field/max 100) + limit 1..20, min 2 → empty, WP_Query s + _sku LIKE, publish only, 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/draft/customer/order, SKU + title/content search, HPOS-safe.
    • UI: template-parts/components/ajax-search.php:1 reusable combobox (role=combobox aria-expanded/controls/autocomplete listbox aria-live data-*, view-all ?s=&post_type=product, hidden post_type when Woo active, RTL via logical, dark via tokens).
    • JS: assets/js/search.js:1 vanilla debounce 250ms, AbortController, stale seq, dedupe lastQuery, fetch, loading/empty/error/view-all, keyboard ArrowUp/Down/Enter/Escape, click outside, aria-activedescendant, no console.log.
    • Style: assets/css/woo.css:1 dropdown absolute→fixed@640 max 60vh token search item grid 48px 1fr + price/stock.
    • Asset: inc/setup/assets.php:1 enqueue search.js only where data-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 in PERFORMANCE.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.log clean.
    • Docs: ARCHITECTURE.md:7 UI-SPEC.md:3,8 SECURITY.md:11 PERFORMANCE.md:8 TESTING.md:M3 RUNTIME-QA.md:M3.
  • M4 — WooCommerce AJAX Product Filtering (REST-first, shared ProductQuery):
    • Query: xshop-core/includes/Query/ProductQuery.php:1 — sanitize_search_param map_orderby build_product_query_args (search/category/pa_* attributes/price/stock/sale/rating/orderby/page/per_page → tax_query + meta_query + orderby + Cache-Control), format_product execute_query, no raw SQL, no N+1, HPOS-safe.
    • Endpoint GET /wp-json/xshop/v1/products (REST/Products.php:1, Core/Plugin.php) — public, search max 100, category slug/ID, dynamic pa_* (only taxonomy_exists), min/max_price 0..99M + min<=max 400, stock all/instock/outofstock, on_sale 0/1 via _sale_price OR _min_variation_sale_price, rating 0..5, orderby allow-list, page 1..100 per_page 1..24 default 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 use Query.
    • UI: template-parts/components/product-filters.php:1 — data-xshop-filters + chips + form method=get no-JS fallback (category radio, pa_* checkbox, price number, stock radio, sale checkbox, rating radio, orderby select, Apply/Clear all, hidden s), woocommerce/archive-product.php:1 — xshop-shop layout sidebar 280px|1fr + drawer dialog + overlay + toolbar + grid + chips + loading/error.
    • JS: assets/js/filter.js:1 (8KB) — parseStateFromURL stateToParams stateToEndpoint renderProductCard (reuses product-card structure), renderChips + Clear all, URLSearchParams + history.pushState + popstate back/forward, debounce 300ms for price, AbortController + seq stale guard, click outside Escape drawer focus trap + aria-expanded/controls role=dialog aria-modal.
    • Style: assets/css/woo.css:1 — .xshop-shop__layout responsive, .xshop-chip, .xshop-filter card, .xshop-drawer fixed, RTL via inset-inline, dark via tokens.
    • Asset: inc/setup/assets.php:1 — filter.js front-end with DOM guard (data-xshop-filters), versioned, woo.css global intentional.
    • Server fallback: inc/woocommerce/setup.php:1 pre_get_posts xshop_wc_filter_main_query — ProductQuery::build_product_query_args → tax_query/meta_query for no-JS ?stock=instock etc.
    • Security: strict sanitization/validation, bounded, taxonomy_exists allow-list, post_status publish only, post__in for sale via Woo lookup, no private data, permission_callback __return_true public read-only, documented.
    • Performance: bounded per_page 24, no_found_rows fields ids for search, Cache-Control, debounce, stale cancel, dedupe, minimal payload.
    • Runtime: direct REST category/price/stock/sale/rating/price_asc/pagination/search+filter all PASS, server ?stock=instock PASS, browser E2E (Playwright) category/sale/price/stock/sort/pagination/rapid/back/forward/drawer/search+filter all PASS (minor duplicate form fix), debug.log clean.