# 機能設計書 53-Emoji

## 概要

本ドキュメントは、Symfony Emojiコンポーネントの機能設計を記述する。EmojiコンポーネントはUnicode CLDRの絵文字データへのアクセスを提供し、絵文字の文字列変換(トランスリタレーション)機能を実現する。

### 本機能の処理概要

Emojiコンポーネントは、絵文字文字列を他の形式(テキスト表現、GitHub/GitLab/Slackのショートコード等)に変換する機能を提供する。PHPのintl拡張のTransliteratorクラスを拡張し、絵文字専用のトランスリタレーションルールを適用する。

**業務上の目的・背景**：ユーザーが入力した絵文字を含むテキストを検索可能なテキスト形式に変換したり、異なるプラットフォーム間で絵文字表現を統一する必要がある場面で利用される。例えば、メール送信時に絵文字をテキスト表現に変換したり、Slackのショートコード形式に変換する際に使用される。

**機能の利用シーン**：テキスト検索のための絵文字のテキスト化、Slack/GitHub/GitLabのショートコードへの変換、ショートコードから絵文字への逆変換、URLスラッグ生成時の絵文字処理。

**主要な処理内容**：
1. 絵文字からテキスト表現への変換(emoji-text)
2. 絵文字からGitHubショートコードへの変換(emoji-github)
3. 絵文字からGitLabショートコードへの変換(emoji-gitlab)
4. 絵文字からSlackショートコードへの変換(emoji-slack)
5. ショートコードから絵文字への逆変換(github-emoji, gitlab-emoji, slack-emoji, text-emoji)
6. 利用可能なトランスリタレーションIDの一覧取得

**関連システム・外部連携**：PHP intl拡張(必須)のTransliteratorクラスを基盤として利用。

**権限による制御**：権限制御は実装されていない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 直接関連する画面はない。アプリケーション内の文字列処理で利用される |

## 機能種別

データ変換 / テキスト処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | string | Yes | トランスリタレーションID(例: 'emoji-github', 'text-emoji') | `/^[a-z0-9@_\\.\\-]*$/`パターンに一致、対応するデータファイルが存在すること |
| direction | int | No | 変換方向(FORWARD=0またはREVERSE=1) | REVERSEABLE_IDSに存在する場合のみREVERSE可能 |
| string | string | Yes | 変換対象の文字列 | UTF-8エンコーディングであること |
| start | int | No | 変換開始位置(デフォルト: 0) | 0以上の整数 |
| end | int | No | 変換終了位置(デフォルト: -1=文字列末尾) | -1または正の整数 |

### 入力データソース

`src/Symfony/Component/Emoji/Resources/data/` 配下のPHPデータファイル(絵文字マッピングテーブル)。一部は.gz形式で圧縮されている。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| transliteratedString | string|false | 変換後の文字列。失敗時はfalse |
| ids | string[] | 利用可能なトランスリタレーションIDの一覧 |

### 出力先

呼び出し元のアプリケーションコード。

## 処理フロー

### 処理シーケンス

```
1. EmojiTransliterator::create($id, $direction)呼び出し
   └─ IDの正規化(小文字化、'emoji-'プレフィックス付与)
2. REVERSE方向の場合
   └─ REVERSEABLE_IDSマッピングで逆方向IDを解決
3. データファイルの読み込み
   └─ Resources/data/{id}.php (または .php.gz) をrequire/GzipStreamWrapper::require
4. インスタンス生成
   └─ ReflectionClassを使用してTransliteratorのカスタムインスタンスを作成
5. transliterate($string, $start, $end)呼び出し
   └─ クイックチェック文字がない場合はそのまま返却(最適化)
   └─ 全範囲指定の場合はstrtr()でマッピングテーブルを適用
   └─ 部分範囲の場合はintl Transliteratorを利用してスライスしてから変換
```

### フローチャート

