# 機能設計書 19-ページブロック編集

## 概要

本ドキュメントは、QuickerSite CMSにおけるページブロック編集機能の設計について記述する。ページブロックは、テンプレート内で定義された8つのプレースホルダ（PAGE_BLOCK01〜PAGE_BLOCK08）に対して、ページ固有のコンテンツを設定するための機能である。

### 本機能の処理概要

ページブロック編集機能は、テンプレート内の[PAGE_BLOCK01]〜[PAGE_BLOCK08]プレースホルダに挿入されるコンテンツを、ページ単位で編集・管理する機能である。各ブロックには、テキストエリアまたはWYSIWYGエディタで入力したHTMLコンテンツを設定できる。

**業務上の目的・背景**：Webサイトのテンプレートには、ページごとに異なるコンテンツを挿入したい領域がある。例えば、サイドバーのバナー、ヘッダーの追加情報、フッターの補足説明などである。本機能により、テンプレートを変更することなく、ページごとにカスタマイズ可能なコンテンツ領域を提供できる。

**機能の利用シーン**：
- 特定ページにのみ表示するバナーやプロモーション情報を設定する場合
- ページ固有のサイドバーコンテンツを追加する場合
- テンプレートの特定領域にカスタムHTMLを挿入する場合
- サイト全体のデフォルト値とは異なるコンテンツを設定する場合

**主要な処理内容**：
1. 対象ページのブロックコンテンツ読み込み
2. 8つのブロック（sProp01〜sProp08）の編集
3. コンテンツの保存（tblPageテーブル更新）
4. フロントエンドでのプレースホルダ置換

**関連システム・外部連携**：FCKEditor（WYSIWYGエディタ）によるリッチテキスト編集機能と連携。

**権限による制御**：セカンドアドミン権限の`bSetupPageElements`により、ページブロック編集画面へのアクセスが制御される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | ページブロック編集 | 主機能 | 8つのブロックコンテンツの編集 |

## 機能種別

CRUD操作（Update） / コンテンツ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| iPageID | Integer（暗号化） | Yes | 対象ページID | 数値であること |
| sProp01 | String | No | ブロック01のコンテンツ | なし |
| sProp02 | String | No | ブロック02のコンテンツ | なし |
| sProp03 | String | No | ブロック03のコンテンツ | なし |
| sProp04 | String | No | ブロック04のコンテンツ | なし |
| sProp05 | String | No | ブロック05のコンテンツ | なし |
| sProp06 | String | No | ブロック06のコンテンツ | なし |
| sProp07 | String | No | ブロック07のコンテンツ | なし |
| sProp08 | String | No | ブロック08のコンテンツ | なし |
| btnaction | String | Yes | アクション種別 | "save"等 |
| QSSEC | String | Yes | CSRFトークン | 有効なセキュリティコード |

### 入力データソース

- 画面入力：ページブロック編集画面（bs_editPageBlocks.asp）からのフォーム入力
- セッションデータ：ログイン管理者情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 保存結果 | Boolean | 保存成功/失敗 |
| メッセージ | String | 処理結果メッセージ（fb_saveOK） |

### 出力先

- 画面表示：管理画面での編集フォーム
- データベース：tblPageテーブル（sProp01〜sProp08カラム）
- フロントエンド：テンプレート内[PAGE_BLOCK]プレースホルダの置換結果

## 処理フロー

### 処理シーケンス

