Snow Monkey Formsのフックを調べた

# 概要
Snow Monkey Formsもバージョンを重ね、気が付いたら便利はアクション/フィルターフックが増えて、さまざまなカスタマイズができるようになっていました。
以下のサイトではその使用方法などが掲載されているので、使い方などとても参考になります。

https://www.cherrypieweb.com/4862

https://olein-design.com/blog/select-admin-send-target-from-form

https://snow-monkey.2inc.org/2020/06/10/snow-monkey-forms-v0-8-0/

この記事では上記の記事には記載されていない

`snow_monkey_forms/select/options`
`snow_monkey_forms/checkboxes/options`
`snow_monkey_forms/radio_buttons/options` 
`snow_monkey_forms/administrator_mailer/after_send`
`snow_monkey_forms/form/append`

などのフックの簡易的な使い方を記載していきます。

# 1.チェックボックス、ラジオボタン、セレクトに後から動的にoptionを追加できるフック
これらは、ver6.3.0から追加された
`snow_monkey_forms/select/options`
`snow_monkey_forms/checkboxes/options`
`snow_monkey_forms/radio_buttons/options` 
で実現できます。

例えばカタログ請求フォームなどで商品情報を商品情報カスタムポストタイプのpost_titleを取得して追加したり、カスタムフィールドから値を取得して追加などの使い方が考えられます。

以下にチェックボックスでの簡単な使い方を提示します。
```php:snow_monkey_forms/checkboxes/optionsの場合
add_filter(
	'snow_monkey_forms/checkboxes/options',
	function( $options, $name, $setting ) {
		if ( 'productName' === $name && intval($setting->get( 'form_id' )) === 6) {
			return array(
                'All設備カタログ' => 'All設備カタログ',
				'商品1カタログ' => '商品1カタログ',
				'商品2カタログ' => '商品2カタログ',
				'商品3カタログ' => '商品3カタログ',
			);
		}
		return $options;
	},
	10,
	3
);
```
デフォルトの返り値は$optionとなります。

## 1-1.コールバック引数
コールバックに渡せる引数は3つほど用意されています。
**`$options`**
これは、フォームエレメントの設定の`OPTIONS`の値が入ってきます。形式は配列となり、`"value" : "label"`という値になります。
例では特定の条件下で新しい配列を返すようにしていますが、もともとのOPTIONSにオプションを追加したい場合は、`array_merge`などで結合する方法が取れると思います。

**`$name`**
フォームのフィールド名です。設定の`NAME`に入力したものとなります。特定のフィールドの時に処理を行うなどの振り分けで使用できます。

**`$setting`**
 Settingクラスのインスタンスオブジェクトになります。Settingクラスは`App/Model/Setting.php`にて定義されているのでこちらのソースを見ると大体の使い方がわかると思います。
 よく使うものとしては`$setting->get('form_id')`でフォーム自体のIDを取得することができます。これにより特定のform_idの時だけの処理を行わせることができます。
 
:::note info
**$setting->get( 'form_id' )を使う時に注意点**
最初のページ表示では`$setting->get( 'form_id' )`は数値での値になりますが、validationでのエラー表示や確認画面ページなどAjax経由での取得する際には文字列になるようなので、`(int)`や`intval()`で数値に変換する必要があります。
**参考URL**
https://snow-monkey.2inc.org/forums/topic/snow-monkey-form　bccで他のメールアドレスにも送信する場合/?v=5fcbef0eb67e
:::

## 1-2.初期値を設定しておきたい場合
初期値を設定したい場合は、`snow_monkey_forms/control/attributes`フィルターフックを使い`$attributes['values']`にチェックしておきたい値を入れておきます。

```php:'snow_monkey_forms/control/attributes'のvaluesの使い方例
/**
 * checkedを設定する場合はattributesにて行う
 */
add_filter(
	'snow_monkey_forms/control/attributes',
	function( $attributes, $setting ) {
		if ( isset( $attributes['name'] ) && 'productName' === $attributes['name'] ) {
			$attributes['values'] = [ 'All設備カタログ' ];
		}
		return $attributes;
	},
	10,
	2
);
```
:::note info
**`attributes`フィルターフックのコールバック引数**
`$attributes`には`$attributes['name'] `としてフィールド名が格納されています。また`$attributes['validations'] `には`requiref : false(true)`などが格納されていてこの辺りは条件によって動的に書き換えなどができると思います。
:::

# 2.メール送信後に処理を追加実行できるアクションフック
`snow_monkey_forms/administrator_mailer/after_send`や`snow_monkey_forms/auto_reply_mailer/after_send`を使うとメール送信後に処理を追加することができます。

例えばSnow Monkey Formsにはデータの保存機能はないのでこのフックを使い、Google Sheets APIやNotion APIなどを使ってフォーム内容を保存させるなども考えられます。

