# 通知設計書 5-DesktopNotification

## 概要

本ドキュメントは、Symfony NotifierコンポーネントにおけるDesktop通知（DesktopNotification）の設計仕様を記述する。DesktopNotificationInterfaceを実装した通知オブジェクトがDesktopChannelを通じてデスクトップ通知を送信する仕組みについて詳細に定義する。

### 本通知の処理概要

DesktopNotificationは、Symfony Notifierコンポーネントが提供するデスクトップ通知チャネルを通じた通知機能である。DesktopNotificationInterfaceを実装することで、JoliNotif等のデスクトップ通知ライブラリに対してカスタムメッセージを生成・送信できる。

**業務上の目的・背景**：デスクトップ通知は、開発者ツールやローカルアプリケーションにおいて、ユーザーのデスクトップ環境に直接通知を表示する手段である。ビルド完了通知、テスト結果の報告、ローカル開発環境でのデバッグ情報の表示など、開発者向けのリアルタイムフィードバックに使用される。

**通知の送信タイミング**：Notifier::send()が呼び出され、Notificationのchannelsに"desktop"が含まれている場合、またはChannelPolicyでdesktopチャネルが選択された場合に送信が実行される。

**通知の受信者**：DesktopChannelはすべてのRecipientInterfaceをサポートする（supports()が常にtrueを返す）。デスクトップ通知はローカル環境に表示されるため、特定の受信者情報は不要。

**通知内容の概要**：件名（subject）と本文（content）がDesktopMessageオブジェクトに含まれる。各デスクトップ通知ライブラリ固有のオプション（アイコン、サウンド等）はMessageOptionsInterfaceで指定可能。

**期待されるアクション**：受信者はデスクトップ通知を確認し、必要に応じてアプリケーションに切り替えて詳細を確認する。

## 通知種別

デスクトップ通知（JoliNotif等）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（Transport直接送信）または非同期（Messenger Bus経由） |
| 優先度 | Notificationのimportanceに依存 |
| リトライ | Notifierコンポーネント自体にはリトライ機構なし |

### 送信先決定ロジック

1. DesktopChannel::supports()は常にtrueを返すため、すべてのRecipientに対して利用可能（DesktopChannel.php 行43-46）
2. 通知オブジェクトがDesktopNotificationInterfaceを実装している場合、asDesktopMessage()メソッドでカスタムDesktopMessageを生成（DesktopChannel.php 行26-28）
3. カスタムメッセージがnullまたはインターフェース未実装の場合、DesktopMessage::fromNotification()によりデフォルトのDesktopMessageを生成（DesktopChannel.php 行30）
4. DesktopMessageのsetTransport()メソッドでTransport名を設定（他チャネルのtransport()メソッドとは命名が異なる点に注意）

## 通知テンプレート

### 本文テンプレート