```
1. ページブロック編集画面表示
   ├─ 権限チェック（bSetupPageElements）
   ├─ 対象ページ情報読み込み
   └─ 8つのブロック入力フィールド表示
       ├─ 奇数ブロック: textarea
       └─ 偶数ブロック: WYSIWYGエディタ

2. 保存処理
   ├─ CSRF検証
   ├─ 8つのブロックコンテンツ取得
   │   └─ removeEmptyP()で空段落除去
   ├─ cls_page.save()実行
   └─ 成功メッセージ表示

3. フロントエンド表示
   └─ replaceBlocks()関数でプレースホルダ置換
       ├─ ページ固有値があれば優先
       └─ なければcustomerデフォルト値を使用
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[権限チェック]
    B --> C{bSetupPageElements?}
    C -->|No| D[アクセス拒否]
    C -->|Yes| E[ページ情報読み込み]
    E --> F[ブロック入力フォーム表示]
    F --> G[各ブロックの現在値表示]
    G --> H[デフォルト値表示]
    H --> I{保存ボタン?}
    I -->|No| J[編集継続]
    I -->|Yes| K[CSRF検証]
    K --> L[8ブロック取得]
    L --> M[removeEmptyP処理]
    M --> N[page.save]
    N --> O{保存成功?}
    O -->|No| P[エラー表示]
    O -->|Yes| Q[成功メッセージ]
    J --> I
    P --> F
    Q --> F
    D --> R[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-19-01 | ブロック優先順位 | ページ固有値がある場合は優先、なければcustomerデフォルト値を使用 | フロントエンド表示時 |
| BR-19-02 | 空ブロック処理 | ページ固有値もデフォルト値もない場合、プレースホルダは空文字に置換 | フロントエンド表示時 |
| BR-19-03 | 入力タイプ | 奇数ブロック（01,03,05,07）はtextarea、偶数ブロック（02,04,06,08）はWYSIWYGエディタ | 編集画面 |
| BR-19-04 | 空段落除去 | 保存時にremoveEmptyP()で空のPタグを除去 | 保存処理時 |

### 計算ロジック

なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ブロック保存 | tblPage | UPDATE | sProp01〜sProp08カラムの更新 |

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

#### tblPage

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | sProp01 | フォーム入力値（サニタイズ済み） | ブロック01 |
| UPDATE | sProp02 | フォーム入力値（サニタイズ済み） | ブロック02 |
| UPDATE | sProp03 | フォーム入力値（サニタイズ済み） | ブロック03 |
| UPDATE | sProp04 | フォーム入力値（サニタイズ済み） | ブロック04 |
| UPDATE | sProp05 | フォーム入力値（サニタイズ済み） | ブロック05 |
| UPDATE | sProp06 | フォーム入力値（サニタイズ済み） | ブロック06 |
| UPDATE | sProp07 | フォーム入力値（サニタイズ済み） | ブロック07 |
| UPDATE | sProp08 | フォーム入力値（サニタイズ済み） | ブロック08 |
| UPDATE | updatedTS | now() | 更新日時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | CSRF検証エラー | セキュリティトークンが無効 | 処理中断 |
| - | 権限エラー | bSetupPageElements権限なし | アクセス拒否 |
| - | ページ不存在 | 指定ページIDが存在しない | エラー表示 |

### リトライ仕様

リトライは実装されていない。エラー発生時は入力画面に戻り、ユーザーに修正を促す。

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

明示的なトランザクション制御は行われていない。

## パフォーマンス要件

- 保存処理: 1秒以内
- 画面表示: 1秒以内

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

1. **CSRF対策**: checkCSRF()によるトークン検証
2. **権限チェック**: secondAdmin.bSetupPageElements権限による制御
3. **入力サニタイズ**: convertStr()およびremoveEmptyP()による入力処理
4. **パラメータ暗号化**: ページIDの暗号化

## 備考

- ブロック01,03,05,07はプレーンテキスト/HTML用のtextarea
- ブロック02,04,06,08はリッチテキスト用のWYSIWYGエディタ（FCKEditor）
- 各ブロックの下にcustomerのデフォルト値が参考表示される
- テンプレート内で[PAGE_BLOCK01]〜[PAGE_BLOCK08]プレースホルダを使用することで、コンテンツが挿入される
- ページ固有値が未設定の場合、サイト全体のデフォルト値（customer.sPropXX）が自動的に使用される

---

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

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

### 推奨読解順序

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

ページブロックのプロパティ定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | page.asp | `asp/includes/page.asp` | sProp01〜sProp08プロパティ（11行目） |
| 1-2 | customer.asp | `asp/includes/customer.asp` | デフォルト値sProp01〜sProp08（15行目） |

**読解のコツ**: cls_pageクラスのsProp01〜sProp08プロパティがページ固有のブロックコンテンツを保持する。cls_customerクラスの同名プロパティがサイト全体のデフォルト値となる。

#### Step 2: 編集画面を理解する

ページブロック編集画面の構造を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | bs_editPageBlocks.asp | `asp/bs_editPageBlocks.asp` | 編集フォームの構造（1-19行目） |

**主要処理フロー**:
- **4行目**: 権限チェック（secondAdmin.bSetupPageElements）
- **5-6行目**: ページオブジェクト生成とデータ読み込み
- **7-8行目**: CSRF検証とボタンアクション判定
- **9-16行目**: 8つのブロック値の取得とremoveEmptyP処理
- **17行目**: page.save()による保存
- **18行目**: フォーム表示（textareaとcreateFCKInstance交互配置）

#### Step 3: 保存処理を理解する

ブロックデータの保存処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | page.asp | `asp/includes/page.asp` | save関数でのsProp保存（556-563行目） |

**主要処理フロー**:
- **556-563行目**: rs("sProp01")〜rs("sProp08")への値設定

#### Step 4: フロントエンド表示を理解する

テンプレート内でのプレースホルダ置換処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | page.asp | `asp/includes/page.asp` | replaceBlocks関数（1607-1654行目） |

**主要処理フロー**:
- **1609行目**: [PAGE_BLOCK0プレフィックス存在チェック
- **1610-1614行目**: ブロック01の置換（ページ固有値優先、なければcustomer値）
- **1615-1649行目**: ブロック02〜08の同様の処理
- **1651-1653行目**: 未使用プレースホルダの空文字置換

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

```
bs_editPageBlocks.asp（ページブロック編集画面）
    │
    ├─ bs_security.asp [権限チェック]
    │      └─ logon.hasaccess secondAdmin.bSetupPageElements
    │
    ├─ cls_page.pick() [ページ情報読み込み]
    │
    ├─ 保存処理
    │      ├─ checkCSRF()
    │      ├─ removeEmptyP(convertStr(Request.Form))
    │      │      └─ sProp01〜sProp08取得
    │      └─ cls_page.save()
    │             └─ tblPage UPDATE (sProp01〜sProp08)
    │
    └─ フォーム表示
           ├─ textarea (sProp01,03,05,07)
           ├─ createFCKInstance (sProp02,04,06,08)
           └─ customer.sPropXX (デフォルト値参考表示)