ここでは簡単なフックの使用例として、フォームの内容をテキストファイルの保存するという例を記載しておきます。
```php
add_action('snow_monkey_forms/administrator_mailer/after_send',

    function($is_sended, $responser, $setting, $mail_parser) {
        $formValues = $responser->get_all();

        $file = fopen('after_send.txt','a');

        foreach($formValues as $key => $val) {
            if(is_array($val)) {
                foreach($val as $v) {
                    fputs($file, $key . " : " . $v . " / ");
                }
                fputs($file,"\n");
            } else if($key === 'snow-monkey-forms-meta') {
                continue;
            } else {
                fputs($file,$key . " : " . $val . "\n");
            }
        }
        fputs($file,"\n-------------------\n");

        fclose($file);

    },
    10,
    4
);
```
## 2-1.コールバック引数
コールバック関数は4つ用意されています。

**`$is_sended`**
送信する/しないのフラグ（boolen)となります。`false`になっているとメール送信をしなくなります。
`true/false`で処理の切り分け処理をする時に使えるかと思います。

:::note info
`$is_sended`自体は`snow_monkey_forms/administrator_mailer/skip`フックや`snow_monkey_forms/administrator_mailer/is_sended`フックで動的に変更することができます。
:::

**`$responser`**
Responserクラスのインスタンスオブジェクトとなります。
`$responser->get('field_name')`や`$responser->get_all()`メソッドなどでフォームの値を取得できます。
 `App/Model/Responser.php`にて定義されているのでこちらのソースを見ると大体の使い方がわかると思います。

 **`$setting`**
Settingクラスのインスタンスオブジェクトになります。SettingクラスはApp/Model/Setting.phpにて定義されているのでこちらのソースを見ると大体の使い方がわかると思います。

**`$mail_parser`**
 MailParserクラスのインスタンスオブジェクト。よく使うメソッドとして`$mail_parser->parse()`など{}で囲んだタグからデータを取得できるメソッドなどがあります。
  `App/Model/MailParser.php`にて定義されています。


```php:USER AGENTやIPアドレスなどを取得して保存したい場合などの例
add_action('snow_monkey_forms/administrator_mailer/after_send',

    function($is_sended, $responser, $setting, $mail_parser) {
        $formValues = $responser->get_all();
        $formValues['user_agent'] = $_SERVER["HTTP_USER_AGENT"];
        $formValues['ip_address'] = $_SERVER["REMOTE_ADDR"];
        $formValues['host'] =  gethostbyaddr($_SERVER["REMOTE_ADDR"]);
		$org_timezone = date_default_timezone_get();
        date_default_timezone_set('Asia/Tokyo'); //タイムゾーンを日本に
        $formValues['date'] =  date("Y年n月j日 H:i:s");
        date_default_timezone_set($org_timezone); //タイムゾーン戻す

        $file = fopen('after_send.txt','a');

        foreach($formValues as $key => $val) {
            if(is_array($val)) {
                foreach($val as $v) {
                    fputs($file, $key . " : " . $v . " / ");
                }
                fputs($file,"\n");
            } else if($key === 'snow-monkey-forms-meta') {
                continue;
            } else {
                fputs($file,$key . " : " . $val . "\n");
            }
        }
        fputs($file,"\n-------------------\n");

        fclose($file);

    },
    10,
    4
);
```

:::note alert
上記サンプルはわかりやすくしたもので、セキュリティの観点含めこのまま本番環境では使用しないでください。
:::

# 3.動的にフォームエレメントを追加する
`snow_monkey_forms/form/append`フィルターフックを使うと動的にフォームエレメントを追加することができます。
Snow Monkey FormsではreCaptchaを設定する時に使っているようです。

使い方などはhidden要素を追加して、そこに例えばリファラをいれておくなどができると思います。
```php
/**
 * 元プラグインからクラス定義ファイルを読み込み
 * 名前空間を指定してクラスを使用できるようにしておく
 */
use Snow_Monkey\Plugin\Forms\App\Helper;
$plugin_dir_path = WP_PLUGIN_DIR;
require_once $plugin_dir_path . '/snow-monkey-forms/App/Helper.php';

add_action( 'snow_monkey_forms/form/append',
    function() {
        //これで
        Helper::the_control(
            'hidden',
            array(
                'attributes' => array(
                    'name' => 'referer',
                    'value' => esc_attr(wp_get_referer()),
                )
            ),
        );
    }
);

```
これでフォームのBODY設定で`{referer}`としておくとリファラが取得できるとそこに情報が入ります。


:::note warn
こちらのフックを使う際には若干の工夫が必要となり、`Helper`クラスを読み込んでおく必要があります。
この方法は正式なプラグイン制作者の意図からは外れてしまう使い方かもしれませんので、使う際には注意が必要かとおもわれます。
:::

:::note warn

`snow_monkey_forms/form/append`フックで追加されるエレメントはsubmitボタンの下に追加されます。
:::


# 参考サイト
上述しましたが、その他のフックに関しては以下のサイトが参考になりますので、ここでの記載は致しません。

https://www.cherrypieweb.com/4862

https://olein-design.com/blog/select-admin-send-target-from-form

https://snow-monkey.2inc.org/2020/06/10/snow-monkey-forms-v0-8-0/