get_records('autoattend_sessions', array('courseid'=>$courseid), $sort); } else { $params = array('courseid'=>$courseid, 'classid'=>$classid); if ($inall) { $select = 'courseid=:courseid AND (classid=:classid OR classid=0)'; $sessions = $DB->get_records_select('autoattend_sessions', $select, $params, $sort); } else { $sessions = $DB->get_records('autoattend_sessions', $params, $sort); } } return $sessions; } // // // function autoattend_count_sessions($courseid, $classid) { global $DB; $select = "courseid=$courseid AND state<>'N' AND (classid=$classid OR classid=0)"; $sescount = $DB->count_records_select('autoattend_sessions', $select); if (!$sescount) $sescount = 0; return $sescount; } ///////////////////////////////////////////////////////////////////////////////////////////// // // Students // // // クラスに属する学生を得る. // $classid==0 の場合は全クラスに属する学生を帰す. // function autoattend_get_attend_students($courseid, $classid=0, $context=null, $sort='') { $students = array(); if (!$courseid) return $students; if (!$context) $context = get_context_instance(CONTEXT_COURSE, $courseid); $users = jbxl_get_course_students($context, $sort); if ($users) { foreach ($users as $user) { $classinfo = autoattend_get_user_class($user->id, $courseid); if ($classinfo->classid>=0 and (($classinfo->classid==$classid or $classid==0) or ($classid==NON_CLASSID and $classinfo->classid==0))) { $students[$user->id] = new stdClass(); $students[$user->id]->id = $user->id; $students[$user->id]->firstname = $user->firstname; $students[$user->id]->lastname = $user->lastname; $students[$user->id]->idnumber = $user->idnumber; $students[$user->id]->fullname = fullname($user); $students[$user->id]->classid = $classinfo->classid; $students[$user->id]->classname = $classinfo->name; $students[$user->id]->user = $user; } } } return $students; } // // クラスに属する学生の人数を得る. // $classid==0 の場合は全クラスに属する学生を帰す. // function autoattend_count_attend_students($courseid, $classid=0, $context=null) { if (!$courseid) return 0; if (!$context) $context = get_context_instance(CONTEXT_COURSE, $courseid); $count = 0; $users = jbxl_get_course_students($context, ''); if ($users) { foreach ($users as $user) { $classinfo = autoattend_get_user_class($user->id, $courseid, true); if ($classinfo->classid>=0 and (($classinfo->classid==$classid or $classid==0) or ($classid==NON_CLASSID and $classinfo->classid==0))) { $count++; } } } return $count; } // // 条件を指定して,出席レコードを用いて学生の数を数える. // // ただし,出席レコードの存在する学生のみ (つまり,statusがYの学生はカウントされない可能性がある) // 出席レコードの存在しない学生も正確にカウントしたい場合は autoattend_count_attend_students() を用いる. // また,欠席から除外された学生はカウントされない. // // クラスを指定する場合は $session->classid にクラスIDを設定する. // // 出席(含む遅刻,早退)した学生の数: $select = "status<>'Y' AND status<>'X'" // function autoattend_count_class_students($session, $courseid, $context, $select='') { global $DB; if (empty($select)) $select = 'attsid=?'; else $select = 'attsid=? AND '.$select; $count = 0; $users = $DB->get_records_select('autoattend_students', $select, array($session->id)); if ($users) { foreach ($users as $user) { $classinfo = autoattend_get_user_class($user->studentid, $courseid, true); if ($classinfo->classid>=0) { if ($classinfo->classid==$session->classid or $session->classid==0) $count++; } } } return $count; } ///////////////////////////////////////////////////////////////////////////////////////////// // // Class // // // // 講義のクラスをDB上に作成 // function autoattend_insert_session_class($courseid, $classname) { global $DB, $USER; $rec = new stdClass(); $rec->name = $classname; $rec->courseid = $courseid; $rec->creator = $USER->id; $rec->timemodified = time(); return $DB->insert_record('autoattend_classes', $rec); } // // 講義のクラス情報(名前)を更新 または削除 // function autoattend_update_session_classes(array $classids, array $classnames, array $classdels) { global $DB, $USER; foreach ($classids as $key=>$classid) { if (isset($classdels[$key])) { $DB->delete_records('autoattend_classes', array('id'=>$classid)); } else { $rec = $DB->get_record('autoattend_classes', array('id'=>$classid)); if (strcmp($rec->name, $classnames[$key])) { $rec->name = $classnames[$key]; $rec->creator = $USER->id; $rec->timemodified = time(); $DB->update_record('autoattend_classes', $rec); } } } } // // 学生の所属するクラスの情報を取得 // idonly: class id のみを取得する.高速化用. // function autoattend_get_user_class($userid, $courseid, $idonly=false) { global $DB; $class = $DB->get_record('autoattend_classifies', array('courseid'=>$courseid, 'studentid'=>$userid)); if (!$class) { $class = new stdClass(); $class->id = 0; $class->courseid = $courseid; $class->studentid = $userid; $class->classid = 0; } if (!$idonly) $class->name = autoattend_get_user_classname($class->classid); return $class; } // // 講義の全クラスの情報を取得 // function autoattend_get_session_classes($courseid) { global $DB; $results = $DB->get_records('autoattend_classes', array('courseid'=>$courseid), 'id'); $classes = array(); /* $classes[0] = new stdClass(); $classes[0]->id = 0; $classes[0]->courseid = $courseid; $classes[0]->creator = 0; $classes[0]->name = get_string('allstudents', 'block_autoattend'); $classes[0]->timemodified = time(); */ if ($results) { foreach($results as $result) { $classes[$result->id] = $result; } } return $classes; } // // 学生の所属するクラスの名前を取得 // function autoattend_get_user_classname($classid) { global $DB; if ($classid==0) return get_string('nonclass', 'block_autoattend'); else if ($classid==-1) return get_string('exclusion', 'block_autoattend'); $class = $DB->get_record('autoattend_classes', array('id'=>$classid)); if (!$class) return get_string('unknownclass', 'block_autoattend'); return $class->name; } // // 講義のクラス名を取得 // function autoattend_get_session_classname($classid) { global $DB; if ($classid==0) return get_string('allstudents', 'block_autoattend'); $class = $DB->get_record('autoattend_classes', array('id'=>$classid)); if (!$class) return get_string('unknownclass', 'block_autoattend'); return $class->name; } // // 講義のクラスの選択ボックスを表示する. // function autoattend_select_session_class($classid, $classes, $url, $url_options) { global $OUTPUT; if ($classes) { $popupurl = $url.$url_options; // $options = array(); $options[0] = get_string('allclasses', 'block_autoattend'); if ($classes) { foreach ($classes as $class) { $options[$class->id] = $class->name; } } // echo $OUTPUT->single_select($popupurl, 'class', $options, $classid); } } // // ユーザクラスの選択ボックスを表示する. // function autoattend_select_user_class($classid, $classes, $url, $url_options, $show_ex=false) { global $OUTPUT; if ($classes or $show_ex) { $popupurl = $url.$url_options; // $options = array(); $options[0] = get_string('allclasses', 'block_autoattend'); if ($classes) { $options[NON_CLASSID] = get_string('nonclass', 'block_autoattend'); foreach ($classes as $class) { $options[$class->id] = $class->name; } } if ($show_ex) $options[-1] = get_string('excludedstudents', 'block_autoattend'); // echo $OUTPUT->single_select($popupurl, 'class', $options, $classid); } } function autoattend_select_attend($attend, $url, $url_options) { global $OUTPUT; $popupurl = $url.$url_options; // $options = array(); $options['A'] = get_string('Aacronymfull', 'block_autoattend'); $options['P'] = get_string('Pacronymfull', 'block_autoattend'); $options['L'] = get_string('Lacronymfull', 'block_autoattend'); $options['E'] = get_string('Eacronymfull', 'block_autoattend'); $options['X'] = get_string('Xacronymfull', 'block_autoattend'); $options['Y'] = get_string('Yacronymfull', 'block_autoattend'); $options['Z'] = get_string('Zacronymfull', 'block_autoattend'); // echo $OUTPUT->single_select($popupurl, 'attend', $options, $attend); } ///////////////////////////////////////////////////////////////////////////////////////////// // // Grade // // // 評定の点数設定を得る // function autoattend_get_grade_settings($courseid) { global $DB; $result= $DB->get_records('autoattend_settings', array('courseid'=>$courseid), 'id'); if (!$result) { $result = $DB->get_records('autoattend_settings', array('courseid'=>0), 'id'); // use default } $settings = array(); foreach ($result as $res) { $settings[$res->status] = $res; } return $settings; } // // 評定の点数設定を更新する // function autoattend_update_grade_settings($courseid, array $grades, $restore=0) { global $DB; if (empty($courseid)) $courseid = 0; //restore defaults if ($restore) { if ($courseid!=0) { $DB->delete_records('autoattend_settings', array('courseid'=>$courseid)); } // restore default grades unset($grades); $grades['P'] = 2; $grades['L'] = 1; $grades['E'] = 1; $grades['X'] = 0; $grades['Y'] = 0; $courseid = 0; } if (!$grades) return; // $status = array('P','L','E','X','Y'); for ($i=0; $iget_record('autoattend_settings', array('courseid'=>$courseid, 'status'=>$status[$i]))) { $update = true; } else { $rec = new stdClass(); $rec->classid = 0; $update = false; } $rec->courseid = $courseid; $rec->status = $status[$i]; $rec->grade = $grades[$status[$i]]; if ($update) { $result = $DB->update_record('autoattend_settings', $rec); if (!$result) break; } else { $result = $DB->insert_record('autoattend_settings', $rec); if (!$result) break; } unset($rec); } } // // 評定を更新する // autoattendmod が必要 // function autoattend_update_grades($courseid) { global $CFG, $DB; if (file_exists($CFG->dirroot.'/mod/autoattendmod/lib.php')) { require_once($CFG->dirroot.'/mod/autoattendmod/lib.php'); if (function_exists('autoattendmod_update_grades')) { $mod = $DB->get_record('autoattendmod', array('course'=>$courseid)); if ($mod) { $mod->cmidnumber = ''; autoattendmod_update_grades($mod); } } } } // // 出席や欠席の回数を返す // $status に 'P', 'L', 'E', 'X', 'Y' を指定する // function autoattend_get_status_num($userid, $courseid, $status) { global $CFG, $DB; $classinfo = autoattend_get_user_class($userid, $courseid); $qry = "SELECT COUNT(*) AS cnt FROM {$CFG->prefix}autoattend_students std ,{$CFG->prefix}autoattend_sessions ses". " WHERE std.attsid = ses.id AND ses.courseid = ".$courseid ." AND std.studentid = ".$userid. " AND std.status = '".$status."' AND (ses.classid = ".$classinfo->classid." OR ses.classid = 0)"; //print "QUERY=> $qry
"; $data = $DB->get_record_sql($qry); return $data->cnt; } // // 出席点を返す // function autoattend_get_grade($userid, $courseid) { $settings = autoattend_get_grade_settings($courseid); $grade = 0; foreach ($settings as $setting) { $count = autoattend_get_status_num($userid, $courseid, $setting->status); $grade = $grade + $count * $setting->grade; } return $grade; } ///////////////////////////////////////////////////////////////////////////////////////////// // // Summary // // // 学生のサマリーを返す // // $summary['userid'] : ユーザID // $summary['courseid'] : コースID // $summary['attitems'] : 学生の各授業のRawデータ(配列) // $summary['settings'] : 出席点の配分Rawデータ(配列) // $summary['complete'] : 出席コマ数(早退,遅刻を含む) // $summary['grade'] : 出席点 // $summary['percent'] : 出席率(出席点ベース) // $summary['P'] : 正常出席数 // $summary['X'] : 欠席数.クローズしたセッションで Y の物を含む. // $summary['L'] : 遅刻数 // $summary['E'] : 早退数 // $summary['Y'] : 未了数.ただしクローズしたセッションは X とする. // $summary['classid'] : クラスID // $summary['classname']: クラス名 // $summary['maxgrade'] : 最高出席点(皆勤の場合の出席点) // $summary['mingrade'] : 最低出席点(全欠の場合の出席点) // $summary['leccount'] : 実施した授業のコマ数 // function autoattend_get_user_summary($userid, $courseid) { global $CFG, $DB; require_once('jbxl/jbxl_moodle_tools.php'); $ntime = time(); $class = autoattend_get_user_class($userid, $courseid); $stqry = "SELECT * FROM {$CFG->prefix}autoattend_students std". " RIGHT JOIN (SELECT * FROM {$CFG->prefix}autoattend_sessions WHERE courseid=$courseid) ses". " ON ses.id=std.attsid AND std.studentid=$userid AND (ses.classid=".$class->classid." OR ses.classid=0)". " ORDER BY ses.sessdate, ses.starttime ASC"; $attitems = $DB->get_records_sql($stqry); if (!$attitems) return false; $summary = array(); $summary['userid'] = $userid; $summary['courseid'] = $courseid; $summary['attitems'] = $attitems; $complete = 0; if ($attitems) { foreach($attitems as $att) { if (!empty($att->status) && $att->status!='Y') $complete++; } } $summary['complete'] = $complete; // 出席コマ数(早退,遅刻を含む) $summary['settings'] = autoattend_get_grade_settings($courseid); $maxgrade = 0; $mingrade = 0; foreach($summary['settings'] as $set) { $summary[$set->status] = 0; foreach($summary['attitems'] as $att) { if ($set->status==$att->status) { // 出席の状態をカウント if ($att->status=='Y') { if ($ntime>$att->endtime) $summary['X']++; else $summary['Y']++; } else { $summary[$set->status]++; } } } if ($set->grade>$maxgrade) $maxgrade = $set->grade; if ($set->grade<$mingrade) $mingrade = $set->grade; } $sessnum = autoattend_count_sessions($courseid, $class->classid); // $summary['grade'] = autoattend_get_grade($userid, $courseid); $summary['maxgrade'] = $maxgrade*$sessnum; $summary['mingrade'] = $mingrade*$sessnum; $summary['leccount'] = $sessnum; // $gradelevel = $summary['maxgrade'] - $summary['mingrade']; if ($gradelevel!=0) { $percent = 100*($summary['grade']-$summary['mingrade'])/$gradelevel; $summary['percent'] = sprintf('%0.1f', $percent); } else { $summary['percent'] = ' - '; } $summary['classid'] = $class->classid; $summary['classname']= $class->name; return $summary; } // // 授業の全クラスのサマリーを返す // // $summary['courseid'] : コースID // $summary['attitems'] : 各授業のRawデータ(配列) // $summary['classes'] : クラスデータ(配列) // $summary['settings'] : 出席点の配分Rawデータ(配列) // $summary['maxgrade'] : 実施された授業での最高出席点(皆勤の場合の出席点) // $summary['mingrade'] : 実施された授業での最低出席点(全欠場合の出席点) // $summary['leccount'] : 実施された授業のコマ数 // function autoattend_get_session_summary($courseid) { global $DB; require_once('jbxl/jbxl_moodle_tools.php'); $attitems = $DB->get_records('autoattend_sessions', array('courseid'=>$courseid), 'starttime'); if (!$attitems) return false; $summary = array(); $summary['courseid'] = $courseid; $summary['attitems'] = $attitems; $summary['settings'] = autoattend_get_grade_settings($courseid); $summary['classes'] = autoattend_get_session_classes($courseid); // $attpoint = 0; $abspoint = 0; foreach($summary['settings'] as $set) { if ($set->grade>$attpoint) $attpoint = $set->grade; if ($set->grade<$abspoint) $abspoint = $set->grade; } $leccount = 0; if (!$summary['classes']) { $summary['classes'][0] = new stdClass(); $summary['classes'][0]->id = 0; $summary['classes'][0]->courseid = $courseid; $summary['classes'][0]->creator = 0; $summary['classes'][0]->name = get_string('allstudents', 'block_autoattend'); $summary['classes'][0]->timemodified = time(); } // クラスによってコマ数が違う場合 foreach ($summary['classes'] as $class) { $count = 0; foreach ($attitems as $att) { if ($att->state<>'N' and ($att->classid==$class->id or $att->classid==0)) $count++; } if ($count>$leccount) $leccount = $count; } $summary['maxgrade'] = $attpoint*$leccount; $summary['mingrade'] = $abspoint*$leccount; $summary['leccount'] = $leccount; return $summary; } ///////////////////////////////////////////////////////////////////////////////////////////// // // View and Print // function autoattend_print_user_row($left, $right) { echo "\n$left $right\n"; } // // 1ユーザの出欠レポートを表示する // function autoattend_print_user($user, $course, $printing=null) { global $CFG, $USER, $OUTPUT, $TIME_OFFSET; $wwwBlock = $CFG->wwwroot.'/blocks/autoattend'; $wwwGrade = $CFG->wwwroot.'/grade/report/user'; $wwwUser = $CFG->wwwroot.'/user'; $courseid = $course->id; $userid = $user->id; $context = get_context_instance(CONTEXT_COURSE, $courseid); $isteacher = jbxl_is_teacher($USER->id, $context); $summary = autoattend_get_user_summary($user->id, $courseid); if(!$summary) { notice(get_string('attendnotstarted','block_autoattend'), $CFG->wwwroot.'/course/view.php?id='.$courseid); } else { $complete = $summary['complete']; $percent = $summary['percent'].' %'; $grade = $summary['grade']; $maxgrade = $summary['maxgrade']; $settings = $summary['settings']; $classid = $summary['classid']; $classname = $summary['classname']; // include('print_user_header.html'); // if ($classid>=0) { // !出欠から除外 // $table = new html_table(); // Header $table->head [] = '#'; $table->align[] = 'right'; $table->size [] = '20px'; $table->wrap [] = 'nowrap'; $table->head [] = get_string('date'); $table->align[] = 'center'; $table->size [] = '40px'; $table->wrap [] = 'nowrap'; $table->head [] = get_string('starttime', 'block_autoattend'); $table->align[] = 'center'; $table->size [] = '60px'; $table->wrap [] = 'nowrap'; $table->head [] = get_string('endtime', 'block_autoattend'); $table->align[] = 'center'; $table->size [] = '60px'; $table->wrap [] = 'nowrap'; $table->head [] = get_string('classname', 'block_autoattend'); $table->align[] = 'center'; $table->size [] = '40px'; $table->wrap [] = 'nowrap'; $table->head [] = get_string('description','block_autoattend'); $table->align[] = 'center'; $table->size [] = '40px'; $table->wrap [] = 'nowrap'; $table->head [] = get_string('status', 'block_autoattend'); $table->align[] = 'center'; $table->size [] = '40px'; $table->wrap [] = 'nowrap'; $table->head [] = get_string('callmethod', 'block_autoattend'); $table->align[] = 'center'; $table->size [] = '60px'; $table->wrap [] = 'nowrap'; $table->head [] = get_string('calledtime', 'block_autoattend'); $table->align[] = 'center'; $table->size [] = '60px'; $table->wrap [] = 'nowrap'; $table->head [] = get_string('ip', 'block_autoattend'); $table->align[] = 'center'; $table->size [] = '80px'; $table->wrap [] = 'nowrap'; $table->head [] = get_string('remarks', 'block_autoattend'); $table->align[] = 'center'; $table->size [] = '120px'; $table->wrap [] = 'nowrap'; $i = 0; foreach($summary['attitems'] as $att) { if ($att->classid==$classid or $att->classid==0) { $table->data[$i][] = $i + 1; $table->data[$i][] = strftime(get_string('strftimedmyw', 'block_autoattend'), $att->sessdate + $TIME_OFFSET); $table->data[$i][] = strftime(get_string('strftimehourmin','block_autoattend'), $att->starttime + $TIME_OFFSET); $table->data[$i][] = strftime(get_string('strftimehourmin','block_autoattend'), $att->endtime + $TIME_OFFSET); $table->data[$i][] = autoattend_get_user_classname($att->classid); $table->data[$i][] = $att->description ? $att->description: get_string('nodescription', 'block_autoattend'); if ($att->studentid) { if ($att->status=='Y') { if (time()>$att->endtime) { $table->data[$i][] = get_string('Xacronymfull','block_autoattend'); } else { $table->data[$i][] = get_string('novalue', 'block_autoattend'); } } else { $table->data[$i][] = get_string($att->status.'acronymfull','block_autoattend'); } $table->data[$i][] = get_string($att->called.'methodfull', 'block_autoattend'); } else { $table->data[$i][] = get_string('novalue', 'block_autoattend'); $table->data[$i][] = get_string('novalue', 'block_autoattend'); } // if (!$att->studentid OR $att->status==='X' OR $att->status==='Y') { $table->data[$i][] = get_string('novalue', 'block_autoattend');; } else { $sessndate = strftime(get_string('strftimedmshort', 'block_autoattend'), $att->sessdate + $TIME_OFFSET); $calleddate = strftime(get_string('strftimedmshort', 'block_autoattend'), $att->calledtime + $TIME_OFFSET); $calledtime = strftime(get_string('strftimehmshort', 'block_autoattend'), $att->calledtime + $TIME_OFFSET); //$table->data[$i][] = strftime(get_string('strftimecalled', 'block_autoattend'), $att->calledtime + $TIME_OFFSET); if ($sessndate===$calleddate) { //$table->data[$i][] = '
'.$calledtime.'
'; $table->data[$i][] = $calledtime; } else { //$table->data[$i][] = '
'.$calledtime.' ('.$calleddate.')
'; $table->data[$i][] = $calledtime.' ('.$calleddate.')'; } } // $ipaddr = $att->ipaddress ? $att->ipaddress : get_string('novalue', 'block_autoattend'); if ($ipaddr) { //$ipurl = jbxl_get_ipresolv_url($ipaddr); $ipurl = autoattend_get_ipresolv_url($ipaddr); if ($ipurl) $table->data[$i][] = "$ipaddr"; else $table->data[$i][] = $ipaddr; } else { $table->data[$i][] = get_string('novalue', 'block_autoattend'); } $table->data[$i][] = $att->remarks; $i++; } } echo '
'; //echo '
'; echo html_writer::table($table); echo '
'; } // echo ''; echo ''; echo ''; echo '
'; } return; } ///////////////////////////////////////////////////////////////////////////////////////////// // // データのダウンロード Excel or Text // function autoattend_download($format, $courseid, $classes='', $classid=0, $viewmode='all', $starttm=0, $attsid='all') { global $CFG, $DB, $TIME_OFFSET; $excellib_version = 0; if (file_exists ($CFG->dirroot.'/lib/excellib.class.php')) { $excellib_version = 2; $tocode = 'utf-8'; require_once($CFG->dirroot.'/lib/excellib.class.php'); } else { $excellib_version = 1; $tocode = 'sjis-win'; require_once($CFG->dirroot.'/lib/excel/Worksheet.php'); require_once($CFG->dirroot.'/lib/excel/Workbook.php'); } // $indclass = ''; $indsess = ''; $indperiod = ''; if ($classid!=0) $indclass = ' AND (classid='.$classid.' OR classid=0)'; if ($attsid!='all') $indsess = ' AND id='.$attsid; if ($viewmode!='all') { if ($starttm==0) $starttm = time(); if ($viewmode==='weeks') { $indperiod = " AND sessdate >= $starttm AND sessdate < ".($starttm + ONE_WEEK); } elseif ($viewmode==='months') { $nxtmon = mktime(0, 0, 0, date('m', $starttm+$TIME_OFFSET)+1, 1, date('Y', $starttm+$TIME_OFFSET)) - $TIME_OFFSET; $indperiod = " AND sessdate >= $starttm AND sessdate < ".$nxtmon; } } // Only Closed Session $qry = "SELECT * FROM {$CFG->prefix}autoattend_sessions where courseid=".$courseid.$indsess.$indclass.$indperiod. " AND state='C' ORDER BY sessdate, starttime ASC"; // $downloadfilename = autoattend_to_localcode(get_string('autoattend', 'block_autoattend'), $tocode); if ($format==='xls') { header("Content-type: application/vnd.ms-excel"); header("Content-Disposition: attachment; filename=\"$downloadfilename.xls\""); /// Creating a workbook if ($excellib_version==2) { $workbook = new MoodleExcelWorkbook('-', 'Excel5'); $workbook->send($downloadfilename); } else { $workbook = new Workbook('-'); } $myxls = $workbook->add_worksheet('attendance'); //define column heading $i = 0; if ($CFG->fullnamedisplay=='lastname firstname') { $myxls->write_string(0, $i++, autoattend_to_localcode(get_string('lastname'), $tocode)); $myxls->write_string(0, $i++, autoattend_to_localcode(get_string('firstname'), $tocode)); $sort = 'lastname'; } else { $myxls->write_string(0, $i++, autoattend_to_localcode(get_string('firstname'), $tocode)); $myxls->write_string(0, $i++, autoattend_to_localcode(get_string('lastname'), $tocode)); $sort = 'firstname'; } if ($CFG->output_idnumber) $myxls->write_string(0, $i++, autoattend_to_localcode('ID', $tocode)); if ($classes) $myxls->write_string(0, $i++, autoattend_to_localcode(get_string('classname', 'block_autoattend'), $tocode)); $myxls->write_string(0, $i++, autoattend_to_localcode(get_string('Cstatefull', 'block_autoattend'), $tocode)); $myxls->write_string(0, $i++, autoattend_to_localcode(get_string('Pacronymfull', 'block_autoattend'), $tocode)); $myxls->write_string(0, $i++, autoattend_to_localcode(get_string('Xacronymfull', 'block_autoattend'), $tocode)); $myxls->write_string(0, $i++, autoattend_to_localcode(get_string('Lacronymfull', 'block_autoattend'), $tocode)); $myxls->write_string(0, $i++, autoattend_to_localcode(get_string('Eacronymfull', 'block_autoattend'), $tocode)); $myxls->write_string(0, $i++, autoattend_to_localcode(get_string('attendpercent','block_autoattend'), $tocode)); $myxls->write_string(0, $i++, autoattend_to_localcode(get_string('attendgrade', 'block_autoattend'), $tocode)); $courseses = array(); if ($sess = $DB->get_records_sql($qry)) { foreach($sess as $id=>$dsess) { $date = strftime(get_string('strftimedmshort','block_autoattend'), $dsess->sessdate); $myxls->write_string(0, $i++, autoattend_to_localcode($date, $tocode)); $courseses[] = $dsess->id; } } /// Print all the lines of data. $i = 1; $j = 0; $context = get_context_instance(CONTEXT_COURSE, $courseid); $students = autoattend_get_attend_students($courseid, $classid, $context, $sort); foreach ($students as $student) { $j = 0; $summary = autoattend_get_user_summary($student->id, $courseid); if ($CFG->fullnamedisplay == 'lastname firstname') { $myxls->write_string($i, $j++, autoattend_to_localcode($student->lastname, $tocode)); $myxls->write_string($i, $j++, autoattend_to_localcode($student->firstname, $tocode)); } else { $myxls->write_string($i, $j++, autoattend_to_localcode($student->firstname, $tocode)); $myxls->write_string($i, $j++, autoattend_to_localcode($student->lastname, $tocode)); } if ($CFG->output_idnumber) { if (empty($student->idnumber)) $idnumber = '-'; else $idnumber = $student->idnumber; $myxls->write_string($i, $j++, autoattend_to_localcode($idnumber, $tocode)); } if ($classes) $myxls->write_string($i, $j++, autoattend_to_localcode($summary['classname'], $tocode)); $myxls->write_number($i, $j++, $summary['complete']); $myxls->write_number($i, $j++, $summary['P']); $myxls->write_number($i, $j++, $summary['X']); $myxls->write_number($i, $j++, $summary['L']); $myxls->write_number($i, $j++, $summary['E']); $myxls->write_number($i, $j++, $summary['percent']); $myxls->write_number($i, $j++, $summary['grade']); foreach ($courseses as $sid) { if ($rec = $DB->get_record('autoattend_students', array('attsid'=>$sid, 'studentid'=>$student->id))) { $desc = autoattend_to_localcode(get_string($rec->status.'acronymfull','block_autoattend'), $tocode); $myxls->write_string($i, $j++ , $desc); } else { $myxls->write_string($i, $j++, '-'); } } $i++; } $workbook->close(); } // else if ($format==='txt') { header("Content-Type: application/download\n"); header("Content-Disposition: attachment; filename=\"$downloadfilename.txt\""); /// Print names of all the fields if ($CFG->fullnamedisplay == 'lastname firstname') { echo autoattend_to_localcode(get_string('lastname'), $tocode)."\t"; echo autoattend_to_localcode(get_string('firstname'), $tocode)."\t"; $sort = 'lastname'; } else { echo autoattend_to_localcode(get_string('firstname'), $tocode)."\t"; echo autoattend_to_localcode(get_string('lastname'), $tocode)."\t"; $sort = 'firstname'; } if ($CFG->output_idnumber) echo autoattend_to_localcode('ID', $tocode)."\t"; if ($classes) echo autoattend_to_localcode(get_string('classname', 'block_autoattend'), $tocode)."\t"; echo autoattend_to_localcode(get_string('Cstatefull', 'block_autoattend'), $tocode)."\t"; echo autoattend_to_localcode(get_string('Pacronymfull', 'block_autoattend'), $tocode)."\t"; echo autoattend_to_localcode(get_string('Xacronymfull', 'block_autoattend'), $tocode)."\t"; echo autoattend_to_localcode(get_string('Lacronymfull', 'block_autoattend'), $tocode)."\t"; echo autoattend_to_localcode(get_string('Eacronymfull', 'block_autoattend'), $tocode)."\t"; echo autoattend_to_localcode(get_string('attendpercent','block_autoattend'), $tocode)."\t"; echo autoattend_to_localcode(get_string('attendgrade', 'block_autoattend'), $tocode)."\t"; $courseses = array(); if ($sess = $DB->get_records_sql($qry)) { foreach($sess as $id=>$dsess) { echo strftime(get_string('strftimedmshort','block_autoattend'), $dsess->sessdate)."\t"; $courseses[] = $dsess->id; } echo "\r\n"; } $context = get_context_instance(CONTEXT_COURSE, $courseid); $students = autoattend_get_attend_students($courseid, $classid, $context, $sort); foreach($students as $student) { $summary = autoattend_get_user_summary($student->id, $courseid); $settings = $summary['settings']; if ($CFG->fullnamedisplay == 'lastname firstname') { echo autoattend_to_localcode($student->lastname, $tocode)."\t"; echo autoattend_to_localcode($student->firstname, $tocode)."\t"; } else { echo autoattend_to_localcode($student->firstname, $tocode)."\t"; echo autoattend_to_localcode($student->lastname, $tocode)."\t"; } if ($CFG->output_idnumber) { if (empty($student->idnumber)) $idnumber = '-'; else $idnumber = $student->idnumber; echo autoattend_to_localcode($idnumber, $tocode)."\t"; } if ($classes) echo autoattend_to_localcode($summary['classname'], $tocode)."\t"; echo $summary['complete']."\t"; echo $summary['P']."\t"; echo $summary['X']."\t"; echo $summary['L']."\t"; echo $summary['E']."\t"; echo $summary['percent']."\t"; echo $summary['grade']."\t"; foreach ($courseses as $sid) { if ($rec = $DB->get_record('autoattend_students', array('attsid'=>$sid, 'studentid'=>$student->id))) { echo autoattend_to_localcode(get_string($rec->status.'acronymfull', 'block_autoattend'), $tocode)."\t"; } else { echo "-\t"; } } echo "\r\n"; } } exit(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // for Automatic Attendance // // // 指定した条件で,現在出席をとっている授業の情報を返す. // // ex.) $sessions = autoattend_get_nowopen_sessions($courseid, 'S', 'O', $ntime); // function autoattend_get_nowopen_sessions($courseid, $method, $state, $checktime) { $sesss = autoattend_update_sessions_users($courseid, $checktime); $sesss = autoattend_update_sessions_state($sesss, $checktime); $sessions = array(); foreach($sesss as $sess) { if ($checktime>=$sess->starttime and $checktime<=$sess->endtime and $method==$sess->method and $state==$sess->state) { $sessions[] = $sess; } } return $sessions; } // // 指定した授業で,指定した評価を得たユーザ(複数)の情報を返す. // $statuss は評価の配列(例:array('Y','P','X'))または評価の文字(例:'Y') // または指定しない 指定しない場合は全ての評価を指定したことになる. // function autoattend_get_users_bystatus($sessid, $statuss='') { global $CFG, $DB; // $status = ''; if (is_array($statuss)) { $substs = implode("' OR status='", $statuss); if (!empty($substs)) $status = " AND ( status='".$substs."' )"; } else { if (!empty($statuss)) $status = " AND status='".$statuss."' "; } $qry = "SELECT * FROM {$CFG->prefix}autoattend_students WHERE attsid=".$sessid." ".$status." ORDER BY studentid ASC"; //print "QUERY = $qry
"; $return = array(); $users = $DB->get_records_sql($qry); if ($users) { foreach($users as $user) { $return[$user->studentid] = new stdClass(); $return[$user->studentid]->id = $user->id; $return[$user->studentid]->attsid = $user->attsid; $return[$user->studentid]->studentid = $user->studentid; $return[$user->studentid]->status = $user->status; $return[$user->studentid]->called = $user->called; $return[$user->studentid]->calledby = $user->calledby; $return[$user->studentid]->calledtime = $user->calledtime; $return[$user->studentid]->remarks = $user->remarks; $return[$user->studentid]->ipaddress = $user->ipaddress; } } return $return; } // // 指定した授業での,指定したユーザの情報を返す. // function autoattend_get_user_atsession($sessid, $userid) { global $CFG, $DB; $qry = "SELECT * FROM {$CFG->prefix}autoattend_students WHERE attsid=".$sessid." AND studentid=".$userid; //print "QUERY = $qry
"; $return = null; $users = $DB->get_records_sql($qry); if ($users) { foreach ($users as $user) { $return = new stdClass(); $return->id = $user->id; $return->attsid = $user->attsid; $return->studentid = $user->studentid; $return->status = $user->status; $return->called = $user->called; $return->calledby = $user->calledby; $return->calledtime = $user->calledtime; $return->remarks = $user->remarks; $return->ipaddress = $user->ipaddress; break; } } return $return; } // // クローズしている時刻であるが,まだクローズしていない授業の情報を返す.. // $methods はデフォルトの点呼方法の配列(例:array('A','S')または点呼方法の文字(例:'S') // または指定なし.指定しない場合は全ての方法を指定したことになる. // また,現在授業中ものも含めて返す場合は $incopen を true にする. // function autoattend_get_unclosed_sessions($courseid, $methods='', $ntime='', $incopen=false) { global $CFG, $DB; $method = ''; if (is_array($methods)) { $submth = implode("' OR method='", $methods); if (!empty($submth)) $method = " AND ( method='".$submth."' )"; } else { if (!empty($methods)) $method = " AND method='".$methods."' "; } if (empty($ntime)) $ntime = time(); if ($incopen) $ctime = 'starttime'; else $ctime = 'endtime'; $qry = "SELECT * FROM {$CFG->prefix}autoattend_sessions ". " WHERE courseid=".$courseid." AND state<>'C'".$method." AND (".$ctime.")<='".$ntime."' ". " ORDER BY sessdate, starttime ASC"; //print "QUERY = $qry
"; $return = array(); $sesss = $DB->get_records_sql($qry); if ($sesss) { foreach($sesss as $sess) { $return[$sess->id] = new stdClass(); $return[$sess->id]->id = $sess->id; $return[$sess->id]->courseid = $sess->courseid; $return[$sess->id]->classid = $sess->classid; $return[$sess->id]->sessdate = $sess->sessdate; $return[$sess->id]->starttime = $sess->starttime; $return[$sess->id]->endtime = $sess->endtime; $return[$sess->id]->latetime = $sess->latetime; $return[$sess->id]->method = $sess->method; $return[$sess->id]->attendkey = $sess->attendkey; $return[$sess->id]->denysameip = $sess->denysameip; $return[$sess->id]->allowip = $sess->allowip; $return[$sess->id]->description = $sess->description; $return[$sess->id]->state = $sess->state; } } return $return; } // // 学生用の授業用データレコードの追加 // function autoattend_add_user_insession($sessid, $userid) { global $DB; $rec = new stdClass(); $rec->attsid = $sessid; $rec->studentid = $userid; $rec->status = 'Y'; $rec->ipaddress = ''; $result = $DB->insert_record('autoattend_students', $rec); return $result; } // // 指定された授業の学生データをリセットする. // function autoattend_reset_session_user($courseid, $sessid) { global $DB; $context = get_context_instance(CONTEXT_COURSE, $courseid); $stdnts = jbxl_get_course_students($context); foreach($stdnts as $stdnt) { $user = autoattend_get_user_atsession($sessid, $stdnt->id); if (empty($user)) { autoattend_add_user_insession($sessid, $stdnt->id); } // else { $rec = new stdClass(); $rec->id = $user->id; $rec->attsid = $user->attsid; $rec->studentid = $user->studentid; $rec->status = 'Y'; $rec->called = 'D'; $rec->calledby = 0; $rec->calledtime = 0; $rec->remarks = ''; $rec->ipaddress = ''; // $DB->update_record('autoattend_students', $rec); unset($rec); } } return; } // // 指定されたセッションに対して,学生(s)の登録状態を最新の状態に更新する. // セッションデータを返す. // function autoattend_update_session_users($courseid, $sessid, $ntime='') { global $DB; if ($sessid<=0) return null; if (empty($ntime)) $ntime = time(); $sess = $DB->get_record('autoattend_sessions', array('id'=>$sessid)); if (!$sess) return null; $context = get_context_instance(CONTEXT_COURSE, $courseid); $stdnts = jbxl_get_course_students($context); if ($sess->state!='C' and $ntime>$sess->starttime) { foreach($stdnts as $stdnt) { $user = autoattend_get_user_atsession($sess->id, $stdnt->id); if (empty($user)) { autoattend_add_user_insession($sess->id, $stdnt->id); } } } return $sess; } // // コースの全セッションに大して,学生(s)の登録状態を最新の状態に更新する. // コースの全セッションデータを返す. // function autoattend_update_sessions_users($courseid, $ntime='') { if (empty($ntime)) $ntime = time(); $sesss = autoattend_get_unclosed_sessions($courseid, '', $ntime, true); $context = get_context_instance(CONTEXT_COURSE, $courseid); $stdnts = jbxl_get_course_students($context); foreach($sesss as $sess) { foreach($stdnts as $stdnt) { $user = autoattend_get_user_atsession($sess->id, $stdnt->id); if (empty($user)) { autoattend_add_user_insession($sess->id, $stdnt->id); } } } return $sesss; } // // 指定された授業(セッション)の点呼状態を最新の状態に更新する. // function autoattend_update_session_state($sess, $ntime='', $close=false) { global $DB; if (empty($ntime)) $ntime = time(); if (!empty($sess)) { // if ($ntime>$sess->endtime) { if ($close) $state = 'C'; else $state = 'O'; // Close 処理しない } else if ($ntime>=$sess->starttime and $ntime<=$sess->endtime) { $state = 'O'; } else { $state = 'N'; } $rec = new stdClass(); $rec->id = $sess->id; $rec->state = $state; $DB->update_record('autoattend_sessions', $rec); unset($rec); $sess->state = $state; } return $sess; } // // コースの全授業(セッション)の点呼状態を最新の状態に更新する. // function autoattend_update_sessions_state($sesss, $ntime='', $close=false) { global $DB; if (empty($ntime)) $ntime = time(); if (!empty($sesss) and is_array($sesss)) { foreach($sesss as $key=>$sess) { // $sesss[$key]->prv_state = $sesss[$key]->state; if ($ntime>$sess->endtime) { if ($close) $state = 'C'; else $state = 'O'; // Close 処理しない } else if ($ntime>=$sess->starttime and $ntime<=$sess->endtime) { $state = 'O'; } else { $state = 'N'; } $rec = new stdClass(); $rec->id = $sess->id; $rec->state = $state; $DB->update_record('autoattend_sessions', $rec); unset($rec); $sesss[$key]->state = $state; } } return $sesss; } // // 指定されたセッションのデータを最新の状態に更新する // function autoattend_update_session($courseid, $sessid, $ntime='') { global $USER; if ($sessid<=0) return false; if (empty($ntime)) $ntime = time(); $sess = autoattend_update_session_users($courseid, $sessid, $ntime); // 学生の授業レコードを登録 $sess = autoattend_update_session_state($sess, $ntime, true); // 授業の状態を更新 if ($sess) { // if ($sess->method=='A') { // 自動処理 $logs = autoattend_get_courselogs($courseid, $sess->starttime, $sess->endtime); autoattend_complete_autoattend($logs, $sess, $ntime); } else if ($sess->method=='S') { // 半自動モードの授業で終了したものをクローズ autoattend_close_semiautoattend($sess, $ntime); } // autoattend_update_grades($courseid); return true; } return false; } // // 指定されたコースの全てのデータを最新の状態に更新する // function autoattend_update_sessions($courseid, $ntime='') { global $USER; if (empty($ntime)) $ntime = time(); $sesss = autoattend_update_sessions_users($courseid, $ntime); // 学生の授業レコードを登録 $sesss = autoattend_update_sessions_state($sesss, $ntime, true); // 授業の状態を更新 if ($sesss) { $getlog = false; $etime = 0; $stime = $ntime; foreach($sesss as $sess) { if ($ntime>$sess->starttime and $sess->prv_state!='C') { if ($stime>$sess->starttime) $stime = $sess->starttime; if ($etime<$sess->endtime) $etime = $sess->endtime; if ($sess->method=='A') $getlog = true; } } if ($getlog) $logs = autoattend_get_courselogs($courseid, $stime, $etime); else $logs = ''; // foreach($sesss as $sess) { if ($ntime>$sess->starttime and $sess->prv_state!='C') { if ($sess->method=='A') { // 自動処理 autoattend_complete_autoattend($logs, $sess, $ntime); } else if ($sess->method=='S') { // 半自動モードの授業で終了したものをクローズ autoattend_close_semiautoattend($sess, $ntime); } } } // autoattend_update_grades($courseid); return true; } // autoattend_update_grades($courseid); return false; } // // 自動モードの処理 // function autoattend_complete_autoattend($logs, $sess, $ntime='') { global $DB; $users = autoattend_get_users_bystatus($sess->id, 'Y'); if ($users) { if (empty($ntime)) $ntime = time(); $attsid = $sess->id; $stime = $sess->starttime; $etime = $sess->endtime; $ltime = $sess->latetime; $allowip = $sess->allowip; $difipf = $sess->denysameip; $ipfmts = jbxl_to_subnetformats($allowip); $used_ips = autoattend_get_usedips($attsid); $sesslogs = array(); if (!empty($logs)) { foreach($logs as $log) { $logtime = $log->time; if ($logtime>=$stime and $logtime<=$etime) $sesslogs[] = $log; } } foreach($users as $user) { $status = 'X'; $match_ip = ''; $match_tm = 0; $err_mesg = ''; $userlogs = array(); if (!empty($sesslogs)) { foreach($sesslogs as $log) { if ($log->userid==$user->studentid) $userlogs[] = $log; } } $rec = new stdClass(); $rec->ipaddress = ''; // if (!empty($userlogs)) { $valid_log = autoattend_check_valid_logip($userlogs, $ipfmts, $used_ips, $difipf); if (!empty($valid_log)) { if (isset($valid_log['ip'])) $match_ip = $valid_log['ip']; if (isset($valid_log['time'])) $match_tm = $valid_log['time']; if (isset($valid_log['error'])) $err_mesg = $valid_log['error']; } if (!empty($match_ip)) { $status = 'P'; if ($difipf) $used_ips[] = $match_ip; if ($ltime!=0) { if ($match_tm > $stime + $ltime) $status = 'L'; } $rec->ipaddress = $match_ip; } } // ここで,$status は X, P, L のいずれか. //print "state = {$sess->state} status = $status
"; if ($sess->state=='C' or $status!='X') { // if ($match_tm!=0) $calledtime = $match_tm; else $calledtime = $ntime; $rec->id = $user->id; $rec->attsid = $sess->id; $rec->studentid = $user->studentid; $rec->status = $status; $rec->called = 'A'; $rec->calledby = CALLED_BY_AUTO; $rec->calledtime = $calledtime; $rec->remarks = $user->remarks; $result = $DB->update_record('autoattend_students', $rec); /* if ($result) { $mdluser = $DB->get_record('user', array('id'=>$user->studentid)); $loginfo = AUTO_SUBMIT_LOG.',id='.$sess->id.',userid='.$user->studentid.',user='.fullname($mdluser).',status='.$status; //add_to_log($sess->courseid, 'autoattend', 'submit autoattend', '', $loginfo); } */ } // if ($err_mesg) { $mdluser = $DB->get_record('user', array('id'=>$user->studentid)); $loginfo = AUTO_SUBMIT_LOG.',id='.$sess->id.',userid='.$user->studentid.',user='.fullname($mdluser).',Error('.$err_mesg.')'; add_to_log($sess->courseid, 'autoattend', 'submit autoattend', '', $loginfo); } unset($rec); } } } // // 半自動モードのクローズ処理 // function autoattend_close_semiautoattend($sess, $ntime='') { global $DB; if ($sess->state=='C') { $users = autoattend_get_users_bystatus($sess->id, 'Y'); if ($users) { if (empty($ntime)) $ntime = time(); foreach($users as $user) { $rec = new stdClass(); $rec->id = $user->id; $rec->attsid = $sess->id; $rec->studentid = $user->studentid; $rec->status = 'X'; $rec->called = 'S'; $rec->calledby = CALLED_BY_SEMIAUTO; $rec->calledtime = $ntime; $rec->remarks = $user->remarks; $rec->ipaddress = $user->ipaddress; // $DB->update_record('autoattend_students', $rec); unset($rec); } } } } // // 自動出欠モードでの学生の出欠を未了状態に戻す. // function autoattend_return_to_Y($sessid) { global $DB; $students = $DB->get_records('autoattend_students', array('attsid'=>$sessid)); if ($students) { foreach ($students as $student) { if ($student->called=='A') { $student->status = 'Y'; $student->ipaddress = ''; $student->calledbya = 0; $DB->update_record('autoattend_students', $student); } } } return; } // // logの中から許可されたフォーマット ipfmts に一致するIPを探す // ただしdifipf が trueの場合,配列 userd_ipsに含まれるIPは一致から除外する. // function autoattend_check_valid_logip($userlogs, $ipfmts, $used_ips, $difipf) { $return = array(); if (empty($userlogs)) return $return; $err_mesg = ''; foreach($userlogs as $log) { $chkip = $log->ip; if (empty($ipfmts) or jbxl_match_ipaddr($chkip, $ipfmts)) { $chkip_f = true; if ($difipf and !empty($used_ips)) { foreach($used_ips as $used_ip) { // 同一IPチェック if ($chkip==$used_ip) { $chkip_f = false; if (!empty($err_mesg)) $err_mesg.= ','; $err_mesg.= 'already:'.$chkip; break; } } } if ($chkip_f) { $return['ip'] = $chkip; $return['time'] = $log->time; $return['userid'] = $log->userid; return $return; } } else { if (!empty($err_mesg)) $err_mesg.= ','; $err_mesg.= 'notmatch:'.$chkip; } } if ($err_mesg) $return['error'] = $err_mesg; return $return; } // // 半自動モードに於いて接続IPの検査を行う. // function autoattend_check_invalid_semiautoip($att) { $ipaddr = getremoteaddr(); $allowip = $att->allowip; $difipf = $att->denysameip; $iperrmesg = ''; $ipfmts = jbxl_to_subnetformats($allowip); if (empty($ipfmts) or jbxl_match_ipaddr($ipaddr, $ipfmts)) { if ($difipf) { $used_ips = autoattend_get_usedips($att->id); if ($used_ips) { foreach($used_ips as $used_ip) { if ($ipaddr==$used_ip) { $iperrmesg = get_string('sameusedip', 'block_autoattend').' '.$ipaddr; break; } } } } } else { $iperrmesg = get_string('mismatchip', 'block_autoattend').' '.$ipaddr; } return $iperrmesg; } // // 既に取られた出席からIPを取り出す // function autoattend_get_usedips($attsid) { global $DB; $results = $DB->get_records('autoattend_students', array('attsid'=>$attsid)); $ips = array(); foreach ($results as $result) { $ips[] = $result->ipaddress; } return $ips; } // // 指定したコースの $stime から $etime までのログを得る // function autoattend_get_courselogs($courseid, $stime, $etime=0) { global $CFG, $DB; $return = array(); $ntime = time(); $where = 'WHERE course='.$courseid; if ($etime<=0) $etime = $ntime; $where.= ' AND time>='.$stime.' AND time<='.$etime; $where.= " AND (action='view' OR action='review') ORDER BY time ASC"; $qry = "SELECT * FROM {$CFG->prefix}log ".$where; //print "QUERY = $qry
"; $logs = $DB->get_records_sql($qry); return $logs; } /* // // 指定したコースの過去 $day日のログを得る // function autoattend_get_courselogs_pastdays($courseid, $day=0) { global $CFG, $DB; $return = array(); $where = 'WHERE course='.$courseid; if ($day>0) { $lmtdy = time() - $day*ONE_DAY; $where.= ' AND time>'.$lmtdy; } $where.= " AND (action='view' OR action='review') ORDER BY time ASC"; $qry = "SELECT * FROM {$CFG->prefix}log ".$where; //print "QUERY = $qry
"; $logs = $DB->get_records_sql($qry); return $logs; } */ ///////////////////////////////////////////////////////////////////////////////////////////// // // function autoattend_get_ipresolv_url($ip) { global $CFG; if (!preg_match('/(^\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $ip, $match)) return ''; if ($match[1]>255 or $match[2]>255 or $match[3]>255 or $match[4]>255) return ''; if ($match[1]=='127' or $match[1]=='10') return ''; if ($match[1]=='172' and $match[2]>='16' and $match[2]<='31') return ''; if ($match[1]=='192' and $match[2]=='168') return ''; if (!empty($CFG->ipresolv_url)) $url = sprintf($CFG->ipresolv_url, $ip); else $url = sprintf(get_string('ipresolv_url','block_autoattend'), $ip); return $url; }