# 機能設計書 102-サイト内検索

## 概要

本ドキュメントは、QuickerSite CMSにおける公開サイトでのサイト内検索機能について記載する。訪問者がキーワードを入力し、サイト内のページやリストアイテム、フォーラム投稿を横断的に検索できる機能である。

### 本機能の処理概要

**業務上の目的・背景**：サイト訪問者が目的のコンテンツを素早く見つけられるようにするために本機能が必要である。大規模なサイトやコンテンツが多いサイトにおいて、ナビゲーションだけでは目的の情報にたどり着けない場合に、検索機能は閲覧者の利便性を大幅に向上させる重要な機能である。

**機能の利用シーン**：サイト訪問者が検索ボックスにキーワードを入力し、検索ボタンを押下した際に利用される。検索結果一覧から目的のページに遷移する。複数キーワードによるAND/OR検索や、イントラネットコンテンツを含めた検索も可能。

**主要な処理内容**：
1. 検索キーワードの取得と前処理（空白分割、長さ検証）
2. ページテーブルからの検索（タイトル、本文テキスト）
3. リストアイテムの検索（オンライン期間チェック含む）
4. テーマ/フォーラム投稿の検索
5. 検索結果のフォーマットとリンク生成
6. 検索キーワードのハイライト表示

**関連システム・外部連携**：データベースから複数テーブル（tblPage, tblPost, tblTheme）を横断的に検索する。

**権限による制御**：パスワード保護されたページは検索対象から除外（includePasswordProtected設定による）。イントラネットコンテンツは認証済みユーザーのみ検索対象となる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 165 | 検索処理 | 主画面 | 公開サイトでのキーワード検索処理 |

## 機能種別

データ検索・表示処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| svalue | String | Yes | 検索キーワード | 最大100文字、3文字以上必須 |
| bIntranet | Boolean | No | イントラネット検索フラグ | true/false |

### 入力データソース

- POSTリクエスト: Request.Form("svalue")
- GETリクエスト: Request.QueryString("svalue")
- Cookie: searchvalue（前回検索キーワード保存）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| searchSnippet | String | 検索結果HTML |
| pageTitle | String | 検索結果件数を含むタイトル |
| pageBody | String | 検索結果本文HTML |

### 出力先

画面表示（HTMLとしてレンダリング）

## 処理フロー

### 処理シーケンス

