Moodle Form API(mform) チートシート

# この記事について
Moodleプラグイン開発者向け。mformを使ってフォームを作る際によく使うパターンをまとめたチートシート。
https://docs.moodle.org/dev/lib/formslib.php_Form_Definition

# 基本
Moodle上に入力フォーム(form)を作成するためには、`moodleform`クラスを継承したクラスを作成し、そのクラスを`view.php`など表示部分のコードで呼び出してあげる必要がある。

## フォームクラス(moodleform)を作成
以下はblockのedit_formの場合。moodleformクラスを継承する。

``` php:edit_hoge_form.php
namespace mod_hogehoge\form;

class edit_hoge_form extends \moodleform {
    public function definition() {
        $mform = $this->_form;
       // ここにフォームを追加する。
        $this->add_action_buttons();
    }
```

## フォームを表示するviewでクラスを呼び出す

view側から呼び出す場合は、次のようにする。

``` php
$mform = new edit_hoge_form (null);
if ($data = $mform->get_data()) {
    ///
}
```

# よく使うmformメソッド
利用頻度が高いフォーム用のメソッドをまとめる。

## 開閉式ヘッダー(header)

``` php
$mform->addElement('header', 'hogesetting1', 'ほげほげセッティング');
// 最初から開いた状態にする場合にするには、↓を追記
$mform->setExpanded('hogesetting1');
```

## テキスト入力

### 1行テキスト(text)

``` php
$mform->addElement('text', 'hoge', 'ほげ');
$mform->setType('hoge', PARAM_TEXT);
```

### 複数行テキスト(textarea)

``` php
$mform->addElement('textarea', 'introduction', 'いんとろだくしょん', 'wrap="virtual" rows="20" cols="50"');
```

### エディタ

``` php
$mform->addElement('editor', 'fieldname', get_string('labeltext', 'langfile'));
$mform->setType('fieldname', PARAM_RAW);
```

## 選択系
### チェックボックス(advcheckbox)
`checkbox`だと何故か値を取れない場合がある。`advcheckbox`を使うのが良い。

``` php
$mform->addElement('advcheckbox', 'check1', 'チェックボックス1');
```

### ラジオボタン(radio)

``` php
$radioarray = [];
$radioarray[] = $mform->createElement('radio', 'yesno', '', get_string('yes'), 1, $attributes);
$radioarray[] = $mform->createElement('radio', 'yesno', '', get_string('no'), 0, $attributes);
$mform->addGroup($radioarray, 'radioar', '', [' '], false);
```

### セレクトボックス(select)

``` php
$options = ['comma'=>',', 'semicolon'=>';', 'colon'=>':', 'tab'=>'\\t'];
$mform->addElement('select', 'type', 'hogehoge', $options, $attributes);
```

#### onchangeイベントリスナー設定
セレクトボックスに、Javascriptによるイベントリスナー(onchange)を設定出来る。

``` php
$form->addElement('select', 'iselTest', 'Test Select:', $arrayOfOptions, array('onchange' => 'javascript:myFunctionToDoSomething();');
```

## フォーム(mform)内に任意のHTMLタグを入れる(html)

任意のHTMLタグをform内に組み込むことが出来る。`html_writer`クラスと組み合わせることでテーブルを作ることも可能。

```php
$mform->addElement('html', '<h5>HogeHoge</h5>');
``` 

## ファイルアップロード
### 単品 (filepicker)
1つのファイルをアップロードする場合に使用する。

``` php
$mform->addElement('filepicker', 'userfile', get_string('file'), null,
                   ['maxbytes' => $maxbytes, 'accepted_types' => '*']);
```

### 複数ファイル(file manager)

複数ファイルを一括アップロードさせる場合は、`filemanager`を使う。

``` php
$mform->addElement('filemanager', 'attachments', get_string('attachment', 'moodle'), null,
                    ['subdirs' => 0, 'maxbytes' => $maxbytes, 'areamaxbytes' => 10485760, 'maxfiles' => 50,
                     'accepted_types' => array('document'), 'return_types'=> FILE_INTERNAL | FILE_EXTERNAL]);
```

#### accepted_types

`accepted_types`は拡張子もしくはmimetypeを指定する。(両方使える)

``` php
['audio', 'video', 'document'];
['.txt', '.jpg', 'audio'];
```

## 入力フォームのデフォルト値を設定する場合

``` php
$mform->setDefault('hoge', 'デフォルト');
```

## 入力ルール(入力必須etc)を設定する場合

フォームを入力必須にしたり、メールアドレスバリデーションを設定することが出来る。

``` php
$mform->addRule('elementname', get_string('error'), 'rule type', 'extraruledata', 'server'(default), false, false);
```

### 例

``` php
$mform->addRule('dbhost', get_string('required'), 'required', null);
```

### Rule Type

`getRegisteredRules()`関数で一覧を取得可能。

|項目|意味|
| --- | --- |
|required|必須項目|
|maxlength|最大文字数|
|minlength|最小文字数|
|rangelength||
|email|メールアドレス|
|regex||
|lettersonly||
|alphanumeric||
|numeric||
|nopunctuation||
|nonzero||
|callback||
|compare||

# 応用
## mformの宣言元から値を受け取る場合

mformを呼び出す際に引数を設定することで、mformの`difinition()`メソッドへ値を受け渡すことが出来る。
view系の処理から`$cmid`等を受け渡したい場合などに有効。

### 呼び出し元

``` php:hoge.php
$mform = new hoge_form(null, ['cmid' => $cmid]);
```

### definition()メソッド

``` php:hoge_form.php
class hoge_form extends \moodleform {
    public function definition() {
        $mform = $this->_form;
        // カスタムデータとして、view側から引数を受け取りたい場合は、↓の通りにする。
        $cm = $this->_customdata['cmid'];
```

## デフォルト値を設定する場合

``` php
$mform->setDefault('hoge', 'デフォルト');
```

# validation
`validation`メソッドをフォームクラスに定義することで、フォームへの入力値に対して、バリデーションを行うことが出来る。`moodleform`クラスを継承する。

## 例：mod/folder/mod_form.php

```php:mod/folder/mod_form.php
    function validation($data, $files) {
        $errors = parent::validation($data, $files);

        // Completion: Automatic on-view completion can not work together with
        // "display inline" option
        if (empty($errors['completion']) &&
                array_key_exists('completion', $data) &&
                $data['completion'] == COMPLETION_TRACKING_AUTOMATIC &&
                !empty($data['completionview']) &&
                $data['display'] == FOLDER_DISPLAY_INLINE) {
            $errors['completion'] = get_string('noautocompletioninline', 'mod_folder');
        }

        return $errors;
    }
```

# コピペ用
## フォームクラスの見本

``` php
<?php

namespace mod_hogehoge\form;

defined('MOODLE_INTERNAL') || die();

global $CFG;
require_once($CFG->libdir . '/formslib.php');

class hoge_form extends \moodleform {
    public function definition() {
        $mform = $this->_form;
        // カスタムデータとして、view側から引数を受け取りたい場合は、↓の通りにする。
        $cm = $this->_customdata['cm'];

        // ここにフォームを定義していく。

        $this->add_action_buttons();
    }
}
```