Drupal でのモジュール開発を理解するということは node のコンセプト(コンテンツタイプ)と hook システム(hook と呼ばれるコールバック関数)とフォーム($form)を理解するということでもある。
「
Drupal で、モジュールを開発するために必要な最低限の hook」 では、Drupal の hook について説明したが、ここでは具体的にモジュールを実装してみることにする。そのモジュールの名前は「hook」。
Drupal 5 からは、yourmodule
.info、yourmodule
.install、yourmodule
.module、yourmodule
.css の 4つのファイルが必要となった。ゆえに hook という名前のモジュールを作る場合、hook
.info、hook
.install、hook
.module、hook
.css の 4つのファイルを作る。この hook モジュールは、タイトル、本文、そして hook モジュール独自の値である 'A'~'E' の hid (=hook ID)を取る(表示上の 'A'~'E' はデータベース中では 1~5 に対応して保存される)。hid のデフォルト値は
https://yourdomain.com/admin/settings/hook で設定することができる。以下、参考にしてほしい。
hook.info
; セミコロンがコメント。
name = Hook
description = "A module template."
package =
version = VERSION
;
version = "5.x-1.x-dev"
project = "Example"
hook.install
<?php
/**
* hook_install() の実装
* これを実装すると Drupal のモジュールシステム admin/build/modules に
* 組み入れることができる。基本的にこのモジュールで扱いたいデータを
* 格納するテーブルを作る。
*/
function hook_install() {
switch ($GLOBALS['db_type']) {
case 'mysql':
case 'mysqli':
db_query("CREATE TABLE {hook}
(
`nid` INT( 10 ) UNSIGNED NOT NULL ,
`hid` INT( 3 ) UNSIGNED NOT NULL DEFAULT '1',
PRIMARY KEY ( `nid` )
) ENGINE = MYISAM"
);
break;
case 'pgsql':
break;
}
}
/**
* hook_uninstall() を実装する。
* このモジュールで使っていたテーブルを drop する。
* variable_del で、このモジュールで使っていた設定値を削除する。
*/
function hook_uninstall() {
db_query('DROP TABLE {hook}');
variable_del('hook_option'); // 忘れないように!!!
}
?>
hook.module
<?php
// コンスタントな文字列の定義
define('MODULE_NAME', 'Hook');
define('CONTENT_TYPE', 'hook');
define('PRIVILEGE_ADMIN' , 'administer' . MODULE_NAME . ' server settings');
define('PRIVILEGE_CREATE' , 'create' . MODULE_NAME . ' forms and docs');
define('PRIVILEGE_VIEW' , 'view' . MODULE_NAME . ' forms and docs');
define('PRIVILEGE_EDIT' , 'edit own' . MODULE_NAME . ' forms and docs');
/**
* hook_help() を実装する。
* case にある URL での説明書き。
*/
function hook_help($section) {
switch ($section) {
case 'admin/help#' . CONTENT_TYPE:
$o .= '<p>' . t('Submit, view and manage ' . CONTENT_TYPE . ' lists.') . '</p>';
return $o;
case 'admin/modules#description':
return t('Allows users to submit, view and manage job records');
case 'node/add#' . CONTENT_TYPE:
return t('Add a ' . MODULE_NAME . ' record.');
}
}
/**
* hook_perm() を実装する。
* ここでの定義は、admin/user/access でのアクセスコントロールで使われる。
*/
function hook_perm() {
return array(
PRIVILEGE_ADMIN,
PRIVILEGE_CREATE,
PRIVILEGE_VIEW,
PRIVILEGE_EDIT
);
}
/**
* hook_access() を実装する。
* create、update、delete、view のアクセス制御を行う。
* @param op create、view、update、delete の 4つの値を取る。
*/
function hook_access($op, $node) {
global $user;
if ($op == 'create') {
return user_access(PRIVILEGE_CREATE);
}
if ($op == 'view') {
return user_access(PRIVILEGE_VIEW);
}
if ($op == 'update' || $op == 'delete') {
if (user_access(PRIVILEGE_EDIT)
&& ($user->uid == $node->uid)) {
return TRUE;
}
}
}
/**
* hook_menu() を実装する。
* Drupal のメニュー(パス)とそれをクリックされたときに呼び出される関数、そして
* アクセス制御の組み合わせを記述する。
*/
function hook_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'path' => 'node/add/' . CONTENT_TYPE,
'title' => t(MODULE_NAME),
'access' => user_access(PRIVILEGE_CREATE)
);
$items[] = array(
'type' => MENU_NORMAL_ITEM,
'path' => 'admin/settings/' . CONTENT_TYPE,
'title' => t(MODULE_NAME . ' default settings'),
'access' => user_access(PRIVILEGE_ADMIN),
'callback' => 'drupal_get_form',
'callback arguments' => CONTENT_TYPE . '_admin',
'description' => 'Configure ' . MODULE_NAME . ' default settings'
);
}
return $items;
}
/**
* hook_node_info() を実装する。
* コンテンツタイプを定義する。'hook' にはモジュール名が入る。
* が、必ずしもこのモジュール名(hook)でなくてもよいため、
* array 配列に hook、name、module、description の組み合わせを追加していけば
* 1つのモジュールで複数のフォームを 実現できる。
* 必ず hook、name、module、description の組み合わせをキープすること。
*/
function hook_node_info() {
return array(
'hook' => array(
'name' => t(MODULE_NAME),
'module' => CONTENT_TYPE,
'description' => t('You can make a ' . CONTENT_TYPE . 'hook record and view them.')
)
);
}
/**
* hook_admin() を実装する。
* この hook を実装すると、admin/settings/hook でこのモジュール固有のデフォルト
* 値を複数定義できる。
*/
function hook_admin() {
// hostname
$form['hook_option'] = array(
'#type' => 'select',
'#title' => t('hid default value'),
'#default_value' => variable_get(CONENT_TYPE . '_option', 1),
'#options' => array('1'=>'A', '2'=>'B', '3'=>'C', '4'=>'D', '5'=>'E'),
'#size' => 1,
'#weight' => -10,
'#required' => TRUE
);
return system_settings_form($form);
}
/**
* hook_form() を実装する。
* フォームを定義する。
* @param node 編集の場合、すでに node は保存済みのためインスタンスが入る。
* @return $form フォームオブジェクトを返すと、Drupal が自動的にフォームを作成する。
*/
function hook_form(&$node) {
// $form['hid']
$hid = $node->hid ? $node->hid : variable_get(CONTENT_TYPE . '_option', 1);
$form['title'] = array(
'#type' => 'textfield',
'#title' => t('Title'),
'#default_value' => $node->title,
'#weight' => -8,
'#required' => TRUE,
);
$form['hid'] = array(
'#type' => 'select',
'#title' => t(MODULE_NAME . ' hid value'),
'#options' => array('1'=>'A', '2'=>'B', '3'=>'C', '4'=>'D', '5'=>'E'),
'#default_value' => $hid,
'#weight' => -6,
'#required' => TRUE
);
// full description / body
$form['body_filter']['body'] = array(
'#type' => 'textarea',
'#title' => t('Body'),
'#rows' => 4,
'#default_value' => $node->body,
'#weight' => -5,
'#required' => TRUE
);
$form['body_filter']['format'] = filter_form($node->format);
return $form;
}
/**
* hook_view() を実装する。
* フォームで保存した値を表示する。
* @param &$node 表示するオブジェクト
* @param $teaser boolean: teaser かフルノードか?
* @param $page boolean: 自身のページを表示するか?
*/
function hook_view(&$node, $teaser = FALSE, $page = FALSE) {
$node = node_prepare($node, $teaser);
$node->content['title'] = array(
'#value' => theme(CONTENT_TYPE . '_title', $node->title),
'#weight' => -8
);
$node->content['hid'] = array(
'#value' => theme(CONTENT_TYPE . '_hid', $node->hid),
'#weight' => -6
);
$node->content['body'] = array(
'#value' => theme(CONTENT_TYPE . '_body', $node->body),
'#weight' => -4
);
return $node;
}
/**
* hook_insert() を実装する。
* フォームで、コンテンツの新規作成から submit ボタンを押したときに呼び出される。
* node に対する基本情報は Drupal が自動的に保存するから、ここでは自分で
* 用意したフィールドに値を保存してあげればよい。
* ただし node の ID である nid が拠り所となっている(リレーションを張っている)
* ので、自身の用意したテーブルにもプライマリキーとしての nid が必要である。
*/
function hook_insert($node) {
db_query(
'INSERT INTO {' . CONTENT_TYPE . '} (`nid`, `hid`) VALUES ( %d, %d )',
$node->nid, $node->hid
);
}
/**
* hook_update() を実装する。
* フォームで、編集から submit ボタンを押したときに呼び出される。
*/
function hook_update($node) {
db_query('UPDATE {' . CONTENT_TYPE . '} set `hid`=%d WHERE nid=%d', $node->hid, $node->nid);
}
/**
* hook_delete() を実装する。
* フォームで、削除ボタンを押したときに呼び出される。
*/
function hook_delete(&$node) {
db_query('DELETE FROM {' . CONTENT_TYPE . '} WHERE `nid`=%d', $node->nid);
}
/**
* hook_load() を実装する。
* Drupal でコンテンツを扱うとき、node というコンテンツの最小単位を基本として、
* あなたのモジュールで扱いたい情報はあなたが用意した別テーブルにあなたが
* 自分で保存する(hook_insert、hook_update)。
* Drupal ではコンテンツ最初単位である node の情報は自動的に処理するものの、
* Drupal があなたのモジュールの扱う情報を表示したりする場合は、
* node との差分情報をどのテーブルのどのフィールドにデータが入っているかを
* あなた自身が Drupal に教えてあげる必要がある。その実装となる関数がコレ。
*/
function hook_load($node) {
$r = db_fetch_object(
db_query('SELECT `hid` FROM {' . CONTENT_TYPE . '} WHERE nid=%d', $node->nid)
);
return $r;
}
/**
* hook_validate() を実装する。
* hook_insert や hook_update が実行される前に呼び出される。
* フォームに入力されてこちらのモジュールに送られてきた値が正しいかどうか
* この関数を実装することによってチェックすることができる。
*/
function hook_validate($form_id, $form_values) {
// dump the form validate variables
//print '<code>' . print_r($form_values, true); exit();
}
/**
* theme_hook_title() を実装する。
* title を表示するときのスタイルシートへの関連付け。
*/
function theme_hook_title($content) {
$output .= '<div class="' . CONTENT_TYPE . '_view_title">';
$output .= t('Title:');
$output .= $content;
$output .= '</div>';
return $output;
}
/**
* theme_hook_body() を実装する。
* body を表示するときのスタイルシートへの関連付け。
*/
function theme_hook_body($content) {
$output .= '<div class="' . CONTENT_TYPE . '_view_body">';
$output .= t('Body:');
$output .= $content;
$output .= '</div>';
return $output;
}
/**
* theme_hook_hid() を実装する。
* hid を表示するときのスタイルシートへの関連付け。
*/
function theme_hook_hid($content) {
$options = array('1'=>'A', '2'=>'B', '3'=>'C', '4'=>'D', '5'=>'E');
$output .= '<div class="' . CONTENT_TYPE . '_view_value">';
$output .= t('hid value: %value', array('%value' => $options[$content]));
$output .= '</div>';
return $output;
}
?>
トラックバック URL:
https://perltips.twinkle.cc/trackback/197