```
1. 検索キーワード取得
   └─ POST/GETパラメータから取得（最大100文字）

2. キーワード検証
   └─ 空文字・3文字未満の場合は処理終了
   └─ スペース区切りで分割し各ワードの長さをチェック

3. ページ検索SQL構築
   └─ tblPageからタイトル・本文でLIKE検索
   └─ オンライン状態、削除フラグ、検索除外フラグをチェック

4. リストアイテム検索
   └─ iListPageIDを持つページを検索
   └─ オンライン期間（dOnlineFrom/dOnlineUntill）をチェック

5. 結果のループ処理
   └─ 各結果ページのリンクを生成
   └─ 本文抜粋（150文字）でキーワードをハイライト

6. テーマ/フォーラム検索
   └─ tblPost,tblThemeをJOINして検索
   └─ 認証状態に応じてiSearchTypeをフィルタ

7. 結果タイトル生成
   └─ 件数とキーワードを含むタイトル文字列を生成
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[キーワード取得]
    B --> C{3文字以上?}
    C -->|No| Z[終了]
    C -->|Yes| D[ページ検索SQL構築]
    D --> E[tblPage検索実行]
    E --> F{認証済み?}
    F -->|Yes| G[イントラネット含む]
    F -->|No| H[公開ページのみ]
    G --> I[結果ループ]
    H --> I
    I --> J[リンク生成]
    J --> K[キーワードハイライト]
    K --> L[テーマ/フォーラム検索]
    L --> M[結果マージ]
    M --> N[タイトル生成]
    N --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-201 | 最小文字数 | 検索キーワードは3文字以上必須 | 常時 |
| BR-202 | 最大結果件数 | 最大250件まで表示 | 常時 |
| BR-203 | フレーズ検索 | ダブルクォートで囲むとフレーズ検索 | キーワードが""で囲まれている場合 |
| BR-204 | パスワード保護除外 | パスワード保護ページは非認証時は検索対象外 | includePasswordProtected=false |

### 計算ロジック

- 本文抜粋: `left(convertStr(treatConstants(RemoveHTMLComments(sValueTextOnly),false)),150)`
- キーワードハイライト: `replace(抜粋, keyword, "<b>"& keyword &"</b>", 1, -1, 1)`

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ページ検索 | tblPage | SELECT | タイトル・本文でキーワード検索 |
| フォーラム検索 | tblPost, tblTheme | SELECT | 投稿タイトル・本文で検索 |

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

#### tblPage

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | iId, sTitle, sValueTextOnly, sExternalURL, iListPageID, iPostID | LIKE検索、bOnline=true、bDeleted=false | 最大250件 |

#### tblPost, tblTheme

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | iId, sSubject, sBody | INNER JOINでテーマと結合、iSearchTypeでフィルタ | 認証状態で条件変更 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 結果0件 | 検索条件に合致するページなし | 0件の結果を表示 |
| - | 検索スキップ | キーワードが3文字未満 | 検索を実行しない |

### リトライ仕様

リトライ処理は実装されていない。

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

参照のみのため、トランザクション制御は不要。

## パフォーマンス要件

- 最大250件の結果制限でレスポンス時間を制御
- LIKE検索のためインデックス効果は限定的

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

- sanitize関数による出力エスケープ（XSS対策）
- cleanup関数によるSQLインジェクション対策
- パスワード保護ページの検索除外
- イントラネットコンテンツの認証チェック

## 備考

- Cookieに前回の検索キーワードを保存
- 検索結果の表示順はsTitleでソート（デフォルト）

---

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

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

### 推奨読解順序

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

まず、検索クラスの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | search.asp | `asp/includes/search.asp` | cls_searchクラスの構造、検索ロジック |

**読解のコツ**: VBScriptのClassモジュールでは、Public変数がプロパティとして機能する。results関数が検索のメインロジック。

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

処理の起点となるファイルを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | process.asp | `asp/process.asp` | pageAction="search"時のinclude処理（50行目） |

**主要処理フロー**:
1. **50行目**: `case "search"` - 検索アクションの分岐
2. **50行目**: `<!-- #include file="process_search.asp"-->` - 検索処理インクルード

#### Step 3: 検索表示処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | process_search.asp | `asp/process_search.asp` | 検索実行と結果表示のメインロジック |

**主要処理フロー**:
- **2行目**: キーワード取得（POST/GET両対応）
- **5-6行目**: 検索オプション設定
- **7行目**: `set results=search.results` - 検索実行
- **10-38行目**: 結果ループとHTML生成
- **43行目**: 結果タイトル生成

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

```
process.asp (エントリーポイント)
    │
    ├─ process_search.asp (検索表示処理)
    │      │
    │      └─ cls_search (検索クラス)
    │             ├─ results() - 検索実行
    │             │    ├─ ページ検索SQL
    │             │    └─ フォーラム検索SQL
    │             └─ allPages() - 全ページ取得
    │
    └─ template (テンプレート処理)
```

### データフロー図

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

svalue ─────────▶ cls_search ─────────▶ searchSnippet
  │                    │                      │
  ▼                    ▼                      ▼
Cookie保存 ◀──── results() ────────▶ pageTitle
                       │
                       ▼
               tblPage検索
               tblPost検索
                       │
                       ▼
               Dictionary結果
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| process_search.asp | `asp/process_search.asp` | ソース | 検索表示メイン処理 |
| process.asp | `asp/process.asp` | ソース | ページアクションルーター |
| search.asp | `asp/includes/search.asp` | ソース | 検索クラス定義 |
| page.asp | `asp/includes/page.asp` | ソース | ページクラス定義 |
| post.asp | `asp/includes/post.asp` | ソース | 投稿クラス定義 |
| functions.asp | `asp/includes/functions.asp` | ソース | 共通関数（sanitize等） |
