|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00027 defined('MOODLE_INTERNAL') || die; 00028 00029 require_once($CFG->libdir.'/completionlib.php'); 00030 require_once($CFG->libdir.'/filelib.php'); 00031 00032 define('COURSE_MAX_LOGS_PER_PAGE', 1000); // records 00033 define('COURSE_MAX_RECENT_PERIOD', 172800); // Two days, in seconds 00034 define('COURSE_MAX_SUMMARIES_PER_PAGE', 10); // courses 00035 define('COURSE_MAX_COURSES_PER_DROPDOWN',1000); // max courses in log dropdown before switching to optional 00036 define('COURSE_MAX_USERS_PER_DROPDOWN',1000); // max users in log dropdown before switching to optional 00037 define('FRONTPAGENEWS', '0'); 00038 define('FRONTPAGECOURSELIST', '1'); 00039 define('FRONTPAGECATEGORYNAMES', '2'); 00040 define('FRONTPAGETOPICONLY', '3'); 00041 define('FRONTPAGECATEGORYCOMBO', '4'); 00042 define('FRONTPAGECOURSELIMIT', 200); // maximum number of courses displayed on the frontpage 00043 define('EXCELROWS', 65535); 00044 define('FIRSTUSEDEXCELROW', 3); 00045 00046 define('MOD_CLASS_ACTIVITY', 0); 00047 define('MOD_CLASS_RESOURCE', 1); 00048 00049 function make_log_url($module, $url) { 00050 switch ($module) { 00051 case 'course': 00052 if (strpos($url, 'report/') === 0) { 00053 // there is only one report type, course reports are deprecated 00054 $url = "/$url"; 00055 break; 00056 } 00057 case 'file': 00058 case 'login': 00059 case 'lib': 00060 case 'admin': 00061 case 'calendar': 00062 case 'mnet course': 00063 if (strpos($url, '../') === 0) { 00064 $url = ltrim($url, '.'); 00065 } else { 00066 $url = "/course/$url"; 00067 } 00068 break; 00069 case 'user': 00070 case 'blog': 00071 $url = "/$module/$url"; 00072 break; 00073 case 'upload': 00074 $url = $url; 00075 break; 00076 case 'coursetags': 00077 $url = '/'.$url; 00078 break; 00079 case 'library': 00080 case '': 00081 $url = '/'; 00082 break; 00083 case 'message': 00084 $url = "/message/$url"; 00085 break; 00086 case 'notes': 00087 $url = "/notes/$url"; 00088 break; 00089 case 'tag': 00090 $url = "/tag/$url"; 00091 break; 00092 case 'role': 00093 $url = '/'.$url; 00094 break; 00095 default: 00096 $url = "/mod/$module/$url"; 00097 break; 00098 } 00099 00100 //now let's sanitise urls - there might be some ugly nasties:-( 00101 $parts = explode('?', $url); 00102 $script = array_shift($parts); 00103 if (strpos($script, 'http') === 0) { 00104 $script = clean_param($script, PARAM_URL); 00105 } else { 00106 $script = clean_param($script, PARAM_PATH); 00107 } 00108 00109 $query = ''; 00110 if ($parts) { 00111 $query = implode('', $parts); 00112 $query = str_replace('&', '&', $query); // both & and & are stored in db :-| 00113 $parts = explode('&', $query); 00114 $eq = urlencode('='); 00115 foreach ($parts as $key=>$part) { 00116 $part = urlencode(urldecode($part)); 00117 $part = str_replace($eq, '=', $part); 00118 $parts[$key] = $part; 00119 } 00120 $query = '?'.implode('&', $parts); 00121 } 00122 00123 return $script.$query; 00124 } 00125 00126 00127 function build_mnet_logs_array($hostid, $course, $user=0, $date=0, $order="l.time ASC", $limitfrom='', $limitnum='', 00128 $modname="", $modid=0, $modaction="", $groupid=0) { 00129 global $CFG, $DB; 00130 00131 // It is assumed that $date is the GMT time of midnight for that day, 00132 // and so the next 86400 seconds worth of logs are printed. 00133 00135 00136 // TODO: I don't understand group/context/etc. enough to be able to do 00137 // something interesting with it here 00138 // What is the context of a remote course? 00139 00142 //if ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) { 00143 // $groupid = get_current_group($course->id); 00144 //} 00146 //else if (!$course->groupmode) { 00147 // $groupid = 0; 00148 //} 00149 00150 $groupid = 0; 00151 00152 $joins = array(); 00153 $where = ''; 00154 00155 $qry = "SELECT l.*, u.firstname, u.lastname, u.picture 00156 FROM {mnet_log} l 00157 LEFT JOIN {user} u ON l.userid = u.id 00158 WHERE "; 00159 $params = array(); 00160 00161 $where .= "l.hostid = :hostid"; 00162 $params['hostid'] = $hostid; 00163 00164 // TODO: Is 1 really a magic number referring to the sitename? 00165 if ($course != SITEID || $modid != 0) { 00166 $where .= " AND l.course=:courseid"; 00167 $params['courseid'] = $course; 00168 } 00169 00170 if ($modname) { 00171 $where .= " AND l.module = :modname"; 00172 $params['modname'] = $modname; 00173 } 00174 00175 if ('site_errors' === $modid) { 00176 $where .= " AND ( l.action='error' OR l.action='infected' )"; 00177 } else if ($modid) { 00178 //TODO: This assumes that modids are the same across sites... probably 00179 //not true 00180 $where .= " AND l.cmid = :modid"; 00181 $params['modid'] = $modid; 00182 } 00183 00184 if ($modaction) { 00185 $firstletter = substr($modaction, 0, 1); 00186 if ($firstletter == '-') { 00187 $where .= " AND ".$DB->sql_like('l.action', ':modaction', false, true, true); 00188 $params['modaction'] = '%'.substr($modaction, 1).'%'; 00189 } else { 00190 $where .= " AND ".$DB->sql_like('l.action', ':modaction', false); 00191 $params['modaction'] = '%'.$modaction.'%'; 00192 } 00193 } 00194 00195 if ($user) { 00196 $where .= " AND l.userid = :user"; 00197 $params['user'] = $user; 00198 } 00199 00200 if ($date) { 00201 $enddate = $date + 86400; 00202 $where .= " AND l.time > :date AND l.time < :enddate"; 00203 $params['date'] = $date; 00204 $params['enddate'] = $enddate; 00205 } 00206 00207 $result = array(); 00208 $result['totalcount'] = $DB->count_records_sql("SELECT COUNT('x') FROM {mnet_log} l WHERE $where", $params); 00209 if(!empty($result['totalcount'])) { 00210 $where .= " ORDER BY $order"; 00211 $result['logs'] = $DB->get_records_sql("$qry $where", $params, $limitfrom, $limitnum); 00212 } else { 00213 $result['logs'] = array(); 00214 } 00215 return $result; 00216 } 00217 00218 function build_logs_array($course, $user=0, $date=0, $order="l.time ASC", $limitfrom='', $limitnum='', 00219 $modname="", $modid=0, $modaction="", $groupid=0) { 00220 global $DB, $SESSION, $USER; 00221 // It is assumed that $date is the GMT time of midnight for that day, 00222 // and so the next 86400 seconds worth of logs are printed. 00223 00225 00228 if ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) { 00229 if (isset($SESSION->currentgroup[$course->id])) { 00230 $groupid = $SESSION->currentgroup[$course->id]; 00231 } else { 00232 $groupid = groups_get_all_groups($course->id, $USER->id); 00233 if (is_array($groupid)) { 00234 $groupid = array_shift(array_keys($groupid)); 00235 $SESSION->currentgroup[$course->id] = $groupid; 00236 } else { 00237 $groupid = 0; 00238 } 00239 } 00240 } 00242 else if (!$course->groupmode) { 00243 $groupid = 0; 00244 } 00245 00246 $joins = array(); 00247 $params = array(); 00248 00249 if ($course->id != SITEID || $modid != 0) { 00250 $joins[] = "l.course = :courseid"; 00251 $params['courseid'] = $course->id; 00252 } 00253 00254 if ($modname) { 00255 $joins[] = "l.module = :modname"; 00256 $params['modname'] = $modname; 00257 } 00258 00259 if ('site_errors' === $modid) { 00260 $joins[] = "( l.action='error' OR l.action='infected' )"; 00261 } else if ($modid) { 00262 $joins[] = "l.cmid = :modid"; 00263 $params['modid'] = $modid; 00264 } 00265 00266 if ($modaction) { 00267 $firstletter = substr($modaction, 0, 1); 00268 if ($firstletter == '-') { 00269 $joins[] = $DB->sql_like('l.action', ':modaction', false, true, true); 00270 $params['modaction'] = '%'.substr($modaction, 1).'%'; 00271 } else { 00272 $joins[] = $DB->sql_like('l.action', ':modaction', false); 00273 $params['modaction'] = '%'.$modaction.'%'; 00274 } 00275 } 00276 00277 00279 if ($groupid and !$user) { 00280 if ($gusers = groups_get_members($groupid)) { 00281 $gusers = array_keys($gusers); 00282 $joins[] = 'l.userid IN (' . implode(',', $gusers) . ')'; 00283 } else { 00284 $joins[] = 'l.userid = 0'; // No users in groups, so we want something that will always be false. 00285 } 00286 } 00287 else if ($user) { 00288 $joins[] = "l.userid = :userid"; 00289 $params['userid'] = $user; 00290 } 00291 00292 if ($date) { 00293 $enddate = $date + 86400; 00294 $joins[] = "l.time > :date AND l.time < :enddate"; 00295 $params['date'] = $date; 00296 $params['enddate'] = $enddate; 00297 } 00298 00299 $selector = implode(' AND ', $joins); 00300 00301 $totalcount = 0; // Initialise 00302 $result = array(); 00303 $result['logs'] = get_logs($selector, $params, $order, $limitfrom, $limitnum, $totalcount); 00304 $result['totalcount'] = $totalcount; 00305 return $result; 00306 } 00307 00308 00309 function print_log($course, $user=0, $date=0, $order="l.time ASC", $page=0, $perpage=100, 00310 $url="", $modname="", $modid=0, $modaction="", $groupid=0) { 00311 00312 global $CFG, $DB, $OUTPUT; 00313 00314 if (!$logs = build_logs_array($course, $user, $date, $order, $page*$perpage, $perpage, 00315 $modname, $modid, $modaction, $groupid)) { 00316 echo $OUTPUT->notification("No logs found!"); 00317 echo $OUTPUT->footer(); 00318 exit; 00319 } 00320 00321 $courses = array(); 00322 00323 if ($course->id == SITEID) { 00324 $courses[0] = ''; 00325 if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname')) { 00326 foreach ($ccc as $cc) { 00327 $courses[$cc->id] = $cc->shortname; 00328 } 00329 } 00330 } else { 00331 $courses[$course->id] = $course->shortname; 00332 } 00333 00334 $totalcount = $logs['totalcount']; 00335 $count=0; 00336 $ldcache = array(); 00337 $tt = getdate(time()); 00338 $today = mktime (0, 0, 0, $tt["mon"], $tt["mday"], $tt["year"]); 00339 00340 $strftimedatetime = get_string("strftimedatetime"); 00341 00342 echo "<div class=\"info\">\n"; 00343 print_string("displayingrecords", "", $totalcount); 00344 echo "</div>\n"; 00345 00346 echo $OUTPUT->paging_bar($totalcount, $page, $perpage, "$url&perpage=$perpage"); 00347 00348 $table = new html_table(); 00349 $table->classes = array('logtable','generalbox'); 00350 $table->align = array('right', 'left', 'left'); 00351 $table->head = array( 00352 get_string('time'), 00353 get_string('ip_address'), 00354 get_string('fullnameuser'), 00355 get_string('action'), 00356 get_string('info') 00357 ); 00358 $table->data = array(); 00359 00360 if ($course->id == SITEID) { 00361 array_unshift($table->align, 'left'); 00362 array_unshift($table->head, get_string('course')); 00363 } 00364 00365 // Make sure that the logs array is an array, even it is empty, to avoid warnings from the foreach. 00366 if (empty($logs['logs'])) { 00367 $logs['logs'] = array(); 00368 } 00369 00370 foreach ($logs['logs'] as $log) { 00371 00372 if (isset($ldcache[$log->module][$log->action])) { 00373 $ld = $ldcache[$log->module][$log->action]; 00374 } else { 00375 $ld = $DB->get_record('log_display', array('module'=>$log->module, 'action'=>$log->action)); 00376 $ldcache[$log->module][$log->action] = $ld; 00377 } 00378 if ($ld && is_numeric($log->info)) { 00379 // ugly hack to make sure fullname is shown correctly 00380 if ($ld->mtable == 'user' && $ld->field == $DB->sql_concat('firstname', "' '" , 'lastname')) { 00381 $log->info = fullname($DB->get_record($ld->mtable, array('id'=>$log->info)), true); 00382 } else { 00383 $log->info = $DB->get_field($ld->mtable, $ld->field, array('id'=>$log->info)); 00384 } 00385 } 00386 00387 //Filter log->info 00388 $log->info = format_string($log->info); 00389 00390 // If $log->url has been trimmed short by the db size restriction 00391 // code in add_to_log, keep a note so we don't add a link to a broken url 00392 $tl=textlib_get_instance(); 00393 $brokenurl=($tl->strlen($log->url)==100 && $tl->substr($log->url,97)=='...'); 00394 00395 $row = array(); 00396 if ($course->id == SITEID) { 00397 if (empty($log->course)) { 00398 $row[] = get_string('site'); 00399 } else { 00400 $row[] = "<a href=\"{$CFG->wwwroot}/course/view.php?id={$log->course}\">". format_string($courses[$log->course])."</a>"; 00401 } 00402 } 00403 00404 $row[] = userdate($log->time, '%a').' '.userdate($log->time, $strftimedatetime); 00405 00406 $link = new moodle_url("/iplookup/index.php?ip=$log->ip&user=$log->userid"); 00407 $row[] = $OUTPUT->action_link($link, $log->ip, new popup_action('click', $link, 'iplookup', array('height' => 440, 'width' => 700))); 00408 00409 $row[] = html_writer::link(new moodle_url("/user/view.php?id={$log->userid}&course={$log->course}"), fullname($log, has_capability('moodle/site:viewfullnames', get_context_instance(CONTEXT_COURSE, $course->id)))); 00410 00411 $displayaction="$log->module $log->action"; 00412 if ($brokenurl) { 00413 $row[] = $displayaction; 00414 } else { 00415 $link = make_log_url($log->module,$log->url); 00416 $row[] = $OUTPUT->action_link($link, $displayaction, new popup_action('click', $link, 'fromloglive'), array('height' => 440, 'width' => 700)); 00417 } 00418 $row[] = $log->info; 00419 $table->data[] = $row; 00420 } 00421 00422 echo html_writer::table($table); 00423 echo $OUTPUT->paging_bar($totalcount, $page, $perpage, "$url&perpage=$perpage"); 00424 } 00425 00426 00427 function print_mnet_log($hostid, $course, $user=0, $date=0, $order="l.time ASC", $page=0, $perpage=100, 00428 $url="", $modname="", $modid=0, $modaction="", $groupid=0) { 00429 00430 global $CFG, $DB, $OUTPUT; 00431 00432 if (!$logs = build_mnet_logs_array($hostid, $course, $user, $date, $order, $page*$perpage, $perpage, 00433 $modname, $modid, $modaction, $groupid)) { 00434 echo $OUTPUT->notification("No logs found!"); 00435 echo $OUTPUT->footer(); 00436 exit; 00437 } 00438 00439 if ($course->id == SITEID) { 00440 $courses[0] = ''; 00441 if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname,c.visible')) { 00442 foreach ($ccc as $cc) { 00443 $courses[$cc->id] = $cc->shortname; 00444 } 00445 } 00446 } 00447 00448 $totalcount = $logs['totalcount']; 00449 $count=0; 00450 $ldcache = array(); 00451 $tt = getdate(time()); 00452 $today = mktime (0, 0, 0, $tt["mon"], $tt["mday"], $tt["year"]); 00453 00454 $strftimedatetime = get_string("strftimedatetime"); 00455 00456 echo "<div class=\"info\">\n"; 00457 print_string("displayingrecords", "", $totalcount); 00458 echo "</div>\n"; 00459 00460 echo $OUTPUT->paging_bar($totalcount, $page, $perpage, "$url&perpage=$perpage"); 00461 00462 echo "<table class=\"logtable\" cellpadding=\"3\" cellspacing=\"0\">\n"; 00463 echo "<tr>"; 00464 if ($course->id == SITEID) { 00465 echo "<th class=\"c0 header\">".get_string('course')."</th>\n"; 00466 } 00467 echo "<th class=\"c1 header\">".get_string('time')."</th>\n"; 00468 echo "<th class=\"c2 header\">".get_string('ip_address')."</th>\n"; 00469 echo "<th class=\"c3 header\">".get_string('fullnameuser')."</th>\n"; 00470 echo "<th class=\"c4 header\">".get_string('action')."</th>\n"; 00471 echo "<th class=\"c5 header\">".get_string('info')."</th>\n"; 00472 echo "</tr>\n"; 00473 00474 if (empty($logs['logs'])) { 00475 echo "</table>\n"; 00476 return; 00477 } 00478 00479 $row = 1; 00480 foreach ($logs['logs'] as $log) { 00481 00482 $log->info = $log->coursename; 00483 $row = ($row + 1) % 2; 00484 00485 if (isset($ldcache[$log->module][$log->action])) { 00486 $ld = $ldcache[$log->module][$log->action]; 00487 } else { 00488 $ld = $DB->get_record('log_display', array('module'=>$log->module, 'action'=>$log->action)); 00489 $ldcache[$log->module][$log->action] = $ld; 00490 } 00491 if (0 && $ld && !empty($log->info)) { 00492 // ugly hack to make sure fullname is shown correctly 00493 if (($ld->mtable == 'user') and ($ld->field == $DB->sql_concat('firstname', "' '" , 'lastname'))) { 00494 $log->info = fullname($DB->get_record($ld->mtable, array('id'=>$log->info)), true); 00495 } else { 00496 $log->info = $DB->get_field($ld->mtable, $ld->field, array('id'=>$log->info)); 00497 } 00498 } 00499 00500 //Filter log->info 00501 $log->info = format_string($log->info); 00502 00503 echo '<tr class="r'.$row.'">'; 00504 if ($course->id == SITEID) { 00505 $courseshortname = format_string($courses[$log->course], true, array('context' => get_context_instance(CONTEXT_COURSE, SITEID))); 00506 echo "<td class=\"r$row c0\" >\n"; 00507 echo " <a href=\"{$CFG->wwwroot}/course/view.php?id={$log->course}\">".$courseshortname."</a>\n"; 00508 echo "</td>\n"; 00509 } 00510 echo "<td class=\"r$row c1\" align=\"right\">".userdate($log->time, '%a'). 00511 ' '.userdate($log->time, $strftimedatetime)."</td>\n"; 00512 echo "<td class=\"r$row c2\" >\n"; 00513 $link = new moodle_url("/iplookup/index.php?ip=$log->ip&user=$log->userid"); 00514 echo $OUTPUT->action_link($link, $log->ip, new popup_action('click', $link, 'iplookup', array('height' => 400, 'width' => 700))); 00515 echo "</td>\n"; 00516 $fullname = fullname($log, has_capability('moodle/site:viewfullnames', get_context_instance(CONTEXT_COURSE, $course->id))); 00517 echo "<td class=\"r$row c3\" >\n"; 00518 echo " <a href=\"$CFG->wwwroot/user/view.php?id={$log->userid}\">$fullname</a>\n"; 00519 echo "</td>\n"; 00520 echo "<td class=\"r$row c4\">\n"; 00521 echo $log->action .': '.$log->module; 00522 echo "</td>\n";; 00523 echo "<td class=\"r$row c5\">{$log->info}</td>\n"; 00524 echo "</tr>\n"; 00525 } 00526 echo "</table>\n"; 00527 00528 echo $OUTPUT->paging_bar($totalcount, $page, $perpage, "$url&perpage=$perpage"); 00529 } 00530 00531 00532 function print_log_csv($course, $user, $date, $order='l.time DESC', $modname, 00533 $modid, $modaction, $groupid) { 00534 global $DB; 00535 00536 $text = get_string('course')."\t".get_string('time')."\t".get_string('ip_address')."\t". 00537 get_string('fullnameuser')."\t".get_string('action')."\t".get_string('info'); 00538 00539 if (!$logs = build_logs_array($course, $user, $date, $order, '', '', 00540 $modname, $modid, $modaction, $groupid)) { 00541 return false; 00542 } 00543 00544 $courses = array(); 00545 00546 if ($course->id == SITEID) { 00547 $courses[0] = ''; 00548 if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname')) { 00549 foreach ($ccc as $cc) { 00550 $courses[$cc->id] = $cc->shortname; 00551 } 00552 } 00553 } else { 00554 $courses[$course->id] = $course->shortname; 00555 } 00556 00557 $count=0; 00558 $ldcache = array(); 00559 $tt = getdate(time()); 00560 $today = mktime (0, 0, 0, $tt["mon"], $tt["mday"], $tt["year"]); 00561 00562 $strftimedatetime = get_string("strftimedatetime"); 00563 00564 $filename = 'logs_'.userdate(time(),get_string('backupnameformat', 'langconfig'),99,false); 00565 $filename .= '.txt'; 00566 header("Content-Type: application/download\n"); 00567 header("Content-Disposition: attachment; filename=$filename"); 00568 header("Expires: 0"); 00569 header("Cache-Control: must-revalidate,post-check=0,pre-check=0"); 00570 header("Pragma: public"); 00571 00572 echo get_string('savedat').userdate(time(), $strftimedatetime)."\n"; 00573 echo $text."\n"; 00574 00575 if (empty($logs['logs'])) { 00576 return true; 00577 } 00578 00579 foreach ($logs['logs'] as $log) { 00580 if (isset($ldcache[$log->module][$log->action])) { 00581 $ld = $ldcache[$log->module][$log->action]; 00582 } else { 00583 $ld = $DB->get_record('log_display', array('module'=>$log->module, 'action'=>$log->action)); 00584 $ldcache[$log->module][$log->action] = $ld; 00585 } 00586 if ($ld && !empty($log->info)) { 00587 // ugly hack to make sure fullname is shown correctly 00588 if (($ld->mtable == 'user') and ($ld->field == $DB->sql_concat('firstname', "' '" , 'lastname'))) { 00589 $log->info = fullname($DB->get_record($ld->mtable, array('id'=>$log->info)), true); 00590 } else { 00591 $log->info = $DB->get_field($ld->mtable, $ld->field, array('id'=>$log->info)); 00592 } 00593 } 00594 00595 //Filter log->info 00596 $log->info = format_string($log->info); 00597 $log->info = strip_tags(urldecode($log->info)); // Some XSS protection 00598 00599 $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); 00600 $firstField = format_string($courses[$log->course], true, array('context' => $coursecontext)); 00601 $fullname = fullname($log, has_capability('moodle/site:viewfullnames', $coursecontext)); 00602 $row = array($firstField, userdate($log->time, $strftimedatetime), $log->ip, $fullname, $log->module.' '.$log->action, $log->info); 00603 $text = implode("\t", $row); 00604 echo $text." \n"; 00605 } 00606 return true; 00607 } 00608 00609 00610 function print_log_xls($course, $user, $date, $order='l.time DESC', $modname, 00611 $modid, $modaction, $groupid) { 00612 00613 global $CFG, $DB; 00614 00615 require_once("$CFG->libdir/excellib.class.php"); 00616 00617 if (!$logs = build_logs_array($course, $user, $date, $order, '', '', 00618 $modname, $modid, $modaction, $groupid)) { 00619 return false; 00620 } 00621 00622 $courses = array(); 00623 00624 if ($course->id == SITEID) { 00625 $courses[0] = ''; 00626 if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname')) { 00627 foreach ($ccc as $cc) { 00628 $courses[$cc->id] = $cc->shortname; 00629 } 00630 } 00631 } else { 00632 $courses[$course->id] = $course->shortname; 00633 } 00634 00635 $count=0; 00636 $ldcache = array(); 00637 $tt = getdate(time()); 00638 $today = mktime (0, 0, 0, $tt["mon"], $tt["mday"], $tt["year"]); 00639 00640 $strftimedatetime = get_string("strftimedatetime"); 00641 00642 $nroPages = ceil(count($logs)/(EXCELROWS-FIRSTUSEDEXCELROW+1)); 00643 $filename = 'logs_'.userdate(time(),get_string('backupnameformat', 'langconfig'),99,false); 00644 $filename .= '.xls'; 00645 00646 $workbook = new MoodleExcelWorkbook('-'); 00647 $workbook->send($filename); 00648 00649 $worksheet = array(); 00650 $headers = array(get_string('course'), get_string('time'), get_string('ip_address'), 00651 get_string('fullnameuser'), get_string('action'), get_string('info')); 00652 00653 // Creating worksheets 00654 for ($wsnumber = 1; $wsnumber <= $nroPages; $wsnumber++) { 00655 $sheettitle = get_string('logs').' '.$wsnumber.'-'.$nroPages; 00656 $worksheet[$wsnumber] =& $workbook->add_worksheet($sheettitle); 00657 $worksheet[$wsnumber]->set_column(1, 1, 30); 00658 $worksheet[$wsnumber]->write_string(0, 0, get_string('savedat'). 00659 userdate(time(), $strftimedatetime)); 00660 $col = 0; 00661 foreach ($headers as $item) { 00662 $worksheet[$wsnumber]->write(FIRSTUSEDEXCELROW-1,$col,$item,''); 00663 $col++; 00664 } 00665 } 00666 00667 if (empty($logs['logs'])) { 00668 $workbook->close(); 00669 return true; 00670 } 00671 00672 $formatDate =& $workbook->add_format(); 00673 $formatDate->set_num_format(get_string('log_excel_date_format')); 00674 00675 $row = FIRSTUSEDEXCELROW; 00676 $wsnumber = 1; 00677 $myxls =& $worksheet[$wsnumber]; 00678 foreach ($logs['logs'] as $log) { 00679 if (isset($ldcache[$log->module][$log->action])) { 00680 $ld = $ldcache[$log->module][$log->action]; 00681 } else { 00682 $ld = $DB->get_record('log_display', array('module'=>$log->module, 'action'=>$log->action)); 00683 $ldcache[$log->module][$log->action] = $ld; 00684 } 00685 if ($ld && !empty($log->info)) { 00686 // ugly hack to make sure fullname is shown correctly 00687 if (($ld->mtable == 'user') and ($ld->field == $DB->sql_concat('firstname', "' '" , 'lastname'))) { 00688 $log->info = fullname($DB->get_record($ld->mtable, array('id'=>$log->info)), true); 00689 } else { 00690 $log->info = $DB->get_field($ld->mtable, $ld->field, array('id'=>$log->info)); 00691 } 00692 } 00693 00694 // Filter log->info 00695 $log->info = format_string($log->info); 00696 $log->info = strip_tags(urldecode($log->info)); // Some XSS protection 00697 00698 if ($nroPages>1) { 00699 if ($row > EXCELROWS) { 00700 $wsnumber++; 00701 $myxls =& $worksheet[$wsnumber]; 00702 $row = FIRSTUSEDEXCELROW; 00703 } 00704 } 00705 00706 $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); 00707 00708 $myxls->write($row, 0, format_string($courses[$log->course], true, array('context' => $coursecontext)), ''); 00709 $myxls->write_date($row, 1, $log->time, $formatDate); // write_date() does conversion/timezone support. MDL-14934 00710 $myxls->write($row, 2, $log->ip, ''); 00711 $fullname = fullname($log, has_capability('moodle/site:viewfullnames', $coursecontext)); 00712 $myxls->write($row, 3, $fullname, ''); 00713 $myxls->write($row, 4, $log->module.' '.$log->action, ''); 00714 $myxls->write($row, 5, $log->info, ''); 00715 00716 $row++; 00717 } 00718 00719 $workbook->close(); 00720 return true; 00721 } 00722 00723 function print_log_ods($course, $user, $date, $order='l.time DESC', $modname, 00724 $modid, $modaction, $groupid) { 00725 00726 global $CFG, $DB; 00727 00728 require_once("$CFG->libdir/odslib.class.php"); 00729 00730 if (!$logs = build_logs_array($course, $user, $date, $order, '', '', 00731 $modname, $modid, $modaction, $groupid)) { 00732 return false; 00733 } 00734 00735 $courses = array(); 00736 00737 if ($course->id == SITEID) { 00738 $courses[0] = ''; 00739 if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname')) { 00740 foreach ($ccc as $cc) { 00741 $courses[$cc->id] = $cc->shortname; 00742 } 00743 } 00744 } else { 00745 $courses[$course->id] = $course->shortname; 00746 } 00747 00748 $count=0; 00749 $ldcache = array(); 00750 $tt = getdate(time()); 00751 $today = mktime (0, 0, 0, $tt["mon"], $tt["mday"], $tt["year"]); 00752 00753 $strftimedatetime = get_string("strftimedatetime"); 00754 00755 $nroPages = ceil(count($logs)/(EXCELROWS-FIRSTUSEDEXCELROW+1)); 00756 $filename = 'logs_'.userdate(time(),get_string('backupnameformat', 'langconfig'),99,false); 00757 $filename .= '.ods'; 00758 00759 $workbook = new MoodleODSWorkbook('-'); 00760 $workbook->send($filename); 00761 00762 $worksheet = array(); 00763 $headers = array(get_string('course'), get_string('time'), get_string('ip_address'), 00764 get_string('fullnameuser'), get_string('action'), get_string('info')); 00765 00766 // Creating worksheets 00767 for ($wsnumber = 1; $wsnumber <= $nroPages; $wsnumber++) { 00768 $sheettitle = get_string('logs').' '.$wsnumber.'-'.$nroPages; 00769 $worksheet[$wsnumber] =& $workbook->add_worksheet($sheettitle); 00770 $worksheet[$wsnumber]->set_column(1, 1, 30); 00771 $worksheet[$wsnumber]->write_string(0, 0, get_string('savedat'). 00772 userdate(time(), $strftimedatetime)); 00773 $col = 0; 00774 foreach ($headers as $item) { 00775 $worksheet[$wsnumber]->write(FIRSTUSEDEXCELROW-1,$col,$item,''); 00776 $col++; 00777 } 00778 } 00779 00780 if (empty($logs['logs'])) { 00781 $workbook->close(); 00782 return true; 00783 } 00784 00785 $formatDate =& $workbook->add_format(); 00786 $formatDate->set_num_format(get_string('log_excel_date_format')); 00787 00788 $row = FIRSTUSEDEXCELROW; 00789 $wsnumber = 1; 00790 $myxls =& $worksheet[$wsnumber]; 00791 foreach ($logs['logs'] as $log) { 00792 if (isset($ldcache[$log->module][$log->action])) { 00793 $ld = $ldcache[$log->module][$log->action]; 00794 } else { 00795 $ld = $DB->get_record('log_display', array('module'=>$log->module, 'action'=>$log->action)); 00796 $ldcache[$log->module][$log->action] = $ld; 00797 } 00798 if ($ld && !empty($log->info)) { 00799 // ugly hack to make sure fullname is shown correctly 00800 if (($ld->mtable == 'user') and ($ld->field == $DB->sql_concat('firstname', "' '" , 'lastname'))) { 00801 $log->info = fullname($DB->get_record($ld->mtable, array('id'=>$log->info)), true); 00802 } else { 00803 $log->info = $DB->get_field($ld->mtable, $ld->field, array('id'=>$log->info)); 00804 } 00805 } 00806 00807 // Filter log->info 00808 $log->info = format_string($log->info); 00809 $log->info = strip_tags(urldecode($log->info)); // Some XSS protection 00810 00811 if ($nroPages>1) { 00812 if ($row > EXCELROWS) { 00813 $wsnumber++; 00814 $myxls =& $worksheet[$wsnumber]; 00815 $row = FIRSTUSEDEXCELROW; 00816 } 00817 } 00818 00819 $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); 00820 00821 $myxls->write_string($row, 0, format_string($courses[$log->course], true, array('context' => $coursecontext))); 00822 $myxls->write_date($row, 1, $log->time); 00823 $myxls->write_string($row, 2, $log->ip); 00824 $fullname = fullname($log, has_capability('moodle/site:viewfullnames', $coursecontext)); 00825 $myxls->write_string($row, 3, $fullname); 00826 $myxls->write_string($row, 4, $log->module.' '.$log->action); 00827 $myxls->write_string($row, 5, $log->info); 00828 00829 $row++; 00830 } 00831 00832 $workbook->close(); 00833 return true; 00834 } 00835 00836 00837 function print_overview($courses, array $remote_courses=array()) { 00838 global $CFG, $USER, $DB, $OUTPUT; 00839 00840 $htmlarray = array(); 00841 if ($modules = $DB->get_records('modules')) { 00842 foreach ($modules as $mod) { 00843 if (file_exists(dirname(dirname(__FILE__)).'/mod/'.$mod->name.'/lib.php')) { 00844 include_once(dirname(dirname(__FILE__)).'/mod/'.$mod->name.'/lib.php'); 00845 $fname = $mod->name.'_print_overview'; 00846 if (function_exists($fname)) { 00847 $fname($courses,$htmlarray); 00848 } 00849 } 00850 } 00851 } 00852 foreach ($courses as $course) { 00853 $fullname = format_string($course->fullname, true, array('context' => get_context_instance(CONTEXT_COURSE, $course->id))); 00854 echo $OUTPUT->box_start('coursebox'); 00855 $attributes = array('title' => s($fullname)); 00856 if (empty($course->visible)) { 00857 $attributes['class'] = 'dimmed'; 00858 } 00859 echo $OUTPUT->heading(html_writer::link( 00860 new moodle_url('/course/view.php', array('id' => $course->id)), $fullname, $attributes), 3); 00861 if (array_key_exists($course->id,$htmlarray)) { 00862 foreach ($htmlarray[$course->id] as $modname => $html) { 00863 echo $html; 00864 } 00865 } 00866 echo $OUTPUT->box_end(); 00867 } 00868 00869 if (!empty($remote_courses)) { 00870 echo $OUTPUT->heading(get_string('remotecourses', 'mnet')); 00871 } 00872 foreach ($remote_courses as $course) { 00873 echo $OUTPUT->box_start('coursebox'); 00874 $attributes = array('title' => s($course->fullname)); 00875 echo $OUTPUT->heading(html_writer::link( 00876 new moodle_url('/auth/mnet/jump.php', array('hostid' => $course->hostid, 'wantsurl' => '/course/view.php?id='.$course->remoteid)), 00877 format_string($course->shortname), 00878 $attributes) . ' (' . format_string($course->hostname) . ')', 3); 00879 echo $OUTPUT->box_end(); 00880 } 00881 } 00882 00883 00888 function print_recent_activity($course) { 00889 // $course is an object 00890 global $CFG, $USER, $SESSION, $DB, $OUTPUT; 00891 00892 $context = get_context_instance(CONTEXT_COURSE, $course->id); 00893 00894 $viewfullnames = has_capability('moodle/site:viewfullnames', $context); 00895 00896 $timestart = round(time() - COURSE_MAX_RECENT_PERIOD, -2); // better db caching for guests - 100 seconds 00897 00898 if (!isguestuser()) { 00899 if (!empty($USER->lastcourseaccess[$course->id])) { 00900 if ($USER->lastcourseaccess[$course->id] > $timestart) { 00901 $timestart = $USER->lastcourseaccess[$course->id]; 00902 } 00903 } 00904 } 00905 00906 echo '<div class="activitydate">'; 00907 echo get_string('activitysince', '', userdate($timestart)); 00908 echo '</div>'; 00909 echo '<div class="activityhead">'; 00910 00911 echo '<a href="'.$CFG->wwwroot.'/course/recent.php?id='.$course->id.'">'.get_string('recentactivityreport').'</a>'; 00912 00913 echo "</div>\n"; 00914 00915 $content = false; 00916 00918 00919 $users = get_recent_enrolments($course->id, $timestart); 00920 00921 //Accessibility: new users now appear in an <OL> list. 00922 if ($users) { 00923 echo '<div class="newusers">'; 00924 echo $OUTPUT->heading(get_string("newusers").':', 3); 00925 $content = true; 00926 echo "<ol class=\"list\">\n"; 00927 foreach ($users as $user) { 00928 $fullname = fullname($user, $viewfullnames); 00929 echo '<li class="name"><a href="'."$CFG->wwwroot/user/view.php?id=$user->id&course=$course->id\">$fullname</a></li>\n"; 00930 } 00931 echo "</ol>\n</div>\n"; 00932 } 00933 00935 00936 $modinfo =& get_fast_modinfo($course); 00937 00938 $changelist = array(); 00939 00940 $logs = $DB->get_records_select('log', "time > ? AND course = ? AND 00941 module = 'course' AND 00942 (action = 'add mod' OR action = 'update mod' OR action = 'delete mod')", 00943 array($timestart, $course->id), "id ASC"); 00944 00945 if ($logs) { 00946 $actions = array('add mod', 'update mod', 'delete mod'); 00947 $newgones = array(); // added and later deleted items 00948 foreach ($logs as $key => $log) { 00949 if (!in_array($log->action, $actions)) { 00950 continue; 00951 } 00952 $info = explode(' ', $log->info); 00953 00954 // note: in most cases I replaced hardcoding of label with use of 00955 // $cm->has_view() but it was not possible to do this here because 00956 // we don't necessarily have the $cm for it 00957 if ($info[0] == 'label') { // Labels are ignored in recent activity 00958 continue; 00959 } 00960 00961 if (count($info) != 2) { 00962 debugging("Incorrect log entry info: id = ".$log->id, DEBUG_DEVELOPER); 00963 continue; 00964 } 00965 00966 $modname = $info[0]; 00967 $instanceid = $info[1]; 00968 00969 if ($log->action == 'delete mod') { 00970 // unfortunately we do not know if the mod was visible 00971 if (!array_key_exists($log->info, $newgones)) { 00972 $strdeleted = get_string('deletedactivity', 'moodle', get_string('modulename', $modname)); 00973 $changelist[$log->info] = array ('operation' => 'delete', 'text' => $strdeleted); 00974 } 00975 } else { 00976 if (!isset($modinfo->instances[$modname][$instanceid])) { 00977 if ($log->action == 'add mod') { 00978 // do not display added and later deleted activities 00979 $newgones[$log->info] = true; 00980 } 00981 continue; 00982 } 00983 $cm = $modinfo->instances[$modname][$instanceid]; 00984 if (!$cm->uservisible) { 00985 continue; 00986 } 00987 00988 if ($log->action == 'add mod') { 00989 $stradded = get_string('added', 'moodle', get_string('modulename', $modname)); 00990 $changelist[$log->info] = array('operation' => 'add', 'text' => "$stradded:<br /><a href=\"$CFG->wwwroot/mod/$cm->modname/view.php?id={$cm->id}\">".format_string($cm->name, true)."</a>"); 00991 00992 } else if ($log->action == 'update mod' and empty($changelist[$log->info])) { 00993 $strupdated = get_string('updated', 'moodle', get_string('modulename', $modname)); 00994 $changelist[$log->info] = array('operation' => 'update', 'text' => "$strupdated:<br /><a href=\"$CFG->wwwroot/mod/$cm->modname/view.php?id={$cm->id}\">".format_string($cm->name, true)."</a>"); 00995 } 00996 } 00997 } 00998 } 00999 01000 if (!empty($changelist)) { 01001 echo $OUTPUT->heading(get_string("courseupdates").':', 3); 01002 $content = true; 01003 foreach ($changelist as $changeinfo => $change) { 01004 echo '<p class="activity">'.$change['text'].'</p>'; 01005 } 01006 } 01007 01009 01010 $usedmodules = array(); 01011 foreach($modinfo->cms as $cm) { 01012 if (isset($usedmodules[$cm->modname])) { 01013 continue; 01014 } 01015 if (!$cm->uservisible) { 01016 continue; 01017 } 01018 $usedmodules[$cm->modname] = $cm->modname; 01019 } 01020 01021 foreach ($usedmodules as $modname) { // Each module gets it's own logs and prints them 01022 if (file_exists($CFG->dirroot.'/mod/'.$modname.'/lib.php')) { 01023 include_once($CFG->dirroot.'/mod/'.$modname.'/lib.php'); 01024 $print_recent_activity = $modname.'_print_recent_activity'; 01025 if (function_exists($print_recent_activity)) { 01026 // NOTE: original $isteacher (second parameter below) was replaced with $viewfullnames! 01027 $content = $print_recent_activity($course, $viewfullnames, $timestart) || $content; 01028 } 01029 } else { 01030 debugging("Missing lib.php in lib/{$modname} - please reinstall files or uninstall the module"); 01031 } 01032 } 01033 01034 if (! $content) { 01035 echo '<p class="message">'.get_string('nothingnew').'</p>'; 01036 } 01037 } 01038 01043 function get_array_of_activities($courseid) { 01044 // cm - course module id 01045 // mod - name of the module (eg forum) 01046 // section - the number of the section (eg week or topic) 01047 // name - the name of the instance 01048 // visible - is the instance visible or not 01049 // groupingid - grouping id 01050 // groupmembersonly - is this instance visible to group members only 01051 // extra - contains extra string to include in any link 01052 global $CFG, $DB; 01053 if(!empty($CFG->enableavailability)) { 01054 require_once($CFG->libdir.'/conditionlib.php'); 01055 } 01056 01057 $course = $DB->get_record('course', array('id'=>$courseid)); 01058 01059 if (empty($course)) { 01060 throw new moodle_exception('courseidnotfound'); 01061 } 01062 01063 $mod = array(); 01064 01065 $rawmods = get_course_mods($courseid); 01066 if (empty($rawmods)) { 01067 return $mod; // always return array 01068 } 01069 01070 if ($sections = $DB->get_records("course_sections", array("course"=>$courseid), "section ASC")) { 01071 foreach ($sections as $section) { 01072 if (!empty($section->sequence)) { 01073 $sequence = explode(",", $section->sequence); 01074 foreach ($sequence as $seq) { 01075 if (empty($rawmods[$seq])) { 01076 continue; 01077 } 01078 $mod[$seq] = new stdClass(); 01079 $mod[$seq]->id = $rawmods[$seq]->instance; 01080 $mod[$seq]->cm = $rawmods[$seq]->id; 01081 $mod[$seq]->mod = $rawmods[$seq]->modname; 01082 01083 // Oh dear. Inconsistent names left here for backward compatibility. 01084 $mod[$seq]->section = $section->section; 01085 $mod[$seq]->sectionid = $rawmods[$seq]->section; 01086 01087 $mod[$seq]->module = $rawmods[$seq]->module; 01088 $mod[$seq]->added = $rawmods[$seq]->added; 01089 $mod[$seq]->score = $rawmods[$seq]->score; 01090 $mod[$seq]->idnumber = $rawmods[$seq]->idnumber; 01091 $mod[$seq]->visible = $rawmods[$seq]->visible; 01092 $mod[$seq]->visibleold = $rawmods[$seq]->visibleold; 01093 $mod[$seq]->groupmode = $rawmods[$seq]->groupmode; 01094 $mod[$seq]->groupingid = $rawmods[$seq]->groupingid; 01095 $mod[$seq]->groupmembersonly = $rawmods[$seq]->groupmembersonly; 01096 $mod[$seq]->indent = $rawmods[$seq]->indent; 01097 $mod[$seq]->completion = $rawmods[$seq]->completion; 01098 $mod[$seq]->extra = ""; 01099 $mod[$seq]->completiongradeitemnumber = 01100 $rawmods[$seq]->completiongradeitemnumber; 01101 $mod[$seq]->completionview = $rawmods[$seq]->completionview; 01102 $mod[$seq]->completionexpected = $rawmods[$seq]->completionexpected; 01103 $mod[$seq]->availablefrom = $rawmods[$seq]->availablefrom; 01104 $mod[$seq]->availableuntil = $rawmods[$seq]->availableuntil; 01105 $mod[$seq]->showavailability = $rawmods[$seq]->showavailability; 01106 $mod[$seq]->showdescription = $rawmods[$seq]->showdescription; 01107 if (!empty($CFG->enableavailability)) { 01108 condition_info::fill_availability_conditions($rawmods[$seq]); 01109 $mod[$seq]->conditionscompletion = $rawmods[$seq]->conditionscompletion; 01110 $mod[$seq]->conditionsgrade = $rawmods[$seq]->conditionsgrade; 01111 } 01112 01113 $modname = $mod[$seq]->mod; 01114 $functionname = $modname."_get_coursemodule_info"; 01115 01116 if (!file_exists("$CFG->dirroot/mod/$modname/lib.php")) { 01117 continue; 01118 } 01119 01120 include_once("$CFG->dirroot/mod/$modname/lib.php"); 01121 01122 if ($hasfunction = function_exists($functionname)) { 01123 if ($info = $functionname($rawmods[$seq])) { 01124 if (!empty($info->icon)) { 01125 $mod[$seq]->icon = $info->icon; 01126 } 01127 if (!empty($info->iconcomponent)) { 01128 $mod[$seq]->iconcomponent = $info->iconcomponent; 01129 } 01130 if (!empty($info->name)) { 01131 $mod[$seq]->name = $info->name; 01132 } 01133 if ($info instanceof cached_cm_info) { 01134 // When using cached_cm_info you can include three new fields 01135 // that aren't available for legacy code 01136 if (!empty($info->content)) { 01137 $mod[$seq]->content = $info->content; 01138 } 01139 if (!empty($info->extraclasses)) { 01140 $mod[$seq]->extraclasses = $info->extraclasses; 01141 } 01142 if (!empty($info->iconurl)) { 01143 $mod[$seq]->iconurl = $info->iconurl; 01144 } 01145 if (!empty($info->onclick)) { 01146 $mod[$seq]->onclick = $info->onclick; 01147 } 01148 if (!empty($info->customdata)) { 01149 $mod[$seq]->customdata = $info->customdata; 01150 } 01151 } else { 01152 // When using a stdclass, the (horrible) deprecated ->extra field 01153 // is available for BC 01154 if (!empty($info->extra)) { 01155 $mod[$seq]->extra = $info->extra; 01156 } 01157 } 01158 } 01159 } 01160 // When there is no modname_get_coursemodule_info function, 01161 // but showdescriptions is enabled, then we use the 'intro' 01162 // and 'introformat' fields in the module table 01163 if (!$hasfunction && $rawmods[$seq]->showdescription) { 01164 if ($modvalues = $DB->get_record($rawmods[$seq]->modname, 01165 array('id' => $rawmods[$seq]->instance), 'name, intro, introformat')) { 01166 // Set content from intro and introformat. Filters are disabled 01167 // because we filter it with format_text at display time 01168 $mod[$seq]->content = format_module_intro($rawmods[$seq]->modname, 01169 $modvalues, $rawmods[$seq]->id, false); 01170 01171 // To save making another query just below, put name in here 01172 $mod[$seq]->name = $modvalues->name; 01173 } 01174 } 01175 if (!isset($mod[$seq]->name)) { 01176 $mod[$seq]->name = $DB->get_field($rawmods[$seq]->modname, "name", array("id"=>$rawmods[$seq]->instance)); 01177 } 01178 01179 // Minimise the database size by unsetting default options when they are 01180 // 'empty'. This list corresponds to code in the cm_info constructor. 01181 foreach (array('idnumber', 'groupmode', 'groupingid', 'groupmembersonly', 01182 'indent', 'completion', 'extra', 'extraclasses', 'iconurl', 'onclick', 'content', 01183 'icon', 'iconcomponent', 'customdata', 'showavailability', 'availablefrom', 01184 'availableuntil', 'conditionscompletion', 'conditionsgrade', 01185 'completionview', 'completionexpected', 'score', 'showdescription') 01186 as $property) { 01187 if (property_exists($mod[$seq], $property) && 01188 empty($mod[$seq]->{$property})) { 01189 unset($mod[$seq]->{$property}); 01190 } 01191 } 01192 // Special case: this value is usually set to null, but may be 0 01193 if (property_exists($mod[$seq], 'completiongradeitemnumber') && 01194 is_null($mod[$seq]->completiongradeitemnumber)) { 01195 unset($mod[$seq]->completiongradeitemnumber); 01196 } 01197 } 01198 } 01199 } 01200 } 01201 return $mod; 01202 } 01203 01204 01208 function get_all_mods($courseid, &$mods, &$modnames, &$modnamesplural, &$modnamesused) { 01209 global $CFG, $DB, $COURSE; 01210 01211 $mods = array(); // course modules indexed by id 01212 $modnames = array(); // all course module names (except resource!) 01213 $modnamesplural= array(); // all course module names (plural form) 01214 $modnamesused = array(); // course module names used 01215 01216 if ($allmods = $DB->get_records("modules")) { 01217 foreach ($allmods as $mod) { 01218 if (!file_exists("$CFG->dirroot/mod/$mod->name/lib.php")) { 01219 continue; 01220 } 01221 if ($mod->visible) { 01222 $modnames[$mod->name] = get_string("modulename", "$mod->name"); 01223 $modnamesplural[$mod->name] = get_string("modulenameplural", "$mod->name"); 01224 } 01225 } 01226 collatorlib::asort($modnames); 01227 } else { 01228 print_error("nomodules", 'debug'); 01229 } 01230 01231 $course = ($courseid==$COURSE->id) ? $COURSE : $DB->get_record('course',array('id'=>$courseid)); 01232 $modinfo = get_fast_modinfo($course); 01233 01234 if ($rawmods=$modinfo->cms) { 01235 foreach($rawmods as $mod) { // Index the mods 01236 if (empty($modnames[$mod->modname])) { 01237 continue; 01238 } 01239 $mods[$mod->id] = $mod; 01240 $mods[$mod->id]->modfullname = $modnames[$mod->modname]; 01241 if (!$mod->visible and !has_capability('moodle/course:viewhiddenactivities', get_context_instance(CONTEXT_COURSE, $courseid))) { 01242 continue; 01243 } 01244 // Check groupings 01245 if (!groups_course_module_visible($mod)) { 01246 continue; 01247 } 01248 $modnamesused[$mod->modname] = $modnames[$mod->modname]; 01249 } 01250 if ($modnamesused) { 01251 collatorlib::asort($modnamesused); 01252 } 01253 } 01254 } 01255 01267 function get_all_sections($courseid) { 01268 global $DB; 01269 static $coursesections = array(); 01270 if (!array_key_exists($courseid, $coursesections)) { 01271 $coursesections[$courseid] = $DB->get_records("course_sections", array("course"=>"$courseid"), "section", 01272 "section, id, course, name, summary, summaryformat, sequence, visible"); 01273 } 01274 return $coursesections[$courseid]; 01275 } 01276 01284 function course_get_display($courseid) { 01285 global $USER, $DB; 01286 01287 if (!isloggedin() or isguestuser()) { 01288 //do not get settings in db for guests 01289 return 0; //return the implicit setting 01290 } 01291 01292 if (!isset($USER->display[$courseid])) { 01293 if (!$display = $DB->get_field('course_display', 'display', array('userid' => $USER->id, 'course'=>$courseid))) { 01294 $display = 0; // all sections option is not stored in DB, this makes the table much smaller 01295 } 01296 //use display cache for one course only - we need to keep session small 01297 $USER->display = array($courseid => $display); 01298 } 01299 01300 return $USER->display[$courseid]; 01301 } 01302 01310 function course_set_display($courseid, $display) { 01311 global $USER, $DB; 01312 01313 if ($display === 'all' or empty($display)) { 01314 $display = 0; 01315 } 01316 01317 if (!isloggedin() or isguestuser()) { 01318 //do not store settings in db for guests 01319 return 0; 01320 } 01321 01322 if ($display == 0) { 01323 //show all, do not store anything in database 01324 $DB->delete_records('course_display', array('userid' => $USER->id, 'course' => $courseid)); 01325 01326 } else { 01327 if ($DB->record_exists('course_display', array('userid' => $USER->id, 'course' => $courseid))) { 01328 $DB->set_field('course_display', 'display', $display, array('userid' => $USER->id, 'course' => $courseid)); 01329 } else { 01330 $record = new stdClass(); 01331 $record->userid = $USER->id; 01332 $record->course = $courseid; 01333 $record->display = $display; 01334 $DB->insert_record('course_display', $record); 01335 } 01336 } 01337 01338 //use display cache for one course only - we need to keep session small 01339 $USER->display = array($courseid => $display); 01340 01341 return $display; 01342 } 01343 01348 function set_section_visible($courseid, $sectionnumber, $visibility) { 01349 global $DB; 01350 01351 if ($section = $DB->get_record("course_sections", array("course"=>$courseid, "section"=>$sectionnumber))) { 01352 $DB->set_field("course_sections", "visible", "$visibility", array("id"=>$section->id)); 01353 if (!empty($section->sequence)) { 01354 $modules = explode(",", $section->sequence); 01355 foreach ($modules as $moduleid) { 01356 set_coursemodule_visible($moduleid, $visibility, true); 01357 } 01358 } 01359 rebuild_course_cache($courseid); 01360 } 01361 } 01362 01376 function get_print_section_cm_text(cm_info $cm, $course) { 01377 global $OUTPUT; 01378 01379 // Get content from modinfo if specified. Content displays either 01380 // in addition to the standard link (below), or replaces it if 01381 // the link is turned off by setting ->url to null. 01382 if (($content = $cm->get_content()) !== '') { 01383 // Improve filter performance by preloading filter setttings for all 01384 // activities on the course (this does nothing if called multiple 01385 // times) 01386 filter_preload_activities($cm->get_modinfo()); 01387 01388 // Get module context 01389 $modulecontext = get_context_instance(CONTEXT_MODULE, $cm->id); 01390 $labelformatoptions = new stdClass(); 01391 $labelformatoptions->noclean = true; 01392 $labelformatoptions->overflowdiv = true; 01393 $labelformatoptions->context = $modulecontext; 01394 $content = format_text($content, FORMAT_HTML, $labelformatoptions); 01395 } else { 01396 $content = ''; 01397 } 01398 01399 // Get course context 01400 $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); 01401 $stringoptions = new stdClass; 01402 $stringoptions->context = $coursecontext; 01403 $instancename = format_string($cm->name, true, $stringoptions); 01404 return array($content, $instancename); 01405 } 01406 01410 function print_section($course, $section, $mods, $modnamesused, $absolute=false, $width="100%", $hidecompletion=false) { 01411 global $CFG, $USER, $DB, $PAGE, $OUTPUT; 01412 01413 static $initialised; 01414 01415 static $groupbuttons; 01416 static $groupbuttonslink; 01417 static $isediting; 01418 static $ismoving; 01419 static $strmovehere; 01420 static $strmovefull; 01421 static $strunreadpostsone; 01422 static $groupings; 01423 static $modulenames; 01424 01425 if (!isset($initialised)) { 01426 $groupbuttons = ($course->groupmode or (!$course->groupmodeforce)); 01427 $groupbuttonslink = (!$course->groupmodeforce); 01428 $isediting = $PAGE->user_is_editing(); 01429 $ismoving = $isediting && ismoving($course->id); 01430 if ($ismoving) { 01431 $strmovehere = get_string("movehere"); 01432 $strmovefull = strip_tags(get_string("movefull", "", "'$USER->activitycopyname'")); 01433 } 01434 $modulenames = array(); 01435 $initialised = true; 01436 } 01437 01438 $tl = textlib_get_instance(); 01439 01440 $modinfo = get_fast_modinfo($course); 01441 $completioninfo = new completion_info($course); 01442 01443 //Accessibility: replace table with list <ul>, but don't output empty list. 01444 if (!empty($section->sequence)) { 01445 01446 // Fix bug #5027, don't want style=\"width:$width\". 01447 echo "<ul class=\"section img-text\">\n"; 01448 $sectionmods = explode(",", $section->sequence); 01449 01450 foreach ($sectionmods as $modnumber) { 01451 if (empty($mods[$modnumber])) { 01452 continue; 01453 } 01454 01458 $mod = $mods[$modnumber]; 01459 01460 if ($ismoving and $mod->id == $USER->activitycopy) { 01461 // do not display moving mod 01462 continue; 01463 } 01464 01465 if (isset($modinfo->cms[$modnumber])) { 01466 // We can continue (because it will not be displayed at all) 01467 // if: 01468 // 1) The activity is not visible to users 01469 // and 01470 // 2a) The 'showavailability' option is not set (if that is set, 01471 // we need to display the activity so we can show 01472 // availability info) 01473 // or 01474 // 2b) The 'availableinfo' is empty, i.e. the activity was 01475 // hidden in a way that leaves no info, such as using the 01476 // eye icon. 01477 if (!$modinfo->cms[$modnumber]->uservisible && 01478 (empty($modinfo->cms[$modnumber]->showavailability) || 01479 empty($modinfo->cms[$modnumber]->availableinfo))) { 01480 // visibility shortcut 01481 continue; 01482 } 01483 } else { 01484 if (!file_exists("$CFG->dirroot/mod/$mod->modname/lib.php")) { 01485 // module not installed 01486 continue; 01487 } 01488 if (!coursemodule_visible_for_user($mod) && 01489 empty($mod->showavailability)) { 01490 // full visibility check 01491 continue; 01492 } 01493 } 01494 01495 if (!isset($modulenames[$mod->modname])) { 01496 $modulenames[$mod->modname] = get_string('modulename', $mod->modname); 01497 } 01498 $modulename = $modulenames[$mod->modname]; 01499 01500 // In some cases the activity is visible to user, but it is 01501 // dimmed. This is done if viewhiddenactivities is true and if: 01502 // 1. the activity is not visible, or 01503 // 2. the activity has dates set which do not include current, or 01504 // 3. the activity has any other conditions set (regardless of whether 01505 // current user meets them) 01506 $canviewhidden = has_capability( 01507 'moodle/course:viewhiddenactivities', 01508 get_context_instance(CONTEXT_MODULE, $mod->id)); 01509 $accessiblebutdim = false; 01510 if ($canviewhidden) { 01511 $accessiblebutdim = !$mod->visible; 01512 if (!empty($CFG->enableavailability)) { 01513 $accessiblebutdim = $accessiblebutdim || 01514 $mod->availablefrom > time() || 01515 ($mod->availableuntil && $mod->availableuntil < time()) || 01516 count($mod->conditionsgrade) > 0 || 01517 count($mod->conditionscompletion) > 0; 01518 } 01519 } 01520 01521 $liclasses = array(); 01522 $liclasses[] = 'activity'; 01523 $liclasses[] = $mod->modname; 01524 $liclasses[] = 'modtype_'.$mod->modname; 01525 $extraclasses = $mod->get_extra_classes(); 01526 if ($extraclasses) { 01527 $liclasses = array_merge($liclasses, explode(' ', $extraclasses)); 01528 } 01529 echo html_writer::start_tag('li', array('class'=>join(' ', $liclasses), 'id'=>'module-'.$modnumber)); 01530 if ($ismoving) { 01531 echo '<a title="'.$strmovefull.'"'. 01532 ' href="'.$CFG->wwwroot.'/course/mod.php?moveto='.$mod->id.'&sesskey='.sesskey().'">'. 01533 '<img class="movetarget" src="'.$OUTPUT->pix_url('movehere') . '" '. 01534 ' alt="'.$strmovehere.'" /></a><br /> 01535 '; 01536 } 01537 01538 $classes = array('mod-indent'); 01539 if (!empty($mod->indent)) { 01540 $classes[] = 'mod-indent-'.$mod->indent; 01541 if ($mod->indent > 15) { 01542 $classes[] = 'mod-indent-huge'; 01543 } 01544 } 01545 echo html_writer::start_tag('div', array('class'=>join(' ', $classes))); 01546 01547 // Get data about this course-module 01548 list($content, $instancename) = 01549 get_print_section_cm_text($modinfo->cms[$modnumber], $course); 01550 01551 //Accessibility: for files get description via icon, this is very ugly hack! 01552 $altname = ''; 01553 $altname = $mod->modfullname; 01554 if (!empty($customicon)) { 01555 $archetype = plugin_supports('mod', $mod->modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER); 01556 if ($archetype == MOD_ARCHETYPE_RESOURCE) { 01557 $mimetype = mimeinfo_from_icon('type', $customicon); 01558 $altname = get_mimetype_description($mimetype); 01559 } 01560 } 01561 // Avoid unnecessary duplication: if e.g. a forum name already 01562 // includes the word forum (or Forum, etc) then it is unhelpful 01563 // to include that in the accessible description that is added. 01564 if (false !== strpos($tl->strtolower($instancename), 01565 $tl->strtolower($altname))) { 01566 $altname = ''; 01567 } 01568 // File type after name, for alphabetic lists (screen reader). 01569 if ($altname) { 01570 $altname = get_accesshide(' '.$altname); 01571 } 01572 01573 // We may be displaying this just in order to show information 01574 // about visibility, without the actual link 01575 $contentpart = ''; 01576 if ($mod->uservisible) { 01577 // Nope - in this case the link is fully working for user 01578 $linkclasses = ''; 01579 $textclasses = ''; 01580 if ($accessiblebutdim) { 01581 $linkclasses .= ' dimmed'; 01582 $textclasses .= ' dimmed_text'; 01583 $accesstext = '<span class="accesshide">'. 01584 get_string('hiddenfromstudents').': </span>'; 01585 } else { 01586 $accesstext = ''; 01587 } 01588 if ($linkclasses) { 01589 $linkcss = 'class="' . trim($linkclasses) . '" '; 01590 } else { 01591 $linkcss = ''; 01592 } 01593 if ($textclasses) { 01594 $textcss = 'class="' . trim($textclasses) . '" '; 01595 } else { 01596 $textcss = ''; 01597 } 01598 01599 // Get on-click attribute value if specified 01600 $onclick = $mod->get_on_click(); 01601 if ($onclick) { 01602 $onclick = ' onclick="' . $onclick . '"'; 01603 } 01604 01605 if ($url = $mod->get_url()) { 01606 // Display link itself 01607 echo '<a ' . $linkcss . $mod->extra . $onclick . 01608 ' href="' . $url . '"><img src="' . $mod->get_icon_url() . 01609 '" class="activityicon" alt="' . 01610 $modulename . '" /> ' . 01611 $accesstext . '<span class="instancename">' . 01612 $instancename . $altname . '</span></a>'; 01613 01614 // If specified, display extra content after link 01615 if ($content) { 01616 $contentpart = '<div class="' . trim('contentafterlink' . $textclasses) . 01617 '">' . $content . '</div>'; 01618 } 01619 } else { 01620 // No link, so display only content 01621 $contentpart = '<div ' . $textcss . $mod->extra . '>' . 01622 $accesstext . $content . '</div>'; 01623 } 01624 01625 if (!empty($mod->groupingid) && has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) { 01626 if (!isset($groupings)) { 01627 $groupings = groups_get_all_groupings($course->id); 01628 } 01629 echo " <span class=\"groupinglabel\">(".format_string($groupings[$mod->groupingid]->name).')</span>'; 01630 } 01631 } else { 01632 $textclasses = $extraclasses; 01633 $textclasses .= ' dimmed_text'; 01634 if ($textclasses) { 01635 $textcss = 'class="' . trim($textclasses) . '" '; 01636 } else { 01637 $textcss = ''; 01638 } 01639 $accesstext = '<span class="accesshide">' . 01640 get_string('notavailableyet', 'condition') . 01641 ': </span>'; 01642 01643 if ($url = $mod->get_url()) { 01644 // Display greyed-out text of link 01645 echo '<div ' . $textcss . $mod->extra . 01646 ' >' . '<img src="' . $mod->get_icon_url() . 01647 '" class="activityicon" alt="' . 01648 $modulename . 01649 '" /> <span>'. $instancename . $altname . 01650 '</span></div>'; 01651 01652 // Do not display content after link when it is greyed out like this. 01653 } else { 01654 // No link, so display only content (also greyed) 01655 $contentpart = '<div ' . $textcss . $mod->extra . '>' . 01656 $accesstext . $content . '</div>'; 01657 } 01658 } 01659 01660 // Module can put text after the link (e.g. forum unread) 01661 echo $mod->get_after_link(); 01662 01663 // If there is content but NO link (eg label), then display the 01664 // content here (BEFORE any icons). In this case cons must be 01665 // displayed after the content so that it makes more sense visually 01666 // and for accessibility reasons, e.g. if you have a one-line label 01667 // it should work similarly (at least in terms of ordering) to an 01668 // activity. 01669 if (empty($url)) { 01670 echo $contentpart; 01671 } 01672 01673 if ($isediting) { 01674 if ($groupbuttons and plugin_supports('mod', $mod->modname, FEATURE_GROUPS, 0)) { 01675 if (! $mod->groupmodelink = $groupbuttonslink) { 01676 $mod->groupmode = $course->groupmode; 01677 } 01678 01679 } else { 01680 $mod->groupmode = false; 01681 } 01682 echo ' '; 01683 echo make_editing_buttons($mod, $absolute, true, $mod->indent, $section->section); 01684 echo $mod->get_after_edit_icons(); 01685 } 01686 01687 // Completion 01688 $completion = $hidecompletion 01689 ? COMPLETION_TRACKING_NONE 01690 : $completioninfo->is_enabled($mod); 01691 if ($completion!=COMPLETION_TRACKING_NONE && isloggedin() && 01692 !isguestuser() && $mod->uservisible) { 01693 $completiondata = $completioninfo->get_data($mod,true); 01694 $completionicon = ''; 01695 if ($isediting) { 01696 switch ($completion) { 01697 case COMPLETION_TRACKING_MANUAL : 01698 $completionicon = 'manual-enabled'; break; 01699 case COMPLETION_TRACKING_AUTOMATIC : 01700 $completionicon = 'auto-enabled'; break; 01701 default: // wtf 01702 } 01703 } else if ($completion==COMPLETION_TRACKING_MANUAL) { 01704 switch($completiondata->completionstate) { 01705 case COMPLETION_INCOMPLETE: 01706 $completionicon = 'manual-n'; break; 01707 case COMPLETION_COMPLETE: 01708 $completionicon = 'manual-y'; break; 01709 } 01710 } else { // Automatic 01711 switch($completiondata->completionstate) { 01712 case COMPLETION_INCOMPLETE: 01713 $completionicon = 'auto-n'; break; 01714 case COMPLETION_COMPLETE: 01715 $completionicon = 'auto-y'; break; 01716 case COMPLETION_COMPLETE_PASS: 01717 $completionicon = 'auto-pass'; break; 01718 case COMPLETION_COMPLETE_FAIL: 01719 $completionicon = 'auto-fail'; break; 01720 } 01721 } 01722 if ($completionicon) { 01723 $imgsrc = $OUTPUT->pix_url('i/completion-'.$completionicon); 01724 $imgalt = s(get_string('completion-alt-'.$completionicon, 'completion')); 01725 if ($completion == COMPLETION_TRACKING_MANUAL && !$isediting) { 01726 $imgtitle = s(get_string('completion-title-'.$completionicon, 'completion')); 01727 $newstate = 01728 $completiondata->completionstate==COMPLETION_COMPLETE 01729 ? COMPLETION_INCOMPLETE 01730 : COMPLETION_COMPLETE; 01731 // In manual mode the icon is a toggle form... 01732 01733 // If this completion state is used by the 01734 // conditional activities system, we need to turn 01735 // off the JS. 01736 if (!empty($CFG->enableavailability) && 01737 condition_info::completion_value_used_as_condition($course, $mod)) { 01738 $extraclass = ' preventjs'; 01739 } else { 01740 $extraclass = ''; 01741 } 01742 echo " 01743 <form class='togglecompletion$extraclass' method='post' action='".$CFG->wwwroot."/course/togglecompletion.php'><div> 01744 <input type='hidden' name='id' value='{$mod->id}' /> 01745 <input type='hidden' name='sesskey' value='".sesskey()."' /> 01746 <input type='hidden' name='completionstate' value='$newstate' /> 01747 <input type='image' src='$imgsrc' alt='$imgalt' title='$imgtitle' /> 01748 </div></form>"; 01749 } else { 01750 // In auto mode, or when editing, the icon is just an image 01751 echo "<span class='autocompletion'>"; 01752 echo "<img src='$imgsrc' alt='$imgalt' title='$imgalt' /></span>"; 01753 } 01754 } 01755 } 01756 01757 // If there is content AND a link, then display the content here 01758 // (AFTER any icons). Otherwise it was displayed before 01759 if (!empty($url)) { 01760 echo $contentpart; 01761 } 01762 01763 // Show availability information (for someone who isn't allowed to 01764 // see the activity itself, or for staff) 01765 if (!$mod->uservisible) { 01766 echo '<div class="availabilityinfo">'.$mod->availableinfo.'</div>'; 01767 } else if ($canviewhidden && !empty($CFG->enableavailability)) { 01768 $ci = new condition_info($mod); 01769 $fullinfo = $ci->get_full_information(); 01770 if($fullinfo) { 01771 echo '<div class="availabilityinfo">'.get_string($mod->showavailability 01772 ? 'userrestriction_visible' 01773 : 'userrestriction_hidden','condition', 01774 $fullinfo).'</div>'; 01775 } 01776 } 01777 01778 echo html_writer::end_tag('div'); 01779 echo html_writer::end_tag('li')."\n"; 01780 } 01781 01782 } elseif ($ismoving) { 01783 echo "<ul class=\"section\">\n"; 01784 } 01785 01786 if ($ismoving) { 01787 echo '<li><a title="'.$strmovefull.'"'. 01788 ' href="'.$CFG->wwwroot.'/course/mod.php?movetosection='.$section->id.'&sesskey='.sesskey().'">'. 01789 '<img class="movetarget" src="'.$OUTPUT->pix_url('movehere') . '" '. 01790 ' alt="'.$strmovehere.'" /></a></li> 01791 '; 01792 } 01793 if (!empty($section->sequence) || $ismoving) { 01794 echo "</ul><!--class='section'-->\n\n"; 01795 } 01796 } 01797 01801 function print_section_add_menus($course, $section, $modnames, $vertical=false, $return=false) { 01802 global $CFG, $OUTPUT; 01803 01804 // check to see if user can add menus 01805 if (!has_capability('moodle/course:manageactivities', get_context_instance(CONTEXT_COURSE, $course->id))) { 01806 return false; 01807 } 01808 01809 $urlbase = "/course/mod.php?id=$course->id§ion=$section&sesskey=".sesskey().'&add='; 01810 01811 $resources = array(); 01812 $activities = array(); 01813 01814 foreach($modnames as $modname=>$modnamestr) { 01815 if (!course_allowed_module($course, $modname)) { 01816 continue; 01817 } 01818 01819 $libfile = "$CFG->dirroot/mod/$modname/lib.php"; 01820 if (!file_exists($libfile)) { 01821 continue; 01822 } 01823 include_once($libfile); 01824 $gettypesfunc = $modname.'_get_types'; 01825 if (function_exists($gettypesfunc)) { 01826 // NOTE: this is legacy stuff, module subtypes are very strongly discouraged!! 01827 if ($types = $gettypesfunc()) { 01828 $menu = array(); 01829 $atype = null; 01830 $groupname = null; 01831 foreach($types as $type) { 01832 if ($type->typestr === '--') { 01833 continue; 01834 } 01835 if (strpos($type->typestr, '--') === 0) { 01836 $groupname = str_replace('--', '', $type->typestr); 01837 continue; 01838 } 01839 $type->type = str_replace('&', '&', $type->type); 01840 if ($type->modclass == MOD_CLASS_RESOURCE) { 01841 $atype = MOD_CLASS_RESOURCE; 01842 } 01843 $menu[$urlbase.$type->type] = $type->typestr; 01844 } 01845 if (!is_null($groupname)) { 01846 if ($atype == MOD_CLASS_RESOURCE) { 01847 $resources[] = array($groupname=>$menu); 01848 } else { 01849 $activities[] = array($groupname=>$menu); 01850 } 01851 } else { 01852 if ($atype == MOD_CLASS_RESOURCE) { 01853 $resources = array_merge($resources, $menu); 01854 } else { 01855 $activities = array_merge($activities, $menu); 01856 } 01857 } 01858 } 01859 } else { 01860 $archetype = plugin_supports('mod', $modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER); 01861 if ($archetype == MOD_ARCHETYPE_RESOURCE) { 01862 $resources[$urlbase.$modname] = $modnamestr; 01863 } else { 01864 // all other archetypes are considered activity 01865 $activities[$urlbase.$modname] = $modnamestr; 01866 } 01867 } 01868 } 01869 01870 $straddactivity = get_string('addactivity'); 01871 $straddresource = get_string('addresource'); 01872 01873 $output = '<div class="section_add_menus">'; 01874 01875 if (!$vertical) { 01876 $output .= '<div class="horizontal">'; 01877 } 01878 01879 if (!empty($resources)) { 01880 $select = new url_select($resources, '', array(''=>$straddresource), "ressection$section"); 01881 $select->set_help_icon('resources'); 01882 $output .= $OUTPUT->render($select); 01883 } 01884 01885 if (!empty($activities)) { 01886 $select = new url_select($activities, '', array(''=>$straddactivity), "section$section"); 01887 $select->set_help_icon('activities'); 01888 $output .= $OUTPUT->render($select); 01889 } 01890 01891 if (!$vertical) { 01892 $output .= '</div>'; 01893 } 01894 01895 $output .= '</div>'; 01896 01897 if ($return) { 01898 return $output; 01899 } else { 01900 echo $output; 01901 } 01902 } 01903 01911 function get_category_or_system_context($categoryid) { 01912 if ($categoryid) { 01913 return get_context_instance(CONTEXT_COURSECAT, $categoryid); 01914 } else { 01915 return get_context_instance(CONTEXT_SYSTEM); 01916 } 01917 } 01918 01926 function get_child_categories($parentid) { 01927 static $allcategories = null; 01928 01929 // only fill in this variable the first time 01930 if (null == $allcategories) { 01931 $allcategories = array(); 01932 01933 $categories = get_categories(); 01934 foreach ($categories as $category) { 01935 if (empty($allcategories[$category->parent])) { 01936 $allcategories[$category->parent] = array(); 01937 } 01938 $allcategories[$category->parent][] = $category; 01939 } 01940 } 01941 01942 if (empty($allcategories[$parentid])) { 01943 return array(); 01944 } else { 01945 return $allcategories[$parentid]; 01946 } 01947 } 01948 01985 function make_categories_list(&$list, &$parents, $requiredcapability = '', 01986 $excludeid = 0, $category = NULL, $path = "") { 01987 01988 // initialize the arrays if needed 01989 if (!is_array($list)) { 01990 $list = array(); 01991 } 01992 if (!is_array($parents)) { 01993 $parents = array(); 01994 } 01995 01996 if (empty($category)) { 01997 // Start at the top level. 01998 $category = new stdClass; 01999 $category->id = 0; 02000 } else { 02001 // This is the excluded category, don't include it. 02002 if ($excludeid > 0 && $excludeid == $category->id) { 02003 return; 02004 } 02005 02006 $context = get_context_instance(CONTEXT_COURSECAT, $category->id); 02007 $categoryname = format_string($category->name, true, array('context' => $context)); 02008 02009 // Update $path. 02010 if ($path) { 02011 $path = $path.' / '.$categoryname; 02012 } else { 02013 $path = $categoryname; 02014 } 02015 02016 // Add this category to $list, if the permissions check out. 02017 if (empty($requiredcapability)) { 02018 $list[$category->id] = $path; 02019 02020 } else { 02021 $requiredcapability = (array)$requiredcapability; 02022 if (has_all_capabilities($requiredcapability, $context)) { 02023 $list[$category->id] = $path; 02024 } 02025 } 02026 } 02027 02028 // Add all the children recursively, while updating the parents array. 02029 if ($categories = get_child_categories($category->id)) { 02030 foreach ($categories as $cat) { 02031 if (!empty($category->id)) { 02032 if (isset($parents[$category->id])) { 02033 $parents[$cat->id] = $parents[$category->id]; 02034 } 02035 $parents[$cat->id][] = $category->id; 02036 } 02037 make_categories_list($list, $parents, $requiredcapability, $excludeid, $cat, $path); 02038 } 02039 } 02040 } 02041 02056 function get_course_category_tree($id = 0, $depth = 0) { 02057 global $DB, $CFG; 02058 $viewhiddencats = has_capability('moodle/category:viewhiddencategories', get_context_instance(CONTEXT_SYSTEM)); 02059 $categories = get_child_categories($id); 02060 $categoryids = array(); 02061 foreach ($categories as $key => &$category) { 02062 if (!$category->visible && !$viewhiddencats) { 02063 unset($categories[$key]); 02064 continue; 02065 } 02066 $categoryids[$category->id] = $category; 02067 if (empty($CFG->maxcategorydepth) || $depth <= $CFG->maxcategorydepth) { 02068 list($category->categories, $subcategories) = get_course_category_tree($category->id, $depth+1); 02069 foreach ($subcategories as $subid=>$subcat) { 02070 $categoryids[$subid] = $subcat; 02071 } 02072 $category->courses = array(); 02073 } 02074 } 02075 02076 if ($depth > 0) { 02077 // This is a recursive call so return the required array 02078 return array($categories, $categoryids); 02079 } 02080 02081 // The depth is 0 this function has just been called so we can finish it off 02082 02083 list($ccselect, $ccjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx'); 02084 list($catsql, $catparams) = $DB->get_in_or_equal(array_keys($categoryids)); 02085 $sql = "SELECT 02086 c.id,c.sortorder,c.visible,c.fullname,c.shortname,c.summary,c.category 02087 $ccselect 02088 FROM {course} c 02089 $ccjoin 02090 WHERE c.category $catsql ORDER BY c.sortorder ASC"; 02091 if ($courses = $DB->get_records_sql($sql, $catparams)) { 02092 // loop throught them 02093 foreach ($courses as $course) { 02094 if ($course->id == SITEID) { 02095 continue; 02096 } 02097 context_instance_preload($course); 02098 if (!empty($course->visible) || has_capability('moodle/course:viewhiddencourses', get_context_instance(CONTEXT_COURSE, $course->id))) { 02099 $categoryids[$course->category]->courses[$course->id] = $course; 02100 } 02101 } 02102 } 02103 return $categories; 02104 } 02105 02110 function print_whole_category_list($category=NULL, $displaylist=NULL, $parentslist=NULL, $depth=-1, $showcourses = true) { 02111 global $CFG; 02112 02113 // maxcategorydepth == 0 meant no limit 02114 if (!empty($CFG->maxcategorydepth) && $depth >= $CFG->maxcategorydepth) { 02115 return; 02116 } 02117 02118 if (!$displaylist) { 02119 make_categories_list($displaylist, $parentslist); 02120 } 02121 02122 if ($category) { 02123 if ($category->visible or has_capability('moodle/category:viewhiddencategories', get_context_instance(CONTEXT_SYSTEM))) { 02124 print_category_info($category, $depth, $showcourses); 02125 } else { 02126 return; // Don't bother printing children of invisible categories 02127 } 02128 02129 } else { 02130 $category = new stdClass(); 02131 $category->id = "0"; 02132 } 02133 02134 if ($categories = get_child_categories($category->id)) { // Print all the children recursively 02135 $countcats = count($categories); 02136 $count = 0; 02137 $first = true; 02138 $last = false; 02139 foreach ($categories as $cat) { 02140 $count++; 02141 if ($count == $countcats) { 02142 $last = true; 02143 } 02144 $up = $first ? false : true; 02145 $down = $last ? false : true; 02146 $first = false; 02147 02148 print_whole_category_list($cat, $displaylist, $parentslist, $depth + 1, $showcourses); 02149 } 02150 } 02151 } 02152 02156 function make_categories_options() { 02157 make_categories_list($cats,$parents); 02158 foreach ($cats as $key => $value) { 02159 if (array_key_exists($key,$parents)) { 02160 if ($indent = count($parents[$key])) { 02161 for ($i = 0; $i < $indent; $i++) { 02162 $cats[$key] = ' '.$cats[$key]; 02163 } 02164 } 02165 } 02166 } 02167 return $cats; 02168 } 02169 02177 function get_course_display_name_for_list($course) { 02178 global $CFG; 02179 if (!empty($CFG->courselistshortnames)) { 02180 return $course->shortname . ' ' .$course->fullname; 02181 } else { 02182 return $course->fullname; 02183 } 02184 } 02185 02190 function print_category_info($category, $depth=0, $showcourses = false) { 02191 global $CFG, $DB, $OUTPUT; 02192 02193 $strsummary = get_string('summary'); 02194 02195 $catlinkcss = null; 02196 if (!$category->visible) { 02197 $catlinkcss = array('class'=>'dimmed'); 02198 } 02199 static $coursecount = null; 02200 if (null === $coursecount) { 02201 // only need to check this once 02202 $coursecount = $DB->count_records('course') <= FRONTPAGECOURSELIMIT; 02203 } 02204 02205 if ($showcourses and $coursecount) { 02206 $catimage = '<img src="'.$OUTPUT->pix_url('i/course') . '" alt="" />'; 02207 } else { 02208 $catimage = " "; 02209 } 02210 02211 $courses = get_courses($category->id, 'c.sortorder ASC', 'c.id,c.sortorder,c.visible,c.fullname,c.shortname,c.summary'); 02212 $context = get_context_instance(CONTEXT_COURSECAT, $category->id); 02213 $fullname = format_string($category->name, true, array('context' => $context)); 02214 02215 if ($showcourses and $coursecount) { 02216 echo '<div class="categorylist clearfix">'; 02217 $cat = ''; 02218 $cat .= html_writer::tag('div', $catimage, array('class'=>'image')); 02219 $catlink = html_writer::link(new moodle_url('/course/category.php', array('id'=>$category->id)), $fullname, $catlinkcss); 02220 $cat .= html_writer::tag('div', $catlink, array('class'=>'name')); 02221 02222 $html = ''; 02223 if ($depth > 0) { 02224 for ($i=0; $i< $depth; $i++) { 02225 $html = html_writer::tag('div', $html . $cat, array('class'=>'indentation')); 02226 $cat = ''; 02227 } 02228 } else { 02229 $html = $cat; 02230 } 02231 echo html_writer::tag('div', $html, array('class'=>'category')); 02232 echo html_writer::tag('div', '', array('class'=>'clearfloat')); 02233 02234 // does the depth exceed maxcategorydepth 02235 // maxcategorydepth == 0 or unset meant no limit 02236 $limit = !(isset($CFG->maxcategorydepth) && ($depth >= $CFG->maxcategorydepth-1)); 02237 if ($courses && ($limit || $CFG->maxcategorydepth == 0)) { 02238 foreach ($courses as $course) { 02239 $linkcss = null; 02240 if (!$course->visible) { 02241 $linkcss = array('class'=>'dimmed'); 02242 } 02243 02244 $coursename = get_course_display_name_for_list($course); 02245 $courselink = html_writer::link(new moodle_url('/course/view.php', array('id'=>$course->id)), format_string($coursename), $linkcss); 02246 02247 // print enrol info 02248 $courseicon = ''; 02249 if ($icons = enrol_get_course_info_icons($course)) { 02250 foreach ($icons as $pix_icon) { 02251 $courseicon = $OUTPUT->render($pix_icon).' '; 02252 } 02253 } 02254 02255 $coursecontent = html_writer::tag('div', $courseicon.$courselink, array('class'=>'name')); 02256 02257 if ($course->summary) { 02258 $link = new moodle_url('/course/info.php?id='.$course->id); 02259 $actionlink = $OUTPUT->action_link($link, '<img alt="'.$strsummary.'" src="'.$OUTPUT->pix_url('i/info') . '" />', 02260 new popup_action('click', $link, 'courseinfo', array('height' => 400, 'width' => 500)), 02261 array('title'=>$strsummary)); 02262 02263 $coursecontent .= html_writer::tag('div', $actionlink, array('class'=>'info')); 02264 } 02265 02266 $html = ''; 02267 for ($i=0; $i <= $depth; $i++) { 02268 $html = html_writer::tag('div', $html . $coursecontent , array('class'=>'indentation')); 02269 $coursecontent = ''; 02270 } 02271 echo html_writer::tag('div', $html, array('class'=>'course clearfloat')); 02272 } 02273 } 02274 echo '</div>'; 02275 } else { 02276 echo '<div class="categorylist">'; 02277 $html = ''; 02278 $cat = html_writer::link(new moodle_url('/course/category.php', array('id'=>$category->id)), $fullname, $catlinkcss); 02279 if (count($courses) > 0) { 02280 $cat .= html_writer::tag('span', ' ('.count($courses).')', array('title'=>get_string('numberofcourses'), 'class'=>'numberofcourse')); 02281 } 02282 02283 if ($depth > 0) { 02284 for ($i=0; $i< $depth; $i++) { 02285 $html = html_writer::tag('div', $html .$cat, array('class'=>'indentation')); 02286 $cat = ''; 02287 } 02288 } else { 02289 $html = $cat; 02290 } 02291 02292 echo html_writer::tag('div', $html, array('class'=>'category')); 02293 echo html_writer::tag('div', '', array('class'=>'clearfloat')); 02294 echo '</div>'; 02295 } 02296 } 02297 02303 function print_course_request_buttons($systemcontext) { 02304 global $CFG, $DB, $OUTPUT; 02305 if (empty($CFG->enablecourserequests)) { 02306 return; 02307 } 02308 if (!has_capability('moodle/course:create', $systemcontext) && has_capability('moodle/course:request', $systemcontext)) { 02310 echo $OUTPUT->single_button('request.php', get_string('requestcourse'), 'get'); 02311 } 02313 if (has_capability('moodle/site:approvecourse', $systemcontext)) { 02314 $disabled = !$DB->record_exists('course_request', array()); 02315 echo $OUTPUT->single_button('pending.php', get_string('coursespending'), 'get', array('disabled'=>$disabled)); 02316 } 02317 } 02318 02325 function can_edit_in_category($categoryid = 0) { 02326 $context = get_category_or_system_context($categoryid); 02327 return has_any_capability(array('moodle/category:manage', 'moodle/course:create'), $context); 02328 } 02329 02337 function update_category_button($categoryid = 0) { 02338 global $CFG, $PAGE, $OUTPUT; 02339 02340 // Check permissions. 02341 if (!can_edit_in_category($categoryid)) { 02342 return ''; 02343 } 02344 02345 // Work out the appropriate action. 02346 if ($PAGE->user_is_editing()) { 02347 $label = get_string('turneditingoff'); 02348 $edit = 'off'; 02349 } else { 02350 $label = get_string('turneditingon'); 02351 $edit = 'on'; 02352 } 02353 02354 // Generate the button HTML. 02355 $options = array('categoryedit' => $edit, 'sesskey' => sesskey()); 02356 if ($categoryid) { 02357 $options['id'] = $categoryid; 02358 $page = 'category.php'; 02359 } else { 02360 $page = 'index.php'; 02361 } 02362 return $OUTPUT->single_button(new moodle_url('/course/' . $page, $options), $label, 'get'); 02363 } 02364 02368 function print_courses($category) { 02369 global $CFG, $OUTPUT; 02370 02371 if (!is_object($category) && $category==0) { 02372 $categories = get_child_categories(0); // Parent = 0 ie top-level categories only 02373 if (is_array($categories) && count($categories) == 1) { 02374 $category = array_shift($categories); 02375 $courses = get_courses_wmanagers($category->id, 02376 'c.sortorder ASC', 02377 array('summary','summaryformat')); 02378 } else { 02379 $courses = get_courses_wmanagers('all', 02380 'c.sortorder ASC', 02381 array('summary','summaryformat')); 02382 } 02383 unset($categories); 02384 } else { 02385 $courses = get_courses_wmanagers($category->id, 02386 'c.sortorder ASC', 02387 array('summary','summaryformat')); 02388 } 02389 02390 if ($courses) { 02391 echo html_writer::start_tag('ul', array('class'=>'unlist')); 02392 foreach ($courses as $course) { 02393 $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); 02394 if ($course->visible == 1 || has_capability('moodle/course:viewhiddencourses', $coursecontext)) { 02395 echo html_writer::start_tag('li'); 02396 print_course($course); 02397 echo html_writer::end_tag('li'); 02398 } 02399 } 02400 echo html_writer::end_tag('ul'); 02401 } else { 02402 echo $OUTPUT->heading(get_string("nocoursesyet")); 02403 $context = get_context_instance(CONTEXT_SYSTEM); 02404 if (has_capability('moodle/course:create', $context)) { 02405 $options = array(); 02406 if (!empty($category->id)) { 02407 $options['category'] = $category->id; 02408 } else { 02409 $options['category'] = $CFG->defaultrequestcategory; 02410 } 02411 echo html_writer::start_tag('div', array('class'=>'addcoursebutton')); 02412 echo $OUTPUT->single_button(new moodle_url('/course/edit.php', $options), get_string("addnewcourse")); 02413 echo html_writer::end_tag('div'); 02414 } 02415 } 02416 } 02417 02424 function print_course($course, $highlightterms = '') { 02425 global $CFG, $USER, $DB, $OUTPUT; 02426 02427 $context = get_context_instance(CONTEXT_COURSE, $course->id); 02428 02429 // Rewrite file URLs so that they are correct 02430 $course->summary = file_rewrite_pluginfile_urls($course->summary, 'pluginfile.php', $context->id, 'course', 'summary', NULL); 02431 02432 echo html_writer::start_tag('div', array('class'=>'coursebox clearfix')); 02433 echo html_writer::start_tag('div', array('class'=>'info')); 02434 echo html_writer::start_tag('h3', array('class'=>'name')); 02435 02436 $linkhref = new moodle_url('/course/view.php', array('id'=>$course->id)); 02437 02438 $coursename = get_course_display_name_for_list($course); 02439 $linktext = highlight($highlightterms, format_string($coursename)); 02440 $linkparams = array('title'=>get_string('entercourse')); 02441 if (empty($course->visible)) { 02442 $linkparams['class'] = 'dimmed'; 02443 } 02444 echo html_writer::link($linkhref, $linktext, $linkparams); 02445 echo html_writer::end_tag('h3'); 02446 02448 if (!empty($CFG->coursecontact)) { 02449 $managerroles = explode(',', $CFG->coursecontact); 02450 $namesarray = array(); 02451 $rusers = array(); 02452 02453 if (!isset($course->managers)) { 02454 $rusers = get_role_users($managerroles, $context, true, 02455 'ra.id AS raid, u.id, u.username, u.firstname, u.lastname, 02456 r.name AS rolename, r.sortorder, r.id AS roleid', 02457 'r.sortorder ASC, u.lastname ASC'); 02458 } else { 02459 // use the managers array if we have it for perf reasosn 02460 // populate the datastructure like output of get_role_users(); 02461 foreach ($course->managers as $manager) { 02462 $u = new stdClass(); 02463 $u = $manager->user; 02464 $u->roleid = $manager->roleid; 02465 $u->rolename = $manager->rolename; 02466 02467 $rusers[] = $u; 02468 } 02469 } 02470 02472 if (isset($context)) { 02473 $aliasnames = $DB->get_records('role_names', array('contextid'=>$context->id), '', 'roleid,contextid,name'); 02474 } 02475 02476 $namesarray = array(); 02477 $canviewfullnames = has_capability('moodle/site:viewfullnames', $context); 02478 foreach ($rusers as $ra) { 02479 if (isset($namesarray[$ra->id])) { 02480 // only display a user once with the higest sortorder role 02481 continue; 02482 } 02483 02484 if (isset($aliasnames[$ra->roleid])) { 02485 $ra->rolename = $aliasnames[$ra->roleid]->name; 02486 } 02487 02488 $fullname = fullname($ra, $canviewfullnames); 02489 $namesarray[$ra->id] = format_string($ra->rolename).': '. 02490 html_writer::link(new moodle_url('/user/view.php', array('id'=>$ra->id, 'course'=>SITEID)), $fullname); 02491 } 02492 02493 if (!empty($namesarray)) { 02494 echo html_writer::start_tag('ul', array('class'=>'teachers')); 02495 foreach ($namesarray as $name) { 02496 echo html_writer::tag('li', $name); 02497 } 02498 echo html_writer::end_tag('ul'); 02499 } 02500 } 02501 echo html_writer::end_tag('div'); // End of info div 02502 02503 echo html_writer::start_tag('div', array('class'=>'summary')); 02504 $options = new stdClass(); 02505 $options->noclean = true; 02506 $options->para = false; 02507 $options->overflowdiv = true; 02508 if (!isset($course->summaryformat)) { 02509 $course->summaryformat = FORMAT_MOODLE; 02510 } 02511 echo highlight($highlightterms, format_text($course->summary, $course->summaryformat, $options, $course->id)); 02512 if ($icons = enrol_get_course_info_icons($course)) { 02513 echo html_writer::start_tag('div', array('class'=>'enrolmenticons')); 02514 foreach ($icons as $icon) { 02515 echo $OUTPUT->render($icon); 02516 } 02517 echo html_writer::end_tag('div'); // End of enrolmenticons div 02518 } 02519 echo html_writer::end_tag('div'); // End of summary div 02520 echo html_writer::end_tag('div'); // End of coursebox div 02521 } 02522 02527 function print_my_moodle() { 02528 global $USER, $CFG, $DB, $OUTPUT; 02529 02530 if (!isloggedin() or isguestuser()) { 02531 print_error('nopermissions', '', '', 'See My Moodle'); 02532 } 02533 02534 $courses = enrol_get_my_courses('summary', 'visible DESC,sortorder ASC'); 02535 $rhosts = array(); 02536 $rcourses = array(); 02537 if (!empty($CFG->mnet_dispatcher_mode) && $CFG->mnet_dispatcher_mode==='strict') { 02538 $rcourses = get_my_remotecourses($USER->id); 02539 $rhosts = get_my_remotehosts(); 02540 } 02541 02542 if (!empty($courses) || !empty($rcourses) || !empty($rhosts)) { 02543 02544 if (!empty($courses)) { 02545 echo '<ul class="unlist">'; 02546 foreach ($courses as $course) { 02547 if ($course->id == SITEID) { 02548 continue; 02549 } 02550 echo '<li>'; 02551 print_course($course); 02552 echo "</li>\n"; 02553 } 02554 echo "</ul>\n"; 02555 } 02556 02557 // MNET 02558 if (!empty($rcourses)) { 02559 // at the IDP, we know of all the remote courses 02560 foreach ($rcourses as $course) { 02561 print_remote_course($course, "100%"); 02562 } 02563 } elseif (!empty($rhosts)) { 02564 // non-IDP, we know of all the remote servers, but not courses 02565 foreach ($rhosts as $host) { 02566 print_remote_host($host, "100%"); 02567 } 02568 } 02569 unset($course); 02570 unset($host); 02571 02572 if ($DB->count_records("course") > (count($courses) + 1) ) { // Some courses not being displayed 02573 echo "<table width=\"100%\"><tr><td align=\"center\">"; 02574 print_course_search("", false, "short"); 02575 echo "</td><td align=\"center\">"; 02576 echo $OUTPUT->single_button("$CFG->wwwroot/course/index.php", get_string("fulllistofcourses"), "get"); 02577 echo "</td></tr></table>\n"; 02578 } 02579 02580 } else { 02581 if ($DB->count_records("course_categories") > 1) { 02582 echo $OUTPUT->box_start("categorybox"); 02583 print_whole_category_list(); 02584 echo $OUTPUT->box_end(); 02585 } else { 02586 print_courses(0); 02587 } 02588 } 02589 } 02590 02591 02592 function print_course_search($value="", $return=false, $format="plain") { 02593 global $CFG; 02594 static $count = 0; 02595 02596 $count++; 02597 02598 $id = 'coursesearch'; 02599 02600 if ($count > 1) { 02601 $id .= $count; 02602 } 02603 02604 $strsearchcourses= get_string("searchcourses"); 02605 02606 if ($format == 'plain') { 02607 $output = '<form id="'.$id.'" action="'.$CFG->wwwroot.'/course/search.php" method="get">'; 02608 $output .= '<fieldset class="coursesearchbox invisiblefieldset">'; 02609 $output .= '<label for="coursesearchbox">'.$strsearchcourses.': </label>'; 02610 $output .= '<input type="text" id="coursesearchbox" size="30" name="search" value="'.s($value).'" />'; 02611 $output .= '<input type="submit" value="'.get_string('go').'" />'; 02612 $output .= '</fieldset></form>'; 02613 } else if ($format == 'short') { 02614 $output = '<form id="'.$id.'" action="'.$CFG->wwwroot.'/course/search.php" method="get">'; 02615 $output .= '<fieldset class="coursesearchbox invisiblefieldset">'; 02616 $output .= '<label for="shortsearchbox">'.$strsearchcourses.': </label>'; 02617 $output .= '<input type="text" id="shortsearchbox" size="12" name="search" alt="'.s($strsearchcourses).'" value="'.s($value).'" />'; 02618 $output .= '<input type="submit" value="'.get_string('go').'" />'; 02619 $output .= '</fieldset></form>'; 02620 } else if ($format == 'navbar') { 02621 $output = '<form id="coursesearchnavbar" action="'.$CFG->wwwroot.'/course/search.php" method="get">'; 02622 $output .= '<fieldset class="coursesearchbox invisiblefieldset">'; 02623 $output .= '<label for="navsearchbox">'.$strsearchcourses.': </label>'; 02624 $output .= '<input type="text" id="navsearchbox" size="20" name="search" alt="'.s($strsearchcourses).'" value="'.s($value).'" />'; 02625 $output .= '<input type="submit" value="'.get_string('go').'" />'; 02626 $output .= '</fieldset></form>'; 02627 } 02628 02629 if ($return) { 02630 return $output; 02631 } 02632 echo $output; 02633 } 02634 02635 function print_remote_course($course, $width="100%") { 02636 global $CFG, $USER; 02637 02638 $linkcss = ''; 02639 02640 $url = "{$CFG->wwwroot}/auth/mnet/jump.php?hostid={$course->hostid}&wantsurl=/course/view.php?id={$course->remoteid}"; 02641 02642 echo '<div class="coursebox remotecoursebox clearfix">'; 02643 echo '<div class="info">'; 02644 echo '<div class="name"><a title="'.get_string('entercourse').'"'. 02645 $linkcss.' href="'.$url.'">' 02646 . format_string($course->fullname) .'</a><br />' 02647 . format_string($course->hostname) . ' : ' 02648 . format_string($course->cat_name) . ' : ' 02649 . format_string($course->shortname). '</div>'; 02650 echo '</div><div class="summary">'; 02651 $options = new stdClass(); 02652 $options->noclean = true; 02653 $options->para = false; 02654 $options->overflowdiv = true; 02655 echo format_text($course->summary, $course->summaryformat, $options); 02656 echo '</div>'; 02657 echo '</div>'; 02658 } 02659 02660 function print_remote_host($host, $width="100%") { 02661 global $OUTPUT; 02662 02663 $linkcss = ''; 02664 02665 echo '<div class="coursebox clearfix">'; 02666 echo '<div class="info">'; 02667 echo '<div class="name">'; 02668 echo '<img src="'.$OUTPUT->pix_url('i/mnethost') . '" class="icon" alt="'.get_string('course').'" />'; 02669 echo '<a title="'.s($host['name']).'" href="'.s($host['url']).'">' 02670 . s($host['name']).'</a> - '; 02671 echo $host['count'] . ' ' . get_string('courses'); 02672 echo '</div>'; 02673 echo '</div>'; 02674 echo '</div>'; 02675 } 02676 02677 02679 02680 function add_course_module($mod) { 02681 global $DB; 02682 02683 $mod->added = time(); 02684 unset($mod->id); 02685 02686 return $DB->insert_record("course_modules", $mod); 02687 } 02688 02695 function get_course_section($section, $courseid) { 02696 global $DB; 02697 02698 if ($cw = $DB->get_record("course_sections", array("section"=>$section, "course"=>$courseid))) { 02699 return $cw; 02700 } 02701 $cw = new stdClass(); 02702 $cw->course = $courseid; 02703 $cw->section = $section; 02704 $cw->summary = ""; 02705 $cw->summaryformat = FORMAT_HTML; 02706 $cw->sequence = ""; 02707 $id = $DB->insert_record("course_sections", $cw); 02708 return $DB->get_record("course_sections", array("id"=>$id)); 02709 } 02717 function add_mod_to_section($mod, $beforemod=NULL) { 02718 global $DB; 02719 02720 if ($section = $DB->get_record("course_sections", array("course"=>$mod->course, "section"=>$mod->section))) { 02721 02722 $section->sequence = trim($section->sequence); 02723 02724 if (empty($section->sequence)) { 02725 $newsequence = "$mod->coursemodule"; 02726 02727 } else if ($beforemod) { 02728 $modarray = explode(",", $section->sequence); 02729 02730 if ($key = array_keys($modarray, $beforemod->id)) { 02731 $insertarray = array($mod->id, $beforemod->id); 02732 array_splice($modarray, $key[0], 1, $insertarray); 02733 $newsequence = implode(",", $modarray); 02734 02735 } else { // Just tack it on the end anyway 02736 $newsequence = "$section->sequence,$mod->coursemodule"; 02737 } 02738 02739 } else { 02740 $newsequence = "$section->sequence,$mod->coursemodule"; 02741 } 02742 02743 $DB->set_field("course_sections", "sequence", $newsequence, array("id"=>$section->id)); 02744 return $section->id; // Return course_sections ID that was used. 02745 02746 } else { // Insert a new record 02747 $section->course = $mod->course; 02748 $section->section = $mod->section; 02749 $section->summary = ""; 02750 $section->summaryformat = FORMAT_HTML; 02751 $section->sequence = $mod->coursemodule; 02752 return $DB->insert_record("course_sections", $section); 02753 } 02754 } 02755 02756 function set_coursemodule_groupmode($id, $groupmode) { 02757 global $DB; 02758 return $DB->set_field("course_modules", "groupmode", $groupmode, array("id"=>$id)); 02759 } 02760 02761 function set_coursemodule_idnumber($id, $idnumber) { 02762 global $DB; 02763 return $DB->set_field("course_modules", "idnumber", $idnumber, array("id"=>$id)); 02764 } 02765 02773 function set_coursemodule_visible($id, $visible, $prevstateoverrides=false) { 02774 global $DB, $CFG; 02775 require_once($CFG->libdir.'/gradelib.php'); 02776 02777 if (!$cm = $DB->get_record('course_modules', array('id'=>$id))) { 02778 return false; 02779 } 02780 if (!$modulename = $DB->get_field('modules', 'name', array('id'=>$cm->module))) { 02781 return false; 02782 } 02783 if ($events = $DB->get_records('event', array('instance'=>$cm->instance, 'modulename'=>$modulename))) { 02784 foreach($events as $event) { 02785 if ($visible) { 02786 show_event($event); 02787 } else { 02788 hide_event($event); 02789 } 02790 } 02791 } 02792 02793 // hide the associated grade items so the teacher doesn't also have to go to the gradebook and hide them there 02794 $grade_items = grade_item::fetch_all(array('itemtype'=>'mod', 'itemmodule'=>$modulename, 'iteminstance'=>$cm->instance, 'courseid'=>$cm->course)); 02795 if ($grade_items) { 02796 foreach ($grade_items as $grade_item) { 02797 $grade_item->set_hidden(!$visible); 02798 } 02799 } 02800 02801 if ($prevstateoverrides) { 02802 if ($visible == '0') { 02803 // Remember the current visible state so we can toggle this back. 02804 $DB->set_field('course_modules', 'visibleold', $cm->visible, array('id'=>$id)); 02805 } else { 02806 // Get the previous saved visible states. 02807 return $DB->set_field('course_modules', 'visible', $cm->visibleold, array('id'=>$id)); 02808 } 02809 } 02810 return $DB->set_field("course_modules", "visible", $visible, array("id"=>$id)); 02811 } 02812 02819 function delete_course_module($id) { 02820 global $CFG, $DB; 02821 require_once($CFG->libdir.'/gradelib.php'); 02822 require_once($CFG->dirroot.'/blog/lib.php'); 02823 02824 if (!$cm = $DB->get_record('course_modules', array('id'=>$id))) { 02825 return true; 02826 } 02827 $modulename = $DB->get_field('modules', 'name', array('id'=>$cm->module)); 02828 //delete events from calendar 02829 if ($events = $DB->get_records('event', array('instance'=>$cm->instance, 'modulename'=>$modulename))) { 02830 foreach($events as $event) { 02831 delete_event($event->id); 02832 } 02833 } 02834 //delete grade items, outcome items and grades attached to modules 02835 if ($grade_items = grade_item::fetch_all(array('itemtype'=>'mod', 'itemmodule'=>$modulename, 02836 'iteminstance'=>$cm->instance, 'courseid'=>$cm->course))) { 02837 foreach ($grade_items as $grade_item) { 02838 $grade_item->delete('moddelete'); 02839 } 02840 } 02841 // Delete completion and availability data; it is better to do this even if the 02842 // features are not turned on, in case they were turned on previously (these will be 02843 // very quick on an empty table) 02844 $DB->delete_records('course_modules_completion', array('coursemoduleid' => $cm->id)); 02845 $DB->delete_records('course_modules_availability', array('coursemoduleid'=> $cm->id)); 02846 02847 delete_context(CONTEXT_MODULE, $cm->id); 02848 return $DB->delete_records('course_modules', array('id'=>$cm->id)); 02849 } 02850 02851 function delete_mod_from_section($mod, $section) { 02852 global $DB; 02853 02854 if ($section = $DB->get_record("course_sections", array("id"=>$section)) ) { 02855 02856 $modarray = explode(",", $section->sequence); 02857 02858 if ($key = array_keys ($modarray, $mod)) { 02859 array_splice($modarray, $key[0], 1); 02860 $newsequence = implode(",", $modarray); 02861 return $DB->set_field("course_sections", "sequence", $newsequence, array("id"=>$section->id)); 02862 } else { 02863 return false; 02864 } 02865 02866 } 02867 return false; 02868 } 02869 02877 function move_section($course, $section, $move) { 02879 global $USER, $DB; 02880 02881 if (!$move) { 02882 return true; 02883 } 02884 02885 $sectiondest = $section + $move; 02886 02887 if ($sectiondest > $course->numsections or $sectiondest < 1) { 02888 return false; 02889 } 02890 02891 if (!$sectionrecord = $DB->get_record("course_sections", array("course"=>$course->id, "section"=>$section))) { 02892 return false; 02893 } 02894 02895 if (!$sectiondestrecord = $DB->get_record("course_sections", array("course"=>$course->id, "section"=>$sectiondest))) { 02896 return false; 02897 } 02898 02899 $DB->set_field("course_sections", "section", $sectiondest, array("id"=>$sectionrecord->id)); 02900 $DB->set_field("course_sections", "section", $section, array("id"=>$sectiondestrecord->id)); 02901 02902 // if the focus is on the section that is being moved, then move the focus along 02903 if (course_get_display($course->id) == $section) { 02904 course_set_display($course->id, $sectiondest); 02905 } 02906 02907 // Check for duplicates and fix order if needed. 02908 // There is a very rare case that some sections in the same course have the same section id. 02909 $sections = $DB->get_records('course_sections', array('course'=>$course->id), 'section ASC'); 02910 $n = 0; 02911 foreach ($sections as $section) { 02912 if ($section->section != $n) { 02913 $DB->set_field('course_sections', 'section', $n, array('id'=>$section->id)); 02914 } 02915 $n++; 02916 } 02917 return true; 02918 } 02919 02930 function move_section_to($course, $section, $destination) { 02932 global $USER, $DB; 02933 02934 if (!$destination && $destination != 0) { 02935 return true; 02936 } 02937 02938 if ($destination > $course->numsections) { 02939 return false; 02940 } 02941 02942 // Get all sections for this course and re-order them (2 of them should now share the same section number) 02943 if (!$sections = $DB->get_records_menu('course_sections', array('course' => $course->id), 02944 'section ASC, id ASC', 'id, section')) { 02945 return false; 02946 } 02947 02948 $sections = reorder_sections($sections, $section, $destination); 02949 02950 // Update all sections 02951 foreach ($sections as $id => $position) { 02952 $DB->set_field('course_sections', 'section', $position, array('id' => $id)); 02953 } 02954 02955 // if the focus is on the section that is being moved, then move the focus along 02956 if (course_get_display($course->id) == $section) { 02957 course_set_display($course->id, $destination); 02958 } 02959 return true; 02960 } 02961 02974 function reorder_sections($sections, $origin_position, $target_position) { 02975 if (!is_array($sections)) { 02976 return false; 02977 } 02978 02979 // We can't move section position 0 02980 if ($origin_position < 1) { 02981 echo "We can't move section position 0"; 02982 return false; 02983 } 02984 02985 // Locate origin section in sections array 02986 if (!$origin_key = array_search($origin_position, $sections)) { 02987 echo "searched position not in sections array"; 02988 return false; // searched position not in sections array 02989 } 02990 02991 // Extract origin section 02992 $origin_section = $sections[$origin_key]; 02993 unset($sections[$origin_key]); 02994 02995 // Find offset of target position (stupid PHP's array_splice requires offset instead of key index!) 02996 $found = false; 02997 $append_array = array(); 02998 foreach ($sections as $id => $position) { 02999 if ($found) { 03000 $append_array[$id] = $position; 03001 unset($sections[$id]); 03002 } 03003 if ($position == $target_position) { 03004 $found = true; 03005 } 03006 } 03007 03008 // Append moved section 03009 $sections[$origin_key] = $origin_section; 03010 03011 // Append rest of array (if applicable) 03012 if (!empty($append_array)) { 03013 foreach ($append_array as $id => $position) { 03014 $sections[$id] = $position; 03015 } 03016 } 03017 03018 // Renumber positions 03019 $position = 0; 03020 foreach ($sections as $id => $p) { 03021 $sections[$id] = $position; 03022 $position++; 03023 } 03024 03025 return $sections; 03026 03027 } 03028 03035 function moveto_module($mod, $section, $beforemod=NULL) { 03036 global $DB, $OUTPUT; 03037 03039 if (! delete_mod_from_section($mod->id, $mod->section)) { 03040 echo $OUTPUT->notification("Could not delete module from existing section"); 03041 } 03042 03044 03045 if ($mod->section != $section->id) { 03046 $mod->section = $section->id; 03047 $DB->update_record("course_modules", $mod); 03048 // if moving to a hidden section then hide module 03049 if (!$section->visible) { 03050 set_coursemodule_visible($mod->id, 0); 03051 } 03052 } 03053 03055 03056 $mod->course = $section->course; 03057 $mod->section = $section->section; // need relative reference 03058 $mod->coursemodule = $mod->id; 03059 03060 if (! add_mod_to_section($mod, $beforemod)) { 03061 return false; 03062 } 03063 03064 return true; 03065 } 03066 03079 function make_editing_buttons(stdClass $mod, $absolute_ignored = true, $moveselect = true, $indent=-1, $section=-1) { 03080 global $CFG, $OUTPUT; 03081 03082 static $str; 03083 03084 $coursecontext = get_context_instance(CONTEXT_COURSE, $mod->course); 03085 $modcontext = get_context_instance(CONTEXT_MODULE, $mod->id); 03086 03087 $editcaps = array('moodle/course:manageactivities', 'moodle/course:activityvisibility', 'moodle/role:assign'); 03088 $dupecaps = array('moodle/backup:backuptargetimport', 'moodle/restore:restoretargetimport'); 03089 03090 // no permission to edit anything 03091 if (!has_any_capability($editcaps, $modcontext) and !has_all_capabilities($dupecaps, $coursecontext)) { 03092 return false; 03093 } 03094 03095 $hasmanageactivities = has_capability('moodle/course:manageactivities', $modcontext); 03096 03097 if (!isset($str)) { 03098 $str = new stdClass; 03099 $str->assign = get_string("assignroles", 'role'); 03100 $str->delete = get_string("delete"); 03101 $str->move = get_string("move"); 03102 $str->moveup = get_string("moveup"); 03103 $str->movedown = get_string("movedown"); 03104 $str->moveright = get_string("moveright"); 03105 $str->moveleft = get_string("moveleft"); 03106 $str->update = get_string("update"); 03107 $str->duplicate = get_string("duplicate"); 03108 $str->hide = get_string("hide"); 03109 $str->show = get_string("show"); 03110 $str->groupsnone = get_string('clicktochangeinbrackets', 'moodle', get_string("groupsnone")); 03111 $str->groupsseparate = get_string('clicktochangeinbrackets', 'moodle', get_string("groupsseparate")); 03112 $str->groupsvisible = get_string('clicktochangeinbrackets', 'moodle', get_string("groupsvisible")); 03113 $str->forcedgroupsnone = get_string('forcedmodeinbrackets', 'moodle', get_string("groupsnone")); 03114 $str->forcedgroupsseparate = get_string('forcedmodeinbrackets', 'moodle', get_string("groupsseparate")); 03115 $str->forcedgroupsvisible = get_string('forcedmodeinbrackets', 'moodle', get_string("groupsvisible")); 03116 } 03117 03118 $baseurl = new moodle_url('/course/mod.php', array('sesskey' => sesskey())); 03119 03120 if ($section >= 0) { 03121 $baseurl->param('sr', $section); 03122 } 03123 $actions = array(); 03124 03125 // leftright 03126 if ($hasmanageactivities) { 03127 if (right_to_left()) { // Exchange arrows on RTL 03128 $rightarrow = 't/left'; 03129 $leftarrow = 't/right'; 03130 } else { 03131 $rightarrow = 't/right'; 03132 $leftarrow = 't/left'; 03133 } 03134 03135 if ($indent > 0) { 03136 $actions[] = new action_link( 03137 new moodle_url($baseurl, array('id' => $mod->id, 'indent' => '-1')), 03138 new pix_icon($leftarrow, $str->moveleft, 'moodle', array('class' => 'iconsmall')), 03139 null, 03140 array('class' => 'editing_moveleft', 'title' => $str->moveleft) 03141 ); 03142 } 03143 if ($indent >= 0) { 03144 $actions[] = new action_link( 03145 new moodle_url($baseurl, array('id' => $mod->id, 'indent' => '1')), 03146 new pix_icon($rightarrow, $str->moveright, 'moodle', array('class' => 'iconsmall')), 03147 null, 03148 array('class' => 'editing_moveright', 'title' => $str->moveright) 03149 ); 03150 } 03151 } 03152 03153 // move 03154 if ($hasmanageactivities) { 03155 if ($moveselect) { 03156 $actions[] = new action_link( 03157 new moodle_url($baseurl, array('copy' => $mod->id)), 03158 new pix_icon('t/move', $str->move, 'moodle', array('class' => 'iconsmall')), 03159 null, 03160 array('class' => 'editing_move', 'title' => $str->move) 03161 ); 03162 } else { 03163 $actions[] = new action_link( 03164 new moodle_url($baseurl, array('id' => $mod->id, 'move' => '-1')), 03165 new pix_icon('t/up', $str->moveup, 'moodle', array('class' => 'iconsmall')), 03166 null, 03167 array('class' => 'editing_moveup', 'title' => $str->moveup) 03168 ); 03169 $actions[] = new action_link( 03170 new moodle_url($baseurl, array('id' => $mod->id, 'move' => '1')), 03171 new pix_icon('t/down', $str->movedown, 'moodle', array('class' => 'iconsmall')), 03172 null, 03173 array('class' => 'editing_movedown', 'title' => $str->movedown) 03174 ); 03175 } 03176 } 03177 03178 // Update 03179 if ($hasmanageactivities) { 03180 $actions[] = new action_link( 03181 new moodle_url($baseurl, array('update' => $mod->id)), 03182 new pix_icon('t/edit', $str->update, 'moodle', array('class' => 'iconsmall')), 03183 null, 03184 array('class' => 'editing_update', 'title' => $str->update) 03185 ); 03186 } 03187 03188 // Duplicate (require both target import caps to be able to duplicate, see modduplicate.php) 03189 if (has_all_capabilities($dupecaps, $coursecontext)) { 03190 $actions[] = new action_link( 03191 new moodle_url($baseurl, array('duplicate' => $mod->id)), 03192 new pix_icon('t/copy', $str->duplicate, 'moodle', array('class' => 'iconsmall')), 03193 null, 03194 array('class' => 'editing_duplicate', 'title' => $str->duplicate) 03195 ); 03196 } 03197 03198 // Delete 03199 if ($hasmanageactivities) { 03200 $actions[] = new action_link( 03201 new moodle_url($baseurl, array('delete' => $mod->id)), 03202 new pix_icon('t/delete', $str->delete, 'moodle', array('class' => 'iconsmall')), 03203 null, 03204 array('class' => 'editing_delete', 'title' => $str->delete) 03205 ); 03206 } 03207 03208 // hideshow 03209 if (has_capability('moodle/course:activityvisibility', $modcontext)) { 03210 if ($mod->visible) { 03211 $actions[] = new action_link( 03212 new moodle_url($baseurl, array('hide' => $mod->id)), 03213 new pix_icon('t/hide', $str->hide, 'moodle', array('class' => 'iconsmall')), 03214 null, 03215 array('class' => 'editing_hide', 'title' => $str->hide) 03216 ); 03217 } else { 03218 $actions[] = new action_link( 03219 new moodle_url($baseurl, array('show' => $mod->id)), 03220 new pix_icon('t/show', $str->show, 'moodle', array('class' => 'iconsmall')), 03221 null, 03222 array('class' => 'editing_show', 'title' => $str->show) 03223 ); 03224 } 03225 } 03226 03227 // groupmode 03228 if ($hasmanageactivities and $mod->groupmode !== false) { 03229 if ($mod->groupmode == SEPARATEGROUPS) { 03230 $groupmode = 0; 03231 $grouptitle = $str->groupsseparate; 03232 $forcedgrouptitle = $str->forcedgroupsseparate; 03233 $groupclass = 'editing_groupsseparate'; 03234 $groupimage = 't/groups'; 03235 } else if ($mod->groupmode == VISIBLEGROUPS) { 03236 $groupmode = 1; 03237 $grouptitle = $str->groupsvisible; 03238 $forcedgrouptitle = $str->forcedgroupsvisible; 03239 $groupclass = 'editing_groupsvisible'; 03240 $groupimage = 't/groupv'; 03241 } else { 03242 $groupmode = 2; 03243 $grouptitle = $str->groupsnone; 03244 $forcedgrouptitle = $str->forcedgroupsnone; 03245 $groupclass = 'editing_groupsnone'; 03246 $groupimage = 't/groupn'; 03247 } 03248 if ($mod->groupmodelink) { 03249 $actions[] = new action_link( 03250 new moodle_url($baseurl, array('id' => $mod->id, 'groupmode' => $groupmode)), 03251 new pix_icon($groupimage, $grouptitle, 'moodle', array('class' => 'iconsmall')), 03252 null, 03253 array('class' => $groupclass, 'title' => $grouptitle) 03254 ); 03255 } else { 03256 $actions[] = new pix_icon($groupimage, $forcedgrouptitle, 'moodle', array('title' => $forcedgrouptitle, 'class' => 'iconsmall')); 03257 } 03258 } 03259 03260 // Assign 03261 if (has_capability('moodle/role:assign', $modcontext)){ 03262 $actions[] = new action_link( 03263 new moodle_url('/'.$CFG->admin.'/roles/assign.php', array('contextid' => $modcontext->id)), 03264 new pix_icon('i/roles', $str->assign, 'moodle', array('class' => 'iconsmall')), 03265 null, 03266 array('class' => 'editing_assign', 'title' => $str->assign) 03267 ); 03268 } 03269 03270 $output = html_writer::start_tag('span', array('class' => 'commands')); 03271 foreach ($actions as $action) { 03272 if ($action instanceof renderable) { 03273 $output .= $OUTPUT->render($action); 03274 } else { 03275 $output .= $action; 03276 } 03277 } 03278 $output .= html_writer::end_tag('span'); 03279 return $output; 03280 } 03281 03286 function course_format_name ($course,$max=100) { 03287 03288 $context = get_context_instance(CONTEXT_COURSE, $course->id); 03289 $shortname = format_string($course->shortname, true, array('context' => $context)); 03290 $fullname = format_string($course->fullname, true, array('context' => get_context_instance(CONTEXT_COURSE, $course->id))); 03291 $str = $shortname.': '. $fullname; 03292 if (textlib::strlen($str) <= $max) { 03293 return $str; 03294 } 03295 else { 03296 return textlib::substr($str,0,$max-3).'...'; 03297 } 03298 } 03299 03300 function update_restricted_mods($course, $mods) { 03301 global $DB; 03302 03304 $DB->delete_records('course_allowed_modules', array('course'=>$course->id)); 03305 03306 if (empty($course->restrictmodules)) { 03307 return; // We're done 03308 } 03309 03311 foreach ($mods as $mod) { 03312 if ($mod == 0) { 03313 continue; // this is the 'allow none' option 03314 } 03315 $am = new stdClass(); 03316 $am->course = $course->id; 03317 $am->module = $mod; 03318 $DB->insert_record('course_allowed_modules',$am); 03319 } 03320 } 03321 03329 function course_allowed_module($course,$mod) { 03330 global $DB; 03331 03332 if (empty($course->restrictmodules)) { 03333 return true; 03334 } 03335 03336 // Admins and admin-like people who can edit everything can also add anything. 03337 // Originally there was a course:update test only, but it did not match the test in course edit form 03338 if (has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) { 03339 return true; 03340 } 03341 03342 if (is_numeric($mod)) { 03343 $modid = $mod; 03344 } else if (is_string($mod)) { 03345 $modid = $DB->get_field('modules', 'id', array('name'=>$mod)); 03346 } 03347 if (empty($modid)) { 03348 return false; 03349 } 03350 03351 return $DB->record_exists('course_allowed_modules', array('course'=>$course->id, 'module'=>$modid)); 03352 } 03353 03360 function category_delete_full($category, $showfeedback=true) { 03361 global $CFG, $DB; 03362 require_once($CFG->libdir.'/gradelib.php'); 03363 require_once($CFG->libdir.'/questionlib.php'); 03364 require_once($CFG->dirroot.'/cohort/lib.php'); 03365 03366 if ($children = $DB->get_records('course_categories', array('parent'=>$category->id), 'sortorder ASC')) { 03367 foreach ($children as $childcat) { 03368 category_delete_full($childcat, $showfeedback); 03369 } 03370 } 03371 03372 $deletedcourses = array(); 03373 if ($courses = $DB->get_records('course', array('category'=>$category->id), 'sortorder ASC')) { 03374 foreach ($courses as $course) { 03375 if (!delete_course($course, false)) { 03376 throw new moodle_exception('cannotdeletecategorycourse','','',$course->shortname); 03377 } 03378 $deletedcourses[] = $course; 03379 } 03380 } 03381 03382 // move or delete cohorts in this context 03383 cohort_delete_category($category); 03384 03385 // now delete anything that may depend on course category context 03386 grade_course_category_delete($category->id, 0, $showfeedback); 03387 if (!question_delete_course_category($category, 0, $showfeedback)) { 03388 throw new moodle_exception('cannotdeletecategoryquestions','','',$category->name); 03389 } 03390 03391 // finally delete the category and it's context 03392 $DB->delete_records('course_categories', array('id'=>$category->id)); 03393 delete_context(CONTEXT_COURSECAT, $category->id); 03394 03395 events_trigger('course_category_deleted', $category); 03396 03397 return $deletedcourses; 03398 } 03399 03406 function category_delete_move($category, $newparentid, $showfeedback=true) { 03407 global $CFG, $DB, $OUTPUT; 03408 require_once($CFG->libdir.'/gradelib.php'); 03409 require_once($CFG->libdir.'/questionlib.php'); 03410 require_once($CFG->dirroot.'/cohort/lib.php'); 03411 03412 if (!$newparentcat = $DB->get_record('course_categories', array('id'=>$newparentid))) { 03413 return false; 03414 } 03415 03416 if ($children = $DB->get_records('course_categories', array('parent'=>$category->id), 'sortorder ASC')) { 03417 foreach ($children as $childcat) { 03418 move_category($childcat, $newparentcat); 03419 } 03420 } 03421 03422 if ($courses = $DB->get_records('course', array('category'=>$category->id), 'sortorder ASC', 'id')) { 03423 if (!move_courses(array_keys($courses), $newparentid)) { 03424 echo $OUTPUT->notification("Error moving courses"); 03425 return false; 03426 } 03427 echo $OUTPUT->notification(get_string('coursesmovedout', '', format_string($category->name)), 'notifysuccess'); 03428 } 03429 03430 // move or delete cohorts in this context 03431 cohort_delete_category($category); 03432 03433 // now delete anything that may depend on course category context 03434 grade_course_category_delete($category->id, $newparentid, $showfeedback); 03435 if (!question_delete_course_category($category, $newparentcat, $showfeedback)) { 03436 echo $OUTPUT->notification(get_string('errordeletingquestionsfromcategory', 'question', $category), 'notifysuccess'); 03437 return false; 03438 } 03439 03440 // finally delete the category and it's context 03441 $DB->delete_records('course_categories', array('id'=>$category->id)); 03442 delete_context(CONTEXT_COURSECAT, $category->id); 03443 03444 events_trigger('course_category_deleted', $category); 03445 03446 echo $OUTPUT->notification(get_string('coursecategorydeleted', '', format_string($category->name)), 'notifysuccess'); 03447 03448 return true; 03449 } 03450 03459 function move_courses($courseids, $categoryid) { 03460 global $CFG, $DB, $OUTPUT; 03461 03462 if (empty($courseids)) { 03463 // nothing to do 03464 return; 03465 } 03466 03467 if (!$category = $DB->get_record('course_categories', array('id'=>$categoryid))) { 03468 return false; 03469 } 03470 03471 $courseids = array_reverse($courseids); 03472 $newparent = get_context_instance(CONTEXT_COURSECAT, $category->id); 03473 $i = 1; 03474 03475 foreach ($courseids as $courseid) { 03476 if ($course = $DB->get_record('course', array('id'=>$courseid), 'id, category')) { 03477 $course = new stdClass(); 03478 $course->id = $courseid; 03479 $course->category = $category->id; 03480 $course->sortorder = $category->sortorder + MAX_COURSES_IN_CATEGORY - $i++; 03481 if ($category->visible == 0) { 03482 // hide the course when moving into hidden category, 03483 // do not update the visibleold flag - we want to get to previous state if somebody unhides the category 03484 $course->visible = 0; 03485 } 03486 03487 $DB->update_record('course', $course); 03488 03489 $context = get_context_instance(CONTEXT_COURSE, $course->id); 03490 context_moved($context, $newparent); 03491 } 03492 } 03493 fix_course_sortorder(); 03494 03495 return true; 03496 } 03497 03503 function course_category_hide($category) { 03504 global $DB; 03505 03506 $category->visible = 0; 03507 $DB->set_field('course_categories', 'visible', 0, array('id'=>$category->id)); 03508 $DB->set_field('course_categories', 'visibleold', 0, array('id'=>$category->id)); 03509 $DB->execute("UPDATE {course} SET visibleold = visible WHERE category = ?", array($category->id)); // store visible flag so that we can return to it if we immediately unhide 03510 $DB->set_field('course', 'visible', 0, array('category' => $category->id)); 03511 // get all child categories and hide too 03512 if ($subcats = $DB->get_records_select('course_categories', "path LIKE ?", array("$category->path/%"))) { 03513 foreach ($subcats as $cat) { 03514 $DB->set_field('course_categories', 'visibleold', $cat->visible, array('id'=>$cat->id)); 03515 $DB->set_field('course_categories', 'visible', 0, array('id'=>$cat->id)); 03516 $DB->execute("UPDATE {course} SET visibleold = visible WHERE category = ?", array($cat->id)); 03517 $DB->set_field('course', 'visible', 0, array('category' => $cat->id)); 03518 } 03519 } 03520 } 03521 03527 function course_category_show($category) { 03528 global $DB; 03529 03530 $category->visible = 1; 03531 $DB->set_field('course_categories', 'visible', 1, array('id'=>$category->id)); 03532 $DB->set_field('course_categories', 'visibleold', 1, array('id'=>$category->id)); 03533 $DB->execute("UPDATE {course} SET visible = visibleold WHERE category = ?", array($category->id)); 03534 // get all child categories and unhide too 03535 if ($subcats = $DB->get_records_select('course_categories', "path LIKE ?", array("$category->path/%"))) { 03536 foreach ($subcats as $cat) { 03537 if ($cat->visibleold) { 03538 $DB->set_field('course_categories', 'visible', 1, array('id'=>$cat->id)); 03539 } 03540 $DB->execute("UPDATE {course} SET visible = visibleold WHERE category = ?", array($cat->id)); 03541 } 03542 } 03543 } 03544 03549 function move_category($category, $newparentcat) { 03550 global $CFG, $DB; 03551 03552 $context = get_context_instance(CONTEXT_COURSECAT, $category->id); 03553 03554 $hidecat = false; 03555 if (empty($newparentcat->id)) { 03556 $DB->set_field('course_categories', 'parent', 0, array('id'=>$category->id)); 03557 03558 $newparent = get_context_instance(CONTEXT_SYSTEM); 03559 03560 } else { 03561 $DB->set_field('course_categories', 'parent', $newparentcat->id, array('id'=>$category->id)); 03562 $newparent = get_context_instance(CONTEXT_COURSECAT, $newparentcat->id); 03563 03564 if (!$newparentcat->visible and $category->visible) { 03565 // better hide category when moving into hidden category, teachers may unhide afterwards and the hidden children will be restored properly 03566 $hidecat = true; 03567 } 03568 } 03569 03570 context_moved($context, $newparent); 03571 03572 // now make it last in new category 03573 $DB->set_field('course_categories', 'sortorder', MAX_COURSES_IN_CATEGORY*MAX_COURSE_CATEGORIES, array('id'=>$category->id)); 03574 03575 // and fix the sortorders 03576 fix_course_sortorder(); 03577 03578 if ($hidecat) { 03579 course_category_hide($category); 03580 } 03581 } 03582 03599 function get_section_name(stdClass $course, stdClass $section) { 03600 global $CFG; 03601 03603 if ($course->format == 'site') { 03604 return get_string('site'); 03605 } 03606 03607 // Use course formatter callback if it exists 03608 $namingfile = $CFG->dirroot.'/course/format/'.$course->format.'/lib.php'; 03609 $namingfunction = 'callback_'.$course->format.'_get_section_name'; 03610 if (!function_exists($namingfunction) && file_exists($namingfile)) { 03611 require_once $namingfile; 03612 } 03613 if (function_exists($namingfunction)) { 03614 return $namingfunction($course, $section); 03615 } 03616 03617 // else, default behavior: 03618 return get_generic_section_name($course->format, $section); 03619 } 03620 03628 function get_generic_section_name($format, stdClass $section) { 03629 return get_string('sectionname', "format_$format") . ' ' . $section->section; 03630 } 03631 03632 03633 function course_format_uses_sections($format) { 03634 global $CFG; 03635 03636 $featurefile = $CFG->dirroot.'/course/format/'.$format.'/lib.php'; 03637 $featurefunction = 'callback_'.$format.'_uses_sections'; 03638 if (!function_exists($featurefunction) && file_exists($featurefile)) { 03639 require_once $featurefile; 03640 } 03641 if (function_exists($featurefunction)) { 03642 return $featurefunction(); 03643 } 03644 03645 return false; 03646 } 03647 03658 function course_format_ajax_support($format) { 03659 global $CFG; 03660 03661 // set up default values 03662 $ajaxsupport = new stdClass(); 03663 $ajaxsupport->capable = false; 03664 $ajaxsupport->testedbrowsers = array(); 03665 03666 // get the information from the course format library 03667 $featurefile = $CFG->dirroot.'/course/format/'.$format.'/lib.php'; 03668 $featurefunction = 'callback_'.$format.'_ajax_support'; 03669 if (!function_exists($featurefunction) && file_exists($featurefile)) { 03670 require_once $featurefile; 03671 } 03672 if (function_exists($featurefunction)) { 03673 $formatsupport = $featurefunction(); 03674 if (isset($formatsupport->capable)) { 03675 $ajaxsupport->capable = $formatsupport->capable; 03676 } 03677 if (is_array($formatsupport->testedbrowsers)) { 03678 $ajaxsupport->testedbrowsers = $formatsupport->testedbrowsers; 03679 } 03680 } 03681 03682 return $ajaxsupport; 03683 } 03684 03692 function can_delete_course($courseid) { 03693 global $USER, $DB; 03694 03695 $context = get_context_instance(CONTEXT_COURSE, $courseid); 03696 03697 if (has_capability('moodle/course:delete', $context)) { 03698 return true; 03699 } 03700 03701 // hack: now try to find out if creator created this course recently (1 day) 03702 if (!has_capability('moodle/course:create', $context)) { 03703 return false; 03704 } 03705 03706 $since = time() - 60*60*24; 03707 03708 $params = array('userid'=>$USER->id, 'url'=>"view.php?id=$courseid", 'since'=>$since); 03709 $select = "module = 'course' AND action = 'new' AND userid = :userid AND url = :url AND time > :since"; 03710 03711 return $DB->record_exists_select('log', $select, $params); 03712 } 03713 03720 function save_local_role_names($courseid, $data) { 03721 global $DB; 03722 $context = get_context_instance(CONTEXT_COURSE, $courseid); 03723 03724 foreach ($data as $fieldname => $value) { 03725 if (strpos($fieldname, 'role_') !== 0) { 03726 continue; 03727 } 03728 list($ignored, $roleid) = explode('_', $fieldname); 03729 03730 // make up our mind whether we want to delete, update or insert 03731 if (!$value) { 03732 $DB->delete_records('role_names', array('contextid' => $context->id, 'roleid' => $roleid)); 03733 03734 } else if ($rolename = $DB->get_record('role_names', array('contextid' => $context->id, 'roleid' => $roleid))) { 03735 $rolename->name = $value; 03736 $DB->update_record('role_names', $rolename); 03737 03738 } else { 03739 $rolename = new stdClass; 03740 $rolename->contextid = $context->id; 03741 $rolename->roleid = $roleid; 03742 $rolename->name = $value; 03743 $DB->insert_record('role_names', $rolename); 03744 } 03745 } 03746 } 03747 03758 function create_course($data, $editoroptions = NULL) { 03759 global $CFG, $DB; 03760 03761 //check the categoryid - must be given for all new courses 03762 $category = $DB->get_record('course_categories', array('id'=>$data->category), '*', MUST_EXIST); 03763 03764 //check if the shortname already exist 03765 if (!empty($data->shortname)) { 03766 if ($DB->record_exists('course', array('shortname' => $data->shortname))) { 03767 throw new moodle_exception('shortnametaken'); 03768 } 03769 } 03770 03771 //check if the id number already exist 03772 if (!empty($data->idnumber)) { 03773 if ($DB->record_exists('course', array('idnumber' => $data->idnumber))) { 03774 throw new moodle_exception('idnumbertaken'); 03775 } 03776 } 03777 03778 $data->timecreated = time(); 03779 $data->timemodified = $data->timecreated; 03780 03781 // place at beginning of any category 03782 $data->sortorder = 0; 03783 03784 if ($editoroptions) { 03785 // summary text is updated later, we need context to store the files first 03786 $data->summary = ''; 03787 $data->summary_format = FORMAT_HTML; 03788 } 03789 03790 if (!isset($data->visible)) { 03791 // data not from form, add missing visibility info 03792 $data->visible = $category->visible; 03793 } 03794 $data->visibleold = $data->visible; 03795 03796 $newcourseid = $DB->insert_record('course', $data); 03797 $context = get_context_instance(CONTEXT_COURSE, $newcourseid, MUST_EXIST); 03798 03799 if ($editoroptions) { 03800 // Save the files used in the summary editor and store 03801 $data = file_postupdate_standard_editor($data, 'summary', $editoroptions, $context, 'course', 'summary', 0); 03802 $DB->set_field('course', 'summary', $data->summary, array('id'=>$newcourseid)); 03803 $DB->set_field('course', 'summaryformat', $data->summary_format, array('id'=>$newcourseid)); 03804 } 03805 03806 $course = $DB->get_record('course', array('id'=>$newcourseid)); 03807 03808 // Setup the blocks 03809 blocks_add_default_course_blocks($course); 03810 03811 $section = new stdClass(); 03812 $section->course = $course->id; // Create a default section. 03813 $section->section = 0; 03814 $section->summaryformat = FORMAT_HTML; 03815 $DB->insert_record('course_sections', $section); 03816 03817 fix_course_sortorder(); 03818 03819 // update module restrictions 03820 if ($course->restrictmodules) { 03821 if (isset($data->allowedmods)) { 03822 update_restricted_mods($course, $data->allowedmods); 03823 } else { 03824 if (!empty($CFG->defaultallowedmodules)) { 03825 update_restricted_mods($course, explode(',', $CFG->defaultallowedmodules)); 03826 } 03827 } 03828 } 03829 03830 // new context created - better mark it as dirty 03831 mark_context_dirty($context->path); 03832 03833 // Save any custom role names. 03834 save_local_role_names($course->id, (array)$data); 03835 03836 // set up enrolments 03837 enrol_course_updated(true, $course, $data); 03838 03839 add_to_log(SITEID, 'course', 'new', 'view.php?id='.$course->id, $data->fullname.' (ID '.$course->id.')'); 03840 03841 // Trigger events 03842 events_trigger('course_created', $course); 03843 03844 return $course; 03845 } 03846 03857 function update_course($data, $editoroptions = NULL) { 03858 global $CFG, $DB; 03859 03860 $data->timemodified = time(); 03861 03862 $oldcourse = $DB->get_record('course', array('id'=>$data->id), '*', MUST_EXIST); 03863 $context = get_context_instance(CONTEXT_COURSE, $oldcourse->id); 03864 03865 if ($editoroptions) { 03866 $data = file_postupdate_standard_editor($data, 'summary', $editoroptions, $context, 'course', 'summary', 0); 03867 } 03868 03869 if (!isset($data->category) or empty($data->category)) { 03870 // prevent nulls and 0 in category field 03871 unset($data->category); 03872 } 03873 $movecat = (isset($data->category) and $oldcourse->category != $data->category); 03874 03875 if (!isset($data->visible)) { 03876 // data not from form, add missing visibility info 03877 $data->visible = $oldcourse->visible; 03878 } 03879 03880 if ($data->visible != $oldcourse->visible) { 03881 // reset the visibleold flag when manually hiding/unhiding course 03882 $data->visibleold = $data->visible; 03883 } else { 03884 if ($movecat) { 03885 $newcategory = $DB->get_record('course_categories', array('id'=>$data->category)); 03886 if (empty($newcategory->visible)) { 03887 // make sure when moving into hidden category the course is hidden automatically 03888 $data->visible = 0; 03889 } 03890 } 03891 } 03892 03893 // Update with the new data 03894 $DB->update_record('course', $data); 03895 03896 $course = $DB->get_record('course', array('id'=>$data->id)); 03897 03898 if ($movecat) { 03899 $newparent = get_context_instance(CONTEXT_COURSECAT, $course->category); 03900 context_moved($context, $newparent); 03901 } 03902 03903 fix_course_sortorder(); 03904 03905 // Test for and remove blocks which aren't appropriate anymore 03906 blocks_remove_inappropriate($course); 03907 03908 // update module restrictions 03909 if (isset($data->allowedmods)) { 03910 update_restricted_mods($course, $data->allowedmods); 03911 } 03912 03913 // Save any custom role names. 03914 save_local_role_names($course->id, $data); 03915 03916 // update enrol settings 03917 enrol_course_updated(false, $course, $data); 03918 03919 add_to_log($course->id, "course", "update", "edit.php?id=$course->id", $course->id); 03920 03921 // Trigger events 03922 events_trigger('course_updated', $course); 03923 } 03924 03929 function average_number_of_participants() { 03930 global $DB, $SITE; 03931 03932 //count total of enrolments for visible course (except front page) 03933 $sql = 'SELECT COUNT(*) FROM ( 03934 SELECT DISTINCT ue.userid, e.courseid 03935 FROM {user_enrolments} ue, {enrol} e, {course} c 03936 WHERE ue.enrolid = e.id 03937 AND e.courseid <> :siteid 03938 AND c.id = e.courseid 03939 AND c.visible = 1) as total'; 03940 $params = array('siteid' => $SITE->id); 03941 $enrolmenttotal = $DB->count_records_sql($sql, $params); 03942 03943 03944 //count total of visible courses (minus front page) 03945 $coursetotal = $DB->count_records('course', array('visible' => 1)); 03946 $coursetotal = $coursetotal - 1 ; 03947 03948 //average of enrolment 03949 if (empty($coursetotal)) { 03950 $participantaverage = 0; 03951 } else { 03952 $participantaverage = $enrolmenttotal / $coursetotal; 03953 } 03954 03955 return $participantaverage; 03956 } 03957 03962 function average_number_of_courses_modules() { 03963 global $DB, $SITE; 03964 03965 //count total of visible course module (except front page) 03966 $sql = 'SELECT COUNT(*) FROM ( 03967 SELECT cm.course, cm.module 03968 FROM {course} c, {course_modules} cm 03969 WHERE c.id = cm.course 03970 AND c.id <> :siteid 03971 AND cm.visible = 1 03972 AND c.visible = 1) as total'; 03973 $params = array('siteid' => $SITE->id); 03974 $moduletotal = $DB->count_records_sql($sql, $params); 03975 03976 03977 //count total of visible courses (minus front page) 03978 $coursetotal = $DB->count_records('course', array('visible' => 1)); 03979 $coursetotal = $coursetotal - 1 ; 03980 03981 //average of course module 03982 if (empty($coursetotal)) { 03983 $coursemoduleaverage = 0; 03984 } else { 03985 $coursemoduleaverage = $moduletotal / $coursetotal; 03986 } 03987 03988 return $coursemoduleaverage; 03989 } 03990 04011 class course_request { 04012 04018 protected $properties; 04019 04026 protected static $summaryeditoroptions; 04027 04039 public static function prepare($data=null) { 04040 if ($data === null) { 04041 $data = new stdClass; 04042 } 04043 $data = file_prepare_standard_editor($data, 'summary', self::summary_editor_options()); 04044 return $data; 04045 } 04046 04057 public static function create($data) { 04058 global $USER, $DB, $CFG; 04059 $data->requester = $USER->id; 04060 04061 // Summary is a required field so copy the text over 04062 $data->summary = $data->summary_editor['text']; 04063 $data->summaryformat = $data->summary_editor['format']; 04064 04065 $data->id = $DB->insert_record('course_request', $data); 04066 04067 // Create a new course_request object and return it 04068 $request = new course_request($data); 04069 04070 // Notify the admin if required. 04071 if ($users = get_users_from_config($CFG->courserequestnotify, 'moodle/site:approvecourse')) { 04072 04073 $a = new stdClass; 04074 $a->link = "$CFG->wwwroot/course/pending.php"; 04075 $a->user = fullname($USER); 04076 $subject = get_string('courserequest'); 04077 $message = get_string('courserequestnotifyemail', 'admin', $a); 04078 foreach ($users as $user) { 04079 $request->notify($user, $USER, 'courserequested', $subject, $message); 04080 } 04081 } 04082 04083 return $request; 04084 } 04085 04092 public static function summary_editor_options() { 04093 global $CFG; 04094 if (self::$summaryeditoroptions === null) { 04095 self::$summaryeditoroptions = array('maxfiles' => 0, 'maxbytes'=>0); 04096 } 04097 return self::$summaryeditoroptions; 04098 } 04099 04107 public function __construct($properties) { 04108 global $DB; 04109 if (empty($properties->id)) { 04110 if (empty($properties)) { 04111 throw new coding_exception('You must provide a course request id when creating a course_request object'); 04112 } 04113 $id = $properties; 04114 $properties = new stdClass; 04115 $properties->id = (int)$id; 04116 unset($id); 04117 } 04118 if (empty($properties->requester)) { 04119 if (!($this->properties = $DB->get_record('course_request', array('id' => $properties->id)))) { 04120 print_error('unknowncourserequest'); 04121 } 04122 } else { 04123 $this->properties = $properties; 04124 } 04125 $this->properties->collision = null; 04126 } 04127 04134 public function __get($key) { 04135 return $this->properties->$key; 04136 } 04137 04146 public function __isset($key) { 04147 return (!empty($this->properties->$key)); 04148 } 04149 04158 public function get_requester() { 04159 global $DB; 04160 static $requesters= array(); 04161 if (!array_key_exists($this->properties->requester, $requesters)) { 04162 $requesters[$this->properties->requester] = $DB->get_record('user', array('id'=>$this->properties->requester)); 04163 } 04164 return $requesters[$this->properties->requester]; 04165 } 04166 04175 public function check_shortname_collision($shortnamemark = '[*]') { 04176 global $DB; 04177 04178 if ($this->properties->collision !== null) { 04179 return $this->properties->collision; 04180 } 04181 04182 if (empty($this->properties->shortname)) { 04183 debugging('Attempting to check a course request shortname before it has been set', DEBUG_DEVELOPER); 04184 $this->properties->collision = false; 04185 } else if ($DB->record_exists('course', array('shortname' => $this->properties->shortname))) { 04186 if (!empty($shortnamemark)) { 04187 $this->properties->shortname .= ' '.$shortnamemark; 04188 } 04189 $this->properties->collision = true; 04190 } else { 04191 $this->properties->collision = false; 04192 } 04193 return $this->properties->collision; 04194 } 04195 04205 public function approve() { 04206 global $CFG, $DB, $USER; 04207 04208 $user = $DB->get_record('user', array('id' => $this->properties->requester, 'deleted'=>0), '*', MUST_EXIST); 04209 04210 $category = get_course_category($CFG->defaultrequestcategory); 04211 $courseconfig = get_config('moodlecourse'); 04212 04213 // Transfer appropriate settings 04214 $data = clone($this->properties); 04215 unset($data->id); 04216 unset($data->reason); 04217 unset($data->requester); 04218 04219 // Set category 04220 $data->category = $category->id; 04221 $data->sortorder = $category->sortorder; // place as the first in category 04222 04223 // Set misc settings 04224 $data->requested = 1; 04225 if (!empty($CFG->restrictmodulesfor) && $CFG->restrictmodulesfor != 'none' && !empty($CFG->restrictbydefault)) { 04226 $data->restrictmodules = 1; 04227 } 04228 04229 // Apply course default settings 04230 $data->format = $courseconfig->format; 04231 $data->numsections = $courseconfig->numsections; 04232 $data->hiddensections = $courseconfig->hiddensections; 04233 $data->newsitems = $courseconfig->newsitems; 04234 $data->showgrades = $courseconfig->showgrades; 04235 $data->showreports = $courseconfig->showreports; 04236 $data->maxbytes = $courseconfig->maxbytes; 04237 $data->groupmode = $courseconfig->groupmode; 04238 $data->groupmodeforce = $courseconfig->groupmodeforce; 04239 $data->visible = $courseconfig->visible; 04240 $data->visibleold = $data->visible; 04241 $data->lang = $courseconfig->lang; 04242 04243 $course = create_course($data); 04244 $context = get_context_instance(CONTEXT_COURSE, $course->id, MUST_EXIST); 04245 04246 // add enrol instances 04247 if (!$DB->record_exists('enrol', array('courseid'=>$course->id, 'enrol'=>'manual'))) { 04248 if ($manual = enrol_get_plugin('manual')) { 04249 $manual->add_default_instance($course); 04250 } 04251 } 04252 04253 // enrol the requester as teacher if necessary 04254 if (!empty($CFG->creatornewroleid) and !is_viewing($context, $user, 'moodle/role:assign') and !is_enrolled($context, $user, 'moodle/role:assign')) { 04255 enrol_try_internal_enrol($course->id, $user->id, $CFG->creatornewroleid); 04256 } 04257 04258 $this->delete(); 04259 04260 $a = new stdClass(); 04261 $a->name = format_string($course->fullname, true, array('context' => get_context_instance(CONTEXT_COURSE, $course->id))); 04262 $a->url = $CFG->wwwroot.'/course/view.php?id=' . $course->id; 04263 $this->notify($user, $USER, 'courserequestapproved', get_string('courseapprovedsubject'), get_string('courseapprovedemail2', 'moodle', $a)); 04264 04265 return $course->id; 04266 } 04267 04276 public function reject($notice) { 04277 global $USER, $DB; 04278 $user = $DB->get_record('user', array('id' => $this->properties->requester), '*', MUST_EXIST); 04279 $this->notify($user, $USER, 'courserequestrejected', get_string('courserejectsubject'), get_string('courserejectemail', 'moodle', $notice)); 04280 $this->delete(); 04281 } 04282 04286 public function delete() { 04287 global $DB; 04288 $DB->delete_records('course_request', array('id' => $this->properties->id)); 04289 } 04290 04300 protected function notify($touser, $fromuser, $name='courserequested', $subject, $message) { 04301 $eventdata = new stdClass(); 04302 $eventdata->component = 'moodle'; 04303 $eventdata->name = $name; 04304 $eventdata->userfrom = $fromuser; 04305 $eventdata->userto = $touser; 04306 $eventdata->subject = $subject; 04307 $eventdata->fullmessage = $message; 04308 $eventdata->fullmessageformat = FORMAT_PLAIN; 04309 $eventdata->fullmessagehtml = ''; 04310 $eventdata->smallmessage = ''; 04311 $eventdata->notification = 1; 04312 message_send($eventdata); 04313 } 04314 } 04315 04322 function course_page_type_list($pagetype, $parentcontext, $currentcontext) { 04323 // if above course context ,display all course fomats 04324 list($currentcontext, $course, $cm) = get_context_info_array($currentcontext->id); 04325 if ($course->id == SITEID) { 04326 return array('*'=>get_string('page-x', 'pagetype')); 04327 } else { 04328 return array('*'=>get_string('page-x', 'pagetype'), 04329 'course-*'=>get_string('page-course-x', 'pagetype'), 04330 'course-view-*'=>get_string('page-course-view-x', 'pagetype') 04331 ); 04332 } 04333 }