# 画面設計書 24-ニュースレター購読確認ページ

## 概要

本ドキュメントは、Shopware 6 Storefrontのニュースレター購読確認ページ（Newsletter Subscribe Confirmation Page）の画面設計書である。顧客がニュースレター登録のダブルオプトイン確認を完了するための画面について記載する。

### 本画面の処理概要

ニュースレター購読確認ページは、ニュースレター登録時のダブルオプトイン（Double Opt-In）メールに含まれる確認リンクをクリックした際に表示される画面である。

**業務上の目的・背景**：GDPRやメールマーケティングのベストプラクティスに準拠するため、ニュースレター登録にはダブルオプトイン方式が採用されている。顧客がメールアドレスを登録すると確認メールが送信され、メール内の確認リンクをクリックすることで登録が完了する。この画面はその確認処理の結果を表示する。

**画面へのアクセス方法**：
- ニュースレター登録確認メールに含まれるリンクをクリック
- URLにはem（暗号化メールアドレス）とhash（認証ハッシュ）パラメータが含まれる

**主要な操作・処理内容**：
1. 確認パラメータの検証
2. ニュースレター購読ステータスの更新
3. 確認完了メッセージの表示

**画面遷移**：
- 遷移元：確認メールのリンク
- 遷移先：ホームページ（エラー時）

**権限による表示制御**：
- 認証不要（URLパラメータで認証）
- 確認リンクは一度のみ有効

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 55 | ニュースレター登録確認 | 主機能 | ニュースレター登録の確認処理（NewsletterController::subscribeMail） |

## 画面種別

確認

## URL/ルーティング

| ルート名 | URL | HTTPメソッド | 説明 |
|----------|-----|--------------|------|
| frontend.newsletter.subscribe | /newsletter-subscribe | GET | ニュースレター購読確認 |

## 入出力項目

### 入力項目（クエリパラメータ）

| 項目名 | パラメータ名 | 型 | 必須 | 説明 |
|--------|-------------|-----|------|------|
| 暗号化メールアドレス | em | string | 必須 | ハッシュ化されたメールアドレス |
| 認証ハッシュ | hash | string | 必須 | 確認用のハッシュ値 |

### 出力項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| page | NewsletterSubscribePage | 購読確認ページオブジェクト |

## 表示項目

### 確認完了画面

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| 成功メッセージ | newsletter.subscriptionCompleted | 購読確認完了のメッセージ |

## イベント仕様

### 1-購読確認処理

ページアクセス時に自動的に確認処理が実行される。確認成功時は成功メッセージを表示、失敗時はエラーメッセージを表示しホームページへリダイレクト。

### HEADリクエスト対策

一部のメールクライアントはリンクのプレビュー取得のためにHEADリクエストを送信する。SymfonyはHEADリクエストをGETとして処理するため、意図せず購読確認が完了してしまう問題がある。これを防ぐため、$_SERVER['REQUEST_METHOD']がHEADの場合は204 No Contentを返し、確認処理をスキップする。

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 購読確認 | newsletter_recipient | UPDATE | 購読ステータスを確認済みに更新 |

### テーブル別更新項目詳細

#### newsletter_recipient

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | status | optIn | 確認完了時 |
| UPDATE | confirmed_at | 現在日時 | 確認日時を記録 |
| UPDATE | updated_at | 現在日時 | 自動更新 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| newsletter.subscriptionCompleted | 成功 | ニュースレターの購読が完了しました | 確認成功時 |
| newsletter.subscriptionConfirmationFailed | エラー | ニュースレターの購読確認に失敗しました | 確認失敗時 |

## 例外処理

| 例外 | 原因 | 処理内容 |
|------|------|----------|
| NewsletterException | 確認パラメータ不正、既に確認済み、期限切れ等 | エラーメッセージをフラッシュに追加、ホームページへリダイレクト |
| \Throwable | その他の予期しないエラー | エラーメッセージをフラッシュに追加、例外を再スロー |

## 備考

