# 機能設計書 21-記事編集

## 概要

本ドキュメントは、Wikipedia iOSアプリケーションにおける記事編集機能の設計を記載する。この機能により、ユーザーはWikipedia記事のウィキテキストを直接編集することができる。

### 本機能の処理概要

記事編集機能は、ユーザーがWikipedia記事のソースコード（ウィキテキスト）を編集するための包括的なエディタ環境を提供する。

**業務上の目的・背景**：Wikipediaはユーザー参加型の百科事典であり、誰でも記事を編集できることがその根幹をなす。モバイルアプリからの編集を可能にすることで、より多くのユーザーが場所を問わずWikipediaへの貢献を行えるようにする。これにより、Wikipediaコミュニティの拡大と記事品質の向上を支援する。

**機能の利用シーン**：ユーザーが記事を閲覧中に誤字脱字を発見した場合、情報を追加・修正したい場合、またはリンクを追加したい場合などに使用される。編集ボタンをタップすることで、該当セクションまたは記事全体のソースコードを編集できる。

**主要な処理内容**：
1. 記事またはセクションのウィキテキストをMediaWiki APIから取得
2. シンタックスハイライト付きのソースエディタを表示
3. テキスト装飾（太字、斜体等）やリンク挿入のツールバーを提供
4. 編集通知（Edit Notices）の表示
5. 検索・置換機能の提供
6. 元に戻す・やり直し操作のサポート
7. テーマ設定とフォントサイズ調整

**関連システム・外部連携**：MediaWiki Action API（ウィキテキスト取得）、WMFSourceEditorコンポーネント（テキスト編集UI）

**権限による制御**：保護されたページでは編集が制限される。ブロックされたユーザーは編集できない。ログインしていないユーザーはIPアドレスまたは一時アカウントで編集が記録される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 記事表示画面 | 呼び出し元 | 編集ボタンタップで遷移 |
| - | エディタ画面 | 主画面 | ウィキテキストの編集操作 |
| - | 編集通知画面 | モーダル | 編集前の注意事項表示 |
| - | リンク挿入画面 | モーダル | 内部・外部リンクの追加 |
| - | メディア挿入画面 | モーダル | 画像の検索と挿入 |
| - | テーマ設定ポップアップ | ポップオーバー | エディタの表示設定 |

## 機能種別

CRUD操作（記事データの読み取り・更新）、テキスト編集、UI制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pageURL | URL | Yes | 編集対象の記事URL | 有効なWikipedia記事URL |
| sectionID | Int? | No | 編集対象のセクションID | nil（全体編集）または0以上の整数 |
| editFlow | EditFlow | Yes | 編集フロー種別 | .editorPreviewSave または .editorSavePreview |
| source | Source | Yes | 編集元の種別 | .article または .talk |
| articleSelectedInfo | SelectedTextEditInfo? | No | 選択テキスト情報 | テキスト選択時に設定 |
| editTag | WMFEditTag | Yes | 編集タグ | .appFullSource, .appSectionSource, .appSelectSource |

### 入力データソース

- MediaWiki Action API（wikitextFetcher経由でウィキテキスト取得）
- EditNoticesFetcher（編集通知取得）
- UserDefaults（ユーザー設定）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| editedWikitext | String | 編集後のウィキテキスト |
| navigateToURL | URL? | 編集通知リンクからの遷移先URL |

### 出力先

- EditPreviewViewController（プレビュー画面へ遷移）
- EditSaveViewController（保存画面へ遷移）
- EditorViewControllerDelegate（編集結果通知）

## 処理フロー

### 処理シーケンス

```
1. エディタ画面の初期化
   └─ ナビゲーションバー、スピナー、フォーカスナビゲーションビューのセットアップ

2. コンテンツ読み込み（並列実行）
   ├─ 編集通知の取得（loadEditNotices）
   ├─ ウィキテキストの取得（loadWikitext）
   └─ 一時アカウント状態の確認（checkWikiStatus）

3. 読み込み結果の処理
   ├─ エラー時：エラーアラート表示
   ├─ ブロック時：ブロックパネル表示（読み取り専用モード）
   ├─ 保護ページ時：警告表示（権限に応じて読み取り専用）
   └─ 成功時：ソースエディタを子ビューとして追加

4. ユーザー編集操作
   ├─ テキスト入力・装飾
   ├─ リンク挿入・編集
   ├─ メディア挿入
   └─ 検索・置換

5. 進行ボタンタップ
   ├─ editorPreviewSaveフロー：プレビュー画面へ遷移
   └─ editorSavePreviewフロー：保存画面へ遷移

6. キャンセル操作
   ├─ 変更なし：直接閉じる
   └─ 変更あり：確認アラート表示後に閉じる
```

### フローチャート

