# GTI Forms Hook Reference (開発者向けドキュメント)

GTI Forms は、開発者がフォームの動作、データ処理、完了後の挙動、および**セキュリティ（Throws SPAM Away 連携など）**を自由に拡張できるよう、多数の WordPress Hook (Action / Filter) を提供しています。

---

## 1. フォーム表示・フィールド注入 (Rendering)

フォームの HTML 生成時や、動的にフィールドを追加するためのフックです。

### `gti_forms_extra_hidden_fields` (Action)
フォーム内に `type="hidden"` などの非表示フィールドを動的に挿入します。
- **用途**: 広告パラメータ、ページコンテキスト、計測用トークンの埋め込みなど。
- **引数**: `$form_id` (int)

```php
add_action('gti_forms_extra_hidden_fields', function($form_id) {
    if (isset($_GET['campaign_id'])) {
        printf('<input type="hidden" name="campaign" value="%s">', esc_attr($_GET['campaign_id']));
    }
});
```

### `gti_forms_extra_form_fields` (Action)
表示される入力フィールド群の先頭に、任意の HTML を挿入します。
- **用途**: CSRF対策、動的な注意書き、プログラムから生成した入力項目など。
- **引数**: `$form_id` (int)

```php
add_action('gti_forms_extra_form_fields', function($form_id) {
    echo '<div class="gti-form-group"><label>本日のキーワード</label><input type="text" name="daily_key" value="HAPPY"></div>';
});
```

### `gti_forms_pre_render_field` (Filter)
特定のブロックのレンダリングを**完全に上書き**します。
- **戻り値**: `null` なら通常の処理、文字列ならその HTML を出力。

```php
add_filter('gti_forms_pre_render_field', function($output, $block, $form_id) {
    // 特定の name のフィールドだけ特殊な HTML に変える例
    if ($block['blockName'] === 'gti/form-text' && $block['attrs']['name'] === 'special') {
        return '<div class="my-custom-input">...</div>';
    }
    return $output;
}, 10, 3);
```

---

## 2. データ処理・バリデーション (Submission)

送信ボタンが押された後、データが保存・送信されるまでのプロセスを制御します。

### `gti_forms_submitted_data` (Filter)
保存・送信される直前の全データを加工・追加します。
- **用途**: URL パラメータから「プラン名」を追加したり、計算結果をデータに混ぜる。
- **引数**: `$submitted_data` (array), `$form_id` (int)

**活用例：メール本文への挿入**
このフックで追加したデータは、メールテンプレート内で `{ラベル名}` として個別に呼び出すことができます。

```php
add_filter('gti_forms_submitted_data', function($data, $form_id) {
    // 例: ホテル予約などで選択プランを GET から拾う
    if (isset($_GET['plan'])) {
        $data['選択プラン'] = sanitize_text_field($_GET['plan']);
    }
    return $data;
}, 10, 2);
```

### `gti_forms_inquiry_post_title` (Filter)
管理画面に保存される「お問い合わせ（`gti-inquiry`）」の投稿タイトルを動的に変更します。
- **用途**: タイトルに「件名」や「プラン名」を含めて、一覧性を高める。
- **引数**: `$title` (string), `$form_id` (int), `$submitted_data` (array)

```php
add_filter('gti_forms_inquiry_post_title', function($title, $form_id, $data) {
    if (isset($data['件名'])) {
        return sprintf('%s - %s', $data['件名'], $data['お名前']);
    }
    return $title;
}, 10, 3);
```

### `gti_forms_before_submit` (Action)
データがデータベースに保存される**直前に**実行されます。
- **用途**: 外部 API との同期、独自のバリデーション（将来的な拡張用）。

### `gti_forms_after_submit` (Action)
保存と通知メール送信がすべて完了した**後に**実行されます。
- **用途**: Slack/Chatwork への通知送信、CRM へのデータ転送。

```php
add_action('gti_forms_after_submit', function($inquiry_id, $form_id, $data) {
    // 例: LINE 等への通知
    // my_send_line_notification($data);
}, 10, 3);
```

### `gti_forms_admin_recipient` / `gti_forms_admin_cc` / `gti_forms_admin_bcc` (Filter)
管理者への通知メールの宛先（To, Cc, Bcc）を動的に変更します。
- **用途**: 入力された「お問い合わせ種別」や「担当部署」に応じて、通知先を振り分ける。
- **引数**: `$recipient` (string), `$form_id` (int), `$data` (array)

