Moodle用プラグインを作る(ブロック) 勉強編

Pocket

Moodle用プラグイン(ブロック)を作る手順です。

主に作り方の概要について調べた内容を記し、実践編で実際にプラグイン(ブロック)を作成してみます。

以下のサイトは参考になりました。
Moodleプラグイン開発チートシート
開発初心者のためのMoodleプラグインの開発と利用(第一部) for Moodle Moot 2015
プログラマから見たMoodle(ムードル) – VeRSION2

現在の感触だと、Moodle Docsを中心に勉強しながらMoodle本体のソースから値の意味などを読み解くのが開発方法になるような気がしています。。。(ちょっとしんどい気がしますね)

設定値などは公式的な情報が見つからないので、さしあたり不明なところは記述せず、分かり次第ページに追記していこうと思います。

ではまず、Moodle Docsを主体に勉強します。
開発者ドキュメント →日本語版で読み易いものの、Moodle 1.9用なのでちょっと古い。英語版と見比べながら使います
Moodle Docs -> Dev docs →2.x用のドキュメントですが、英語です 以下はBlocks(Moodle Docs)の意訳になります。よく分からない部分は機械翻訳レベルです。


独自ブロックを作成するための、Moodle2.0用のドキュメントです。多少のPHPの技能が必要とされます。

■コンテンツ

項目 意訳 内容
1 Basic Concepts 基本コンセプト このガイドについて
2 Ready, Set, Go! さあ、準備ができました 基本的なブロックを作成
 2.1 block_simplehtml.php ブロック用PHP サンプル、init()説明
 2.2 db/access.php DB用PHP 表示用の設定値?
 2.3 lang/en/block_simplehtml.php 言語用PHP en(英語)とその他の言語設定
 2.4 version.php バージョン用PHP ブロックと必須Moodleのバージョン情報
3 I Just Hear Static 静的なものの話? ブロックにテキストを表示
4 Configure That Out 外に構成する ブロック用の文字列等をブロック用コード外で設定
5 The Specialists 専門化 ブロックの設定値を反映させる
6 Now You See Me, Now You Don’t 今行わず、参照する 中身がないブロックを表示しない
7 We Are Legion 多くの 複数のメソッド?同一ページ内に複数のブロック?
8 The Effects of Globalization Global化の影響 変数名の衝突防止方法
 8.1 Enabling Global Configuration Global Configurationの有効化 Global Configurationの有効化
 8.2 Accessing Global Config Data Global設定値へのアクセス Global設定値へのアクセス方法
 8.3 Rolling It All Together まとめて作動 入力値のHTML除去
 8.4 Exercise 課題 HTMLをはぎ取る課題
9 Eye Candy 見た目 見た目の情報(タイトル等)を直接コードに記述しないやり方
10 Authorized Personnel Only 関係者以外立ち入り禁止 ページ種類ごとのブロック使用許可
11 Responding to Cron Cronへの反応 Cronの対応手順
12 Additional Content Types 追加のコンテンツタイプ タイプの追加
 12.1 Lists リスト リスト形式のブロックの作り方
 12.2 Trees 木構造 木構造形式のブロックの作り方
13 Database support DBサポート DBへの対応
14 See also 関連項目 関連する項目
15 Appendices 付録 付録について

1 Basic Concepts(基本コンセプト)
このガイドに沿ってブロック機能のためのHTML作成をゼロから始められます。ブロック名(ディレクトリ名)の制約はないが、小文字を使う習慣があります。
ガイド内の「simplehtml」部分は都度変更するが、その他の箇所は標準化(そのまま利用)します。 ファイルについてはスラッシュから始めるが、これはMoodleホームディレクトリに該当します。

2 Ready, Set, Go!(さあ、準備ができました)
Moodleで最も基本的なブロックを作成する場合、4つのPHPファイルが必要になります。 4つのファイルは「blocks/simplehtml」内に配置します(simplehtmlは独自のブロック名に変更)。

 2.1 block_simplehtml.php(ブロック用PHP)
このファイルはブロックのためのクラス定義である。 スクリーン上に表示するプラグインとして管理するのに使われます。 主要なオブジェクトファイル(block_simplehtml.php)を作成します。

<?php
class block_simplehtml extends block_base {
    public function init() {
        $this->title = get_string('simplehtml', 'block_simplehtml');
    }
    // The PHP tag and the curly bracket for the class definition 
    // will only be closed after there is another function added in the next section.

変数の意味。

変数 意味
$this->title

先頭行はブロックのクラス定義です。正確に名前を付ける必要があります。

「simplehtml」部分を変更し、その他は標準化されます。 init()メソッドはブロックに不可欠で、クラスメンバ(変数)に値を設定するのに使われます。この基本例では「$this->title」に値をセットするだけです(ブロックの表題で示されるタイトル値)。

言語ファイルから実際のタイトル値が設定されます。タイトルを示さない(セットしない)場合は別の方法がある(空文字列を設定するわけではない)。

