Skip to content

Commit

Permalink
MDL-4782 course: Allow activities in the "stealth" mode
Browse files Browse the repository at this point in the history
Add field 'visibleoncoursepage' to the course_modules table
Add site-wide setting for turning on stealth mode availability
Add callback for "stealth" mode support in the course formats
Change display of modules/sections availability on the course page
  • Loading branch information
marinaglancy committed Feb 14, 2017
1 parent 4b6728e commit 8341055
Show file tree
Hide file tree
Showing 34 changed files with 658 additions and 260 deletions.
6 changes: 6 additions & 0 deletions admin/settings/subsystems.php
Expand Up @@ -54,4 +54,10 @@

$optionalsubsystems->add(new admin_setting_configcheckbox('enableglobalsearch', new lang_string('enableglobalsearch', 'admin'),
new lang_string('enableglobalsearch_desc', 'admin'), 0, 1, 0));

$choices = array();
$choices[0] = new lang_string('no');
$choices[1] = new lang_string('yes');
$optionalsubsystems->add(new admin_setting_configselect('allowstealth', new lang_string('allowstealthmodules'),
new lang_string('allowstealthmodules_help'), 0, $choices));
}
2 changes: 1 addition & 1 deletion backup/moodle2/backup_stepslib.php
Expand Up @@ -264,7 +264,7 @@ protected function define_structure() {

$module = new backup_nested_element('module', array('id', 'version'), array(
'modulename', 'sectionid', 'sectionnumber', 'idnumber',
'added', 'score', 'indent', 'visible',
'added', 'score', 'indent', 'visible', 'visibleoncoursepage',
'visibleold', 'groupmode', 'groupingid',
'completion', 'completiongradeitemnumber', 'completionview', 'completionexpected',
'availability', 'showdescription'));
Expand Down
8 changes: 4 additions & 4 deletions blocks/site_main_menu/block_site_main_menu.php
Expand Up @@ -59,7 +59,7 @@ function get_content() {
if (!empty($modinfo->sections[0])) {
foreach($modinfo->sections[0] as $cmid) {
$cm = $modinfo->cms[$cmid];
if (!$cm->uservisible) {
if (!$cm->uservisible || !$cm->is_visible_on_course_page()) {
continue;
}

Expand All @@ -72,7 +72,7 @@ function get_content() {
if (!empty($cm->url)) {
$content = html_writer::div($courserenderer->course_section_cm_name($cm), 'activity');
} else {
$content = $cm->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
$content = $courserenderer->course_section_cm_text($cm);
}

$this->content->items[] = $indent . html_writer::div($content, 'main-menu-content');
Expand Down Expand Up @@ -103,7 +103,7 @@ function get_content() {
if (!empty($modinfo->sections[0])) {
foreach ($modinfo->sections[0] as $modnumber) {
$mod = $modinfo->cms[$modnumber];
if (!$mod->uservisible) {
if (!$mod->uservisible || !$mod->is_visible_on_course_page()) {
continue;
}
if (!$ismoving) {
Expand Down Expand Up @@ -138,7 +138,7 @@ function get_content() {
$indent = '';
}
if (!$mod->url) {
$content = $mod->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
$content = $courserenderer->course_section_cm_text($mod);
} else {
$content = html_writer::div($courserenderer->course_section_cm_name($mod), ' activity');
}
Expand Down
8 changes: 4 additions & 4 deletions blocks/social_activities/block_social_activities.php
Expand Up @@ -61,12 +61,12 @@ function get_content() {
if (!empty($modinfo->sections[0])) {
foreach($modinfo->sections[0] as $cmid) {
$cm = $modinfo->cms[$cmid];
if (!$cm->uservisible) {
if (!$cm->uservisible || !$cm->is_visible_on_course_page()) {
continue;
}

if (!$cm->url) {
$content = $cm->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
$content = $courserenderer->course_section_cm_text($cm);
$this->content->items[] = $content;
$this->content->icons[] = '';
} else {
Expand Down Expand Up @@ -98,7 +98,7 @@ function get_content() {
if (!empty($modinfo->sections[0])) {
foreach ($modinfo->sections[0] as $modnumber) {
$mod = $modinfo->cms[$modnumber];
if (!$mod->uservisible) {
if (!$mod->uservisible || !$mod->is_visible_on_course_page()) {
continue;
}
if (!$ismoving) {
Expand Down Expand Up @@ -128,7 +128,7 @@ function get_content() {
$this->content->icons[] = '';
}
if (!$mod->url) {
$content = $mod->get_formatted_content(array('overflowdiv' => true, 'noclean' => true));
$content = $courserenderer->course_section_cm_text($mod);
$this->content->items[] = $content . $editbuttons;
$this->content->icons[] = '';
} else {
Expand Down
74 changes: 74 additions & 0 deletions course/format/lib.php
Expand Up @@ -1170,6 +1170,68 @@ protected function get_form_start_date($mform, $fieldnames) {
$startdate = $mform->getElementValue($fieldnames['startdate']);
return $mform->getElement($fieldnames['startdate'])->exportValue($startdate);
}

/**
* Returns whether this course format allows the activity to
* have "triple visibility state" - visible always, hidden on course page but available, hidden.
*
* @param stdClass|cm_info $cm course module (may be null if we are displaying a form for adding a module)
* @param stdClass|section_info $section section where this module is located or will be added to
* @return bool
*/
public function allow_stealth_module_visibility($cm, $section) {
return false;
}

/**
* Callback used in WS core_course_edit_section when teacher performs an AJAX action on a section (show/hide)
*
* Access to the course is already validated in the WS but the callback has to make sure
* that particular action is allowed by checking capabilities
*
* Course formats should register
*
* @param stdClass|section_info $section
* @param string $action
* @param int $sr
* @return null|array|stdClass any data for the Javascript post-processor (must be json-encodeable)
*/
public function section_action($section, $action, $sr) {
global $PAGE;
if (!$this->uses_sections() || !$section->section) {
// No section actions are allowed if course format does not support sections.
// No actions are allowed on the 0-section by default (overwrite in course format if needed).
throw new moodle_exception('sectionactionnotsupported', 'core', null, s($action));
}

$course = $this->get_course();
$coursecontext = context_course::instance($course->id);
switch($action) {
case 'hide':
case 'show':
require_capability('moodle/course:sectionvisibility', $coursecontext);
$visible = ($action === 'hide') ? 0 : 1;
course_update_section($course, $section, array('visible' => $visible));
break;
default:
throw new moodle_exception('sectionactionnotsupported', 'core', null, s($action));
}

$modules = [];

$modinfo = get_fast_modinfo($course);
$coursesections = $modinfo->sections;
if (array_key_exists($section->section, $coursesections)) {
$courserenderer = $PAGE->get_renderer('core', 'course');
$completioninfo = new completion_info($course);
foreach ($coursesections[$section->section] as $cmid) {
$cm = $modinfo->get_cm($cmid);
$modules[] = $courserenderer->course_section_cm_list_item($course, $completioninfo, $cm, $sr);
}
}

return ['modules' => $modules];
}
}

/**
Expand Down Expand Up @@ -1231,4 +1293,16 @@ public function course_format_options($foreditform = false) {
}
return $courseformatoptions;
}

/**
* Returns whether this course format allows the activity to
* have "triple visibility state" - visible always, hidden on course page but available, hidden.
*
* @param stdClass|cm_info $cm course module (may be null if we are displaying a form for adding a module)
* @param stdClass|section_info $section section where this module is located or will be added to
* @return bool
*/
public function allow_stealth_module_visibility($cm, $section) {
return true;
}
}
73 changes: 44 additions & 29 deletions course/format/renderer.php
Expand Up @@ -38,7 +38,7 @@
*/
abstract class format_section_renderer_base extends plugin_renderer_base {

/** @var contains instance of core course renderer */
/** @var core_course_renderer contains instance of core course renderer */
protected $courserenderer;

/**
Expand Down Expand Up @@ -127,7 +127,8 @@ protected function section_edit_control_menu($controls, $course, $section) {
$menu->add($al);
}

$o .= html_writer::div($this->render($menu), 'section_action_menu');
$o .= html_writer::div($this->render($menu), 'section_action_menu',
array('data-sectionid' => $section->id));
}

return $o;
Expand Down Expand Up @@ -194,7 +195,8 @@ protected function section_header($section, $course, $onsectionpage, $sectionret
// Only in the non-general sections.
if (!$section->visible) {
$sectionstyle = ' hidden';
} else if (course_get_format($course)->is_section_current($section)) {
}
if (course_get_format($course)->is_section_current($section)) {
$sectionstyle = ' current';
}
}
Expand Down Expand Up @@ -226,10 +228,7 @@ protected function section_header($section, $course, $onsectionpage, $sectionret
$sectionname = html_writer::tag('span', $this->section_title($section, $course));
$o.= $this->output->heading($sectionname, 3, 'sectionname' . $classes);

$context = context_course::instance($course->id);

$o .= $this->section_availability_message($section,
has_capability('moodle/course:viewhiddensections', $context));
$o .= $this->section_availability($section);

$o .= html_writer::start_tag('div', array('class' => 'summary'));
$o .= $this->format_summary_text($section);
Expand Down Expand Up @@ -306,14 +305,12 @@ protected function section_edit_control_items($course, $section, $onsectionpage
return array();
}

$sectionreturn = $onsectionpage ? $section->section : null;

$coursecontext = context_course::instance($course->id);
$isstealth = isset($course->numsections) && ($section->section > $course->numsections);

if ($onsectionpage) {
$baseurl = course_get_url($course, $section->section);
} else {
$baseurl = course_get_url($course);
}
$baseurl = course_get_url($course, $sectionreturn);
$baseurl->param('sesskey', sesskey());

$controls = array();
Expand All @@ -326,7 +323,6 @@ protected function section_edit_control_items($course, $section, $onsectionpage
$streditsection = get_string('editsection');
}

$sectionreturn = $onsectionpage ? $section->section : 0;
$controls['edit'] = array(
'url' => new moodle_url('/course/editsection.php', array('id' => $section->id, 'sr' => $sectionreturn)),
'icon' => 'i/settings',
Expand All @@ -347,7 +343,8 @@ protected function section_edit_control_items($course, $section, $onsectionpage
'icon' => 'i/hide',
'name' => $strhidefromothers,
'pixattr' => array('class' => '', 'alt' => $strhidefromothers),
'attr' => array('class' => 'icon editing_showhide', 'title' => $strhidefromothers));
'attr' => array('class' => 'icon editing_showhide', 'title' => $strhidefromothers,
'data-sectionreturn' => $sectionreturn, 'data-action' => 'hide'));
} else {
$strshowfromothers = get_string('showfromothers', 'format_'.$course->format);
$url->param('show', $section->section);
Expand All @@ -356,7 +353,8 @@ protected function section_edit_control_items($course, $section, $onsectionpage
'icon' => 'i/show',
'name' => $strshowfromothers,
'pixattr' => array('class' => '', 'alt' => $strshowfromothers),
'attr' => array('class' => 'icon editing_showhide', 'title' => $strshowfromothers));
'attr' => array('class' => 'icon editing_showhide', 'title' => $strshowfromothers,
'data-sectionreturn' => $sectionreturn, 'data-action' => 'show'));
}
}

Expand Down Expand Up @@ -399,14 +397,14 @@ protected function section_edit_control_items($course, $section, $onsectionpage
}
$url = new moodle_url('/course/editsection.php', array(
'id' => $section->id,
'sr' => $onsectionpage ? $section->section : 0,
'sr' => $sectionreturn,
'delete' => 1));
$controls['delete'] = array(
'url' => $url,
'icon' => 'i/delete',
'name' => $strdelete,
'pixattr' => array('class' => '', 'alt' => $strdelete),
'attr' => array('class' => 'icon delete', 'title' => $strdelete));
'attr' => array('class' => 'icon editing_delete', 'title' => $strdelete));
}
}

Expand Down Expand Up @@ -453,9 +451,7 @@ protected function section_summary($section, $course, $mods) {
$o.= html_writer::end_tag('div');
$o.= $this->section_activity_summary($section, $course, null);

$context = context_course::instance($course->id);
$o .= $this->section_availability_message($section,
has_capability('moodle/course:viewhiddensections', $context));
$o .= $this->section_availability($section);

$o .= html_writer::end_tag('div');
$o .= html_writer::end_tag('li');
Expand Down Expand Up @@ -549,31 +545,50 @@ protected function section_activity_summary($section, $course, $mods) {
* are going to be unavailable etc). This logic is the same as for
* activities.
*
* @param stdClass $section The course_section entry from DB
* @param section_info $section The course_section entry from DB
* @param bool $canviewhidden True if user can view hidden sections
* @return string HTML to output
*/
protected function section_availability_message($section, $canviewhidden) {
global $CFG;
$o = '';
if (!$section->uservisible) {
// Note: We only get to this function if availableinfo is non-empty,
// so there is definitely something to print.
$formattedinfo = \core_availability\info::format_info(
$section->availableinfo, $section->course);
$o .= html_writer::div($formattedinfo, 'availabilityinfo');
} else if ($canviewhidden && !empty($CFG->enableavailability) && $section->visible) {
if (!$section->visible) {
if ($canviewhidden) {
$o .= $this->courserenderer->availability_info(get_string('hiddenfromstudents'), 'ishidden');
}
} else if (!$section->uservisible) {
if ($section->availableinfo) {
// Note: We only get to this function if availableinfo is non-empty,
// so there is definitely something to print.
$formattedinfo = \core_availability\info::format_info(
$section->availableinfo, $section->course);
$o .= $this->courserenderer->availability_info($formattedinfo);
}
} else if ($canviewhidden && !empty($CFG->enableavailability)) {
// Check if there is an availability restriction.
$ci = new \core_availability\info_section($section);
$fullinfo = $ci->get_full_information();
if ($fullinfo) {
$formattedinfo = \core_availability\info::format_info(
$fullinfo, $section->course);
$o .= html_writer::div($formattedinfo, 'availabilityinfo');
$o .= $this->courserenderer->availability_info($formattedinfo);
}
}
return $o;
}

/**
* Displays availability information for the section (hidden, not available unles, etc.)
*
* @param section_info $section
* @return string
*/
public function section_availability($section) {
$context = context_course::instance($section->course);
$canviewhidden = has_capability('moodle/course:viewhiddensections', $context);
return html_writer::div($this->section_availability_message($section, $canviewhidden), 'section_availability');
}

/**
* Show if something is on on the course clipboard (moving around)
*
Expand Down
12 changes: 12 additions & 0 deletions course/format/social/lib.php
Expand Up @@ -108,4 +108,16 @@ public function course_format_options($foreditform = false) {
}
return $courseformatoptions;
}

/**
* Returns whether this course format allows the activity to
* have "triple visibility state" - visible always, hidden on course page but available, hidden.
*
* @param stdClass|cm_info $cm course module (may be null if we are displaying a form for adding a module)
* @param stdClass|section_info $section section where this module is located or will be added to
* @return bool
*/
public function allow_stealth_module_visibility($cm, $section) {
return true;
}
}

0 comments on commit 8341055

Please sign in to comment.