```php
// 例: 入力内容に基づいて To（宛先）を振り分ける
add_filter('gti_forms_admin_recipient', function($recipient, $form_id, $data) {
    if (isset($data['カテゴリ']) && $data['カテゴリ'] === '採用について') {
        return 'hr@example.com';
    }
    return $recipient;
}, 10, 3);

// 例: 特定のフォームの場合に Cc を追加
add_filter('gti_forms_admin_cc', function($cc, $form_id, $data) {
    $extra_cc = 'manager@example.com';
    return $cc ? "{$cc}, {$extra_cc}" : $extra_cc;
}, 10, 3);

// 実践例：複数店舗展開しているサイトでの「店舗オートルーティング」
// 選択された店舗名に応じて、その店舗の店長メールアドレスを CC に自動追加する
add_filter('gti_forms_admin_cc', function($cc, $form_id, $data) {
    // フォームに「希望店舗」というセレクトボックスがある想定
    $store_emails = [
        '新宿店' => 'shinjuku-manager@example.com',
        '渋谷店' => 'shibuya-manager@example.com',
        '池袋店' => 'ikebukuro-manager@example.com',
    ];

    $selected_store = isset($data['希望店舗']) ? $data['希望店舗'] : '';

    if (isset($store_emails[$selected_store])) {
        $store_email = $store_emails[$selected_store];
        return $cc ? "{$cc}, {$store_email}" : $store_email;
    }

    return $cc;
}, 10, 3);
```

---

## 3. 送信完了後の挙動 (Redirection)

### `gti_forms_redirect_url` (Filter)
送信完了後の遷移先（サンクスページ）の URL を動的に変更します。
- **用途**: 入力内容（美容室のメニュー、居酒屋の予約コースなど）に応じて別のページに飛ばす。
- **引数**: `$url` (string), `$form_id` (int), `$data` (array)

```php
add_filter('gti_forms_redirect_url', function($url, $form_id, $data) {
    // 例: 「プレミアムプラン」の申し込み時だけ別のページへ
    if (isset($data['プラン']) && $data['プラン'] === 'プレミアム') {
        return site_url('/thanks-premium/');
    }
    return $url;
}, 10, 3);
```

### `gti_forms_thanks_message` (Filter)
送信完了後に画面に表示されるメッセージを動的に変更します。
- **用途**: サンクスページを作成せず、同じページで完了メッセージだけ条件分岐させたい場合。
- **引数**: `$message` (string), `$form_id` (int)

```php
add_filter('gti_forms_thanks_message', function($message, $form_id) {
    if ($form_id === 123) {
        return '特別なフォームへのご応募ありがとうございました！';
    }
    return $message;
}, 10, 2);
```

### `gti_forms_stripe_session_args` (Filter)
Stripe の決済パラメータ（金額、商品名など）を送信データの直前に変更します。
- **用途**: 選択したオプションや数量に基づいて、合計金額を動的に計算する（簡易カート機能）。
- **引数**: `$session_args` (array), `$form_id` (int), `$submitted_data` (array)

```php
// 例: 数量に応じて合計金額を計算する（単価1,000円）
add_filter('gti_forms_stripe_session_args', function($args, $form_id, $data) {
    $quantity = isset($data['数量']) ? intval($data['数量']) : 1;
    $unit_price = 1000;
    
    // Line items の金額を書き換え
    $args['line_items'][0]['price_data']['unit_amount'] = $unit_price * $quantity;
    
    return $args;
}, 10, 3);
```

---

## 4. 管理画面の拡張 (Admin Customization)

### `manage_gti-inquiry_posts_columns` (Filter)
お問い合わせ一覧（`gti-inquiry`）のカラムをカスタマイズします。

```php
add_filter('manage_gti-inquiry_posts_columns', function($columns) {
    $columns['ref_url'] = '参照元URL';
    return $columns;
});

add_action('manage_gti-inquiry_posts_custom_column', function($column, $post_id) {
    if ($column === 'ref_url') {
        echo esc_url(get_post_meta($post_id, '_gti_ref', true));
    }
}, 10, 2);
```

---

## 5. セキュリティ・スパム対策 (Security)

### `gti_forms_validate` (Filter)
送信データをバリデーションし、エラーがある場合は送信を中断します。
- **戻り値**: `null` なら正常、`WP_Error` オブジェクトを返すと送信を中断しエラーメッセージを表示します。
- **引数**: `$null`, `$form_id`, `$data`

#### 「Throws SPAM Away」との連携例
このプラグインの日本語判定機能などを使って、スパムを強力にブロックする実装例です。

```php
add_filter('gti_forms_validate', function($error, $form_id, $data) {
    if ( ! class_exists('ThrowsSpamAway') ) {
        return $error;
    }

    // 全入力内容を結合してチェック対象にする
    $content = implode("\n", $data);
    $author = isset($data['お名前']) ? $data['お名前'] : 'Guest';
    $email = isset($data['メールアドレス']) ? $data['メールアドレス'] : '';

    $tsa = new ThrowsSpamAway();
    $tsa_error_msg = '';
    
    // Throws SPAM Away のバリデーションを実行
    $is_spam = $tsa->throws_spam_away_validation($content, $author, $email, '', 'comment', 0, $tsa_error_msg);

    if ($is_spam) {
        return new WP_Error('spam_detected', $tsa_error_msg ?: 'スパムと判定されました。');
    }

    return $error;
}, 10, 3);
```