 2.2 db/access.php(DB用PHP)
このファイルはブロックによって生成できる新しいことを保持する。 Moodle 2.4ではcore blocksのためにaddinstanceとmyaddinstanceを導入しました。ブロック個々を制御できるように導入されました。

これらは独自ブロック、つまり「blocks/simplehtml/db/access.php」に追加されるべきです。もしブロックが「ダッシュボード(旧:マイMoodle)」で使われないなら、myaddinstanceは必要ではありません。

以下は配列と、新しいブロックのためにどのように探すべきかである。(意味わからない。。。)

<?php
    $capabilities = array(
 
    'block/simplehtml:myaddinstance' => array(
        'captype' => 'write',
        'contextlevel' => CONTEXT_SYSTEM,
        'archetypes' => array(
            'user' => CAP_ALLOW
        ),
 
        'clonepermissionsfrom' => 'moodle/my:manageblocks'
    ),
 
    'block/simplehtml:addinstance' => array(
        'riskbitmask' => RISK_SPAM | RISK_XSS,
 
        'captype' => 'write',
        'contextlevel' => CONTEXT_BLOCK,
        'archetypes' => array(
            'editingteacher' => CAP_ALLOW,
            'manager' => CAP_ALLOW
        ),
 
        'clonepermissionsfrom' => 'moodle/site:manageblocks'
    ),
);

それぞれの変数/配列の意味は現状、調べても情報が見つからない(もしかしてMoodle本体のコード読まないと分からない?)ので、一旦保留して先に進みます。今のところは、提示されたコードをそのまま使おうと思います。

変数/連想配列キー 意味
capabilities 各種設定値
 block/simplehtml:myaddinstance ログイン後ダッシュボードの設定値?
 captype
 archentypes
  user
 clonepermissionsfrom (block/simplehtml:myaddistance内)
 block/simplehtml:addinstance ログイン前ダッシュボード又は他画面の設定値?
 riskbitmask
 captype
 contextlevel
 archetypes
  editingteacher
  manager
 clonepermissionsfrom (block/simplehtml:addistance内)

 2.3 lang/en/block_simplehtml.php(言語用PHP)
あなたのブロックのための言語ファイル(英語)です。英語以外の場合、「en」を適切な文字コードと入れ替えます。言語ファイルは「blocks/simplehtml/lang」の下に配置します。

追加したい言語については、言語パッケージを導入しておく。

<?php
$string['pluginname'] = 'Simple HTML block';
$string['simplehtml'] = 'Simple HTML';
$string['simplehtml:addinstance'] = 'Add a new simple HTML block';
$string['simplehtml:myaddinstance'] = 'Add a new simple HTML block to the My Moodle page';

それぞれの連想配列キーの意味。

連想配列キー 意味
pluginname
simplehtml
simplehtml:addinstance
simplehtml:myaddinstance

 2.4 version.php(バージョン用PHP)
このファイルはプラグインのためのバージョン情報です。Moodle 2.0より前ではクラスフィールドに格納されていました。Moodle 2.0では「/blocks/simplehtml/version.php」に格納されます。

このファイルは非常に単純で、フィールド定義が少し含まれるだけです。以下がその例。

<?php
$plugin->version = 2011062800;  // YYYYMMDDHH (year, month, day, 24-hr time)
$plugin->requires = 2010112400; // YYYYMMDDHH (This is the release version for Moodle 2.0)

それぞれの変数の意味。

変数 意味
$plugin->version プラグインのバージョン
$plugin->requires プラグインが要求するMoodleのバージョン

ブロックを使うために必要なMoodleの最小限バージョン情報と、ブロック自体のバージョン情報を意味するフィールド定義です。 ファイル内で変数$plugin自体を作成する必要はありません。閉じタグ(?>)を含めないのは意図的なので、注意して下さい。

3 I Just Hear Static(静的なものの話?)
実際にブロックを使って画面上に何かを表示する場合、クラスにメソッドの追加を必要とします。(block_simplehtml.phpに記述する内容と思われます) 新しいコードは以下。

public function get_content() {
    if ($this->content !== null) {
      return $this->content;
    }
 
    $this->content         =  new stdClass;
    $this->content->text   = 'The content of our SimpleHTML block!';
    $this->content->footer = 'Footer here...';
 
    return $this->content;
  }
}   // Here's the closing bracket for the class definition

変数の意味。

変数 意味
$this->content
$this->content->text
$this->content->footer

ブロックをフロントページ(ログイン前ページ)に加えてください。(特に新しいユーザーの場合)フロントページへの追加を忘れずに。Turn Editing On, そしてあなたのブロックをページに追加します。

よりシンプルな事ができませんよね?このメソッドについて何を行っているか分析しましょう。

このメソッドについて説明します。まず$this->contentの値がNULLかどうかチェックしており、NULLの場合は処理を継続します。1つのブロック内で複数回呼ばれるため、処理にかかる時間を節約する手段です。

前に処理されていない(NULLだった)場合、ゼロから処理を始めます。テキストとフッタでHTMLが使える事も覚えておいて下さい。

