# 機能設計書 68-Cookie同意

## 概要

本ドキュメントは、Shopware StorefrontにおけるCookie同意バナーを表示する機能について、その処理内容、入出力仕様、およびコード構造を記述した機能設計書である。

### 本機能の処理概要

本機能は、GDPR（EU一般データ保護規則）やePrivacy規制に準拠するため、ユーザーにCookieの使用について同意を求めるバナーを表示し、Cookie設定を管理する機能を提供する。

**業務上の目的・背景**：EU圏をはじめとする多くの地域で、WebサイトがCookieを使用する際にはユーザーの同意を得ることが法的に義務付けられている。Cookie同意機能により、必須Cookie、統計用Cookie、快適機能Cookie、マーケティングCookieなどをグループ化して提示し、ユーザーが選択的に同意できるようにする。これにより法令遵守を実現しつつ、ユーザーのプライバシー選択権を尊重する。

**機能の利用シーン**：
- サイト初回訪問時のCookie同意バナー表示
- Cookie設定の変更（オフキャンバスでの詳細設定）
- 特定機能（ウィッシュリスト等）のCookie同意取得
- Cookie設定のJSON形式での取得

**主要な処理内容**：
1. CookieProviderからCookieグループ情報を取得
2. Cookieグループ・エントリの翻訳処理
3. Cookie設定ハッシュの生成（設定変更検知用）
4. 各種テンプレートでのレンダリング

**関連システム・外部連携**：Store APIのCookieRoute、CookieProvider

**権限による制御**：特別な権限制御なし（公開領域）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | Cookie同意バナー | 主機能 | Cookie同意バナーの表示 |
| - | Cookie設定モーダル | 補助機能 | 詳細なCookie設定 |

## 機能種別

画面表示 / ユーザー同意管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| request | Request | Yes | HTTPリクエストオブジェクト | - |
| salesChannelContext | SalesChannelContext | Yes | 販売チャネルコンテキスト | - |
| featureName | string | No | 機能名（consent用） | デフォルト: 'wishlist' |
| cookieName | string | No | Cookie名（consent用） | デフォルト: 'wishlist-enabled' |

### 入力データソース

- CookieProvider: Cookieグループおよびエントリ情報
- 翻訳システム: Cookieグループ名・説明の翻訳

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| cookieGroups | CookieGroupCollection | Cookieグループのコレクション |
| cookieGroups.* | CookieGroup | 個別のCookieグループ |
| cookieGroups.*.entries | CookieEntryCollection | グループ内のCookieエントリ |

### 出力先

- HTMLレスポンス:
  - `/cookie/offcanvas`: `cookie-configuration.html.twig`
  - `/cookie/permission`: `cookie-permission.html.twig`
  - `/cookie/consent-offcanvas`: `cookie-consent-offcanvas.html.twig`
- JSONレスポンス:
  - `/cookie/groups`: CookieGroupCollectionのJSON

## 処理フロー

### 処理シーケンス

