Skip to content

Commit 117a68b

Browse files
committed
清掉程式碼與文件裡已失效的歷史敘述
只留現況,不留「這裡以前是錯的」——那種註記本身就是未來的誤導來源, 機械化守衛(MutationAllowedFieldsSchemaDriftTest)才是防復發的手段。 - 移除 5 個 handler 裡的「幻影欄/假欄已移除」註解 (ASSOC/KIN/POSSESSION,前次清理留下的墓誌銘) - 移除 PinyinUmlaut 與 VariantReplaceScope 裡關於已刪欄位的說明段落, 改為直接陳述現況(ALTNAME_DATA 沒有 Tier 1 欄位、只有 c_alt_name 一個排除欄) - PINYIN_SAVE_NORMALIZE_DESIGN.md 拿掉開頭修訂區塊與刪除線標註, 直接改寫成現行設計;掛點表移除已不存在的 #4/#5 與其交叉引用 - CHAR_VARIANT_MAP_TEXT_COLUMN_ROLLOUT_PLAN.md 拿掉更正區塊; CHAR_VARIANT_MAP_CONSOLIDATION_PLAN.md/.en.md 修掉「掛鉤點會對 c_alt_name_pinyin 做 PinyinUmlaut 正規化」的失效描述 - 測試註解同樣只留當下要釘住的合約 CHANGELOG 保留完整記錄——那是變更史該待的地方。 已執行 ./vendor/bin/phpunit(2988 tests 全綠)與 php-cs-fixer
1 parent 28d1862 commit 117a68b

17 files changed

Lines changed: 29 additions & 88 deletions

app/Services/Mutations/AssociationCreateHandler.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,8 @@ protected function allowedFields(): array {
249249
'c_source',
250250
'c_pages',
251251
'c_notes',
252-
// ⚠️ 移除幻影 c_supplement(ASSOC_DATA 無此欄)。
253252
'c_sequence',
254253
'c_assoc_count',
255-
// Task 27:補回舊表單可錄入欄位(皆 ASSOC_DATA 真實欄)。
256254
'c_topic_code',
257255
'c_occasion_code',
258256
'c_tertiary_personid',

app/Services/Mutations/AssociationMutationHandler.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,10 +332,8 @@ protected function allowedFields(): array {
332332
'c_source',
333333
'c_pages',
334334
'c_notes',
335-
// ⚠️ 移除幻影 c_supplement(ASSOC_DATA 無此欄)。
336335
'c_sequence',
337336
'c_assoc_count',
338-
// Task 27:補回舊表單可錄入欄位(皆 ASSOC_DATA 真實欄)。
339337
'c_topic_code',
340338
'c_occasion_code',
341339
'c_tertiary_personid',

app/Services/Mutations/KinshipCreateHandler.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,6 @@ protected function allowedFields(): array {
179179
'c_source',
180180
'c_pages',
181181
'c_notes',
182-
// Task 27 補回:c_autogen_notes 為 KIN_DATA 真實欄(舊表單以 textarea 暴露為可錄入);
183-
// 移除幻影 c_supplement(KIN_DATA 無此欄,SHOW COLUMNS 確認)。
184182
'c_autogen_notes',
185183
];
186184
}

app/Services/Mutations/KinshipMutationHandler.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,6 @@ protected function allowedFields(): array {
265265
'c_source',
266266
'c_pages',
267267
'c_notes',
268-
// Task 27 補回:c_autogen_notes 為 KIN_DATA 真實欄;移除幻影 c_supplement(KIN_DATA 無此欄)。
269268
'c_autogen_notes',
270269
];
271270
}

app/Services/Mutations/PossessionMutationHandler.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,6 @@ protected function validatePersonIdInRow(int $personId, object $original): ?Json
208208
}
209209