これがblockで出力できる唯一のコンテンツではないという事に言及しておきます。リスト、階層的な木構造を作ることもできます。特定の種類の出力(例えばメニュー)に適しています。

これらの異なるコンテンツは、コンテンツとその作り方に影響を及ぼします。詳細は付録Aを見て下さい。

ブロックはMoodleへの自動インストールとコース追加が行えるべきです。管理ページでインストールする(「通知」をクリックする)。その後、チュートリアルの継続に戻る。

4 Configure That Out(外に構成する)
ブロックの現バージョンをマッチさせること(例として提示されたブロックを使う事?)は現実的でない。 固定メッセージを表示するので、あまり便利ではない。

真にやりたいのは、教員がブロックの中身をカスタマイズできるようにすることです。 これはブロックで「instance configuration」と呼ばれています。基本的なinstance configurationは Moodle 2.0で自動になっています。

「編集モード」でどこかのページにブロックを配置すると、タイトルバーに編集ボタンがある事に気付きます。 クリックすると、ブロック構成の設定に移行します

Moodleが標準で加える設定は、ブロックの出現とMoodleページ上の位置に関係するものです。

設定formを広げる、カスタムの選択フィールドを追加できることで、ユーザーはブロックを所定の仕事、ページに合わせる事が出来る。

構成formを広げて、ファイル「/blocks/simplehtml/edit_form.php」を作り、以下のコードで満たす。

<?php
 
class block_simplehtml_edit_form extends block_edit_form {
 
    protected function specific_definition($mform) {
 
        // Section header title according to language file.
        $mform->addElement('header', 'configheader', get_string('blocksettings', 'block'));
 
        // A sample string variable with a default value.
        $mform->addElement('text', 'config_text', get_string('blockstring', 'block_simplehtml'));
        $mform->setDefault('config_text', 'default value');
        $mform->setType('config_text', PARAM_RAW);        
 
    }
}

変数、文字列の意味。

変数/文字列 意味
$mform->addElement
$mform->setType
‘header’
‘configheader’
‘blocksettings’
‘block’
‘text’
‘blockstring’
‘block_simplehtml’
‘config_text’
‘default value’
‘config_text’

1行目はblock_edit_formからクラスを継承する宣言。Moodleが構成ページで実行するコードを許可する。

specific_definition()メソッドはformの要素が定義される場所。これらは標準的なMoodleのformライブラリと同様のフォーマット。

specific_definitionメソッドの範囲内で、ブロックで使われるテキストの入力フィールド、ヘッダを作る。

注意:ブロックの言語ファイルを拡張したいと望むかもしれない(「lang/en/block_simplehtml.php」)。上記のコードで「blockstring」を定義するために、値を追加する

重要:フィールド名は「config_」から始める必要がある。さもないと保存されず、$this->configを通してブロックの中で利用できない。

構成formが保存されると、ブロックの中で入力されたテキストを使うことができる。

if (! empty($this->config->text)) {
    $this->content->text = $this->config->text;
}

init()はブロック作成、セッティングする目的と同様に直接呼ばれる。$this->configはまだ具体的に示されていません。

チェックボックスについての注意:form内のチェックボックス要素は使えない(設定されてとどまる)。代わりにadvcheckboxを使わなければならない。

5 The Specialists(専門化)

ブロックの内容のための設定例を実行する事は、興味を十分に強めました。
しかし、そこで止めますか?ブロックのタイトルもカスタマイズしませんか?

最初達成するには、これは十分に自然です。「/blocks/simplehtml/edit_form.php」に他のフィールドを追加しましょう。
では、行きましょう。

// A sample string variable with a default value.
    $mform->addElement('text', 'config_title', get_string('blocktitle', 'block_simplehtml'));
    $mform->setDefault('config_title', 'default value');
    $mform->setType('config_title', PARAM_TEXT);

編集されたファイルを保存し、コースに進みます。ブロックのタイトルを編集しますが・・・何も起きません!

例の構成は正しく保存されました。(一度編集することで証明)しかし表示されません。
単純に「SimpleHTML」のタイトルを取得することが全てです。

思い出すと、それは変ではありません。

どこに$this->titleを設定したか、init()メソッドを覚えていますか?実際にその時から値を変えていませんでした。そして$this->titleは$this->config->titleと同じではありません(少なくともMoodleでは)

例の構成では、$this->titleを更新する方法を必要としている。しかし前述したように、init()以外の全てのメソッドで$this->configが使える。

では、どのようにすべきか?

sleeveから他のaceを引き抜き、blockクラスに小さなメソッドを追加しましょう。

public function specialization() {
    if (isset($this->config)) {
        if (empty($this->config->title)) {
            $this->title = get_string('defaulttitle', 'block_simplehtml');            
        } else {
            $this->title = $this->config->title;
        }
 
        if (empty($this->config->text)) {
            $this->config->text = get_string('defaulttext', 'block_simplehtml');
        }    
    }
}

