# 機能設計書 64-サイトマップ表示

## 概要

本ドキュメントは、Shopware StorefrontにおけるXMLサイトマップを生成・表示する機能について、その処理内容、入出力仕様、およびコード構造を記述した機能設計書である。

### 本機能の処理概要

本機能は、検索エンジン向けのXMLサイトマップを動的に生成し、`/sitemap.xml`エンドポイントで提供する機能である。

**業務上の目的・背景**：SEO（検索エンジン最適化）において、サイトマップは検索エンジンのクローラーがサイト構造を効率的に把握するための重要な要素である。XMLサイトマップを提供することで、商品ページ、カテゴリページ、CMSページなどの全URLを検索エンジンに通知し、インデックス効率を向上させる。

**機能の利用シーン**：
- 検索エンジンのクローラー（Googlebot等）がサイトマップを取得する際
- 管理者がサイトマップの内容を確認する際
- Search Consoleなどのツールからサイトマップを参照する際

**主要な処理内容**：
1. リクエストを受信（`/sitemap.xml`または`/sitemap/{filePath}`）
2. Store API経由でサイトマップ情報を取得
3. サイトマップインデックスまたは個別サイトマップファイルを生成
4. XML形式でレスポンスを返却

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

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 62 | SEO設定 | 補助機能 | SEO URL・メタ情報の設定 |
| 63 | サイトマップ設定 | 主機能 | サイトマップ生成の設定 |

## 機能種別

データ連携 / ファイル出力

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| filePath | string | No | サイトマップファイルのパス（.xml.gz形式） | 正規表現: `.+\.xml\.gz` |
| request | Request | Yes | HTTPリクエストオブジェクト | - |
| context | SalesChannelContext | Yes | 販売チャネルコンテキスト | - |

### 入力データソース

- Store API: AbstractSitemapRoute（サイトマップ一覧）、SitemapFileRoute（個別ファイル）
- ファイルシステム: 生成済みサイトマップファイル（gzip圧縮）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| page | SitemapPage | サイトマップページオブジェクト |
| page.sitemaps | array<Sitemap> | サイトマップ情報の配列 |

### 出力先

- XML形式のHTTPレスポンス
- Content-Type: `text/xml; charset=utf-8`
- サイトマップインデックス: `sitemap.xml.twig`テンプレート
- 個別ファイル: gzip圧縮されたXMLファイル

## 処理フロー

### 処理シーケンス

