Merge branch 'MDL-25981'

This commit is contained in:
Petr Skoda 2011-01-31 22:44:17 +01:00
commit 46df3c6059
14 changed files with 1415 additions and 410 deletions

View file

@ -27,7 +27,8 @@ class block_activity_modules extends block_list {
$archetypes = array(); $archetypes = array();
foreach($modinfo->cms as $cm) { foreach($modinfo->cms as $cm) {
if (!$cm->uservisible or $cm->modname === 'label') { // Exclude activities which are not visible or have no link (=label)
if (!$cm->uservisible or !$cm->has_view()) {
continue; continue;
} }
if (array_key_exists($cm->modname, $modfullnames)) { if (array_key_exists($cm->modname, $modfullnames)) {

View file

@ -40,21 +40,19 @@ class block_site_main_menu extends block_list {
if (!$cm->uservisible) { if (!$cm->uservisible) {
continue; continue;
} }
if ($cm->modname == 'label') {
$this->content->items[] = format_text($cm->extra, FORMAT_HTML, $options); list($content, $instancename) =
get_print_section_cm_text($cm, $course);
if (!($url = $cm->get_url())) {
$this->content->items[] = $content;
$this->content->icons[] = ''; $this->content->icons[] = '';
} else { } else {
$linkcss = $cm->visible ? '' : ' class="dimmed" '; $linkcss = $cm->visible ? '' : ' class="dimmed" ';
$instancename = format_string($cm->name, true, $course->id);
//Accessibility: incidental image - should be empty Alt text //Accessibility: incidental image - should be empty Alt text
if (!empty($cm->icon)) { $icon = '<img src="' . $cm->get_icon_url() . '" class="icon" alt="" />&nbsp;';
$icon = $OUTPUT->pix_url($cm->icon);
} else {
$icon = $OUTPUT->pix_url('icon', $cm->modname);
}
$icon = '<img src="'.$icon.'" class="icon" alt="" />&nbsp;';
$this->content->items[] = '<a title="'.$cm->modplural.'" '.$linkcss.' '.$cm->extra. $this->content->items[] = '<a title="'.$cm->modplural.'" '.$linkcss.' '.$cm->extra.
' href="'.$CFG->wwwroot.'/mod/'.$cm->modname.'/view.php?id='.$cm->id.'">'.$icon.$instancename.'</a>'; ' href="' . $url . '">' . $icon . $instancename . '</a>';
} }
} }
} }
@ -114,28 +112,18 @@ class block_site_main_menu extends block_list {
'<img style="height:16px; width:80px; border:0px" src="'.$OUTPUT->pix_url('movehere') . '" alt="'.$strmovehere.'" /></a>'; '<img style="height:16px; width:80px; border:0px" src="'.$OUTPUT->pix_url('movehere') . '" alt="'.$strmovehere.'" /></a>';
$this->content->icons[] = ''; $this->content->icons[] = '';
} }
$instancename = $modinfo->cms[$modnumber]->name; list($content, $instancename) =
$instancename = format_string($instancename, true, $course->id); get_print_section_cm_text($modinfo->cms[$modnumber], $course);
$linkcss = $mod->visible ? '' : ' class="dimmed" '; $linkcss = $mod->visible ? '' : ' class="dimmed" ';
if (!empty($modinfo->cms[$modnumber]->extra)) {
$extra = $modinfo->cms[$modnumber]->extra;
} else {
$extra = '';
}
if (!empty($modinfo->cms[$modnumber]->icon)) {
$icon = $OUTPUT->pix_url($modinfo->cms[$modnumber]->icon);
} else {
$icon = $OUTPUT->pix_url('icon', $mod->modname);
}
if ($mod->modname == 'label') { if (!($url = $mod->get_url())) {
$this->content->items[] = format_text($extra, FORMAT_HTML,$options).$editbuttons; $this->content->items[] = $content . $editbuttons;
$this->content->icons[] = ''; $this->content->icons[] = '';
} else { } else {
//Accessibility: incidental image - should be empty Alt text //Accessibility: incidental image - should be empty Alt text
$icon = '<img src="'.$icon.'" class="icon" alt="" />&nbsp;'; $icon = '<img src="' . $mod->get_icon_url() . '" class="icon" alt="" />&nbsp;';
$this->content->items[] = '<a title="'.$mod->modfullname.'" '.$linkcss.' '.$extra. $this->content->items[] = '<a title="' . $mod->modfullname . '" ' . $linkcss . ' ' . $mod->extra .
' href="'.$CFG->wwwroot.'/mod/'.$mod->modname.'/view.php?id='.$mod->id.'">'.$icon.$instancename.'</a>'.$editbuttons; ' href="' . $url . '">' . $icon . $instancename . '</a>' . $editbuttons;
} }
} }
} }

View file