ああ、ずっとやりたかった事はこれです!
しかしspecialization()メソッドでは何が行われているのでしょう?

この「魔法」のようなメソッドは実にすばらしいプロパティを持っています。

これは、例構成が呼ばれて有効化される(init()が呼ばれた直後)と、すぐにMoodleによって自動で呼ばれる事を保障します。

初回の為に、そしてblockによって実行される以外の何かの前に処理されたblock要素を意味します。

この例では、構成データを実行する必要があるか、「できるだけ早く」利用可能とするための自然な選択としてspecialization()メソッドを提供している。

6 Now You See Me, Now You Don’t(今行わず、参照する)

他のすばらしいやり方、非常に役に立つことについて言及するよいタイミングです。具体的にこの場合、blockは表示するのに面白い何かを持っているでしょう。しかし若干の他の場合、役に立つ何かを持ちません。

最近の活動が存在しないケースで、この例は「最近の活動」ブロックです。しかし活動の欠落を明白に通知する事を望むblockの場合、きっと役立ちます。

もしその表示を必要としない場合、ブロックの「消去」をできるならば素晴らしいでしょう。

それは可能です。get_content()メソッドが呼ばれた後、ブロックが表示内容を持っていないことを確認する方法です。

$this->contentの全フィールドは空の文字列と同等であるべき事を意味します。HTMLベースのブロックの場合、これらのフィールドは$this->content->textと$this->content->footerです。

ブロックのis_empty()メソッドが呼ばれた事によって実行されるMoodleのチェックはブロックが空である時、まったく表示されません。

ブロックのタイトルの正確な値と配置(存在?)、またはこの振る舞いに影響を与えないhide_header()メソッドの欠如に注意します。何も内容を持たない場合、他の何かに関わりなくブロックは空を考慮されない。

7 We Are Legion(多くの)

現在のブロックは、タイトルと内容の両方を設定可能です。ほとんど何でも綺麗に作る事ができ、実際に多目的に利用できます。

1つのコースにこのタイプの複数のブロックを追加することは実に素晴らしい。ブロッククラスに小さなメソッドを追加することはシンプルだと思うかも知れません。

public function instance_allow_multiple() {
  return true;
}

多くのコースにSimpeHTMLブロックのインスタンスを許可すべきだとMoodleは言います。ファイルの変更を保存した後、ごたごたもなく、Moodleはすぐに複数のブロックのコピーを許可します。

ブロック自身が同じページで複数のインスタンスを許可しても、管理者はまだそのような振舞いを許可しないオプションを持つことに注意して下さい。管理者からそれぞれのブロックのために個別の設定ができます。

8 The Effects of Globalization(Global化の影響)

自身の個人データによるインスタンスをそれぞれ設定することは、十分に素敵です。しかし時々管理者は、特定のブロックを同じタイミングで全て「触る」方法を必要とします。

SimpleHTMLブロックの場合、少しの設定で、全てのインスタンスにおいて提案するのが困難ということを意味するわけではありません。

例えば、多くの文字だけのブロックそれぞれの要素を制限したいかも知れません。またはブロックの内容の外側でHTMLフィルタを設定したい、単純な文字を許可したいだけ。

仮に、このような特徴がSimpleHTMLと名付けられたブロックのために獲得できなかったとしても、どこかで役立つかも知れません。

この種の設定は「global configuration」と呼ばれ、特定のブロックだけに当てはまります(しかしブロックのインスタンスの全ては影響を受けます)。ブロックのためのこのような設定を実装することは、例の構成を実装することと酷似している。

2番目の例を実装する方法を見ると、ブロックの内容にHTMLがなく、テキストを許可するだけの設定を持っていることが分かります。

新しいファイル「/blocks/simplehtml/setting.php」を作り、それぞれの設定のフィールド定義から配置、ブロックで「global configuration」を有効にすることは、Moodleが「global settings」フォームを生成して制御する用途とする。それは初期の設定フォームのインスタンス生成する方法と考えが似ている。

しかし、以前生成されたフォームとフィールドの実際のコードは幾らか異なる。

setting.phpファイルに以下を配置して下さい。

<?php
$settings->add(new admin_setting_heading(
            'headerconfig',
            get_string('headerconfig', 'block_simplehtml'),
            get_string('descconfig', 'block_simplehtml')
        ));
 
$settings->add(new admin_setting_configcheckbox(
            'simplehtml/Allow_HTML',
            get_string('labelallowhtml', 'block_simplehtml'),
            get_string('descallowhtml', 'block_simplehtml'),
            '0'
        ));

ご覧のとおり、global configurationフォームを作成し、単に管理設定オブジェクトを作成して配列に加えます。配列は作成の設定フォームを超えて、入力値は自動でデータベースに保存される。

利用できる設定タイプの詳細と追加方法は、Admin_settings#Individual_settingsに見付けられます。

管理サイトから設定の詳細を受け入れるために、フォーム要素からヘッダーとチェックボックスを作成した。