```mermaid
flowchart TD
    A[編集開始] --> B[コンテンツ読み込み]
    B --> C{読み込み成功?}
    C -->|No| D[エラー表示]
    C -->|Yes| E{ブロック/保護?}
    E -->|ブロック| F[読み取り専用モード]
    E -->|保護| G{編集権限あり?}
    G -->|No| F
    G -->|Yes| H[編集可能モード]
    E -->|なし| H
    H --> I[ソースエディタ表示]
    I --> J{ユーザー操作}
    J -->|編集| K[テキスト変更]
    J -->|進む| L{編集フロー}
    L -->|Preview→Save| M[プレビュー画面]
    L -->|Save→Preview| N[保存画面]
    J -->|キャンセル| O{変更あり?}
    O -->|Yes| P[確認ダイアログ]
    O -->|No| Q[終了]
    P --> Q
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 編集保護チェック | 保護されたページは権限のないユーザーは編集不可 | ページに編集保護が設定されている場合 |
| BR-002 | ブロックチェック | ブロックされたユーザーは編集不可 | ユーザーがブロックされている場合 |
| BR-003 | 編集通知表示 | 編集前に編集通知を表示 | 編集通知が存在し、表示設定がONの場合 |
| BR-004 | 初回編集警告 | セクション0の初回編集時に警告表示 | セクション0かつ初回編集メッセージ未表示 |
| BR-005 | 選択テキスト検索 | 記事から選択されたテキストをウィキテキスト内で検索 | 選択テキスト情報がある場合 |

### 計算ロジック

該当なし

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 設定読み込み | UserDefaults | SELECT | 編集関連の設定値取得 |
| 設定保存 | UserDefaults | UPDATE | 初回メッセージ表示フラグ等の更新 |

### テーブル別操作詳細

#### UserDefaults

| 操作 | 項目（キー名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT/UPDATE | didShowInformationEditingMessage | Bool | 初回編集警告表示済みフラグ |
| SELECT/UPDATE | wmf_IsSyntaxHighlightingEnabled | Bool | シンタックスハイライト設定 |
| SELECT | wmf_alwaysDisplayEditNotices | Bool | 編集通知常時表示設定 |
| SELECT | didShowEditingOnboarding | Bool | 編集オンボーディング表示済みフラグ |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| networkError | 接続エラー | ネットワーク接続なし | エラーアラート表示、編集中止 |
| blockedMessage | ブロックエラー | ユーザーがブロックされている | ブロックパネル表示、読み取り専用 |
| protectedPage | 保護エラー | ページが保護されている | 警告パネル表示、権限なしは読み取り専用 |
| articleSelectFail | 選択範囲エラー | 選択テキストがウィキテキスト内に見つからない | アラート表示、通常編集へ |
| serverError | サーバーエラー | API応答エラー | エラーアラート表示、編集中止 |

### リトライ仕様

自動リトライは行わない。ユーザーが再度編集操作を行う必要がある。

## トランザクション仕様

本機能は編集内容の準備のみを行い、実際のWikipediaへの保存はEditSaveViewControllerで行われる。トランザクション管理は保存時に適用される。

## パフォーマンス要件

- ウィキテキスト取得：5秒以内
- 編集通知取得：3秒以内
- スピナー表示：1秒の遅延後に開始（短時間読み込みでのちらつき防止）

## セキュリティ考慮事項

- 一時アカウント対応：ログインしていないユーザーへの警告表示
- 編集権限検証：保護ページ・ブロックユーザーの編集制限
- 編集トラッキング：EditInteractionFunnel、EditAttemptFunnelによる編集行動の記録（プライバシー考慮）

## 備考

- 編集フローは2種類存在：editorPreviewSave（記事編集用）、editorSavePreview（トークページ用）
- WMFSourceEditorViewControllerはWMFComponentsフレームワークで提供される再利用可能なソースエディタ

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、エディタで使用されるデータ構造と設定を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | EditorViewController.swift | `Wikipedia/Code/EditorViewController.swift` | EditFlow, Source, WikitextFetchResponseの定義（L17-34） |

**読解のコツ**: EditFlowは編集画面遷移のフローを、Sourceは編集元（記事/トーク）を表す。WikitextFetchResponseはAPI応答をまとめた内部構造体。

#### Step 2: エントリーポイントを理解する

処理の起点となる記事画面からの呼び出しを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ArticleViewController+Editing.swift | `Wikipedia/Code/ArticleViewController+Editing.swift` | 編集開始メソッド群（L9-44） |

**主要処理フロー**:
1. **L9-22**: showEditorForSectionOrTitleDescription - セクション編集または説明文編集のダイアログ表示
2. **L24-34**: showEditorForFullSource - 記事全体のソース編集
3. **L36-44**: showEditorForSection - 特定セクションの編集開始
4. **L109-160**: presentEditor - エディタのモーダル表示（一時アカウント確認含む）

#### Step 3: メインコントローラーを理解する

EditorViewControllerの初期化とライフサイクルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | EditorViewController.swift | `Wikipedia/Code/EditorViewController.swift` | 初期化とviewDidLoad（L91-121） |

**主要処理フロー**:
- **L91-105**: init - 依存オブジェクト（fetcher等）の初期化
- **L111-121**: viewDidLoad - UI設定とコンテンツ読み込み開始
- **L191-294**: loadContent - ウィキテキスト・編集通知・一時アカウント状態の並列取得

#### Step 4: コンテンツ読み込みを理解する

ウィキテキストと編集通知の取得処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | EditorViewController.swift | `Wikipedia/Code/EditorViewController.swift` | loadWikitext, loadEditNotices（L296-396） |

**主要処理フロー**:
- **L296-313**: loadEditNotices - EditNoticesFetcherを使用した編集通知取得
- **L357-396**: loadWikitext - WikitextFetcherを使用したウィキテキスト取得と権限チェック

#### Step 5: ソースエディタ表示を理解する

WMFSourceEditorViewControllerの初期化と設定を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | EditorViewController.swift | `Wikipedia/Code/EditorViewController.swift` | addChildEditor（L495-584） |

**主要処理フロー**:
- **L496-555**: ローカライズ文字列の設定
- **L557-559**: WMFSourceEditorViewModelの作成
- **L561-582**: 子ViewControllerとしてエディタを追加

#### Step 6: ユーザー操作ハンドリングを理解する

ナビゲーションとデリゲート処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | EditorViewController.swift | `Wikipedia/Code/EditorViewController.swift` | EditorNavigationItemControllerDelegate（L812-883） |

**主要処理フロー**:
- **L813-838**: didTapProgressButton - 進行ボタンタップ時のフロー分岐
- **L652-673**: showEditPreview - プレビュー画面への遷移
- **L675-698**: showEditSave - 保存画面への遷移

### プログラム呼び出し階層図

```
ArticleViewController
    │
    ├─ showEditorForSection(with:)
    │      └─ presentEditor(editorViewController:)
    │              └─ EditorViewController.init()
    │                      ├─ viewDidLoad()
    │                      │      └─ loadContent()
    │                      │              ├─ loadEditNotices()
    │                      │              ├─ loadWikitext()
    │                      │              └─ checkWikiStatus()
    │                      │
    │                      └─ addChildEditor()
    │                              └─ WMFSourceEditorViewController
    │
    └─ showEditorForFullSource()
           └─ (同上)