```
件名: {Notification::getSubject()}
本文: {Notification::getContent()}
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| 該当なし | - | - | DesktopMessageの基本構造には添付ファイル機能なし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| subject | 通知タイトル | Notification::getSubject() | Yes |
| content | 通知本文 | Notification::getContent() | Yes |
| options | デスクトップ通知固有オプション | DesktopMessage::getOptions() | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | Notifier::send()の実行 | Notificationのchannelsに"desktop"が含まれる | アプリケーションコードから直接呼び出し |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| なし | DesktopChannel::supports()は常にtrueを返すため、Recipient側の制限はない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[Notifier::send呼び出し] --> B[getChannels: チャネル決定]
    B --> C[DesktopChannel::supports チェック]
    C -->|常にtrue| D[DesktopChannel::notify 実行]
    D --> E{DesktopNotificationInterface?}
    E -->|Yes| F[asDesktopMessage でカスタムメッセージ生成]
    E -->|No| G[DesktopMessage::fromNotification でデフォルト生成]
    F --> H[Transport名設定 setTransport]
    G --> H
    H --> I{Bus設定あり?}
    I -->|Yes| J[Messenger Bus経由で非同期送信]
    I -->|No| K[Transport直接送信]
    J --> L[終了]
    K --> L
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| 該当なし | - | Notifierコンポーネント自体はデータベースを直接参照しない |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| 該当なし | - | Notifierコンポーネント自体はデータベースを直接更新しない |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| LogicException | TransportもBusも両方nullの場合（AbstractChannel.php 行28-30） | DesktopChannelのコンストラクタでTransportまたはBusの少なくとも一方を指定する |
| TransportExceptionInterface | デスクトップ通知送信時のエラー | アプリケーション側でcatchして適切に処理する |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Notifierコンポーネント自体にはリトライ機構なし |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | Notifierコンポーネント自体にはレート制限なし |
| 1日あたり上限 | 同上 |

### 配信時間帯

Notifierコンポーネント自体に配信時間帯の制限機能はない。

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

- デスクトップ通知はローカル環境に表示されるため、ネットワーク上のセキュリティリスクは低い
- ただし、通知内容がスクリーンショットやスクリーンレコーディングで第三者に見られる可能性があるため、機密情報の表示には注意すること

## 備考

- DesktopChannelはAbstractChannelを継承しているが、DesktopMessageのTransport設定メソッドがsetTransport()（他のメッセージクラスのtransport()とは異なる命名）である点に注意（DesktopChannel.php 行33、DesktopMessage.php 行98-103）
- DesktopMessage::fromNotification()ではsetNotification()を明示的に呼び出している（DesktopMessage.php 行35）。他のメッセージクラスではprivateプロパティに直接代入しているのとは異なるアプローチ
- DesktopMessageのsetter/getterはsetXxx()/getXxx()形式の命名規約を使用（他のメッセージクラスのfluent形式と異なる）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DesktopNotificationInterface.php | `src/Symfony/Component/Notifier/Notification/DesktopNotificationInterface.php` | asDesktopMessage()のシグネチャ（行22）。RecipientInterfaceを受け取る |
| 1-2 | DesktopMessage.php | `src/Symfony/Component/Notifier/Message/DesktopMessage.php` | コンストラクタ（行24-29）、fromNotification()（行31-38）、setTransport()（行98-103）の命名規約の違いに注目 |

**読解のコツ**: DesktopMessageは他のメッセージクラスと命名規約が異なる。setSubject()/setContent()/setTransport()/setOptions()/setNotification()というJavaBean形式のsetterを使用しており、ChatMessage等のfluent形式（subject()/content()/transport()）とは異なる。

#### Step 2: チャネル処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | DesktopChannel.php | `src/Symfony/Component/Notifier/Channel/DesktopChannel.php` | notify()（行24-41）でsetTransport()を使用している点（行33）に注目 |

**主要処理フロー**:
- **行26-28**: DesktopNotificationInterface実装時はasDesktopMessage()でカスタムメッセージ生成
- **行30**: デフォルトはDesktopMessage::fromNotification(notification)
- **行32-34**: transportNameをsetTransport()で設定（他チャネルはtransport()メソッド）
- **行36-40**: Bus有無による送信方式の分岐

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

```
Notifier::send()
    |
    +-- getChannels()
    |
    +-- DesktopChannel::supports()  [常にtrue]
    |
    +-- DesktopChannel::notify()
            |
            +-- [DesktopNotificationInterface] notification->asDesktopMessage()
            |       または
            +-- DesktopMessage::fromNotification(notification)
            |       +-- new DesktopMessage(subject, content)
            |       +-- setNotification(notification)
            |
            +-- DesktopMessage::setTransport() [transportName設定]
            |
            +-- [Bus == null] Transport::send(message)
            +-- [Bus != null] Bus::dispatch(message)
```

### データフロー図

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

Notification                    Notifier::send()
  - subject          -------->    |
  - content                       v
  - channels                   DesktopChannel::notify()
                                  |
RecipientInterface                v                    -------->  デスクトップ通知表示
  （任意の実装）     -------->  DesktopMessage生成                 (Transport or Bus)
                                  |
                                  v
                               送信実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| DesktopNotificationInterface.php | `src/Symfony/Component/Notifier/Notification/DesktopNotificationInterface.php` | ソース | Desktop通知インターフェース |
| DesktopChannel.php | `src/Symfony/Component/Notifier/Channel/DesktopChannel.php` | ソース | デスクトップ通知送信チャネル |
| AbstractChannel.php | `src/Symfony/Component/Notifier/Channel/AbstractChannel.php` | ソース | チャネル基底クラス |
| DesktopMessage.php | `src/Symfony/Component/Notifier/Message/DesktopMessage.php` | ソース | デスクトップメッセージクラス |
| Notification.php | `src/Symfony/Component/Notifier/Notification/Notification.php` | ソース | 通知基本クラス |
| Notifier.php | `src/Symfony/Component/Notifier/Notifier.php` | ソース | 通知送信エントリーポイント |
