第 6 章 システムの実現方法
6.5 追加または編集したプログラムファイル
6.5.7 locallib.php に追加
6.5.7.1att_take_page_paramsクラスに追加
class att_take_page_params {
~中略~
public $roomrows;//この行を追加 public $roomcols;//この行を追加
~中略~
public function init() {
if (!isset($this->group)) { $this->group = 0;
}
if (!isset($this->sort)) {
$this->sort = ATT_SORT_LASTNAME;
}
$this->init_view_mode();
$this->init_gridcols();
$this->init_roomrows();//この行を追加 $this->init_roomcols();//この行を追加 }
~中略~
private function init_roomrows() {//このメソッドを追加 if (isset($this->roomrows)) {
set_user_preference("attendance_roomrows", $this->roomrows);
} else {
$this->roomrows = get_user_preferences("attendance_roomrows", 10);
} }
private function init_roomcols() {//このメソッドを追加 if (isset($this->roomcols)) {
set_user_preference("attendance_roomcolumns", $this->roomcols);
} else {
$this->roomcols = get_user_preferences("attendance_roomcolumns", 10);
} }
~中略~
} 図 6-46 att_take_page_paramsクラスの追加した部分
111
図 6-46のクラスのインスタンスはtake.php、showseat.php、decideroom.phpの中で作 成され、インスタンスのメンバー変数にはPOSTやGETから取得された値が格納され る。そしてインスタンスはattendanceのコンストラクタへ渡されattendanceクラスのイ ンスタンスのメンバー変数へ格納される。さらにattendanceクラスのインスタンスは別の クラスのインスタンスへ渡され、最終的にatt_take_page_paramsクラスのインスタンスは
take.php、showseat.php、decideroom.phpの画面を作成するメソッドに渡される。
図 6-46クラスのメンバー変数はtake.php、showseat.php、decideroom.phpの画面を作 成する際のパラメータとして利用される。
3行目に追加した変数はdecideroom.phpの画面の行数を選択するセレクトボックスの デフォルト値として利用される。この変数の値は同画面に表示するチェックボックスの表 の行数になる。
4行目に追加した変数はdecideroom.phpの画面の列数を選択するセレクトボックスの デフォルト値として利用される。この変数の値同画面に表示するチェックボックスの表の 列数になる。
112 6.5.7.2 attendanceクラスに追加
6.5.3にもurl_***という名前のメソッドが複数あり、各phpファイルへのurlを返す。
そしてこれらのメソッドの本体はlocallib.phpのattendanceクラスの中のurl_***メソッド である。
各***.phpファイルのページに遷移する時に必要なurlを返すメソッドである。
url_showseatメソッドはshowseat.phpへの、url_decideroomメソッドは
decideroom.phpへのurlを返す。変数$paramsはmoodle_urlメソッドに渡すurlクエリパ
ラメータを格納する。2行目と6行目ではurlクエリパラメータにidパラメータを追加し ている。idパラメータはmoodleのどのコースかを表す。
public function url_showseat($params=array()) {
$params = array_merge(array('id' => $this->cm->id), $params);
return new moodle_url('/mod/attendance/showseat.php', $params);
}
public function url_decideroom($params=array()) {
$params = array_merge(array('id' => $this->cm->id), $params);
return new moodle_url('/mod/attendance/decideroom.php', $params);
}
図 6-47 attendanceクラスの追加した部分
113 6.5.7.3 add_sessionsメソッドへ追加
public function add_sessions($sessions) { global $DB;
foreach ($sessions as $sess) {
$sess->attendanceid = $this->id;
$sess->id = $DB->insert_record('attendance_sessions', $sess);
$description = file_save_draft_area_files($sess->descriptionitemid, $this->context->id, 'mod_attendance', 'session', $sess->id, array('subdirs' => false, 'maxfiles' => -1, 'maxbytes' => 0), $sess->description);
$DB->set_field('attendance_sessions', 'description', $description, array('id' =>
$sess->id));
$info_array = array();
$info_array[] = construct_session_full_date_time(>sessdate,
$sess->duration);
// Trigger a session added event.
$event = \mod_attendance\event\session_added::create(array(
'objectid' => $this->id, 'context' => $this->context,
'other' => array('info' => implode(',', $info_array)) ));
$event->add_record_snapshot('course_modules', $this->cm);
$sess->description = $description;
$sess->lasttaken = 0;
$sess->lasttakenby = 0;
$sess->studentscanmark = 0;
$sess->studentsmarkmyseat = 0;//追加した行
$event->add_record_snapshot('attendance_sessions', $sess);
$event->trigger();
} }
図 6-48 add_sessionsメソッド
114
add_sessionsメソッドは追加するセッションの情報を受け取り、データベースの
attendance_sessionsテーブルに追加するセッションのレコードを挿入するためのメソッド
である。
渡される変数$sessionsは配列であり、追加するセッションの情報がセッションごとに配 列の要素となっている。
foreach文では配列$sessionsから要素を1つずつ取り出し$sessに代入しているので、
foreach文の中の処理は追加するセッション1つずつに対しての処理となる。
7行目でinsert_recordメソッドを使って$attendance_sessionsテーブルにレコードを挿
入している。
115 6.5.7.4 take_from_student_byseatメソッドを追加
図 6-49のメソッドは学生が送信した座席位置をattendance_seatテーブルに保存する機 能を持つ。また、
4行目から8行目ではオブジェクト型の変数$seatのメンバー変数にセッションのidと 学生のユーザーid、学生の座っている座席の前からの列数、右からの列数を格納してい る。
11行目からのif文ではattendance_seatテーブルにデータを保存する処理が書かれて いる。
public function take_from_student_byseat($mformdata) { global $DB, $USER;
~中略~
$seat = new stdClass(); //この行を追加 $seat->sessionid = $mformdata->sessid; //この行を追加 $seat->studentid = $USER->id; //この行を追加 $seat->seatrow = $mformdata->row; //この行を追加 $seat->seatcol = $mformdata->column; //この行を追加
$dbsesslog = $this->get_session_log($mformdata->sessid);
if (array_key_exists($record->studentid, $dbsesslog)) { $DB->update_record('attendance_seat', $seat, false);
return false;
} else {
$DB->insert_record('attendance_seat', $seat, false);
}
~中略~
return true;
}
図 6-49 take_from_student_byseatメソッド
116 6.5.7.5 take_from_form_data_byseatメソッドを追加
(a) 前半部分
public function take_from_form_data_byseat($formdata,$users) { global $DB, $USER;
$sessid = $this->pageparams->sessionid;
$seatlog = $DB->get_records('attendance_seat',array('sessionid' => $sessid));
$seatexistlog = $DB->get_records('attendance_seatexist',array('sessionid' =>
$sessid));
$seatvacantlog = $DB->get_records('attendance_seatvacant',array('sessionid' =>
$sessid));
foreach($seatlog as $slog){
$wisw['user'.$slog->studentid] = $slog->seatrow.':'.$slog->seatcol;
}
foreach($seatvacantlog as $vlog){
$wisw[] = $vlog->seatvacantrow.':'.$vlog->seatvacantcol;
}
$count = array_count_values($wisw);
$attend = $wisw;
$absence = $wisw;
foreach($count as $seat => $dnum){
if($dnum > 1){
while(array_search($seat, $attend) !== false){
$key = array_search($seat, $attend);
unset($attend[$key]);
}
} else {//absence list
while(array_search($seat, $absence) !== false){
$key = array_search($seat, $absence);
unset($absence[$key]);
} } }
117 (b) 中間部分前半
foreach($seatexistlog as $elog){
$seatexist[] = $elog->seatexistrow.':'.$elog->seatexistcol;
}
$attendtmp = array_intersect($attend, $seatexist);
$tmp = array_diff($attend, $seatexist);
$absence = array_merge($absence, $tmp);
$attend = $attendtmp;
$formdata = (array)$formdata;
$formdata = array_merge($fromdata, $wisw);
$attstatus = array_keys( (array)$this->get_statuses() );
$statuses = implode(',', array_keys( (array)$this->get_statuses() ));
$now = time();
$sesslog = array();
foreach ($attend as $key => $value) { if (substr($key, 0, 4) == 'user') { $sid = substr($key, 4);
if (!(is_numeric($sid) )) {
print_error('nonnumericid', 'attendance');
}
$sesslog[$sid] = new stdClass();
$sesslog[$sid]->studentid = $sid;
$sesslog[$sid]->statusid = $attstatus[0];
$sesslog[$sid]->statusset = $statuses;
$sesslog[$sid]->remarks = array_key_exists('remarks'.$sid,
$formdata) ? clean_param($formdata['remarks'.$sid], PARAM_TEXT) : '';
$sesslog[$sid]->sessionid = $this->pageparams->sessionid;
$sesslog[$sid]->timetaken = $now;
$sesslog[$sid]->takenby = $USER->id;
} }
118 (c)中間部分後半 foreach ($absence as $key => $value) {
if (substr($key, 0, 4) == 'user') { $sid = substr($key, 4);
if (!(is_numeric($sid) )) {
print_error('nonnumericid', 'attendance');
}
$sesslog[$sid] = new stdClass();
$sesslog[$sid]->studentid = $sid;
$sesslog[$sid]->statusid = $attstatus[3];
$sesslog[$sid]->statusset = $statuses;
$sesslog[$sid]->remarks = array_key_exists('remarks'.$sid,
$formdata) ? clean_param($formdata['remarks'.$sid], PARAM_TEXT) : '';
$sesslog[$sid]->sessionid = $this->pageparams->sessionid;
$sesslog[$sid]->timetaken = $now;
$sesslog[$sid]->takenby = $USER->id;
} }
$dbsesslog = $this->get_session_log($this->pageparams->sessionid);
foreach ($sesslog as $log) { if ($log->statusid) {
if (array_key_exists($log->studentid, $dbsesslog)) { $log->id = $dbsesslog[$log->studentid]->id;
$DB->update_record('attendance_log', $log);
} else {
$DB->insert_record('attendance_log', $log, false);
} } }
119
図 6-50のメソッドはtake.phpの画面の「座席情報を元に出欠をとる」チェックボック スをチェックして「出欠を保存する」ボタンを押した場合に呼び出されるメソッドであ る。このメソッドでは、学生の送信した座席位置同士が重なっていないか、学生が送信し た座席位置が教室の範囲に収まっているか、教員が記録した空席の位置に座っていると送 信した学生はいないかをチェックする。もし、複数の学生が同じ座席に座っていると送信 した場合や、教室の範囲に収まっていない座席を送信した場合や、空席だと記録したはず の座席に座っていると送信した学生は欠席と登録され、そうでない座席位置に座っている と送信した学生は出席と登録される。
take.phpはセッションの出席登録を行う画面を表示するので、このメソッドはある1つ
のセッションの出席登録の処理に関わるものである。
5行目では学生の送信した座席位置の情報を$seatlogに格納している。
6行目では教室に存在する座席位置の情報を$seatexistlogに格納している。
7行目では空席だと記録された座席の位置の情報を$seatvacantlogに格納している。
9行目のforeach文では、配列$wiswのキーに学生一人ひとりのidを、要素にその学生
が送信した前からの列数と右からの列数を間に「:」を挟み文字列結合している。
12行目のforeach文では、配列$wiswに空席と記録された座席の前からの列数と右か らの列数を間に「:」を挟み文字列結合したものを1席ずつ要素として格納している。
$session = $this->get_session_info($this->pageparams->sessionid);
$session->lasttaken = $now;
$session->lasttakenby = $USER->id;
$DB->update_record('attendance_sessions', $session);
~中略~
redirect($this->url_manage(), get_string('attendancesuccess', 'attendance'));
}
(d) 後半部分
図 6-50 take_from_form_data_byseatメソッド
120 6.5.7.6 checkseat_from_form_dataメソッドを追加
図 6-51のメソッドは空席記録画面で選んだ座席の位置をattendance_seatvacantテーブ ルに保存するメソッドである。
23行目付近のinsert_recordメソッドでテーブルにレコードを挿入している。
public function checkseat_from_form_data($formdata) { global $DB, $USER;
$formdata = (array)$formdata;
$seatcheck = array();
$snum = array();
foreach ($formdata as $key => $value) { if (substr($key, 0, 4) == 'seat') { $snum = substr($key, 4);
$snumber = explode(":", $snum);
$seatvacantrow = $snumber[0];
$seatvacantcol = $snumber[1];
$seatvacantlog[$snum] = new stdClass();
$seatvacantlog[$snum]->sessionid = $this->pageparams->sessionid;
$seatvacantlog[$snum]->seatvacantrow = $seatvacantrow;
$seatvacantlog[$snum]->seatvacantcol = $seatvacantcol;
} }
$sessid = $this->pageparams->sessionid;
$DB->delete_records('attendance_seatvacant', array('sessionid'=>$sessid));
foreach ($seatvacantlog as $log) {
$DB->insert_record('attendance_seatvacant', $log, false);
}
redirect($this->url_manage(), OK);
}
図 6-51 checkseat_from_form_dataメソッド
121 6.5.7.7 decideroom_from_form_dataメソッドを追加
public function decideroom_from_form_data($formdata) { global $DB, $USER;
$formdata = (array)$formdata;
$seatcheck = array();
foreach ($formdata as $key => $value) { if (substr($key, 0, 4) == 'seat') {
$snum = substr($key, 4); //seat num $seatcheck[] = $value;
} }
$count = array_count_values($seatcheck);
foreach ($count as $key => $value) { for($i=1; $i<=$value; $i++){
$seatexistrow = $key;
$seatexistcol = $i;
$seatexist[$key.':'.$i] = new stdClass();
$seatexist[$key.':'.$i]->sessionid = $this->pageparams->sessionid;
$seatexist[$key.':'.$i]->seatexistrow = $seatexistrow;
$seatexist[$key.':'.$i]->seatexistcol = $seatexistcol;
} }
$sessid = $this->pageparams->sessionid;
$DB->delete_records('attendance_seatexist', array('sessionid'=>$sessid));
foreach ($seatexist as $log) {
$DB->insert_record('attendance_seatexist', $log, false);
}
~中略~
redirect($this->url_manage(), OK);
}
図 6-52 decideroom_from_form_dataメソッド
122 6.5.7.8 get_seatexist_logメソッドを追加
図 6-53のメソッドは作成した教室データを取り出すためのメソッドである。
3行目ではセッションのsessionidを取得し$sessionidへ格納している。
4行目ではattendance_seatexistテーブルからsessionidフィールドの値が変数
$sessionidの値と同じレコードをすべて取得している。取得したレコードの中身は変数
$sessに格納する。
public function get_seatexist_log(){
global $DB;
$sessionid = $this->pageparams->sessionid;
$sess = $DB->get_records('attendance_seatexist', array('sessionid' => $sessionid));
return $sess;
}
図 6-53 get_seatexist_logメソッド
123 6.5.7.9 get_seat_logメソッドを追加
図 6-54のメソッドはあるセッションの学生が送信したすべての座席位置情報を取得す るメソッドである。
座席表画面で学生の名前を学生の送信した座席位置に表示するために、学生の座席位置 を取得する必要がある。取得したデータは座席表画面を表示するために使われる。
public functionget_seat_log(){
global $DB;
$sessionid = $this->pageparams->sessionid;
$sess = $DB->get_records('attendance_seat', array('sessionid' => $sessionid));
return $sess;
}
図 6-54 get_seat_logメソッド
124
6.5.7.10 get_user_filtered_sessions_log_extendedメソッドへの追加
(a) 前半部分
public function get_user_filtered_sessions_log_extended($userid) { global $DB;
// All taked sessions (including previous groups).
if ($this->pageparams->startdate && $this->pageparams->enddate) { $where = "ats.attendanceid = :aid AND ats.sessdate >= :csdate AND ats.sessdate >= :sdate AND ats.sessdate < :edate";
} else {
$where = "ats.attendanceid = :aid AND ats.sessdate >= :csdate";
}
$id = $DB->sql_concat(':value', 'ats.id');
if ($this->get_group_mode()) {
$sql = "SELECT $id, ats.id, ats.groupid, ats.sessdate, ats.duration,
ats.description, al.statusid, al.remarks, ats.studentscanmark, ats.studentsmarkmyseat FROM {attendance_sessions} ats
RIGHT JOIN {attendance_log} al
ON ats.id = al.sessionid AND al.studentid = :uid
LEFT JOIN {groups_members} gm ON gm.userid = al.studentid AND gm.groupid = ats.groupid
WHERE $where AND (ats.groupid = 0 or gm.id is NOT NULL) ORDER BY ats.sessdate ASC";
} else {
$sql = "SELECT $id, ats.id, ats.groupid, ats.sessdate, ats.duration,
ats.description, al.statusid, al.remarks, ats.studentscanmark, ats.studentsmarkmyseat FROM {attendance_sessions} ats
RIGHT JOIN {attendance_log} al
ON ats.id = al.sessionid AND al.studentid = :uid WHERE $where
ORDER BY ats.sessdate ASC";
}
125 (b) 中間部分 $params = array(
'uid' => $userid, 'aid' => $this->id,
'csdate' => $this->course->startdate, 'sdate' => $this->pageparams->startdate, 'edate' => $this->pageparams->enddate, 'value' => 'c');
$sessions = $DB->get_records_sql($sql, $params);
// All sessions for current groups.
$groups = array_keys(groups_get_all_groups($this->course->id, $userid));
$groups[] = 0;
list($gsql, $gparams) = $DB->get_in_or_equal($groups, SQL_PARAMS_NAMED, 'gid0');
if ($this->pageparams->startdate && $this->pageparams->enddate) { $where = "ats.attendanceid = :aid AND ats.sessdate >= :csdate AND ats.sessdate >= :sdate AND ats.sessdate < :edate AND ats.groupid $gsql";
} else {
$where = "ats.attendanceid = :aid AND ats.sessdate >= :csdate AND ats.groupid $gsql";
}
$sql = "SELECT $id, ats.id, ats.groupid, ats.sessdate, ats.duration, ats.description, al.statusid, al.remarks, ats.studentscanmark, ats.studentsmarkmyseat
FROM {attendance_sessions} ats LEFT JOIN {attendance_log} al
ON ats.id = al.sessionid AND al.studentid = :uid WHERE $where
126
get_user_filtered_sessions_log_extendedメソッドはattendance_user_dataクラスのコン ストラクタの中で呼び出される。attendance_user_dataクラスのインスタンスはview.php の中で作成される。view.phpファイルは学生や教員がある学生の出席状況を見る画面を表 示するファイルである。view.phpの中でattendance_user_dataクラスのインスタンスが作 成され、作成されたインスタンスはMoodleのrenderメソッド(16)に渡される。その 後、attendance_user_dataクラスのメンバー変数がrenderer.phpのメソッドに渡され、あ る学生の出席状況を見る画面を作成する。
図 6-55のメソッドは学生の出席状況を見る画面を作成するためにある学生に関連する セッションの情報を同じ出欠モジュールからすべて集めてattendance_user_dataクラスの コンストラクタへ返す。このメソッドはattendance_user_dataクラスのコンストラクタ内 で呼び出された後、attendance_user_dataクラスのメンバーである変数$sessionslogへ値を 返す。
改造前のセッションには座席位置を用いた出席管理機能がなかったため、
attendance_sessionsテーブルにもその情報の記録がなかった。しかし、改造後は
attendance_sessionsにセッション毎に「座席位置を用いた出席管理が可能かどうか」を記
録する。また本システムにおいてview.phpは学生ユーザーから見ると出席状況やセッショ ORDER BY ats.sessdate ASC";
$params = array_merge($params, $gparams);
$sessions = array_merge($sessions, $DB->get_records_sql($sql, $params));
foreach ($sessions as $sess) {
if (empty($sess->description)) {
$sess->description = get_string('nodescription', 'attendance');
} else {
$sess->description =
file_rewrite_pluginfile_urls($sess->description,
'pluginfile.php', $this->context->id, 'mod_attendance', 'session', $sess->id);
} }
return $sessions;
}
(c) 後半部分
図 6-55 get_user_filtered_sessions_log_extendedメソッド