Files
wordpress-theme-aksrt/tools/adr-classes-domain-placement.md
T
kate522andClaude Opus 5 dbb7de41e9 feat(ticket): replace the after-sale flow with a general ticket system
The old 售后 flow was an order-refund appendage: tickets were hard-bound to an
order number, users could only file them from 「我的订单」against a paid order,
and the admin action bottomed out at 「标记订单已退款」. It could not carry
account questions or feature requests that have nothing to do with an order.

Replace it with a general ticket system modelled on 魔方财务云's idcsmart_ticket:
title + department + description are required, linking an order is optional
(user's own paid orders only). Add departments, custom statuses, preset replies
and internal admin notes as four configuration surfaces. Conversation history
moves off the ticket row's JSON log into dedicated ticket_reply rows, which
unlocks quoted replies. Front end gets a 工单中心 panel under 我的服务; back end
moves from 支付中心 → 售后服务 to users.php → 工单管理.

Per CLAUDE.md's rewrite-over-compatibility rule: drop the old table, build new
ones, delete the old code. No dual paths, no data migration. The upstream
plugin's upstream/downstream delivery and internal-ticket conversion are
deliberately left out — both are multi-provider platform concerns with no
meaning on a single WordPress site.

Data: order_aftersale becomes six aksrt_ticket* tables (ticket, ticket_reply,
ticket_status, ticket_type, ticket_prereply, ticket_note). SCHEMA_VERSION
2.6.0 -> 3.0.0. Status and department seeds are idempotent; the default status
「待接单」is flagged as non-editable.

Domain: new src/Ticket/ (13 files, all under 460 lines). Attachments reuse
UserController::rest_upload_comment_image with a ticket-specific permission
callback, mirroring the existing /report/upload-image route rather than
growing a second upload path.

Notifications go through AKSRT\Messages\Message::send() and deep-link to the
right surface; email/SMS stay out of scope since the theme's mail and SMS
stacks are separate implementations.

Refund gate opens up: marking an order refunded no longer requires an in-flight
ticket, only that the order is paid.

Also generalise a hardcoded special case in tools/audit-admin-contracts.php —
schema domain inference now reads the parent directory instead of matching
"PostList" by name, so new leaf schema files need no per-name exception.

Verification:
  php tools/audit-admin-contracts.php   exit 0, errors=0
  node --test (widget-system + admin)   664 pass / 0 fail
  php -l over all new/changed files     clean
  node --check over all JS              clean
  npm run build + build:public          clean

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-25 23:29:51 +08:00

3.5 KiB

ADR: Domain folder placement + PSR-4 namespaces for theme types

Status

Accepted (2026-07-17); updated 2026-08-02 for Composer PSR-4 root flatten to src/.

Context

Domain folders were frozen after the root→domain move. Theme types then migrated from global AKSRT_* + manual require_once to real PHP namespaces under src/ with Composer PSR-4.

Decision

Domain ownership (unchanged)

Concern Domain Why
Theme shell (setup, scripts, templates, SEO, meta boxes, DB migrator, front-submit, docs presenter, home modules, stats, redirects, update checker, comment actions) Core Shared CMS plumbing
SPA shell + controllers + schema + native ops Admin Dual-surface IA
Settings facade + runtime delegates Settings Single public settings API
Auth, OAuth, captcha, moderation, email rollback Auth Identity & access
User center/home/badges/level/metrics/notifications/follow User Account surface
Credits, balance wallet, signin, invite, points-free Credits Points + cash wallet
Download tokens/state, content pay, VIP, visibility Content Post-centric paid content
Orders, gateways, coupon, charge-card, revenue, creator-revenue, withdrawal, rebate, discount, shipping, wechat-notify Payment Commerce + settlement
Shop services/meta/reviews Shop Product catalog / cart
SMS stack Sms Messaging channel
AI runtime (admin AI controller stays in Admin) Ai Generation helpers
Message, private message, site notice, report center Messages In-site messaging
MeiliSearch, search-push, ip-geo, content-audit, api-audit Extensions Optional integrations
Widgets + registry Widgets WP widgets
Inline style / custom code / loading overlay Frontend Asset render helpers

PSR-4 layout

  • Composer: "AKSRT\\": "src/"
  • Namespace AKSRT\{Domain}\… ↔ path src/{Domain}/…
  • One type per file; StudlyCaps filename = short class/trait/interface name
  • Nested segments: Admin\Schema, Admin\Native, Payment\Gateways, Admin\Schema\PostList
  • OAuth stays under Auth (AKSRT\Auth\OAuth) — no separate oauth/ tree
  • Do not move TopicPay / PlateFollowPay into Content without updating this ADR
  • CreatorRevenue and WeChatNotify stay under Payment

Loader

  1. functions.php loads vendor/autoload.php (Composer: third-party + theme PSR-4)
  2. Immediately after, canary class_exists(\AKSRT\Core\DomainModel::class) — if missing, wp_die with composer install / composer dump-autoload -o (stale vendor/ after PSR-4 cutover is the common failure)
  3. inc/bootstrap.php loads helpers + procedural modules (inc/modules/*) + core-hooks only
  4. Singleton init() remains in functions.php using FQCNs

Deploy note: vendor/ is gitignored. After pull/upload, run composer install --no-dev --optimize-autoloader (or at least composer dump-autoload -o) in the theme root so autoload_psr4 includes "AKSRT\\": ["…/src"].

Procedural (not PSR-4)

  • inc/helpers/* function libraries
  • inc/modules/* (captcha, user-hub/parts, user-notifications, widgets-register, …)
  • inc/core-hooks.php (+ parts)

The one-shot tools/build-psr4-map.php migrator (and tools/psr4-map/ artifacts) were removed when inc/classes was deleted — they scanned the old tree and cannot run anymore.

Out of scope

  • Dual-read class_alias shims for old AKSRT_* global names (rewrite references instead)
  • Converting all helpers to classes