210210
protected function allowedFields(): array {
211-
// 僅列 POSSESSION_DATA 真實欄位(對照 schema migration)。
212-
// 早期版本含 c_supplement / c_measure_value / c_firstyear / c_lastyear 等不存在欄位(假欄),已移除。
213211
return [
214212
'c_sequence',
215213
'c_possession_act_code',

app/Support/PinyinUmlaut.php

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,11 @@ class PinyinUmlaut {
2828
*
2929
* 僅列**定義上即漢語拼音**的欄:`c_surname`/`c_mingzi`(其他羅馬化另存於 `c_*_rm`/`c_*_proper`)、
3030
* 以及由二者組出的 `c_name`。**刻意不含** `c_*_rm`(Wade-Giles)/`c_*_proper`(母語拉丁名,
31-
* 可能含真 `v`)。設計見 docs/PINYIN_SAVE_NORMALIZE_DESIGN.md。
31+
* 可能含真 `v`)。ALTNAME_DATA 沒有 Tier 1 欄位——其唯一的別名羅馬字欄 `c_alt_name` 可能含
32+
* 西文別名(如 Denver),走前端 Tier 2 互動確認。設計見 docs/PINYIN_SAVE_NORMALIZE_DESIGN.md。
3233
*/
3334
public const BIOG_MAIN_PINYIN_V_FIELDS = ['c_surname', 'c_mingzi', 'c_name'];
3435

35-
/*
36-
* ALTNAME_DATA 沒有 Tier 1 欄位(#1284)。
37-
*
38-
* 原本的 ALTNAME_PINYIN_V_FIELDS 列的 `c_alt_name_pinyin`/`2`/`3` 三欄,migration 從未
39-
* 建立、prod 也不存在(baseline `import_cbdb_schema.php` 的 ALTNAME_DATA 就是 12 欄),
40-
* 是照著同樣有誤的 v2 白名單挑出來的。這裡刻意不留空常數:留著會讓下一個人以為
41-
* 「只是暫時沒有欄位」而重新填進去。
42-
*
43-
* ALTNAME_DATA 唯一的別名羅馬字欄是 `c_alt_name`,它可能含西文別名(如 Denver),
44-
* 一律走前端 Tier 2 互動確認(AltnameEditor 的 detectUmlautConversions),後端不轉。
45-
*/
46-
4736
/** 將字串中作為 ü 代寫的 v 正規化為 ü。null/空字串原樣返回。 */
4837
public static function normalize(?string $value): string {
4938
if ($value === null || $value === '') {

app/Support/VariantReplaceScope.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,6 @@ final class VariantReplaceScope {
9191
// 跨表代碼鍵 → INDEXYEAR_TYPE_CODES.c_index_year_type_code(varchar PK)。
9292
'c_index_year_type_code',
9393
],
94-
// ALTNAME_DATA 只有 c_alt_name 一個拉丁人名欄。原本這裡還列了 c_alt_name_pinyin/
95-
// _pinyin2/_pinyin3/c_alt_name_role,並註記為「prod-only」——那是錯的(#1284):
96-
// 四欄 migration 從未建立、prod 也不存在,只出現在 v2 白名單與測試合成表裡。
97-
// 型別導向的範圍本來就看不到不存在的欄,排除它們是純粹的雜訊。
9894
'ALTNAME_DATA' => ['c_alt_name'],
9995

10096
// ── 跨表 join/樹狀關聯的「代碼鍵」(D3)。

docs/CHAR_VARIANT_MAP_CONSOLIDATION_PLAN.en.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ The following describes the **future** direction for rewiring `TITLE_VARIANT_MAP
129129
- **Update/proposal path**: `BiogMainMutationHandler::prepareProposalPayload()` (`app/Services/Mutations/BiogMainMutationHandler.php:196-200`) and `BiogMainRepository::updateById()` (`app/Repositories/BiogMainRepository.php:246`) each independently combine `c_surname_chn`+`c_mingzi_chn` into `c_name_chn` — a clear hook point, with the query condition `c_strict_excluded = 0` (strict mode; currently corresponds to 6 rows: 愼, 槀, 靑, 頴, 淸, 厰; 峯 is excluded because `c_strict_excluded=1`). **Open item**: implementation must explicitly decide the replacement order — either replace `c_surname_chn`/`c_mingzi_chn` in their own fields first and then compose `c_name_chn` (preserving the current invariant `c_name_chn === c_surname_chn.c_mingzi_chn`), or replace only the composed `c_name_chn` (which would leave it inconsistent with the component fields). This plan leans toward the former (replace the component fields first, then compose), but implementation must pin this down explicitly in code and tests before starting — the two paths must not each assume a different approach.
130130
- **Create path**: `BiogMainCreateHandler.php` itself has no name-composition logic; it only lists `c_name_chn`/`c_surname_chn`/`c_mingzi_chn` in its field allowlist and delegates to `store(Request $request)` in `app/Repositories/BiogMainRepository.php:353-365`. `store()` starts with `$data = $request->all()`, then runs `timestamp()`, `auto_pinyin($data)`, `BracketNormalizer::normalizeBiogMain()`, `PinyinUmlaut::normalizeFields()` (lines 355-361) in sequence before `BiogMain::create($data)` — **none of these existing steps re-derive `c_name_chn`**. In other words, when a new person is created, `c_name_chn` is the raw string sent by the frontend throughout, with no logic that recomposes it from `c_surname_chn`+`c_mingzi_chn`. This means the create path **has no existing "data replacement" hook to modify** (unlike the update path, which already has name-composition logic where a condition can simply be added in place) — applying variant-character replacement here requires **adding** a new piece of normalization code inside `store()`. This is a larger scope of work than the update path, and it's entirely new behavior (the current create path does no variant-character replacement on person names at all), so future task planning needs to estimate create and update separately and should not assume they're symmetric.
131131

132-
3. **ALTNAME_DATA (person's alternate names) write path**: unlike BIOG_MAIN, `AltnameCreateHandler`/`AltnameMutationHandler` each already have clear preprocessing hook points (`AltnameCreateHandler::preprocessCreateData()` lines 61-71, `AltnameMutationHandler::preprocessUpdateData()` around lines 61-66), which already apply `BracketNormalizer`/`PinyinUmlaut::normalizeFields` normalization to fields like `c_alt_name_pinyin` — a more ready-made hook point than the BIOG_MAIN create path. The query condition is likewise `c_strict_excluded = 0` (strict mode), applied to the `c_alt_name_chn` field (`c_alt_name_chn` is part of `ALTNAME_DATA`'s composite primary key: `c_personid + c_alt_name_chn + c_alt_name_type_code`; rewriting this field constitutes a "composite primary key value change" rather than a plain field update, and implementation needs to stay consistent with existing rename/primary-key-change handling — e.g. the primary-key-change handling logic in `AltnameMutationHandler` — rather than being simplified into a plain field overwrite).
132+
3. **ALTNAME_DATA (person's alternate names) write path**: unlike BIOG_MAIN, `AltnameCreateHandler`/`AltnameMutationHandler` each already have clear preprocessing hook points (`AltnameCreateHandler::preprocessCreateData()` lines 61-71, `AltnameMutationHandler::preprocessUpdateData()` around lines 61-66), which already apply `BracketNormalizer` normalization — a more ready-made hook point than the BIOG_MAIN create path. The query condition is likewise `c_strict_excluded = 0` (strict mode), applied to the `c_alt_name_chn` field (`c_alt_name_chn` is part of `ALTNAME_DATA`'s composite primary key: `c_personid + c_alt_name_chn + c_alt_name_type_code`; rewriting this field constitutes a "composite primary key value change" rather than a plain field update, and implementation needs to stay consistent with existing rename/primary-key-change handling — e.g. the primary-key-change handling logic in `AltnameMutationHandler` — rather than being simplified into a plain field overwrite).
133133

134134
4. Add `app/Services/CharVariantMapService` (working name; naming can be finalized during implementation) as a unified query interface.
135135

docs/CHAR_VARIANT_MAP_CONSOLIDATION_PLAN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ return new class () extends Migration {
129129
- **Update/proposal 路徑**`BiogMainMutationHandler::prepareProposalPayload()``app/Services/Mutations/BiogMainMutationHandler.php:196-200`)與 `BiogMainRepository::updateById()``app/Repositories/BiogMainRepository.php:246`)都各自組合 `c_surname_chn`+`c_mingzi_chn``c_name_chn`,是明確的掛鉤點,查詢條件為 `c_strict_excluded = 0`(嚴格模式,目前對應 6 筆:愼、槀、靑、頴、淸、厰;「峯」因 `c_strict_excluded=1` 被排除)。**待決事項**:實作時必須明確決定替換順序——是先對 `c_surname_chn`/`c_mingzi_chn` 這兩個分欄各自做落地替換、再組出 `c_name_chn`(維持 `c_name_chn === c_surname_chn.c_mingzi_chn` 這個現行 invariant),還是只替換組合後的 `c_name_chn`(會讓 `c_name_chn` 與分欄內容不一致)。本計畫傾向前者(分欄先替換再組字),但實作階段需要在動工前於程式碼與測試中明確寫死這個順序,不能兩條路徑各自假設不同做法。
130130
- **Create 路徑**:`BiogMainCreateHandler.php` 本身沒有組字邏輯,只在欄位白名單列出 `c_name_chn`/`c_surname_chn`/`c_mingzi_chn`,實際委派給 `app/Repositories/BiogMainRepository.php:353-365` 的 `store(Request $request)`。`store()` 以 `$data = $request->all()` 起手,接著依序跑 `timestamp()`、`auto_pinyin($data)`、`BracketNormalizer::normalizeBiogMain()`、`PinyinUmlaut::normalizeFields()`(355-361 行)才 `BiogMain::create($data)`——**這些既有步驟都不會重新推導 `c_name_chn`**,換言之新建人物時 `c_name_chn` 全程是前端送來的原始字串,沒有從 `c_surname_chn`+`c_mingzi_chn` 重新組字的邏輯。這代表 create 路徑**沒有現成的「落地替換」掛鉤點可以修改**(不像 update 路徑本來就有組字邏輯可以就地加條件),要套用異體字落地替換得在 `store()` 內**新增**一段正規化程式碼——這是比 update 路徑更大的實作範圍,且屬於全新行為(現行 create 完全不做人名異體字替換),需要在後續任務規劃時把 create/update 分開估工,不能假設兩者對稱。
131131

132-
3. **ALTNAME_DATA(人物別名)寫入路徑**:與 BIOG_MAIN 不同,`AltnameCreateHandler``AltnameMutationHandler` 已經各自有明確的預處理掛鉤點(`AltnameCreateHandler::preprocessCreateData()` 61-71 行、`AltnameMutationHandler::preprocessUpdateData()` 61-66 行附近),現行已在這兩個方法內對 `c_alt_name_pinyin` 等欄位做 `BracketNormalizer`/`PinyinUmlaut::normalizeFields` 正規化,是比 BIOG_MAIN create 路徑更現成的掛鉤點。查詢條件同樣是 `c_strict_excluded = 0`(嚴格模式),套用在 `c_alt_name_chn` 欄位上(`c_alt_name_chn``ALTNAME_DATA` 複合主鍵的一部分:`c_personid + c_alt_name_chn + c_alt_name_type_code`,改寫這個欄位屬於「複合主鍵值變更」而非單純欄位更新,實作時需要跟現行改名/改主鍵的既有處理方式〔如 `AltnameMutationHandler` 對主鍵變更的處理邏輯〕保持一致,不能簡化成普通欄位覆寫)。
132+
3. **ALTNAME_DATA(人物別名)寫入路徑**:與 BIOG_MAIN 不同,`AltnameCreateHandler``AltnameMutationHandler` 已經各自有明確的預處理掛鉤點(`AltnameCreateHandler::preprocessCreateData()` 61-71 行、`AltnameMutationHandler::preprocessUpdateData()` 61-66 行附近),現行已在這兩個方法內做 `BracketNormalizer` 正規化,是比 BIOG_MAIN create 路徑更現成的掛鉤點。查詢條件同樣是 `c_strict_excluded = 0`(嚴格模式),套用在 `c_alt_name_chn` 欄位上(`c_alt_name_chn``ALTNAME_DATA` 複合主鍵的一部分:`c_personid + c_alt_name_chn + c_alt_name_type_code`,改寫這個欄位屬於「複合主鍵值變更」而非單純欄位更新,實作時需要跟現行改名/改主鍵的既有處理方式〔如 `AltnameMutationHandler` 對主鍵變更的處理邏輯〕保持一致,不能簡化成普通欄位覆寫)。
133133

134134
4. 新增 `app/Services/CharVariantMapService`(暫定名稱,命名可於實作階段再定)作為統一查詢介面。
135135

docs/CHAR_VARIANT_MAP_TEXT_COLUMN_ROLLOUT_PLAN.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ S0~S9 全部完成,逐步 rebase merge 進 `develop`(線性歷史):
145145
| **預設:所有文本欄** | **lenient(全量 7 筆)** |
146146
| `BIOG_MAIN.c_name_chn``c_surname_chn``c_mingzi_chn` | strict(6 筆,排除「峯→峰」) |
147147
| `ALTNAME_DATA.c_alt_name_chn` | strict |
148-
| `BIOG_MAIN``c_surname``c_mingzi``c_name``c_surname_proper``c_mingzi_proper``c_name_proper``c_surname_rm``c_mingzi_rm``c_name_rm``ALTNAME_DATA``c_alt_name` | **排除**(共 10 欄)<br>原記 13 欄,含 `ALTNAME_DATA``c_alt_name_pinyin``_pinyin2``_pinyin3`——那三欄不存在,已於 #1284 移除 |
148+
| `BIOG_MAIN``c_surname``c_mingzi``c_name``c_surname_proper``c_mingzi_proper``c_name_proper``c_surname_rm``c_mingzi_rm``c_name_rm``ALTNAME_DATA``c_alt_name` | **排除**(共 10 欄,使用者確認) |
149149

150150
- `modeFor()`**預設回傳是 `'lenient'`**;只有命中 strict 清單才 `'strict'`,命中排除/未知表/非文本欄才 `null`**不得**寫成「查不到就 strict」或「整張 BIOG_MAIN/ALTNAME_DATA 都 strict」。
151151
- strict/lenient 是**逐欄位**:同一列 BIOG_MAIN 裡姓名欄 strict、`c_notes` lenient;ALTNAME_DATA 裡 `c_alt_name_chn` strict、`c_notes` lenient。
@@ -283,8 +283,6 @@ D3 已內嵌一份已查證的代碼鍵清單,直接進排除常數。本步
283283

284284
**另跑一次 prod schema 欄位比對**(不是 migrations):型別導向的範圍會靜默納入 **prod-only 文本欄**,而 `TEXT_TYPES` 守衛與已知表守衛都看不到它們(D2 的 caveat 只涵蓋 prod-only 的****)。
285285

286-
> ⚠️ **更正(#1284**:本段原本把 `ALTNAME_DATA.c_alt_name_pinyin``_pinyin2``_pinyin3``c_alt_name_role` 記為「已知 prod-only」。**那是錯的**——這四欄 migration 未曾建立、prod 也不存在,只出現在 v2 `allowedFields()` 白名單與**測試自建的合成表**裡。本段自己記下的線索(「只在合成測試表出現」「結構式掃描碰不到它」)其實正指向這個結論,只是當時下成了 prod-only。四欄已從白名單與 `VariantReplaceScope` 排除清單移除;`tests/Feature/MutationAllowedFieldsSchemaDriftTest.php` 是防復發的機械化守衛。
287-
288286
### S1:基礎設施
289287

290288
- `VariantReplaceScope``replaceRow()``replaceFor()``assertWritable()`(見實作設計)。

0 commit comments

Comments
 (0)