EditorViewController
    │
    ├─ EditorNavigationItemControllerDelegate
    │      └─ didTapProgressButton()
    │              ├─ showEditPreview() → EditPreviewViewController
    │              └─ showEditSave() → EditSaveViewController
    │
    ├─ WMFSourceEditorViewControllerDelegate
    │      ├─ sourceEditorViewControllerDidTapLink() → EditLinkViewController
    │      └─ sourceEditorViewControllerDidTapImage() → InsertMediaViewController
    │
    └─ EditNoticesViewControllerDelegate
           └─ editNoticesControllerUserTapped(url:)
```

### データフロー図

```
[入力]                      [処理]                           [出力]

pageURL         ───▶ WikitextFetcher.fetchSection() ───▶ wikitext
                           │
                           ▼
                    EditorViewController
                           │
                    ┌──────┼──────┐
                    ▼      ▼      ▼
              EditNotices Wikitext TempAccountStatus
                    │      │      │
                    └──────┼──────┘
                           ▼
                 WMFSourceEditorViewController
                           │
                    ユーザー編集
                           │
                           ▼
                    editedWikitext ───▶ EditPreviewViewController
                                        または
                                        EditSaveViewController
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| EditorViewController.swift | `Wikipedia/Code/EditorViewController.swift` | ソース | メインエディタコントローラー |
| ArticleViewController+Editing.swift | `Wikipedia/Code/ArticleViewController+Editing.swift` | ソース | 記事画面からの編集開始処理 |
| EditorNavigationItemController.swift | `Wikipedia/Code/EditorNavigationItemController.swift` | ソース | ナビゲーションバーアイテム管理 |
| EditNoticesViewController.swift | `Wikipedia/Code/EditNoticesViewController.swift` | ソース | 編集通知表示画面 |
| EditNoticesView.swift | `Wikipedia/Code/EditNoticesView.swift` | ソース | 編集通知ビュー |
| EditLinkViewController.swift | `Wikipedia/Code/EditLinkViewController.swift` | ソース | リンク編集画面 |
| InsertLinkViewController.swift | `Wikipedia/Code/InsertLinkViewController.swift` | ソース | リンク挿入画面 |
| InsertMediaViewController.swift | `Wikipedia/Code/InsertMediaViewController.swift` | ソース | メディア挿入画面 |
| WikitextFetcher.swift | `WMF Framework/` | ソース | ウィキテキスト取得 |
| EditNoticesFetcher.swift | `WMF Framework/` | ソース | 編集通知取得 |
| WMFSourceEditorViewController | `WMFComponents/` | フレームワーク | ソースエディタUI |