チェックボックス要素の名前には特別な注意を払うべき。保存する方法以外‘simplehtml/Allow_HTML’は構成オプションの名前だけでなく明示する。設定オプションの名前を特に単純にするなら、_configデータベーステーブルに、globalの$CFGオブジェクトに保存される。

これは更なるデータベースの呼び出しなしで、$CFGを経由して利用できる構成になる。$CFGオブジェクトのサイズも増えます。加えて、ブロックの名前を変数の前に置く必要がある。さもないとMoodle内で、他のプラグインと同様の変数名を共有してしまうリスクがある。

ブロックの設定値を格納する好ましい方法は、ファイル「settings.php」の各々の設定の変数名に接頭辞としてブロック名を付けることです。上記を行う事で、構成する変数の名前、スラッシュ(/)に続く。

このようにファイル「setting.php」を記述するなら、ブロック名の下で「_config_plugin」テーブルに変数は保存されます。設定値はget_config()の呼び出しを経由して利用でき、プラグイン間での名前衝突はありえないことになります。

最後に、要素ごとに指定される二つの言語タグについて不思議に思うなら、最初のタグは要素のラベルまたは主要なテキストのため、次のタグは説明のためのものです。

簡単ですね。

 8.1 Enabling Global Configuration(Global Configurationの有効化)※Moodle 2.4

Since version 2.4, the following line must be added to the /blocks/simplehtml/block_simplehtml.php file in order to enable global configuration:

   function has_config() {return true;}

This line tells Moodle that the block has a settings.php file.

NOTE FOR UPGRADERS(UPGRADERSの注意)

Moodleの古いストレージメソッドにとって代わるパースされた要素名、ファイル「setting.php」で、ブロックのconfig_save()メソッドが全ての構成情報を送信する点において、データ保存方法を上書き許可することに気付く。

config_save()メソッドはMoodle 2.xでもはや使われません。しかし間もなく分かるように、instance_config_save()メソッドはよく使われます。

 8.2 Accessing Global Config Data(Global設定値へのアクセス)

プラグインのためのglobal値の定義をした今、コード内でアクセスする方法を知っておくべきです。

globalネームスペースの設定変数を保存したなら、このようにglobalの$CFGオブジェクトからアクセスできます。

$allowHTML = $CFG->Allow_HTML;

これを勧める。ブロックのためのカスタム名前空間の設定変数を保存したら、get_config()を通してアクセスできる。

$allowHTML = get_config('simplehtml', 'Allow_HTML');

 8.3 Rolling It All Together(まとめて作動)

OK。ユーザーにブロックのためのカスタムされたテキストのコンテンツの入力を許可する設定フォームが現在あるように、コンテンツの一部をHTMLタグとして入力する事を許可するべきかどうかを問わず、global設定オプションを必要とする。

2つを結びつける必要があります。しかしMoodleが「edit_form.php」で構造のフォーム処理を引き受けるなら、それを捕まえて、HTMLタグを除去することができますか?

幸いに、これを行える方法があります。ブロッククラスにおけるinstance_config_save()メソッドのオーバーライドによって、入力後に格納される設定データを編集することができます。

標準の実装は以下。

public function instance_config_save($data) {
  $data = stripslashes_recursive($data);
  $this->config = $data;
  return set_field('block_instance', 
                   'configdata',
                    base64_encode(serialize($data)),
                   'id', 
                   $this->instance->id);
}

はじめは恐ろしく見えるかもしれません(このようなserialize()、base64_encode()、stripslashes_recursive()といったもの)しかし恐れないでください。その何にも触る必要はありません。

最初に特別な確認コードを加え、Moodleに指示し、標準のデータを実際に保存する実装を呼び出すだけです。具体的には、このようにクラスにメソッドを追加します。

public function instance_config_save($data) {
  if(get_config('simplehtml', 'Allow_HTML') == '1') {
    $data->text = strip_tags($data->text);
  }
 
  // And now forward to the default implementation defined in the parent class
  return parent::instance_config_save($data);
}

(この例はブロックのためのカスタム名前空間を使うと仮定しています)

ついに!「SimpleHTML」ブロックの許可された内容のタイプを超えて、管理者は生存と消失の絶対的な権限を持ちます。確かな?

正確には少し違います。実際、しばらくそれについて考えるなら、許可されたHTMLの幾つかのポイントが明白になり、読み込まれたHTMLのコンテンツを保存した幾つかのブロック、その後、管理者が設定を「off」に変更、それは読み込まれたHTMLからコンテンツの変更を防ぐだけです。

それらのコンテンツでHTMLを既に持つブロックは、表示を続けます。

継続して考えた後、怠惰なアプローチを選択した場合、この問題は次に停止します。なぜならその場合、それぞれのブロックの内容はちょうど表示する前に「サニタイズ」する。

熱心なアプローチができる唯一のことは、管理設定が「HTML off」に変わるとすぐ、SimpleHTMLインスタンス全ての内容から全てのタグを剥ぐことです。しかし、設定を「HTML on」に戻しても、はぎ取ったタグは戻りません。