```
1. CookieController がリクエストを受信
   ├─ offcanvas(): /cookie/offcanvas
   ├─ permission(): /cookie/permission
   ├─ cookieConsentOffcanvas(): /cookie/consent-offcanvas
   └─ groups(): /cookie/groups

2. offcanvas() / permission() の場合
   ├─ getCookieGroupsFromCookieRoute() を呼び出し
   │   └─ CookieRoute::getCookieGroups()
   ├─ CookieProviderでCookieグループを生成
   │   ├─ 必須Cookie
   │   ├─ 統計Cookie
   │   ├─ 快適機能Cookie
   │   └─ マーケティングCookie
   ├─ CookieGroupCollectEventをディスパッチ
   ├─ 翻訳処理
   ├─ 空のグループを除去
   ├─ Cookie設定ハッシュを生成・設定
   └─ テンプレートをレンダリング
       └─ x-robots-tag: noindex,follow を設定

3. cookieConsentOffcanvas() の場合
   └─ 機能名とCookie名をテンプレートに渡してレンダリング

4. groups() の場合
   └─ CookieGroupCollectionをJSON形式で返却
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{エンドポイント}
    B -->|/cookie/offcanvas| C[offcanvas]
    B -->|/cookie/permission| D[permission]
    B -->|/cookie/consent-offcanvas| E[cookieConsentOffcanvas]
    B -->|/cookie/groups| F[groups]

    C --> G[CookieRoute::getCookieGroups]
    D --> G
    F --> G

    G --> H[CookieProvider::getCookieGroups]
    H --> I[必須Cookieグループ]
    H --> J[統計Cookieグループ]
    H --> K[快適機能Cookieグループ]
    H --> L[マーケティングCookieグループ]

    I --> M[CookieGroupCollectEvent]
    J --> M
    K --> M
    L --> M

    M --> N[空グループ除去]
    N --> O[翻訳処理]
    O --> P[ハッシュ生成]

    P --> Q{レスポンス形式}
    Q -->|HTML| R[Twigレンダリング]
    Q -->|JSON| S[JsonResponse]

    E --> T[cookie-consent-offcanvas.html.twig]

    R --> U[x-robots-tag設定]
    U --> V[レスポンス返却]
    S --> V
    T --> V
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 必須Cookie | セッション、タイムゾーン、Cookie設定などは必須Cookieとして常に有効 | 常時 |
| BR-002 | 空グループ除去 | Cookieエントリがないグループは表示しない | 常時 |
| BR-003 | 翻訳処理 | Cookieグループ名と説明は現在の言語に翻訳される | 常時 |
| BR-004 | ハッシュ生成 | Cookie設定の変更検知用にハッシュを生成 | 常時 |
| BR-005 | noindex設定 | Cookie設定ページは検索エンジンにインデックスさせない | offcanvas/permission時 |

### 計算ロジック

#### Cookie設定ハッシュ
Cookie設定の変更を検知するため、以下の情報からハッシュを生成：
- グループのtechnicalName、isRequired、description、value、expiration、name、cookie
- エントリのcookie、value、expiration、name、description、hidden

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| なし | - | - | データベース操作なし（静的設定を使用） |

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

データベース操作は行わない。Cookie設定はCookieProviderクラスで静的に定義され、イベントを通じて動的に拡張可能。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| COOKIE__HASH_GENERATION_FAILED | CookieException | ハッシュ生成失敗 | Cookie設定を確認 |

### リトライ仕様

リトライ処理なし

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

読み取り専用のためトランザクション制御なし

## パフォーマンス要件

- レスポンス時間：100ms以内推奨

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

- 認証不要（公開領域）
- x-robots-tag: noindex,follow により検索エンジンにインデックスさせない
- XSS対策：Twigのエスケープ機能を使用

## 備考

- Cookie設定はCookieProviderで静的に定義
- CookieGroupCollectEventを通じて動的にCookieグループを追加可能
- GDPR/ePrivacy規制への準拠を支援
- cookie-config-hashでCookie設定変更を検知

---

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

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

### 推奨読解順序

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

Cookieグループとエントリのデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CookieGroup.php | `src/Core/Content/Cookie/Struct/CookieGroup.php` | Cookieグループの構造（technicalName, isRequired, entries等） |
| 1-2 | CookieEntry.php | `src/Core/Content/Cookie/Struct/CookieEntry.php` | 個別Cookieエントリの構造 |
| 1-3 | CookieGroupCollection.php | `src/Core/Content/Cookie/Struct/CookieGroupCollection.php` | グループコレクション |

**読解のコツ**: CookieGroupは複数のCookieEntryを持つ。isRequiredフラグで必須Cookie（ユーザーが拒否できない）を識別する。

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

処理の起点となるコントローラーを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CookieController.php | `src/Storefront/Controller/CookieController.php` | offcanvas(), permission(), cookieConsentOffcanvas(), groups()メソッド |

**主要処理フロー**:
1. **37-47行目**: offcanvas() - Cookie設定のオフキャンバス表示
2. **49-59行目**: permission() - Cookie許可バナー表示
3. **61-71行目**: cookieConsentOffcanvas() - 機能別Cookie同意
4. **73-79行目**: groups() - CookieグループのJSON取得
5. **81-86行目**: getCookieGroupsFromCookieRoute() - 共通のCookieグループ取得

#### Step 3: Store APIルートを理解する

Cookie情報の取得処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | CookieRoute.php | `src/Core/Content/Cookie/SalesChannel/CookieRoute.php` | getCookieGroups()メソッド（41-48行目） |

**主要処理フロー**:
- **43行目**: CookieProvider::getCookieGroups()を呼び出し
- **44行目**: Cookie設定ハッシュを生成
- **45行目**: ハッシュ値をcookie-config-hashエントリに設定

#### Step 4: CookieProviderを理解する

Cookieグループの定義と処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | CookieProvider.php | `src/Core/Content/Cookie/Service/CookieProvider.php` | getCookieGroups()、各グループ生成メソッド |

**主要処理フロー**:
- **51-73行目**: getCookieGroups() - メインの処理
- **59-63行目**: 4つのCookieグループを生成
- **65行目**: CookieGroupCollectEventをディスパッチ
- **67-72行目**: 空グループ除去と翻訳処理

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

```
CookieController
    │
    ├─ offcanvas() / permission()
    │      └─ getCookieGroupsFromCookieRoute()
    │             └─ CookieRoute::getCookieGroups()
    │                    ├─ CookieProvider::getCookieGroups()
    │                    │      ├─ getCookieGroupRequiredEntries()
    │                    │      ├─ getCookieGroupStatistical()
    │                    │      ├─ getCookieGroupComfortFeatures()
    │                    │      ├─ getCookieGroupMarketing()
    │                    │      ├─ CookieGroupCollectEvent
    │                    │      ├─ removeCookieGroupsWithoutCookies()
    │                    │      └─ translateCookieGroupsAndTheirEntries()
    │                    └─ generateCookieConfigurationHash()
    │
    ├─ cookieConsentOffcanvas()
    │      └─ renderStorefront() → cookie-consent-offcanvas.html.twig
    │
    └─ groups()
           └─ CookieRoute::getCookieGroups()
                  └─ JsonResponse