[フロントエンド表示]
テンプレート読み込み
    │
    └─ cls_page.replaceBlocks()
           ├─ [PAGE_BLOCK01]→sProp01 or customer.sProp01
           ├─ [PAGE_BLOCK02]→sProp02 or customer.sProp02
           │      ...
           └─ [PAGE_BLOCK08]→sProp08 or customer.sProp08
```

### データフロー図

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

sProp01〜sProp08       ───▶  bs_editPageBlocks.asp       ───▶  tblPage
(フォーム入力)                (保存処理)                         (sProp01〜sProp08)
                              │
                              ├─ removeEmptyP()
                              └─ cls_page.save()

[フロントエンド表示]

テンプレート           ───▶  replaceBlocks()             ───▶  HTML出力
([PAGE_BLOCK01]等)           │
                              ├─ ページ固有値チェック
                              │   └─ あり: sPropXX使用
                              │   └─ なし: customer.sPropXX使用
                              └─ プレースホルダ置換
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| bs_editPageBlocks.asp | `asp/bs_editPageBlocks.asp` | ソース | ページブロック編集画面 |
| page.asp | `asp/includes/page.asp` | ソース | ページクラス（sProp01〜08、save、replaceBlocks） |
| customer.asp | `asp/includes/customer.asp` | ソース | 顧客クラス（デフォルト値sProp01〜08） |
| bs_editProps.asp | `asp/bs_editProps.asp` | ソース | サイト全体のデフォルトブロック編集 |