一方、怠惰なアプローチは遅いかもしれませんが、融通が利きます。内容を表示する前にHTMLを維持またははぎ取るか選ぶことができます。そして、管理で設定のon/offを再度切り替える場合にそれを失いません。

開発の命は単純で素晴らしくないですか?

 8.4 Exercise(課題)

読者の為の必須の練習として選択し、チュートリアルのこの部分を行わせました。

SimpleHTMLブロックを「正しく」動作させるため、ブロックのインスタンス全ての既存の構成から全てのタグを剥ぎ取る熱心なアプローチを強化する方法を見付けるか、もしくは代わりに怠惰なアプローチに戻ります。

(ヒント:get_content()メソッドで実行します)

9 Eye Candy(見た目)

ブロックは機能的に完成しています。すぐに役に立つ挙動のカスタマイズについて、我々が使える幾つかのコツについて見てみましょう。

第一に、ブロックの視覚面を調節できる一対の方法があります。手始めに、全てのヘッダー(タイトル)を表示しないブロックを作ることが役立つかも知れません。

Moodleのコース説明ブロックの挙動の影響を見る事ができます。ふるまいを達成するのに推測し、ブロッククラスのメソッドにもう一つのメソッドを加える。

public function hide_header() {
  return true;
}

もう一つメモ:ブロックのinit()メソッドの中でタイトルを空に設定することができません。init()が呼び出された後、各々のブロックは固有の、空でないタイトルが必要です。

そしてMoodleはブロックのインスタンス全てを区別するタイトルとしてそれらを使えます。

次に、ブロックの表示に使われる実際のHTMLの特性(プロパティ)に働きかけることができます。ブロックを表示するための全てのHTML内で、それぞれのブロックは<div>や<table>要素に含まれます。

入れ物(コンテナ)にHTML属性と特別な値を加えるようMoodleに指示することができます。

これは一般的にCSSを使った結果を自由にカスタマイズすることによって行われます。(以下のように、これは標準で行われます)

この特徴の標準的なふるまいは、「block_simplehtml」の値を付与する事によってブロックのクラスのHTML属性を編集します。(小文字のブロック名に従った接頭辞「block_」)

ブロックの視覚的なスタイルを変えるためにテーマでCSSセレクターを製造したクラスを使う事ができます。
(例えば、「.block_simplehtml {border: 1px black solid}」)

標準的な振舞いを変更するのに、属性の連想配列と値を返すメソッドを定義する必要があります。

例:

public function html_attributes() {
    $attributes = parent::html_attributes(); // Get default values
    $attributes['class'] .= ' block_'. $this->name(); // Append our class to class attribute
    return $attributes;
}

結果、全ての通常のHTML属性を持つブロックはベースのブロッククラスから受け継がれるように、追加したクラス名を加えます。ブロックのスタイルを変更するためにこのクラス名を使えます。YUIなどを通し、JavaScriptのイベントを追加して下さい。

最終的に手際よく触れ、「block_simplehtml」の値をハードコードしないで、代わりに直接ブロック名にマッチさせるためにname()メソッドを使いました。

10 Authorized Personnel Only(関係者以外立ち入り禁止)

幾つかのブロックは他ではなく、状況によって役立ちます。「ソーシャルな活動」ブロックの例です。「週」フォーマットのコースでなく、「ソーシャル」フォーマットのコースに役立ちます。

ブロックが利用できる事を制限する必要があり、ページ上で選択されるだけで、コンテンツまたは能力を割り当てる事ができる。

Moodleは、ブロックがどのページフォーマットで利用可能か宣言することを許可する。いつでもブロックの開発者によって、これらの規制を強制できます。

Moodleの基準となる連想配列から与えられた情報は、互いのキーと一致するページフォーマットとboolean値(true/false)で定義されており、ブロックがそのページフォーマットでの出現を許可すべきかどうかにかかわらず、定義すべきです。

上記の節で、コースの代わりに計画的な学期ページを使用した計画性について注意して下さい。なぜならMoodle 1.5とそれ以前で、ページのブロックは表示できる事を維持します。

そのようなページの最適な例はコースページですが、それらは制限されません。例えば、小テストビュー(小テスト名をクリックした際に最初に見るもの)も、ブロックを維持します。

ページの為に使う事のできる名前のフォーマットは、ページの表示に用いられるスクリプトの名前に由来する。例えばコースを見ているときに、スクリプトは「/course/view.php」(これはブラウザーのアドレス行から明白)

このように、ページのフォーマット名は「course-view」です。小テスト表示ページのフォーマット名が、確かに従い、「mod-quiz-view」である。しかしこの原則には、多少の例外があります。

Moodleのフロントページのフォーマット名は「site-index」です。コースのフォーマット名は「course-view」ではありません。「course-view-weeks」、「course-view-topics」、等です。

例えそのようなページがなくとも、フォーマット名がどのような場合にも対応できるオプションとして使われる事ができます。適用できるフォーマットの定義で望むのと同じ多くのフォーマット名を含める事ができます。