```mermaid
flowchart TD
    A[create呼び出し] --> B[IDの正規化]
    B --> C{REVERSE方向?}
    C -->|Yes| D{逆変換可能?}
    D -->|Yes| E[逆方向IDに変換]
    D -->|No| F[IntlException]
    C -->|No| G[データファイル読み込み]
    E --> G
    G --> H[インスタンス生成]
    H --> I[transliterate呼び出し]
    I --> J{クイックチェック}
    J -->|絵文字なし| K[入力文字列をそのまま返却]
    J -->|絵文字あり| L{全範囲?}
    L -->|Yes| M[strtrでマッピング適用]
    L -->|No| N[部分範囲をスライスして変換]
    M --> O[結果返却]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-53-01 | 双方向変換 | emoji-github/gitlab/slack/textとその逆方向のみ双方向変換が可能 | REVERSEABLE_IDS定義に含まれるID |
| BR-53-02 | IDプレフィックス | 'emoji-'で始まらないIDには自動的にプレフィックスを付与 | REVERSEABLE_IDSに含まれないID |
| BR-53-03 | クイックチェック最適化 | 絵文字の先頭バイト特徴文字(\xA9, \xAE, \xE2, \xE3, \xF0)がない場合は変換をスキップ | transliterate()実行時 |

### 計算ロジック

特になし。マッピングテーブルによる文字列置換処理。

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

本コンポーネントはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | LogicException | intl拡張がインストールされていない場合 | PHP intl拡張をインストール |
| - | IntlException | REVERSE不可能なIDで逆変換を試行した場合 | 正しいIDを指定するか、FORWARD方向を使用 |
| - | IntlException | 不正なIDが指定された場合 | listIDs()で有効なIDを確認 |

### リトライ仕様

リトライ機構は不要。

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

トランザクション管理は対象外。

## パフォーマンス要件

- クイックチェック最適化により、絵文字を含まない文字列は高速にスキップ(EmojiTransliterator.php 119-120行目)
- マッピングテーブルは静的変数にキャッシュされ、同一IDでの再利用時にファイル読み込みが不要(76行目)
- Gzip圧縮ファイル対応によりディスク使用量を削減

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

- IDパラメータは正規表現でバリデーションされ、パスインジェクションを防止(61行目)

## 備考

intl拡張が必須。PHP intl拡張なしの環境では利用不可。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Resources/data/*.php | `src/Symfony/Component/Emoji/Resources/data/` | マッピングテーブルの形式(絵文字文字列 => 変換後文字列の連想配列) |

**読解のコツ**: データファイルはPHP配列として定義されており、キーが元の絵文字、値が変換後の文字列。一部は.gz圧縮されている。

#### Step 2: メインクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | EmojiTransliterator.php | `src/Symfony/Component/Emoji/EmojiTransliterator.php` | \Transliteratorの拡張、create()のファクトリパターン、transliterate()の最適化 |

**主要処理フロー**:
- **22-32行目**: 定数定義 - QUICK_CHECK文字とREVERSEABLE_IDSマッピング
- **42-79行目**: create() - ID正規化、方向処理、データファイル読み込み、ReflectionClassによるインスタンス生成
- **96-113行目**: listIDs() - Resources/data/ディレクトリをスキャンして有効IDを列挙
- **115-144行目**: transliterate() - クイックチェック最適化、strtr()によるマッピング適用、部分範囲処理

#### Step 3: ユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | GzipStreamWrapper.php | `src/Symfony/Component/Emoji/Util/GzipStreamWrapper.php` | .gz圧縮ファイルのPHP require対応 |

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

```
EmojiTransliterator::create($id, $direction)
    |
    +-- [IDの正規化・バリデーション]
    +-- [REVERSE処理: REVERSEABLE_IDSマッピング]
    +-- [データファイルロード: require / GzipStreamWrapper::require]
    +-- [ReflectionClass::newInstanceWithoutConstructor()]
    |
    v
EmojiTransliterator::transliterate($string, $start, $end)
    |
    +-- [クイックチェック: strcspn($string, QUICK_CHECK)]
    +-- [全範囲: strtr($string, $this->map)]
    +-- [部分範囲: Transliterator::transliterate() + strtr]
```

### データフロー図

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

絵文字含む文字列 ─────────> EmojiTransliterator          変換後文字列
                            ::transliterate()
                                |
                                v
                    Resources/data/{id}.php
                    (マッピングテーブル)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| EmojiTransliterator.php | `src/Symfony/Component/Emoji/EmojiTransliterator.php` | ソース | 絵文字トランスリタレーションのメインクラス |
| GzipStreamWrapper.php | `src/Symfony/Component/Emoji/Util/GzipStreamWrapper.php` | ソース | Gzip圧縮ファイルのrequireサポート |
| Resources/data/ | `src/Symfony/Component/Emoji/Resources/data/` | データ | 絵文字マッピングテーブル群 |