- HEADリクエスト対策として$_SERVER['REQUEST_METHOD']を直接確認（$request->getMethod()やgetRealMethod()は使用不可）
- 確認処理はAbstractNewsletterConfirmRoute::confirmを使用
- 確認成功後のページ遷移はなく、そのまま確認完了画面を表示

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | NewsletterSubscribePage.php | `src/Storefront/Page/Newsletter/Subscribe/NewsletterSubscribePage.php` | ページ構造（ほぼ空） |
| 1-2 | NewsletterRecipientEntity.php | `src/Core/Content/Newsletter/Aggregate/NewsletterRecipient/NewsletterRecipientEntity.php` | 購読者エンティティ |

**読解のコツ**: このページは確認結果を表示するだけのシンプルな構造。主要なロジックはNewsletterConfirmRouteにある。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | NewsletterController.php | `src/Storefront/Controller/NewsletterController.php` | subscribeMail()メソッド |

**主要処理フロー**:
1. **38-42行**: ルート定義（/newsletter-subscribe, GET）
2. **43-69行**: subscribeMail() - 確認処理本体
3. **45-53行**: HEADリクエスト対策
4. **55-65行**: 確認処理とエラーハンドリング
5. **67-69行**: 確認完了ページのレンダリング

#### Step 3: ページローダーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | NewsletterSubscribePageLoader.php | `src/Storefront/Page/Newsletter/Subscribe/NewsletterSubscribePageLoader.php` | load()メソッド |

**主要処理フロー**:
- **34-44行**: load() - GenericPageLoaderで基本ページ作成、イベント発行

#### Step 4: テンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | confirm-subscribe.html.twig | `src/Storefront/Resources/views/storefront/page/newsletter/confirm-subscribe.html.twig` | 確認完了画面 |

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

```
NewsletterController::subscribeMail()
    │
    ├─ [HEADリクエストチェック]
    │      └─ Response(204 No Content)
    │
    ├─ AbstractNewsletterConfirmRoute::confirm()
    │      │
    │      └─ newsletter_recipient UPDATE
    │
    ├─ [NewsletterException]
    │      ├─ addFlash(danger)
    │      └─ forwardToRoute('frontend.home.page')
    │
    ├─ NewsletterSubscribePageLoader::load()
    │      ├─ GenericPageLoaderInterface::load()
    │      └─ NewsletterSubscribePageLoadedEvent dispatch
    │
    └─ renderStorefront('confirm-subscribe.html.twig')
```

### データフロー図

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

確認メールリンク
(em, hash)
         │
         ▼
 $_SERVER['REQUEST_METHOD'] チェック
         │
         ├─► [HEAD] ──► 204 No Content
         │
         └─► [GET]
                   │
                   ▼
 AbstractNewsletterConfirmRoute::confirm()
         │
         ├─► [成功]
         │         │
         │         ▼
         │    NewsletterSubscribePageLoader::load()
         │         │
         │         ▼
         │    confirm-subscribe.html.twig
         │         │
         │         ▼
         │    「購読完了」メッセージ表示
         │
         └─► [失敗]
                   │
                   ├─► addFlash(danger)
                   └─► redirect to frontend.home.page
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| NewsletterController.php | `src/Storefront/Controller/NewsletterController.php` | コントローラー | リクエスト処理 |
| NewsletterSubscribePageLoader.php | `src/Storefront/Page/Newsletter/Subscribe/NewsletterSubscribePageLoader.php` | ページローダー | ページデータ組み立て |
| NewsletterSubscribePage.php | `src/Storefront/Page/Newsletter/Subscribe/NewsletterSubscribePage.php` | ページエンティティ | ページデータ型定義 |
| AbstractNewsletterConfirmRoute.php | `src/Core/Content/Newsletter/SalesChannel/AbstractNewsletterConfirmRoute.php` | Store API | 確認処理API |
| confirm-subscribe.html.twig | `src/Storefront/Resources/views/storefront/page/newsletter/confirm-subscribe.html.twig` | テンプレート | 確認完了画面 |
| NewsletterException.php | `src/Core/Content/Newsletter/NewsletterException.php` | 例外 | ニュースレター関連例外 |