各々のフォーマットは許可されるか否か、「このブロックはこのページで許可されるか否か?」という疑問を解明する三つの規則があります。

フォーマット名の接頭辞は、フォーマット名に一致します。例えばmodは全ての活動モジュールに該当します。コースフォーマットに構わず、「course-view」はどんなコースにも一致します。最後に、「site」はフロントページに一致します。(完全なフォーマット名は「site-index」である事を思い出して下さい)

ブロックが許可されるかを決定する時、高い優先度で、より特殊化したフォーマット名でページと一致する。例えば「mod」、「mod-quiz」と「mod-quiz-view」は全て小テストビューページに一致する。

しかし三つ全てが存在するなら、より一致するので、「mod-quiz-view」は他の二つより優先されます。「*」の文字は全ての文字の場所で使われる。例えば「mod」と「mod-*」は等しい。

この文章を記述している時点で、「ワイルドカードに一致する」を利用する実際の理由は存在しないが、将来のために存在している。フォーマット名が現れる指令は、多少の違いも生じません。

上記の全ては、状況を複雑に聞こえさせるに十分なので、幾つかの特殊な例を見てみましょう。第一に、サイトのフロントページだけに現れるブロックには、以下を使います。

public function applicable_formats() {
  return array('site' => true);
}

全てがなくなっているので、ブロックは全てのコースフォーマットで出現が認められません。しかしサイトはTRUEに設定されるので、サイトのフロントページに出現する事を許可されているのは明白である。(それが接頭辞なので、「site」が「site-index」に一致する事を思い出して下さい)

もう一つの例。ソーシャルを除いた全てのコースフォーマットにおいて出現するブロックを許可したい場合、コース以外のどこにも許可されません。以下を行います。

public function applicable_formats() {
  return array(
           'course-view' => true, 
    'course-view-social' => false);
}

今度は、まず全てのコースで現れるブロックを許可します。その時、ソーシャルフォーマットを明白に許しません。

最終的に最も複雑な例で、小テストを除いた活動モジュールを見ている時に、フロントページ上に表示することのできるブロック(ソーシャルコースを除く)を考えます。これは以下の通り。

public function applicable_formats() {
  return array(
           'site-index' => true,
          'course-view' => true, 
   'course-view-social' => false,
                  'mod' => true, 
             'mod-quiz' => false
  );
}

もしこれらが「最も一致する」方針で結果を決定することを覚えているなら、目的を達成する事は難しくない。

11 Responding to Cron(Cronへの反応)

ブロックをglobalのMoodle cronプロセスに対応させることは可能です。ユーザーインストラクションに関係なく規則的な間隔で動作するメソッドを持つ事ができます。

二つのパーツがここにあります。第一に、ブロッククラス内で新しい関数を定義する必要があります。

public function cron() {
    mtrace( "Hey, my cron script is running" );
 
    // do something
 
    return true;
}

注意:cron関数がtrueを返さない場合、ブロック表のlastcronフィールドは更新されず、その結果、cron関数はcron処理が走るたびに呼ばれます。それと、cron関数のために(最小限の)実行間隔を設定する必要があります。

Moodle 2.0の前では、これはinit()メソッドによる、ブロックの$this->cronフィールドの値の設定によって達成されました。現在、「/blocks/simplehtml/version.php」ファイルに更なる行を追加することによって達成されます。

それを開き、以下を加えて下さい。

$plugin->cron = 300;

cron間隔は秒で設定できるので、上記の行では最小の実行間隔を5分に設定します。しかし関数はMoodleインストールの実行を設定したcronと同じ頻度で呼ぶことができます。

もしこの例のようにブロックが少なくとも5分は実行を待つ設定なら、しかしMoodleのcronシステムは24時間ごとに実行する設定となっているだけです。その時、ブロックは予想しているよりも長い間実行を待つことになります。

もしバージョンファイルかブロックファイルの値を変えた場合、バージョン番号を突き合わせ、ブロックを更新するために通知ページを訪れる必要があることを思い出して下さい。さもなければ無視されます。

注意:このブロックcronは、そのブロックのタイプだけのために呼ばれるcronスクリプトとして設計されています。
つまり、cronはブロックの個々のインスタンスについて気に掛けません。

cron機能の中に$thisが定義されますが、その中にはほとんど何も持ちません。(タイトルと内容フィールドだけ)
もし個々のインスタンスのためにcronを実行する必要があるなら、ブロックのcron機能の中で繰り返し遂行する。

例:

public function cron() {
 
    global $DB; // Global database object
 
    // Get the instances of the block
    $instances = $DB->get_records( 'block_instances', array('blockname'=>'simplehtml') );
 
    // Iterate over the instances
    foreach ($instances as $instance) {
 
        // Recreate block object
        $block = block_instance('simplehtml', $instance);
 
        // $block is now the equivalent of $this in 'normal' block
        // usage, e.g.
        $someconfigitem = $block->config->item2;
    }
}

