# 機能設計書 50-タグ追加

## 概要

本ドキュメントは、LEGACY CMSのタグ管理機能における「タグ追加」機能の設計仕様を定義する。

### 本機能の処理概要

コンテンツ（記事、ページ、イベント等）に新しいタグを追加する機能である。管理者はAjaxダイアログを通じてタグ文字列を入力し、コンテンツにタグを関連付ける。重複チェックが行われ、同一コンテンツに同じタグが複数登録されることを防止する。

**業務上の目的・背景**：CMSでは、コンテンツの分類や検索を効率化するためにタグ機能が提供されている。管理者がコンテンツに適切なタグを付与することで、ユーザーは関連するコンテンツを容易に見つけられる。タグの追加機能により、コンテンツの整理と検索性を向上させる。

**機能の利用シーン**：記事に新しいキーワードをタグ付けする場合、イベントにカテゴリ横断的な分類タグを追加する場合、ページにナビゲーション用のタグを設定する場合などに使用される。

**主要な処理内容**：
1. タグ文字列、コンテンツタイプ、スレーブIDの取得
2. 重複チェック（同一コンテンツに同じタグがないか確認）
3. バリデーション（必須項目のチェック）
4. tagsテーブルへの新規レコード挿入
5. 追加完了または重複エラーメッセージの表示

**関連システム・外部連携**：タグオートコンプリート機能と連携し、既存タグの候補表示を提供する。Dojo Toolkitを使用したAjaxダイアログで操作インターフェースを実現している。

**権限による制御**：特に権限チェックは実装されていない（コンテンツ編集画面へのアクセス権限で間接的に制御）。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | タグ追加ダイアログ | 主画面 | 新規タグの追加処理 |
| 38 | 記事詳細画面 | 遷移元画面 | 記事へのタグ追加 |
| 63 | ページ詳細画面 | 遷移元画面 | ページへのタグ追加 |
| 51 | イベント詳細画面 | 遷移元画面 | イベントへのタグ追加 |

## 機能種別

CRUD操作（Create） / Ajaxダイアログ処理 / 重複チェック

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| tag | string | Yes | タグ文字列 | NotEmpty、StringTrim、StripTags |
| type | string | Yes | コンテンツタイプ（A:記事, P:ページ, E:イベント） | NotEmpty |
| slave | integer | Yes | 紐づくコンテンツのID | NotEmpty、数値 |

### 入力データソース

- 全パラメータ: POSTリクエストのフォームデータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 成功メッセージ | HTML | 「Tag Added」のメッセージと閉じるボタン |
| 重複エラー | HTML | 「Duplicate Tag」のメッセージと閉じるボタン |
| バリデーションエラー | array | バリデーションエラー時のメッセージ |

### 出力先

- Ajaxダイアログ内にHTMLレスポンスとして出力
- tagsテーブルに新規レコードを挿入

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ newActionがコールされる
2. レイアウト・ビュー無効化
   └─ Ajaxレスポンス用に無効化
3. POSTリクエスト判定
   └─ POSTでない場合は「No data received」を出力
4. パラメータ取得
   └─ tag, type, slaveパラメータを取得
5. 重複チェック
   └─ 同一type+slave+tagの組み合わせが存在するか確認
6. 重複判定
   └─ 存在する場合: 「Duplicate Tag」エラー表示
   └─ 存在しない場合: 次のステップへ
7. バリデーション実行
   └─ Zend_Filter_Inputでフォーム入力を検証
8. バリデーション結果判定
   └─ 失敗時: エラーメッセージを表示
   └─ 成功時: 次のステップへ
9. データベース挿入
   └─ tagsテーブルにINSERT
10. 成功レスポンス出力
    └─ 「Tag Added」メッセージとCloseボタンを表示
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[レイアウト・ビュー無効化]
    B --> C{POSTリクエスト?}
    C -->|No| D[「No data received」出力]
    C -->|Yes| E[パラメータ取得]
    E --> F[重複チェックSELECT]
    F --> G{重複あり?}
    G -->|Yes| H[「Duplicate Tag」出力]
    G -->|No| I[バリデーション実行]
    I --> J{バリデーション成功?}
    J -->|No| K[エラーメッセージ出力]
    J -->|Yes| L[tags INSERT]
    L --> M[「Tag Added」出力]
    D --> N[終了]
    H --> N
    K --> N
    M --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-50-01 | 重複チェック | 同一コンテンツに同じタグは登録不可 | 常時 |
| BR-50-02 | タグ必須 | タグ文字列は必須入力 | 常時 |
| BR-50-03 | タイプ必須 | コンテンツタイプは必須 | 常時 |
| BR-50-04 | スレーブ必須 | コンテンツIDは必須 | 常時 |
| BR-50-05 | タグサニタイズ | タグはTrim、StripTagsでサニタイズ | 常時 |

