異體字落地替換 S3:人物子資源與 BIOG_MAIN 全面串接,並補上兩形並存查重 - #1273
Merged
Merged
Conversation
在兩個抽象基底類別(AbstractPersonSubresourceCreateHandler/
AbstractPersonSubresourceMutationHandler)的 handle() 內插入通用掛鉤(新
Concerns\AppliesVariantReplacement),21 個人物子資源 handler 自動生效;體系外
三個例外(PossessionCreateHandler/PostingCreateHandler/SourceMutationHandler)
各自補掛。掛鉤點一律早於 preprocess、PK 計算與查重,所以文本型 PK 成員
(ALTNAME_DATA.c_alt_name_chn、ASSOC_DATA.c_text_title、BIOG_SOURCE_DATA.c_pages)
替換後的值會成為實際落庫的 PK。notices 由 handle() 統一掛上,成功與 409/422 都帶。
移除 Altname 兩個子類重複的 replaceStrict() + assign(通用掛鉤先跑後它的 replaced
恆為空,會讓別名替換通知靜默消失),基底改用 merge 收集。
BIOG_MAIN 三處手掛姓名欄改為整列 replaceRow('BIOG_MAIN')(c_notes/c_tribe 等文本欄
原本全漏),但 v2 路徑把替換範圍收窄到「使用者本次實際變更的欄」——它的 payload 是
「原列 ∪ changes」的整列,整列替換等於對使用者沒碰過的欄做回溯校正(D6 明說不做),
還會讓沒改任何欄的存檔變成一筆真實 UPDATE。store() 的回傳 key 統一為 variant_replaced。
D7「兩形並存」查重從 CodesController 抽成 App\Support\VariantEquivalentLookup 並接到
v2 的 create 與改鍵(update)兩側、以及 ASSOC_DATA 鏡像同步的三條寫入分支(既有列
更新、backfill 補建、#70 force 收斂)與反向碼為哨兵 0 的盲插。既有列可能存變體形
(D6 不回溯校正),只比對替換後的值會鑄出兩列語義相同、字形不同的資料,而唯一鍵
擋不住——那比完全不替換更糟。查重只在真的改鍵時執行,否則歷史上就已兩形並存的資料
會變成任何更新都做不了。
其他一併修掉的缺口:
- VariantReplaceScope::loadColumnTypes() 只在「表確實不存在」才降級並快取,其餘
Throwable 一律 rethrow——原本一次連線抖動就會讓該表在整個 process 的剩餘生命週期
都不做替換,資料靜默留變體形。
- char_variant_map 的結構驗證與快取重置下移到落庫層(新 Concerns\GuardsCharVariantMapWrites
掛在代碼表 create/update/proposal,通用核准的 applyCreateProposal/applyUpdateProposal
也補上)。原本只掛在 Codes UI,用 API 或核准歷史提案就能寫入成環的對照,之後
dropCycleEdges() 會把整組邊丟掉、該組字的替換在全站靜默停止。
- Api\MutationController 剝掉客戶端 meta 的 __ 前綴內部鍵:__approving_operation_id
原本可由客戶端帶進來,用來關掉待審重複提案的防呆。
- BIOG_MAIN 的 422「未偵測到任何修改內容」帶上 notices;PostingMutationHandler 的
地址衝突 409 也帶。
- 修好既有的姓名清空 bug:updateById()/prepareProposalPayload() 原本無條件
c_name_chn = 姓 . 名,沒有明確姓氏的歷史人物(分欄 NULL、c_name_chn 存完整姓名)
更新任何一欄都會被靜默清空。store() 早有等價保護,現在三處一致。
測試 harness(CodesControllerTest 的假 driver)補 Schema::getColumns()/getForeignKeys()
與 QueryBuilder::lazyById(),並修好 matchCondition() 把 '!=' 當等值比較(語義正好反過來)。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
這一步做了什麼
docs/CHAR_VARIANT_MAP_TEXT_COLUMN_ROLLOUT_PLAN.md的 S3:異體字落地替換從「手掛少數姓名欄」改為由VariantReplaceScope按「表.欄位型別」決定的整列替換,涵蓋 21 個人物子資源 v2 handler、體系外三個例外 handler 與 BIOG_MAIN 三處寫入。Concerns\AppliesVariantReplacement)插在兩個抽象基底類別的handle()內,早於preprocess、PK 計算與查重 ⇒ 文本型 PK 成員(ALTNAME_DATA.c_alt_name_chn、ASSOC_DATA.c_text_title、BIOG_SOURCE_DATA.c_pages)替換後的值成為實際落庫的 PK。notices由handle()統一掛上,成功與 409/422 都帶。replaceStrict()+ assign(會讓別名替換通知靜默消失),基底改用 merge。replaceRow()(c_notes/c_tribe等原本全漏),但 v2 路徑把範圍收窄到「使用者本次實際變更的欄」——它的 payload 是「原列 ∪ changes」,整列替換等於回溯改寫使用者沒碰過的欄(D6 明說不做)。Review 過程中補上的防護(都不在原計畫的 S3 清單裡)
App\Support\VariantEquivalentLookup並接到 create、改鍵、以及ASSOC_DATA鏡像同步的三條寫入分支與反向碼哨兵 0 的盲插VariantReplaceScope::loadColumnTypes()快取瞬時錯誤char_variant_map的守衛只在 Codes UIdropCycleEdges()把整組邊丟掉、該組字的替換全站靜默停止。守衛下移到落庫層(含通用核准的 create/update)meta.__approving_operation_id客戶端可控__前綴鍵c_name_chn存完整姓名)更新任何一欄都會被靜默清空。三處寫入現在一致查重只在真的改鍵時執行——否則歷史上就已兩形並存的資料會變成任何更新都做不了(假 409)。
驗證
./vendor/bin/phpunit全綠:2886 tests / 15299 assertionsphp-cs-fixer(清 cache、dist config):0 fixestests/Feature/ApiV2MutateVariantReplacementTest.php(29 條)+ 既有測試檔補強;每一條都以「把機制中和掉會紅」逐一驗證過鑑別力,唯二例外在測試註解裡明寫(有第二道保護擋著)🤖 Generated with Claude Code