```

### データフロー図

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

Request ────────────────────────┐
                                ▼
SalesChannelContext ──────▶ CookieController ──────▶ Response
                                │                       │
                                ▼                       │
                         CookieRoute                    │
                                │                       │
                                ▼                       │
                         CookieProvider                 │
                                │                       │
                                ├─ RequiredCookies      │
                                ├─ StatisticalCookies   │
                                ├─ ComfortCookies       │
                                └─ MarketingCookies     │
                                       │                │
                                       ▼                │
                         CookieGroupCollectEvent        │
                                       │                │
                                       ▼                │
                         翻訳・空グループ除去            │
                                       │                │
                                       ▼                ▼
                         CookieGroupCollection ──▶ HTML/JSON
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CookieController.php | `src/Storefront/Controller/CookieController.php` | コントローラー | Cookie同意のエントリーポイント |
| CookieRoute.php | `src/Core/Content/Cookie/SalesChannel/CookieRoute.php` | Store API | Cookieグループ取得ルート |
| AbstractCookieRoute.php | `src/Core/Content/Cookie/SalesChannel/AbstractCookieRoute.php` | 抽象クラス | Cookieルートの抽象定義 |
| CookieProvider.php | `src/Core/Content/Cookie/Service/CookieProvider.php` | サービス | Cookieグループの定義・生成 |
| CookieGroup.php | `src/Core/Content/Cookie/Struct/CookieGroup.php` | データ構造 | Cookieグループの構造 |
| CookieEntry.php | `src/Core/Content/Cookie/Struct/CookieEntry.php` | データ構造 | Cookieエントリの構造 |
| CookieGroupCollection.php | `src/Core/Content/Cookie/Struct/CookieGroupCollection.php` | データ構造 | グループコレクション |
| CookieGroupCollectEvent.php | `src/Core/Content/Cookie/Event/CookieGroupCollectEvent.php` | イベント | Cookieグループ収集イベント |