```
1. SitemapController がリクエストを受信
   ├─ sitemapXml(): /sitemap.xml
   └─ sitemapProxy(): /sitemap/{filePath}

2. sitemapXml() の場合
   ├─ SitemapPageLoader::load() を呼び出し
   │   └─ SitemapRoute::load() でサイトマップ一覧を取得
   ├─ SitemapPageLoadedHook を実行
   ├─ sitemap.xml.twig でXMLを生成
   └─ Content-Type: text/xml を設定して返却

3. sitemapProxy() の場合
   ├─ SitemapFileRoute::getSitemapFile() を呼び出し
   └─ gzip圧縮されたサイトマップファイルを返却
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{エンドポイント}
    B -->|/sitemap.xml| C[sitemapXml]
    B -->|/sitemap/*.xml.gz| D[sitemapProxy]

    C --> E[SitemapPageLoader::load]
    E --> F[SitemapRoute::load]
    F --> G[SitemapPage生成]
    G --> H[SitemapPageLoadedHook]
    H --> I[sitemap.xml.twig]
    I --> J[Content-Type: text/xml]
    J --> K[レスポンス返却]

    D --> L[SitemapFileRoute::getSitemapFile]
    L --> M[gzipファイル返却]
    M --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | サイトマップインデックス | メインの/sitemap.xmlは他のサイトマップファイルへのインデックスとして機能 | 常時 |
| BR-002 | ファイル分割 | 大量のURLがある場合、複数のサイトマップファイルに分割される | URL数が閾値を超えた場合 |
| BR-003 | gzip圧縮 | 個別のサイトマップファイルはgzip圧縮で提供 | 個別ファイルアクセス時 |
| BR-004 | 販売チャネル別 | サイトマップは販売チャネルごとに生成される | 常時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| サイトマップ情報取得 | sitemap | SELECT | サイトマップファイル情報の取得 |

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

#### sitemap

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, filename, created_at等 | sales_channel_id = {販売チャネルID} | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | Not Found | 指定されたサイトマップファイルが存在しない | サイトマップを再生成する |

### リトライ仕様

リトライ処理なし（読み取り専用処理のため）

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

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

## パフォーマンス要件

- レスポンス時間：500ms以内推奨（ファイルサイズに依存）
- gzip圧縮による転送効率の最適化

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

- 認証不要（公開領域）
- 非公開ページはサイトマップに含めない
- robots.txtからサイトマップへの参照を設定可能

## 備考

- サイトマップは定期的なバッチ処理で事前生成されることが多い
- 大規模サイトでは複数のサイトマップファイルに分割される
- Google Search Console等へのサイトマップ登録に使用

---

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

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

### 推奨読解順序

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

サイトマップのデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SitemapPage.php | `src/Storefront/Page/Sitemap/SitemapPage.php` | サイトマップページの構造（sitemaps配列） |
| 1-2 | Sitemap.php | `src/Core/Content/Sitemap/Struct/Sitemap.php` | 個別サイトマップの構造 |

**読解のコツ**: SitemapPageはSitemap構造体の配列を保持する。各Sitemapは filename、lastmod 等の情報を持つ。

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

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

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

**主要処理フロー**:
1. **33-44行目**: sitemapXml() - サイトマップインデックスを返却
2. **46-50行目**: sitemapProxy() - 個別サイトマップファイルを返却

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

サイトマップデータの読み込み処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SitemapPageLoader.php | `src/Storefront/Page/Sitemap/SitemapPageLoader.php` | load()メソッド（30-40行目） |

**主要処理フロー**:
- **32行目**: SitemapPageオブジェクトを生成
- **33行目**: SitemapRoute::load()でサイトマップ一覧を取得
- **35-37行目**: SitemapPageLoadedEventをディスパッチ

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

サイトマップデータの取得処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AbstractSitemapRoute.php | `src/Core/Content/Sitemap/SalesChannel/AbstractSitemapRoute.php` | サイトマップ取得の抽象クラス |
| 4-2 | SitemapFileRoute.php | `src/Core/Content/Sitemap/SalesChannel/SitemapFileRoute.php` | 個別ファイル取得ルート |

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

```
SitemapController
    │
    ├─ sitemapXml()
    │      ├─ SitemapPageLoader::load()
    │      │      └─ AbstractSitemapRoute::load()
    │      │             └─ Sitemap配列
    │      ├─ hook(SitemapPageLoadedHook)
    │      └─ renderStorefront() → sitemap.xml.twig
    │
    └─ sitemapProxy()
           └─ SitemapFileRoute::getSitemapFile()
                  └─ gzip圧縮ファイル
```

### データフロー図

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

Request (/sitemap.xml) ────────┐
                               ▼
SalesChannelContext ──────▶ SitemapController ──────▶ XML Response
                               │                          │
                               ▼                          │
                        SitemapPageLoader                 │
                               │                          │
                               ▼                          │
                        SitemapRoute::load()              │
                               │                          │
                               ▼                          ▼
                        Sitemap[] ──────────────▶ sitemap.xml.twig
                                                          │
                                                          ▼
                                               Content-Type: text/xml

Request (/sitemap/*.xml.gz) ─────────┐
                                     ▼
                              SitemapFileRoute
                                     │
                                     ▼
                              gzip圧縮ファイル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SitemapController.php | `src/Storefront/Controller/SitemapController.php` | コントローラー | サイトマップ表示のエントリーポイント |
| SitemapPageLoader.php | `src/Storefront/Page/Sitemap/SitemapPageLoader.php` | ローダー | サイトマップデータの読み込み |
| SitemapPage.php | `src/Storefront/Page/Sitemap/SitemapPage.php` | ページ | サイトマップページのデータ構造 |
| SitemapPageLoadedEvent.php | `src/Storefront/Page/Sitemap/SitemapPageLoadedEvent.php` | イベント | サイトマップ読み込み完了イベント |
| SitemapPageLoadedHook.php | `src/Storefront/Page/Sitemap/SitemapPageLoadedHook.php` | フック | App Scripts用拡張ポイント |
| AbstractSitemapRoute.php | `src/Core/Content/Sitemap/SalesChannel/AbstractSitemapRoute.php` | Store API | サイトマップ取得の抽象クラス |
| SitemapFileRoute.php | `src/Core/Content/Sitemap/SalesChannel/SitemapFileRoute.php` | Store API | 個別ファイル取得ルート |
| Sitemap.php | `src/Core/Content/Sitemap/Struct/Sitemap.php` | データ構造 | サイトマップエントリの構造 |