@ -42,21 +42,19 @@ class block_social_activities extends block_list {
if (!$cm->uservisible) { if (!$cm->uservisible) {
continue; continue;
} }
if ($cm->modname == 'label') {
$this->content->items[] = format_text($cm->extra, FORMAT_HTML, $options); list($content, $instancename) =
get_print_section_cm_text($cm, $course);
if (!($url = $cm->get_url())) {
$this->content->items[] = $content;
$this->content->icons[] = ''; $this->content->icons[] = '';
} else { } else {
$linkcss = $cm->visible ? '' : ' class="dimmed" '; $linkcss = $cm->visible ? '' : ' class="dimmed" ';
$instancename = format_string($cm->name, true, $course->id);
//Accessibility: incidental image - should be empty Alt text //Accessibility: incidental image - should be empty Alt text
if (!empty($cm->icon)) { $icon = '<img src="' . $cm->get_icon_url() . '" class="icon" alt="" />&nbsp;';
$icon = $OUTPUT->pix_url($cm->icon);
} else {
$icon = $OUTPUT->pix_url('icon', $cm->modname);
}
$icon = '<img src="'.$icon.'" class="icon" alt="" />&nbsp;';
$this->content->items[] = '<a title="'.$cm->modplural.'" '.$linkcss.' '.$cm->extra. $this->content->items[] = '<a title="'.$cm->modplural.'" '.$linkcss.' '.$cm->extra.
' href="'.$CFG->wwwroot.'/mod/'.$cm->modname.'/view.php?id='.$cm->id.'">'.$icon.$instancename.'</a>'; ' href="' . $url . '">' . $icon . $instancename . '</a>';
} }
} }
} }
@ -123,28 +121,19 @@ class block_social_activities extends block_list {
'<img style="height:16px; width:80px; border:0px" src="'.$OUTPUT->pix_url('movehere') . '" alt="'.$strmovehere.'" /></a>'; '<img style="height:16px; width:80px; border:0px" src="'.$OUTPUT->pix_url('movehere') . '" alt="'.$strmovehere.'" /></a>';
$this->content->icons[] = ''; $this->content->icons[] = '';
} }
$instancename = $modinfo->cms[$modnumber]->name; list($content, $instancename) =
$instancename = format_string($instancename, true, $course->id); get_print_section_cm_text($modinfo->cms[$modnumber], $course);
$linkcss = $mod->visible ? '' : ' class="dimmed" ';
if (!empty($modinfo->cms[$modnumber]->extra)) {
$extra = $modinfo->cms[$modnumber]->extra;
} else {
$extra = '';
}
if (!empty($modinfo->cms[$modnumber]->icon)) {
$icon = $OUTPUT->pix_url($modinfo->cms[$modnumber]->icon);
} else {
$icon = $OUTPUT->pix_url('icon', $mod->modname);
}
if ($mod->modname == 'label') { $linkcss = $mod->visible ? '' : ' class="dimmed" ';
$this->content->items[] = format_text($extra, FORMAT_HTML, $options).$editbuttons;
if (!($url = $mod->get_url())) {
$this->content->items[] = $content . $editbuttons;
$this->content->icons[] = ''; $this->content->icons[] = '';
} else { } else {
//Accessibility: incidental image - should be empty Alt text //Accessibility: incidental image - should be empty Alt text
$icon = '<img src="'.$icon.'" class="icon" alt="" />&nbsp;'; $icon = '<img src="' . $mod->get_icon_url() . '" class="icon" alt="" />&nbsp;';
$this->content->items[] = '<a title="'.$mod->modfullname.'" '.$linkcss.' '.$extra. $this->content->items[] = '<a title="' . $mod->modfullname . '" ' . $linkcss . ' ' . $mod->extra .
' href="'.$CFG->wwwroot.'/mod/'.$mod->modname.'/view.php?id='.$mod->id.'">'.$icon.$instancename.'</a>'.$editbuttons; ' href="' . $url . '">' . $icon . $instancename . '</a>' . $editbuttons;
} }
} }
} }

View file

