# 機能設計書 10-記事カテゴリ管理

## 概要

本ドキュメントは、LEGACY CMSにおける記事カテゴリ管理機能の設計を記述したものである。記事のカテゴリを作成・編集・削除する仕様を定義する。

### 本機能の処理概要

**業務上の目的・背景**：記事を分類するためのカテゴリを管理する機能である。適切なカテゴリ分類により、サイト訪問者が目的の記事を見つけやすくなり、管理者も記事を効率的に管理できる。カテゴリは記事作成時に選択必須であり、コンテンツ管理の基盤となる。

**機能の利用シーン**：管理者が記事管理画面のカテゴリ管理セクションから、新規カテゴリの作成、既存カテゴリの名称変更、不要なカテゴリの削除を行う。カテゴリ削除時は、そのカテゴリに属する記事は自動的にデフォルトカテゴリ（Uncategorised）に移動される。

**主要な処理内容**：
1. カテゴリ一覧の表示
2. 新規カテゴリの作成
3. カテゴリ名の編集
4. カテゴリの削除（関連記事はデフォルトカテゴリへ移動）

**関連システム・外部連携**：特になし

**権限による制御**：
- カテゴリ一覧/編集: `aarticles` + `acategoryedit`
- カテゴリ新規作成: `aarticles` + `acategorynew`
- カテゴリ削除: `aarticles` + `acategorydelete`

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 10 | カテゴリ別記事一覧画面 | 補助機能 | カテゴリ情報の取得 |
| 39 | 記事カテゴリ管理画面 | 主機能 | 記事カテゴリ一覧の管理 |
| 40 | 記事カテゴリ新規作成画面 | 主機能 | 新規カテゴリの作成処理 |

## 機能種別

CRUD操作 / マスタ管理

## 入力仕様

### 入力パラメータ

#### カテゴリ新規作成（categorynewAction）
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| categorytitle | string | Yes | カテゴリ名 | NotEmpty, Alnum(スペース許可), Db_NoRecordExists |

#### カテゴリ編集（categoryAction）
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | int | Yes | カテゴリID | isset |
| categorytitle | string | Yes | カテゴリ名 | NotEmpty, Alnum(スペース許可), Db_NoRecordExists(自身を除外) |

#### カテゴリ削除（categorydeleteAction）
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | int | Yes | カテゴリID | isset, id != 1（デフォルトカテゴリは削除不可） |
| confirm | string | Yes | 確認フラグ | 値が'1'の場合のみ削除実行 |

### 入力データソース

- URLパラメータ（id, confirm）
- フォーム入力（POSTリクエスト）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| categoryArray | array | カテゴリ一覧 |
| HTML | string | Ajaxダイアログ用HTML |
| messages | array | バリデーションエラーメッセージ |

### 出力先

- 画面表示（カテゴリ一覧）
- データベース操作（articles_categoriesテーブル）
- Ajaxダイアログ（作成/編集/削除結果）

## 処理フロー

### 処理シーケンス（カテゴリ削除）

```
1. 権限チェック
   └─ aarticles + acategorydelete 権限を確認
2. レイアウト・ビュー無効化
3. パラメータ取得
4. 確認フラグの判定
   ├─ confirm != '1': 確認ダイアログを表示
   └─ confirm == '1': 削除処理を実行
5. デフォルトカテゴリチェック
   └─ id == 1の場合は削除不可
6. 関連記事のカテゴリ変更
   └─ デフォルトカテゴリ(id=1)に移動
7. カテゴリレコードの削除
8. 完了画面の表示
```

### フローチャート