ヒント:このブロックを作る事は、低いオーバヘッドで応答する事が可能なcronのコードを生成する方法を意味します。ブロックの実際のインスタンスは必要とされません。

12 Additional Content Types(追加のコンテンツタイプ)

 12.1 Lists(リスト)

ガイドの最終部分で、Moodleのブロックシステムに付加される能力(すなわち、異なる種類の内容をユーザーに表示するブロックを作成する能力)について幾つか手短に論じる。最初に、オプションのリストを作成してこれらをユーザーに表示します。

このリストは1行に1つのアイテムとアイテムの隣の画像(アイコン)で表示されます。そのようなリストブロックの標準的な例はMoodleの管理ブロックです。それは、このセクションで論じられる全ての点を例示します。

ここまで見てきたように、ブロックは$this->contentの2つのプロパティを使います。テキストとフッターです。テキストはブロック内容として下条のまま表示されます。フッターはより小さいフォントサイズで内容の下に表示されます。

リストブロックは正確な同じ内容の$this->content->footerを使います。しかしこれらは$this->content->textを無視します。

代わりに、get_content()メソッドが呼ばれた時、Moodleはそのようなブロックが2つのプロパティを設定する事を期待します。$this->content->itemsと$this->content->iconsです。

$this->content->itemsは表示されそうなリスト内の各々のアイテムのために、HTMLを意味する要素を含む数値的にインデックスされた配列でなければなりません。通常、これらのアイテムはページにリンクを提供するHTMLアンカータグです。

$this->content->itemsが保持するアイテムと同じ数のの正確さで、$this->content->iconsは数値的なインデックスを付けられた配列でなければなりません。

「src」、「height」、「width」と「alt」の属性で、各々のアイテムは完全に適したHTMLタグでなければなりません。明らかに均一なサイズで小さな画像を維持する事を意味します。この目的のために16×16のイメージを標準として推奨します。

標準のテキストボックスの代わりにリストボックスを持ちたいとMoodleに指示するために、ブロッククラスの宣言を少し変更する必要があります。

block_baseクラスを継承する代わりに、block_listクラスを継承します。

例:

class block_my_menu extends block_list {
     // The init() method does not need to change at all
}

In addition to making this change, we must of course also modify the get_content() method to construct the $this->content variable as discussed above:

public function get_content() {
  if ($this->content !== null) {
    return $this->content;
  }
 
  $this->content         = new stdClass;
  $this->content->items  = array();
  $this->content->icons  = array();
  $this->content->footer = 'Footer here...';
 
  $this->content->items[] = html_writer::tag('a', 'Menu Option 1', array('href' => 'some_file.php'));
  $this->content->icons[] = html_writer::empty_tag('img', array('src' => 'images/icons/1.gif', 'class' => 'icon'));
 
  // Add more list items here
 
  return $this->content;
}

要約すると、テキストブロックの代わりにリストブロックを作りたいなら、ちょうどブロッククラスの宣言とget_content()メソッドを変更する必要がある。

init()メソッドを追加する義務があり、すぐに最初のリストブロックを与えます。

 12.2 Trees(木構造)

2011/12/23現在、この機能はすべてのMoodle 2.x版で実施できません。

クラスがコードベースから失われているように見えます。これは以下のURLトラッカーに加えられました。この機能を必要とするならば、イシューに賛同して下さい。

Visit this issue on the tracker @ MDL28289

13 Database support(DBサポート)

ブロックの中で使われる特定の情報を保持する場合、、データベーステーブルを持つ必要がある。これを含むテーブルスキーマをファイル「/blocks/simplehtml/install.xml」に作成する必要がある。XMLDBエディタを使って「install.xml」ファイルを作ります。

詳細のための データベースFAQ > XMLDB を見てください。

14 See also(関連項目)

ブロック拡張このチュートリアルの継続。

Moodleプログラミングコースの導入のUnit7はこのコースを追跡します。(しかしまだバグと矛盾があり、フォーラムで詳しくコースの議論を追及するべきです)

Daniel Neis Araujoの新しいブロックのテンプレート

15 Appendices(付録)

付録は別のページに移動しました。

付録A: block_base 参照

以下はテンプレートをダウンロードした際の作業メモ。
【作業メモ】
Moodleのプラグインは基本的に構成や命名に規則があるようなので、既存のソースを編集するのよさそうです。

danielneisという方がGitHub上にMoodle用プラグイン(ブロックのみ)を公開しているので、ダウンロードします。(ここから)

GitHubのアカウントがあればCloneするか、なければZIPファイルをダウンロードします。とりあえず私はZIPファイルをダウンロードして、ローカルで展開しました。 展開してみると、中身は以下のようになっています。けっこう簡単な構成ですね。

ファイル名/フォルダ名 内容
block名 block_newblock.php
edit_form.php
setting.php
version.php バージョン情報
composer.json
README.txt
db access.php
lang en block_newblock.php メッセージ(英語)
広告

Pocket