@ -48,10 +48,6 @@ define('FIRSTUSEDEXCELROW', 3);
define('MOD_CLASS_ACTIVITY', 0); define('MOD_CLASS_ACTIVITY', 0);
define('MOD_CLASS_RESOURCE', 1); define('MOD_CLASS_RESOURCE', 1);
if (!defined('MAX_MODINFO_CACHE_SIZE')) {
define('MAX_MODINFO_CACHE_SIZE', 10);
}
function make_log_url($module, $url) { function make_log_url($module, $url) {
switch ($module) { switch ($module) {
case 'course': case 'course':
@ -959,6 +955,9 @@ function print_recent_activity($course) {
} }
$info = explode(' ', $log->info); $info = explode(' ', $log->info);
// note: in most cases I replaced hardcoding of label with use of
// $cm->has_view() but it was not possible to do this here because
// we don't necessarily have the $cm for it
if ($info[0] == 'label') { // Labels are ignored in recent activity if ($info[0] == 'label') { // Labels are ignored in recent activity
continue; continue;
} }
@ -1112,9 +1111,6 @@ function get_array_of_activities($courseid) {
if (function_exists($functionname)) { if (function_exists($functionname)) {
if ($info = $functionname($rawmods[$seq])) { if ($info = $functionname($rawmods[$seq])) {
if (!empty($info->extra)) {
$mod[$seq]->extra = $info->extra;
}
if (!empty($info->icon)) { if (!empty($info->icon)) {
$mod[$seq]->icon = $info->icon; $mod[$seq]->icon = $info->icon;
} }
@ -1124,11 +1120,45 @@ function get_array_of_activities($courseid) {
if (!empty($info->name)) { if (!empty($info->name)) {
$mod[$seq]->name = $info->name; $mod[$seq]->name = $info->name;
} }
if ($info instanceof cached_cm_info) {
// When using cached_cm_info you can include three new fields
// that aren't available for legacy code
if (!empty($info->content)) {
$mod[$seq]->content = $info->content;
}
if (!empty($info->extraclasses)) {
$mod[$seq]->extraclasses = $info->extraclasses;
}
if (!empty($info->onclick)) {
$mod[$seq]->onclick = $info->onclick;
}
if (!empty($info->customdata)) {
$mod[$seq]->customdata = $info->customdata;
}
} else {
// When using a stdclass, the (horrible) deprecated ->extra field
// is available for BC
if (!empty($info->extra)) {
$mod[$seq]->extra = $info->extra;
}
}
} }
} }
if (!isset($mod[$seq]->name)) { if (!isset($mod[$seq]->name)) {
$mod[$seq]->name = $DB->get_field($rawmods[$seq]->modname, "name", array("id"=>$rawmods[$seq]->instance)); $mod[$seq]->name = $DB->get_field($rawmods[$seq]->modname, "name", array("id"=>$rawmods[$seq]->instance));
} }
// Minimise the database size by unsetting default options when they are
// 'empty'. This list corresponds to code in the cm_info constructor.
foreach(array('idnumber', 'groupmode', 'groupingid', 'groupmembersonly',
'indent', 'completion', 'extra', 'extraclasses', 'onclick', 'content',
'icon', 'iconcomponent', 'customdata', 'availablefrom', 'availableuntil',
'conditionscompletion', 'conditionsgrade') as $property) {
if (property_exists($mod[$seq], $property) &&
empty($mod[$seq]->{$property})) {
unset($mod[$seq]->{$property});
}
}
} }
} }
} }
@ -1250,6 +1280,44 @@ function set_section_visible($courseid, $sectionnumber, $visibility) {
} }
} }
/**
* Obtains shared data that is used in print_section when displaying a
* course-module entry.
*
* Calls format_text or format_string as appropriate, and obtains the correct icon.
*
* This data is also used in other areas of the code.
* @param cm_info $cm Course-module data (must come from get_fast_modinfo)
* @param object $course Moodle course object
* @return array An array with the following values in this order:
* $content (optional extra content for after link),
* $instancename (text of link)
*/
function get_print_section_cm_text(cm_info $cm, $course) {
global $OUTPUT;
// Get course context
$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
// Get content from modinfo if specified. Content displays either
// in addition to the standard link (below), or replaces it if
// the link is turned off by setting ->url to null.
if (($content = $cm->get_content()) !== '') {
$labelformatoptions = new stdClass();
$labelformatoptions->noclean = true;
$labelformatoptions->overflowdiv = true;
$labelformatoptions->context = $coursecontext;
$content = format_text($content, FORMAT_HTML, $labelformatoptions);
} else {
$content = '';
}
$stringoptions = new stdClass;
$stringoptions->context = $coursecontext;
$instancename = format_string($cm->name, true, $stringoptions);
return array($content, $instancename);
}
/** /**
* Prints a section full of activity modules * Prints a section full of activity modules
*/ */
@ -1265,8 +1333,8 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
static $strmovehere; static $strmovehere;
static $strmovefull; static $strmovefull;
static $strunreadpostsone; static $strunreadpostsone;
static $usetracking;
static $groupings; static $groupings;
static $modulenames;
if (!isset($initialised)) { if (!isset($initialised)) {
$groupbuttons = ($course->groupmode or (!$course->groupmodeforce)); $groupbuttons = ($course->groupmode or (!$course->groupmodeforce));
@ -1277,18 +1345,12 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
$strmovehere = get_string("movehere"); $strmovehere = get_string("movehere");
$strmovefull = strip_tags(get_string("movefull", "", "'$USER->activitycopyname'")); $strmovefull = strip_tags(get_string("movefull", "", "'$USER->activitycopyname'"));
} }
include_once($CFG->dirroot.'/mod/forum/lib.php'); $modulenames = array();
if ($usetracking = forum_tp_can_track_forums()) {
$strunreadpostsone = get_string('unreadpostsone', 'forum');
}
$initialised = true; $initialised = true;
} }
$labelformatoptions = new stdClass(); $tl = textlib_get_instance();
$labelformatoptions->noclean = true;
$labelformatoptions->overflowdiv = true;
/// Casting $course->modinfo to string prevents one notice when the field is null
$modinfo = get_fast_modinfo($course); $modinfo = get_fast_modinfo($course);
$completioninfo = new completion_info($course); $completioninfo = new completion_info($course);
@ -1304,6 +1366,9 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
continue; continue;
} }
/**
* @var cm_info
*/
$mod = $mods[$modnumber]; $mod = $mods[$modnumber];
if ($ismoving and $mod->id == $USER->activitycopy) { if ($ismoving and $mod->id == $USER->activitycopy) {
@ -1341,6 +1406,11 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
} }
} }
if (!isset($modulenames[$mod->modname])) {
$modulenames[$mod->modname] = get_string('modulename', $mod->modname);
}
$modulename = $modulenames[$mod->modname];
// In some cases the activity is visible to user, but it is // In some cases the activity is visible to user, but it is
// dimmed. This is done if viewhiddenactivities is true and if: // dimmed. This is done if viewhiddenactivities is true and if:
// 1. the activity is not visible, or // 1. the activity is not visible, or
@ -1366,6 +1436,10 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
$liclasses[] = 'activity'; $liclasses[] = 'activity';
$liclasses[] = $mod->modname; $liclasses[] = $mod->modname;
$liclasses[] = 'modtype_'.$mod->modname; $liclasses[] = 'modtype_'.$mod->modname;
$extraclasses = $mod->get_extra_classes();
if ($extraclasses) {
$liclasses = array_merge($liclasses, explode(' ', $extraclasses));
}
echo html_writer::start_tag('li', array('class'=>join(' ', $liclasses), 'id'=>'module-'.$modnumber)); echo html_writer::start_tag('li', array('class'=>join(' ', $liclasses), 'id'=>'module-'.$modnumber));
if ($ismoving) { if ($ismoving) {
echo '<a title="'.$strmovefull.'"'. echo '<a title="'.$strmovefull.'"'.
@ -1384,105 +1458,122 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
} }
echo html_writer::start_tag('div', array('class'=>join(' ', $classes))); echo html_writer::start_tag('div', array('class'=>join(' ', $classes)));
$extra = ''; // Get data about this course-module
if (!empty($modinfo->cms[$modnumber]->extra)) { list($content, $instancename) =
$extra = $modinfo->cms[$modnumber]->extra; get_print_section_cm_text($modinfo->cms[$modnumber], $course);
//Accessibility: for files get description via icon, this is very ugly hack!
$altname = '';
$altname = $mod->modfullname;
if (!empty($customicon)) {
$archetype = plugin_supports('mod', $mod->modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER);
if ($archetype == MOD_ARCHETYPE_RESOURCE) {
$mimetype = mimeinfo_from_icon('type', $customicon);
$altname = get_mimetype_description($mimetype);
}
}
// Avoid unnecessary duplication: if e.g. a forum name already
// includes the word forum (or Forum, etc) then it is unhelpful
// to include that in the accessible description that is added.
if (false !== strpos($tl->strtolower($instancename),
$tl->strtolower($altname))) {
$altname = '';
}
// File type after name, for alphabetic lists (screen reader).
if ($altname) {
$altname = get_accesshide(' '.$altname);
} }
if ($mod->modname == "label") { // We may be displaying this just in order to show information
if ($accessiblebutdim || !$mod->uservisible) { // about visibility, without the actual link
echo '<div class="dimmed_text"><span class="accesshide">'. $contentpart = '';
get_string('hiddenfromstudents').'</span>'; if ($mod->uservisible) {
// Nope - in this case the link is fully working for user
$linkclasses = '';
$textclasses = '';
if ($accessiblebutdim) {
$linkclasses .= ' dimmed';
$textclasses .= ' dimmed_text';
$accesstext = '<span class="accesshide">'.
get_string('hiddenfromstudents').': </span>';
} else { } else {
echo '<div>'; $accesstext = '';
} }
echo format_text($extra, FORMAT_HTML, $labelformatoptions); if ($linkclasses) {
echo "</div>"; $linkcss = 'class="' . trim($linkclasses) . '" ';
} else {
$linkcss = '';
}
if ($textclasses) {
$textcss = 'class="' . trim($textclasses) . '" ';
} else {
$textcss = '';
}
// Get on-click attribute value if specified
$onclick = $mod->get_on_click();
if ($onclick) {
$onclick = ' onclick="' . $onclick . '"';
}
if ($url = $mod->get_url()) {
// Display link itself
echo '<a ' . $linkcss . $mod->extra . $onclick .
' href="' . $url . '"><img src="' . $mod->get_icon_url() .
'" class="activityicon" alt="' .
$modulename . '" /> ' .
$accesstext . '<span class="instancename">' .
$instancename . $altname . '</span></a>';
// If specified, display extra content after link
if ($content) {
$contentpart = '<div class="contentafterlink' .
trim($textclasses) . '">' . $content . '</div>';
}
} else {
// No link, so display only content
$contentpart = '<div ' . $textcss . $mod->extra . '>' .
$accesstext . $content . '</div>';
}
if (!empty($mod->groupingid) && has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) { if (!empty($mod->groupingid) && has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) {
if (!isset($groupings)) { if (!isset($groupings)) {
$groupings = groups_get_all_groupings($course->id); $groupings = groups_get_all_groupings($course->id);
} }
echo " <span class=\"groupinglabel\">(".format_string($groupings[$mod->groupingid]->name).')</span>'; echo " <span class=\"groupinglabel\">(".format_string($groupings[$mod->groupingid]->name).')</span>';
} }
} else {
} else { // Normal activity $textclasses = $extraclasses;
$instancename = format_string($modinfo->cms[$modnumber]->name, true, $course->id); $textclasses .= ' dimmed_text';
if ($textclasses) {
$customicon = $modinfo->cms[$modnumber]->icon; $textcss = 'class="' . trim($textclasses) . '" ';
if (!empty($customicon)) {
if (substr($customicon, 0, 4) === 'mod/') {
list($modname, $iconname) = explode('/', substr($customicon, 4), 2);
$icon = $OUTPUT->pix_url($iconname, $modname);
} else {
$icon = $OUTPUT->pix_url($customicon);
}
} else { } else {
$icon = $OUTPUT->pix_url('icon', $mod->modname); $textcss = '';
} }
$accesstext = '<span class="accesshide">' .
get_string('notavailableyet', 'condition') .
': </span>';
//Accessibility: for files get description via icon, this is very ugly hack! if ($url = $mod->get_url()) {
$altname = '';
$altname = $mod->modfullname;
if (!empty($customicon)) {
$archetype = plugin_supports('mod', $mod->modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER);
if ($archetype == MOD_ARCHETYPE_RESOURCE) {
$mimetype = mimeinfo_from_icon('type', $customicon);
$altname = get_mimetype_description($mimetype);
}
}
// Avoid unnecessary duplication.
if (false !== stripos($instancename, $altname)) {
$altname = '';
}
// File type after name, for alphabetic lists (screen reader).
if ($altname) {
$altname = get_accesshide(' '.$altname);
}
// We may be displaying this just in order to show information
// about visibility, without the actual link
if ($mod->uservisible) {
// Display normal module link
if (!$accessiblebutdim) {
$linkcss = '';
$accesstext ='';
} else {
$linkcss = ' class="dimmed" ';
$accesstext = '<span class="accesshide">'.
get_string('hiddenfromstudents').': </span>';
}
echo '<a '.$linkcss.' '.$extra.
' href="'.$CFG->wwwroot.'/mod/'.$mod->modname.'/view.php?id='.$mod->id.'">'.
'<img src="'.$icon.'" class="activityicon" alt="'.get_string('modulename',$mod->modname).'" /> '.
$accesstext.'<span class="instancename">'.$instancename.$altname.'</span></a>';
if (!empty($mod->groupingid) && has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) {
if (!isset($groupings)) {
$groupings = groups_get_all_groupings($course->id);
}
echo " <span class=\"groupinglabel\">(".format_string($groupings[$mod->groupingid]->name).')</span>';
}
} else {
// Display greyed-out text of link // Display greyed-out text of link
echo '<span class="dimmed_text" '.$extra.' ><span class="accesshide">'. echo '<div ' . $textcss . $mod->extra .
get_string('notavailableyet','condition').': </span>'. ' >' . '<img src="' . $mod->get_icon_url() .
'<img src="'.$icon.'" class="activityicon" alt="'.get_string('modulename', $mod->modname).'" /> <span>'. '" class="activityicon" alt="' .
$instancename.$altname.'</span></span>'; $modulename .
} '" /> <span>'. $instancename . $altname .
} '</span></div>';
if ($usetracking && $mod->modname == 'forum') {
if ($unread = forum_tp_count_forum_unread_posts($mod, $course)) { // Do not display content after link when it is greyed out like this.
echo '<span class="unread"> <a href="'.$CFG->wwwroot.'/mod/forum/view.php?id='.$mod->id.'">'; } else {
if ($unread == 1) { // No link, so display only content (also greyed)
echo $strunreadpostsone; $contentpart = '<div ' . $textcss . $mod->extra . '>' .
} else { $accesstext . $content . '</div>';
print_string('unreadpostsnumber', 'forum', $unread);
}
echo '</a></span>';
} }
} }
// Module can put text after the link (e.g. forum unread)
echo $mod->get_after_link();
if ($isediting) { if ($isediting) {
if ($groupbuttons and plugin_supports('mod', $mod->modname, FEATURE_GROUPS, 0)) { if ($groupbuttons and plugin_supports('mod', $mod->modname, FEATURE_GROUPS, 0)) {
if (! $mod->groupmodelink = $groupbuttonslink) { if (! $mod->groupmodelink = $groupbuttonslink) {
@ -1494,6 +1585,7 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
} }
echo '&nbsp;&nbsp;'; echo '&nbsp;&nbsp;';
echo make_editing_buttons($mod, $absolute, true, $mod->indent, $section->section); echo make_editing_buttons($mod, $absolute, true, $mod->indent, $section->section);
echo $mod->get_after_edit_icons();
} }
// Completion // Completion
@ -1566,6 +1658,9 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
} }
} }
// Display the content (if any) at this part of the html
echo $contentpart;
// Show availability information (for someone who isn't allowed to // Show availability information (for someone who isn't allowed to
// see the activity itself, or for staff) // see the activity itself, or for staff)
if (!$mod->uservisible) { if (!$mod->uservisible) {

View file

@ -74,7 +74,7 @@
foreach ($modinfo->sections as $sectionnum=>$section) { foreach ($modinfo->sections as $sectionnum=>$section) {
foreach ($section as $cmid) { foreach ($section as $cmid) {
$cm = $modinfo->cms[$cmid]; $cm = $modinfo->cms[$cmid];
if ($cm->modname == 'label') { if (!$cm->has_view()) {
continue; continue;
} }
if (!$cm->uservisible) { if (!$cm->uservisible) {

View file

@ -63,7 +63,7 @@
$modinfo = get_fast_modinfo($course); $modinfo = get_fast_modinfo($course);
$modules = $DB->get_records_select('modules', "visible = 1 AND name <> 'label'", null, 'name ASC'); $modules = $DB->get_records_select('modules', "visible = 1", null, 'name ASC');
$instanceoptions = array(); $instanceoptions = array();
foreach ($modules as $module) { foreach ($modules as $module) {
@ -72,8 +72,16 @@
} }
$instances = array(); $instances = array();
foreach ($modinfo->instances[$module->name] as $cm) { foreach ($modinfo->instances[$module->name] as $cm) {
// Skip modules such as label which do not actually have links;
// this means there's nothing to participate in
if (!$cm->has_view()) {
continue;
}
$instances[$cm->id] = format_string($cm->name); $instances[$cm->id] = format_string($cm->name);
} }
if (count($instances) == 0) {
continue;
}
$instanceoptions[] = array(get_string('modulenameplural', $module->name)=>$instances); $instanceoptions[] = array(get_string('modulenameplural', $module->name)=>$instances);
} }

View file

@ -37,9 +37,6 @@ $allmodules = $DB->get_records('modules', array('visible'=>1));
$modules = array(); $modules = array();
foreach ($allmodules as $key=>$module) { foreach ($allmodules as $key=>$module) {
$modname = $module->name; $modname = $module->name;
if ($modname === 'label') {
continue;
}
$libfile = "$CFG->dirroot/mod/$modname/lib.php"; $libfile = "$CFG->dirroot/mod/$modname/lib.php";
if (!file_exists($libfile)) { if (!file_exists($libfile)) {
continue; continue;
@ -80,6 +77,10 @@ foreach ($modinfo->cms as $cm) {
if (!array_key_exists($cm->modname, $modules)) { if (!array_key_exists($cm->modname, $modules)) {
continue; continue;
} }
if (!$cm->has_view()) {
// Exclude label and similar
continue;
}
$cms[$cm->id] = $cm; $cms[$cm->id] = $cm;
$resources[$cm->modname][] = $cm->instance; $resources[$cm->modname][] = $cm->instance;
} }

1092
lib/modinfolib.php Normal file

File diff suppressed because it is too large Load diff

View file

@ -352,6 +352,8 @@ define('FEATURE_COMPLETION_TRACKS_VIEWS', 'completion_tracks_views');
/** True if module has custom completion rules */ /** True if module has custom completion rules */
define('FEATURE_COMPLETION_HAS_RULES', 'completion_has_rules'); define('FEATURE_COMPLETION_HAS_RULES', 'completion_has_rules');
/** True if module has no 'view' page (like label) */
define('FEATURE_NO_VIEW_LINK', 'viewlink');
/** True if module supports outcomes */ /** True if module supports outcomes */
define('FEATURE_IDNUMBER', 'idnumber'); define('FEATURE_IDNUMBER', 'idnumber');
/** True if module supports groups */ /** True if module supports groups */
@ -2312,6 +2314,14 @@ function require_login($courseorid = NULL, $autologinguest = true, $cm = NULL, $
if ($cm->course != $course->id) { if ($cm->course != $course->id) {
throw new coding_exception('course and cm parameters in require_login() call do not match!!'); throw new coding_exception('course and cm parameters in require_login() call do not match!!');
} }
// make sure we have a $cm from get_fast_modinfo as this contains activity access details
if (!($cm instanceof cm_info)) {
// note: nearly all pages call get_fast_modinfo anyway and it does not make any
// db queries so this is not really a performance concern, however it is obviously
// better if you use get_fast_modinfo to get the cm before calling this.
$modinfo = get_fast_modinfo($course);
$cm = $modinfo->get_cm($cm->id);
}
$PAGE->set_cm($cm, $course); // set's up global $COURSE $PAGE->set_cm($cm, $course); // set's up global $COURSE
$PAGE->set_pagelayout('incourse'); $PAGE->set_pagelayout('incourse');
} else { } else {
@ -2583,47 +2593,15 @@ function require_login($courseorid = NULL, $autologinguest = true, $cm = NULL, $
} }
} }
// test visibility // Check visibility of activity to current user; includes visible flag, groupmembersonly,
if ($cm && !$cm->visible && !has_capability('moodle/course:viewhiddenactivities', $cmcontext)) { // conditional availability, etc
if ($cm && !$cm->uservisible) {
if ($preventredirect) { if ($preventredirect) {
throw new require_login_exception('Activity is hidden'); throw new require_login_exception('Activity is hidden');
} }
redirect($CFG->wwwroot, get_string('activityiscurrentlyhidden')); redirect($CFG->wwwroot, get_string('activityiscurrentlyhidden'));
} }
// groupmembersonly access control
if (!empty($CFG->enablegroupmembersonly) and $cm and $cm->groupmembersonly and !has_capability('moodle/site:accessallgroups', get_context_instance(CONTEXT_MODULE, $cm->id))) {
if (isguestuser() or !groups_has_membership($cm)) {
if ($preventredirect) {
throw new require_login_exception('Not member of a group');
}
print_error('groupmembersonlyerror', 'group', $CFG->wwwroot.'/course/view.php?id='.$cm->course);
}
}
// Conditional activity access control
if (!empty($CFG->enableavailability) and $cm) {
// TODO: this is going to work with login-as-user, sorry!
// We cache conditional access in session
if (!isset($SESSION->conditionaccessok)) {
$SESSION->conditionaccessok = array();
}
// If you have been allowed into the module once then you are allowed
// in for rest of session, no need to do conditional checks
if (!array_key_exists($cm->id, $SESSION->conditionaccessok)) {
// Get condition info (does a query for the availability table)
require_once($CFG->libdir.'/conditionlib.php');
$ci = new condition_info($cm, CONDITION_MISSING_EXTRATABLE);
// Check condition for user (this will do a query if the availability
// information depends on grade or completion information)
if ($ci->is_available($junk) || has_capability('moodle/course:viewhiddenactivities', $cmcontext)) {
$SESSION->conditionaccessok[$cm->id] = true;
} else {
print_error('activityiscurrentlyhidden');
}
}
}
// Finally access granted, update lastaccess times // Finally access granted, update lastaccess times
user_accesstime_log($course->id); user_accesstime_log($course->id);
} }
@ -2674,16 +2652,29 @@ function require_logout() {
*/ */
function require_course_login($courseorid, $autologinguest = true, $cm = NULL, $setwantsurltome = true, $preventredirect = false) { function require_course_login($courseorid, $autologinguest = true, $cm = NULL, $setwantsurltome = true, $preventredirect = false) {
global $CFG, $PAGE, $SITE; global $CFG, $PAGE, $SITE;
$issite = (is_object($courseorid) and $courseorid->id == SITEID)
or (!is_object($courseorid) and $courseorid == SITEID);
if ($issite && !empty($cm) && !($cm instanceof cm_info)) {
// note: nearly all pages call get_fast_modinfo anyway and it does not make any
// db queries so this is not really a performance concern, however it is obviously
// better if you use get_fast_modinfo to get the cm before calling this.
if (is_object($courseorid)) {
$course = $courseorid;
} else {
$course = clone($SITE);
}
$modinfo = get_fast_modinfo($course);
$cm = $modinfo->get_cm($cm->id);
}
if (!empty($CFG->forcelogin)) { if (!empty($CFG->forcelogin)) {
// login required for both SITE and courses // login required for both SITE and courses
require_login($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect); require_login($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect);
} else if (!empty($cm) and !$cm->visible) { } else if ($issite && !empty($cm) and !$cm->uservisible) {
// always login for hidden activities // always login for hidden activities
require_login($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect); require_login($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect);
} else if ((is_object($courseorid) and $courseorid->id == SITEID) } else if ($issite) {
or (!is_object($courseorid) and $courseorid == SITEID)) {
//login for SITE not required //login for SITE not required
if ($cm and empty($cm->visible)) { if ($cm and empty($cm->visible)) {
// hidden activities are not accessible without login // hidden activities are not accessible without login
@ -3006,207 +2997,6 @@ function reset_login_count() {
$SESSION->logincount = 0; $SESSION->logincount = 0;
} }
/**
* Returns reference to full info about modules in course (including visibility).
* Cached and as fast as possible (0 or 1 db query).
*
* @global object
* @global object
* @global object
* @uses CONTEXT_MODULE
* @uses MAX_MODINFO_CACHE_SIZE
* @param mixed $course object or 'reset' string to reset caches, modinfo may be updated in db
* @param int $userid Defaults to current user id
* @return mixed courseinfo object or nothing if resetting
*/
function &get_fast_modinfo(&$course, $userid=0) {
global $CFG, $USER, $DB;
require_once($CFG->dirroot.'/course/lib.php');
if (!empty($CFG->enableavailability)) {
require_once($CFG->libdir.'/conditionlib.php');
}
static $cache = array();
if ($course === 'reset') {
$cache = array();
$nothing = null;
return $nothing; // we must return some reference
}
if (empty($userid)) {
$userid = $USER->id;
}
if (array_key_exists($course->id, $cache) and $cache[$course->id]->userid == $userid) {
return $cache[$course->id];
}
if (!property_exists($course, 'modinfo')) {
debugging('Coding problem - missing course modinfo property in get_fast_modinfo() call');
}
if (empty($course->modinfo)) {
// no modinfo yet - load it
rebuild_course_cache($course->id);
$course->modinfo = $DB->get_field('course', 'modinfo', array('id'=>$course->id));
}
$modinfo = new stdClass();
$modinfo->courseid = $course->id;
$modinfo->userid = $userid;
$modinfo->sections = array();
$modinfo->cms = array();
$modinfo->instances = array();
$modinfo->groups = null; // loaded only when really needed - the only one db query
$info = unserialize($course->modinfo);
if (!is_array($info)) {
// hmm, something is wrong - lets try to fix it
rebuild_course_cache($course->id);
$course->modinfo = $DB->get_field('course', 'modinfo', array('id'=>$course->id));
$info = unserialize($course->modinfo);
if (!is_array($info)) {
return $modinfo;
}
}
if ($info) {
// detect if upgrade required
$first = reset($info);
if (!isset($first->id)) {
rebuild_course_cache($course->id);
$course->modinfo = $DB->get_field('course', 'modinfo', array('id'=>$course->id));
$info = unserialize($course->modinfo);
if (!is_array($info)) {
return $modinfo;
}
}
}
$modlurals = array();
// If we haven't already preloaded contexts for the course, do it now
preload_course_contexts($course->id);
foreach ($info as $mod) {
if (empty($mod->name)) {
// something is wrong here
continue;
}
// reconstruct minimalistic $cm
$cm = new stdClass();
$cm->id = $mod->cm;
$cm->instance = $mod->id;
$cm->course = $course->id;
$cm->modname = $mod->mod;
$cm->idnumber = $mod->idnumber;
$cm->name = $mod->name;
$cm->visible = $mod->visible;
$cm->sectionnum = $mod->section;
$cm->groupmode = $mod->groupmode;
$cm->groupingid = $mod->groupingid;
$cm->groupmembersonly = $mod->groupmembersonly;
$cm->indent = $mod->indent;
$cm->completion = $mod->completion;
$cm->extra = isset($mod->extra) ? $mod->extra : '';
$cm->icon = isset($mod->icon) ? $mod->icon : '';
$cm->iconcomponent = isset($mod->iconcomponent) ? $mod->iconcomponent : '';
$cm->uservisible = true;
if (!empty($CFG->enableavailability)) {
// We must have completion information from modinfo. If it's not
// there, cache needs rebuilding
if(!isset($mod->availablefrom)) {
debugging('enableavailability option was changed; rebuilding '.
'cache for course '.$course->id);
rebuild_course_cache($course->id,true);
// Re-enter this routine to do it all properly
return get_fast_modinfo($course, $userid);
}
$cm->availablefrom = $mod->availablefrom;
$cm->availableuntil = $mod->availableuntil;
$cm->showavailability = $mod->showavailability;
$cm->conditionscompletion = $mod->conditionscompletion;
$cm->conditionsgrade = $mod->conditionsgrade;
}
// preload long names plurals and also check module is installed properly
if (!isset($modlurals[$cm->modname])) {
if (!file_exists("$CFG->dirroot/mod/$cm->modname/lib.php")) {
continue;
}
$modlurals[$cm->modname] = get_string('modulenameplural', $cm->modname);
}
$cm->modplural = $modlurals[$cm->modname];
$modcontext = get_context_instance(CONTEXT_MODULE,$cm->id);
if (!empty($CFG->enableavailability)) {
// Unfortunately the next call really wants to call
// get_fast_modinfo, but that would be recursive, so we fake up a
// modinfo for it already
if (empty($minimalmodinfo)) { //TODO: this is suspicious (skodak)
$minimalmodinfo = new stdClass();
$minimalmodinfo->cms = array();
foreach($info as $mod) {
if (empty($mod->name)) {
// something is wrong here
continue;
}
$minimalcm = new stdClass();
$minimalcm->id = $mod->cm;
$minimalcm->name = $mod->name;
$minimalmodinfo->cms[$minimalcm->id]=$minimalcm;
}
}
// Get availability information
$ci = new condition_info($cm);
$cm->available = $ci->is_available($cm->availableinfo, true, $userid, $minimalmodinfo);
} else {
$cm->available = true;
}
if ((!$cm->visible or !$cm->available) and !has_capability('moodle/course:viewhiddenactivities', $modcontext, $userid)) {
$cm->uservisible = false;
} else if (!empty($CFG->enablegroupmembersonly) and !empty($cm->groupmembersonly)
and !has_capability('moodle/site:accessallgroups', $modcontext, $userid)) {
if (is_null($modinfo->groups)) {
$modinfo->groups = groups_get_user_groups($course->id, $userid);
}
if (empty($modinfo->groups[$cm->groupingid])) {
$cm->uservisible = false;
}
}
if (!isset($modinfo->instances[$cm->modname])) {
$modinfo->instances[$cm->modname] = array();
}
$modinfo->instances[$cm->modname][$cm->instance] =& $cm;
$modinfo->cms[$cm->id] =& $cm;
// reconstruct sections
if (!isset($modinfo->sections[$cm->sectionnum])) {
$modinfo->sections[$cm->sectionnum] = array();
}
$modinfo->sections[$cm->sectionnum][] = $cm->id;
unset($cm);
}
unset($cache[$course->id]); // prevent potential reference problems when switching users
$cache[$course->id] = $modinfo;
// Ensure cache does not use too much RAM
if (count($cache) > MAX_MODINFO_CACHE_SIZE) {
reset($cache);
$key = key($cache);
unset($cache[$key]);
}
return $cache[$course->id];
}
/** /**
* Determines if the currently logged in user is in editing mode. * Determines if the currently logged in user is in editing mode.
* Note: originally this function had $userid parameter - it was not usable anyway * Note: originally this function had $userid parameter - it was not usable anyway

View file

@ -1026,10 +1026,14 @@ class global_navigation extends navigation_node {
if ($course->id !== SITEID) { if ($course->id !== SITEID) {
// Find the section for the $CM associated with the page and collect // Find the section for the $CM associated with the page and collect
// its section number. // its section number.
foreach ($sections as $section) { if (isset($cm->sectionnum)) {
if ($section->id == $cm->section) { $cm->sectionnumber = $cm->sectionnum;
$cm->sectionnumber = $section->section; } else {
break; foreach ($sections as $section) {
if ($section->id == $cm->section) {
$cm->sectionnumber = $section->section;
break;
}
} }
} }
@ -1429,10 +1433,10 @@ class global_navigation extends navigation_node {
* *
* @param navigation_node $sectionnode * @param navigation_node $sectionnode
* @param int $sectionnumber * @param int $sectionnumber
* @param stdClass $modinfo Object returned from {@see get_fast_modinfo()} * @param course_modinfo $modinfo Object returned from {@see get_fast_modinfo()}
* @return array Array of activity nodes * @return array Array of activity nodes
*/ */
protected function load_section_activities(navigation_node $sectionnode, $sectionnumber, $modinfo) { protected function load_section_activities(navigation_node $sectionnode, $sectionnumber, course_modinfo $modinfo) {
if (!array_key_exists($sectionnumber, $modinfo->sections)) { if (!array_key_exists($sectionnumber, $modinfo->sections)) {
return true; return true;
} }
@ -1449,11 +1453,12 @@ class global_navigation extends navigation_node {
} else { } else {
$icon = new pix_icon('icon', get_string('modulename', $cm->modname), $cm->modname); $icon = new pix_icon('icon', get_string('modulename', $cm->modname), $cm->modname);
} }
$url = new moodle_url('/mod/'.$cm->modname.'/view.php', array('id'=>$cm->id)); $url = $cm->get_url();
$activitynode = $sectionnode->add(format_string($cm->name), $url, navigation_node::TYPE_ACTIVITY, null, $cm->id, $icon); $activitynode = $sectionnode->add(format_string($cm->name), $url, navigation_node::TYPE_ACTIVITY, null, $cm->id, $icon);
$activitynode->title(get_string('modulename', $cm->modname)); $activitynode->title(get_string('modulename', $cm->modname));
$activitynode->hidden = (!$cm->visible); $activitynode->hidden = (!$cm->visible);
if ($cm->modname == 'label') { if (!$url) {
// Do not show activities that don't have links!
$activitynode->display = false; $activitynode->display = false;
} else if ($this->module_extends_navigation($cm->modname)) { } else if ($this->module_extends_navigation($cm->modname)) {
$activitynode->nodetype = navigation_node::NODETYPE_BRANCH; $activitynode->nodetype = navigation_node::NODETYPE_BRANCH;
@ -1482,11 +1487,12 @@ class global_navigation extends navigation_node {
} else { } else {
$icon = new pix_icon('icon', get_string('modulename', $cm->modname), $cm->modname); $icon = new pix_icon('icon', get_string('modulename', $cm->modname), $cm->modname);
} }
$url = new moodle_url('/mod/'.$cm->modname.'/view.php', array('id'=>$cm->id)); $url = $cm->get_url();
$activitynode = $coursenode->add(format_string($cm->name), $url, navigation_node::TYPE_ACTIVITY, null, $cm->id, $icon); $activitynode = $coursenode->add(format_string($cm->name), $url, navigation_node::TYPE_ACTIVITY, null, $cm->id, $icon);
$activitynode->title(get_string('modulename', $cm->modname)); $activitynode->title(get_string('modulename', $cm->modname));
$activitynode->hidden = (!$cm->visible); $activitynode->hidden = (!$cm->visible);
if ($cm->modname == 'label') { if (!$url) {
// Don't show activities that don't have links!
$activitynode->display = false; $activitynode->display = false;
} else if ($this->module_extends_navigation($cm->modname)) { } else if ($this->module_extends_navigation($cm->modname)) {
$activitynode->nodetype = navigation_node::NODETYPE_BRANCH; $activitynode->nodetype = navigation_node::NODETYPE_BRANCH;
@ -1509,7 +1515,7 @@ class global_navigation extends navigation_node {
* @param navigation_node $activity * @param navigation_node $activity
* @return bool * @return bool
*/ */
protected function load_activity(stdClass $cm, stdClass $course, navigation_node $activity) { protected function load_activity($cm, stdClass $course, navigation_node $activity) {
global $CFG, $DB; global $CFG, $DB;
$activity->make_active(); $activity->make_active();

View file

@ -414,6 +414,7 @@ require_once($CFG->libdir .'/grouplib.php'); // Groups functions
require_once($CFG->libdir .'/sessionlib.php'); // All session and cookie related stuff require_once($CFG->libdir .'/sessionlib.php'); // All session and cookie related stuff
require_once($CFG->libdir .'/editorlib.php'); // All text editor related functions and classes require_once($CFG->libdir .'/editorlib.php'); // All text editor related functions and classes
require_once($CFG->libdir .'/messagelib.php'); // Messagelib functions require_once($CFG->libdir .'/messagelib.php'); // Messagelib functions
require_once($CFG->libdir .'/modinfolib.php'); // Cached information on course-module instances
// make sure PHP is not severly misconfigured // make sure PHP is not severly misconfigured
setup_validate_php_configuration(); setup_validate_php_configuration();

View file

@ -2181,7 +2181,8 @@ function navmenulist($course, $sections, $modinfo, $strsection, $strjumpto, $wid
$menu[] = '<ul class="navmenulist"><li class="jumpto section"><span>'.$strjumpto.'</span><ul>'; $menu[] = '<ul class="navmenulist"><li class="jumpto section"><span>'.$strjumpto.'</span><ul>';
foreach ($modinfo->cms as $mod) { foreach ($modinfo->cms as $mod) {
if ($mod->modname == 'label') { if (!$mod->has_view()) {
// Don't show modules which you can't link to!
continue; continue;
} }

View file

@ -7792,3 +7792,35 @@ class forum_existing_subscriber_selector extends forum_subscriber_selector_base
} }
} }
/**
* Adds information about unread messages, that is only required for the course view page (and
* similar), to the course-module object.
* @param cm_info $cm Course-module object
*/
function forum_cm_info_view(cm_info $cm) {
global $CFG;
// Get tracking status (once per request)
static $initialised;
static $usetracking, $strunreadpostsone;
if (!isset($initialised)) {
if ($usetracking = forum_tp_can_track_forums()) {
$strunreadpostsone = get_string('unreadpostsone', 'forum');
}
$initialised = true;
}
if ($usetracking) {
if ($unread = forum_tp_count_forum_unread_posts($cm, $cm->get_course())) {
$out = '<span class="unread"> <a href="' . $cm->get_url() . '">';
if ($unread == 1) {
$out .= $strunreadpostsone;
} else {
$out .= get_string('unreadpostsnumber', 'forum', $unread);
}
$out .= '</a></span>';
$cm->set_after_link($out);
}
}
}

View file

@ -209,6 +209,7 @@ function label_supports($feature) {
case FEATURE_GRADE_OUTCOMES: return false; case FEATURE_GRADE_OUTCOMES: return false;
case FEATURE_MOD_ARCHETYPE: return MOD_ARCHETYPE_RESOURCE; case FEATURE_MOD_ARCHETYPE: return MOD_ARCHETYPE_RESOURCE;
case FEATURE_BACKUP_MOODLE2: return true; case FEATURE_BACKUP_MOODLE2: return true;
case FEATURE_NO_VIEW_LINK: return true;
default: return null; default: return null;
} }