```mermaid
flowchart TD
    A[カテゴリ削除リクエスト] --> B{権限チェック}
    B -->|権限なし| C[権限エラー画面]
    B -->|権限あり| D{confirm == 1?}
    D -->|No| E[確認ダイアログ表示]
    E --> F[ユーザー操作]
    F -->|確認| G[confirm=1で再リクエスト]
    G --> D
    F -->|キャンセル| H[ダイアログを閉じる]
    D -->|Yes| I{id == 1?}
    I -->|Yes| J[削除不可メッセージ]
    I -->|No| K[関連記事をデフォルトカテゴリへ移動]
    K --> L[カテゴリ削除]
    L --> M[完了画面表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | デフォルトカテゴリ保護 | id=1（Uncategorised）は削除不可 | 削除時 |
| BR-002 | カテゴリ名重複禁止 | 同名のカテゴリは作成・変更不可 | 作成/編集時 |
| BR-003 | カスケード更新 | 削除されたカテゴリの記事はデフォルトへ移動 | 削除時 |
| BR-004 | カテゴリ名制限 | 英数字とスペースのみ許可 | 作成/編集時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| カテゴリ作成 | articles_categories | INSERT | 新規カテゴリを追加 |
| カテゴリ編集 | articles_categories | UPDATE | カテゴリ名を更新 |
| カテゴリ削除 | articles_categories | DELETE | カテゴリを削除 |
| 記事移動 | articles | UPDATE | 削除カテゴリの記事をデフォルトへ |

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

#### articles_categories（INSERT）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | acat_title | 入力されたカテゴリ名 | 必須 |

#### articles_categories（UPDATE）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | acat_title | 入力されたカテゴリ名 | 必須 |

#### articles_categories（DELETE）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | acat_id | パラメータのid | id != 1 |

#### articles（UPDATE - カテゴリ移動）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | article_category | 1（デフォルトカテゴリ） | 削除カテゴリに属する記事 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 権限エラー | 必要な権限がない | 権限エラー画面へフォワード |
| IS_EMPTY | バリデーションエラー | カテゴリ名未入力 | 'Title is required'を表示 |
| NOT_ALNUM | バリデーションエラー | カテゴリ名に不正文字 | 'Invalid Title'を表示 |
| ERROR_RECORD_FOUND | バリデーションエラー | カテゴリ名重複 | 'Category Already Exists'を表示 |
| - | 削除不可 | デフォルトカテゴリ削除試行 | 'This category cannot be deleted'を表示 |

### リトライ仕様

特になし

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

カテゴリ削除時の記事移動とカテゴリ削除は明示的なトランザクション制御なし。foreachループ内で各記事を個別にUPDATEするため、途中で失敗した場合は部分的に移動された状態になる可能性がある。

## パフォーマンス要件

- レスポンス時間: 1秒以内
- カテゴリ削除時は関連記事数に依存

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

- 権限ベースのアクセス制御
- デフォルトカテゴリの保護
- Zend_Validate_Alnum(true)によるカテゴリ名検証
- Zend_Validate_Db_NoRecordExistsによる重複チェック

## 備考

- デフォルトカテゴリ「Uncategorised」はシステム必須
- カテゴリ名は英数字とスペースのみ許可

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | database.sql | `database.sql` | articles_categoriesテーブル（26-30行目）とarticles.article_categoryとの関連 |

**読解のコツ**: articles_categoriesのacat_id=1は「Uncategorised」として初期データが投入されている（36-37行目）。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ArticlesController.php | `application/modules/admin/controllers/ArticlesController.php` | categorynewAction(465-524行目), categoryAction(529-597行目), categorydeleteAction(407-460行目) |

**主要処理フロー（categorynewAction）**:
1. **467行目**: 権限チェック（`aarticles` + `acategorynew`）
2. **469行目**: レイアウト無効化
3. **478-485行目**: バリデータの設定（Alnum, NoRecordExists）
4. **491-492行目**: カテゴリ作成

**主要処理フロー（categorydeleteAction）**:
1. **409行目**: 権限チェック（`aarticles` + `acategorydelete`）
2. **419行目**: デフォルトカテゴリチェック
3. **421-422行目**: カテゴリ削除

#### Step 3: モデル層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Articles.php | `application/models/Articles.php` | newCategory(243-254行目), updateCategory(389-396行目), deleteCategory(283-308行目), fetchCategory(202-216行目) |

**主要処理フロー（deleteCategory）**:
- **285行目**: ID検証（id != 1）
- **287-291行目**: 関連記事の検索
- **293-301行目**: 関連記事のカテゴリ変更
- **303行目**: カテゴリの削除

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

```
Admin_ArticlesController::categorynewAction()
    │
    ├─ ACL権限チェック
    │
    ├─ Zend_Filter_Input (バリデーション)
    │      ├─ NotEmpty
    │      ├─ Zend_Validate_Alnum(true)
    │      └─ Zend_Validate_Db_NoRecordExists
    │
    └─ Articles::newCategory($params)
           └─ INSERT articles_categories

Admin_ArticlesController::categorydeleteAction()
    │
    ├─ ACL権限チェック
    │
    └─ Articles::deleteCategory($id)
           │
           ├─ SELECT articles (関連記事取得)
           │
           ├─ UPDATE articles (カテゴリ移動)
           │      └─ article_category = 1
           │
           └─ DELETE articles_categories
```

### データフロー図

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

categorytitle  ───▶ バリデーション       ───▶ 検証済みカテゴリ名
                    │
                    ▼
              newCategory()
                    │
                    ▼
              INSERT articles_categories

id, confirm   ───▶ deleteCategory()     ───▶ 完了画面
                    │
              ┌─────┴─────┐
              ▼           ▼
           UPDATE      DELETE
           articles    articles_categories
           (カテゴリ=1)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ArticlesController.php | `application/modules/admin/controllers/ArticlesController.php` | コントローラー | カテゴリ管理処理（407-460行目: categorydeleteAction, 465-524行目: categorynewAction, 529-597行目: categoryAction） |
| Articles.php | `application/models/Articles.php` | モデル | カテゴリCRUD操作（202-216行目: fetchCategory, 243-254行目: newCategory, 283-308行目: deleteCategory, 389-396行目: updateCategory） |
| database.sql | `database.sql` | DDL | articles_categoriesテーブル定義（26-30行目）、初期データ（36-37行目） |