### 計算ロジック

- 重複判定: SELECT COUNT(*) WHERE tag_type = {type} AND tag_slave = {slave} AND tag_tag = {tag}

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 重複チェック | tags | SELECT | 同一タグの存在確認 |
| タグ追加 | tags | INSERT | 新規タグレコードを挿入 |

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

#### tags（SELECT - 重複チェック）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | WHERE tag_type = {type} AND tag_slave = {slave} AND tag_tag = {tag} | 重複確認 |

#### tags（INSERT）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | tag_type | フォーム入力値(type) | コンテンツタイプ |
| INSERT | tag_tag | フォーム入力値(tag) | タグ文字列 |
| INSERT | tag_slave | フォーム入力値(slave) | コンテンツID |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 重複エラー | 同一コンテンツに同じタグが存在 | 「Duplicate Tag」メッセージ表示 |
| - | バリデーションエラー | タグが空 | 「Tag is required」メッセージ表示 |
| - | バリデーションエラー | タイプが空 | 「Type is required」メッセージ表示 |
| - | バリデーションエラー | スレーブが空 | 「Slave is required」メッセージ表示 |
| - | データなし | POSTリクエストでない | 「No data received」表示 |

### リトライ仕様

特になし。重複エラーの場合は異なるタグを入力して再試行可能。

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

重複チェック（SELECT）とタグ追加（INSERT）の間にトランザクション制御はない。同時実行時に重複登録のリスクあり。

## パフォーマンス要件

- Ajaxダイアログのレスポンス時間: 1秒以内
- レイアウトとビューを無効化することでレスポンスサイズを最小化

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

- StringTrimとStripTagsフィルターによる入力値のサニタイズ
- XSS対策: タグ文字列からHTMLタグを除去
- newActionには明示的な権限チェックがないが、親画面のアクセス権限で制御される

## 備考

- タグのオートコンプリート機能（autocompleteAction）と連携して使用される
- タグは大文字小文字を区別する（重複チェック時）
- 追加完了後、ダイアログを閉じるとタグ一覧が自動的に更新される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | database.sql | `database.sql` | tagsテーブルの構造を確認（335-341行目） |

**読解のコツ**: tag_idは自動採番、tag_typeは1文字のコード、tag_tagがタグ文字列（最大60文字）、tag_slaveはコンテンツへの参照。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TagsController.php | `application/modules/admin/controllers/TagsController.php` | newActionメソッド（81-191行目） |

**主要処理フロー**:
1. **83-84行目**: レイアウト・ビューレンダラー無効化
2. **86行目**: POSTリクエスト判定
3. **88-90行目**: type, slave, tagパラメータ取得
4. **96-100行目**: 重複チェック用SELECTクエリ構築
5. **103-109行目**: 重複判定ロジック
6. **113-137行目**: バリデータ定義（filters, validators）
7. **139行目**: Zend_Filter_Inputでバリデーション実行
8. **144行目**: バリデーション成功判定
9. **146-151行目**: INSERTデータ配列構築
10. **154行目**: tagsテーブルへINSERT
11. **156-161行目**: 成功メッセージ出力
12. **178-186行目**: 重複エラーメッセージ出力

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

```
Admin_TagsController::newAction()
    │
    ├─ $this->_helper->layout()->disableLayout()
    │      └─ レイアウト無効化
    │
    ├─ $this->_helper->viewRenderer->setNoRender(true)
    │      └─ ビューレンダラー無効化
    │
    ├─ $registry->db->select()
    │      ├─ ->from('tags')
    │      ├─ ->where('tag_type')
    │      ├─ ->where('tag_slave')
    │      └─ ->where('tag_tag')
    │             └─ 重複チェック
    │
    ├─ new Zend_Filter_Input($filters, $validators, $_POST, $options)
    │      └─ バリデーション実行
    │
    └─ $registry->db->insert('tags', $data)
           └─ MySQLへのINSERT実行
```

### データフロー図

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

POSTデータ               TagsController                 tags
  - tag           ─────▶  ::newAction()          ─────▶ テーブル
  - type                  │                             │
  - slave                 ├─ 重複チェック               ├─ tag_type
                          │   └─ SELECT                 ├─ tag_tag
                          │                             └─ tag_slave
                          ├─ バリデーション
                          │   └─ StringTrim, StripTags
                          │
                          └─ INSERT
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TagsController.php | `application/modules/admin/controllers/TagsController.php` | コントローラー | タグ追加アクションの定義 |
| Tags.php | `application/models/Tags.php` | モデル | タグのCRUD操作 |
| autocomplete.phtml | `application/modules/admin/views/scripts/tags/autocomplete.phtml` | ビュー | オートコンプリート候補 |
| database.sql | `database.sql` | スキーマ | tagsテーブル定義 |
