General developer forum

Request for help in implementing a maintenance mode setting for the course context

 
Picture of Roel Cantada
Request for help in implementing a maintenance mode setting for the course context
 

I'm trying to implement a proof of concept for adding course settings that will set the course in maintenance mode. In other words a maintenance mode at the course level. This had been in my mind for years now and it is only now that I can articulate it but I just can't figure out the code. If anyone has done this already I'd appreciate any info.

The problem I'm trying to solve is this. When students are enrolled two weeks before the start of classes, course sites are hidden so students get frustrated and send support request that basically just asks where their courses are. As far as I know visibility has only two settings, hide and show, so students have no idea where the course site is until it is shown by the teacher. This is a situation wherein the control of the visibility of the course site is with the teacher.

Anyways I've been using meta linked courses as workaround (the topic for my proposed paper in MoodleMoot Philippines on April 2018) but I think a simple setting for maintenance mode at the course level is what is really needed. What I've done so far is to mock up what I mean by course maintenance mode as shown in the screenshot that was done by hacking moodle/course/view.php with:

21 //course maintenance mode test start
22     $maintenance_mode = 1;
23 //course maintenance mode test end
...

268 //maintenance test start 2
269    if ($USER->editing == 0 && $maintenance_mode == 1) {
270    echo "<h1>This course site is in maintenance mode.</h1>";
271    } else {
272 //maintenance test end 2

display maintenance mode in course

The problems that I need help are:

1. How to display the maintenance text only for users without editing capabilities. Those with editing capabilites should see the normal course page.

2. How to get rid of nav block menu items except for participants, for users without editing capabilities. Those with editing capabilities should see the normal nav block.

3. and how to add custom message text box in the settings.

The settings would simply add a select yes/no setting in the course editing page like so:

mock up of course maintenance setting

I guess I should add a db field for this but I don't know where to put it.

Any hints would be appreciated. I've attached some of the files in /moodle/course I've been trying to hack.





 
Average of ratings: Useful (1)
Picture of Richard Oelmann
Re: Request for help in implementing a maintenance mode setting for the course context
Core developersParticularly helpful MoodlersPlugin developersTesters

I had a similar issue but took a different approach.

I added a conditional which creates a class added to body, based on the start date of the course and whether the user had editing rights. Then added some css to hide the course content and show a notice banner until 2 weeks prior to the course start date.

Very simplified psuedo code:

In layout

IF (now > 2weeks before startdate AND user != editor) {add 'hidecontent' to body class}

In stylesheet

body.hidecontent .contenthiddenbanner {display:block}

body.hidecontent .maincontent {display:none}

(on boost themes, rather than clean/more based ones, I think this would be page-content and maybe would also need to target the nav-drawer, but I'm not at my test system right now to check my code - but essentially with the relevant body tag in place you can target whatever other selectors within that as needed)

There's actually a bit more to what I did than that, because in fact I went with only displaying the hidden content when editing is turned on, had a different contenthidden banner for students and editors, and obviously the layout file also has to include the contenthidden banner that I haven't put here (Its just actually a bootstrap alert in practice), but that's the basic principle - much easier than implementing a full maintenance mode for a single context.

Essentially its automatic - teachers can reveal their course early if they want to, by altering the course start date, or using a different theme if that's allowed on the site. But the students get to see their modules as soon as they are enrolled, but dont get the content until 2 weeks before the start of the semester.

 
Average of ratings: -
Picture of Roel Cantada
Re: Request for help in implementing a maintenance mode setting for the course context
 

Thanks Richard for the alternative solution.

I've finally figured it out and here is a proof of concept. Attached are the files I've modified in a Moodle $version  = 2017111302.04;  $release  = '3.4.2+ (Build: 20180405)';.

Warning for non-devs: This is a proof of concept that hack the core code! Don't try this in your production server.

Here is the course maintenance mode settings.

course maintenance mode settings

And the output when an enrolled student tries to enter a course in maintenance mode.

course maintenance message output


The following changes should be applied on a fresh install because I could not resolve an exception when I added the XMLDB generated php code in /lib/db/upgrade.php. So the db change is in /lib/db/install.xml .

lang/en/role.php

$string['course:coursemaintenanceaccess'] = 'Access course site while in maintenance mode';

lang/en/moodle.php

$string['coursemaintenance'] = 'Course maintenance mode';
$string['coursemaintenance_message'] = 'Course maintenance message';
$string['coursemaintenance_help'] = 'Sets the course in maintenance mode.';
$string['coursemaintenance_message_help'] = 'Allows custom message in maintenance mode.';

admin/settings/courses.php
line 65

    //Course maintenance mode
    $temp->add(new admin_setting_configselect('moodlecourse/coursemaintenance', new lang_string('coursemaintenance'), new lang_string('coursemaintenance_help'), 0,array(0 => new lang_string('no'), 1 => new lang_string('yes'))));


course/edit_form.PHP
line 124

        //Course maintenance mode
        $mform->addElement('selectyesno', 'coursemaintenance', get_string('coursemaintenance'));
        $mform->addHelpButton('coursemaintenance', 'coursemaintenance');
        $mform->setDefault('coursemaintenance', $courseconfig->coursemaintenance);
       
        //Course maintenance message
        $mform->addElement('textarea','coursemaintenance_message', get_string('coursemaintenance_message'));
        $mform->addHelpButton('coursemaintenance_message', 'coursemaintenance_message');
        $mform->setType('shortname', PARAM_TEXT);

lib/db/access.php
line 2381

    'moodle/course:coursemaintenanceaccess' => array(
        'captype' => 'write',
        'contextlevel' => CONTEXT_COURSE,
        'archetypes' => array(
            'teacher' => CAP_ALLOW,
            'editingteacher' => CAP_ALLOW,
            'manager' => CAP_ALLOW
        )
    ),

lib/db/services.php
line 451

    'core_course_update_courses' => array(
        'classname' => 'core_course_external',
        'methodname' => 'update_courses',
        'classpath' => 'course/externallib.php',
        'description' => 'Update courses',
        'type' => 'write',
        'capabilities' => 'moodle/course:update, moodle/course:changecategory, moodle/course:changefullname, '
        . 'moodle/course:changeshortname, moodle/course:changeidnumber, moodle/course:changesummary, moodle/course:visibility, moodle/course:coursemaintenanceaccess'
    ),


moodle/lib/db/install.xml
line 91

        <FIELD NAME="visible" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
        <FIELD NAME="visibleold" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="the state of visible field when hiding parent category, this helps us to recover hidden states when unhiding the parent category later"/>

        <FIELD NAME="coursemaintenance" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
        <FIELD NAME="coursemaintenance_message" TYPE="text" NOTNULL="false" SEQUENCE="false"/>

/lib/moodlelib.php
line 2876


        //course maintenance test
        //$coursemaintenance = true;
       
        if (!has_capability("moodle/course:coursemaintenanceaccess",$coursecontext) and $access and ($course->coursemaintenance == 1)) {
            if ($preventredirect) {
                throw new require_login_exception('The course is not available yet.');
            }
            if ($setwantsurltome) {
                $SESSION->wantsurl = qualified_me();
            }
            $PAGE->set_context(null);
            print_coursemaintenance_message($course->coursemaintenance_message,$course->fullname);
        }

/lib/weblib.php
line 3004


/**
 * Prints a maintenance message for course.
 */
function print_coursemaintenance_message($message,$fullname) {
    global $CFG, $SITE, $PAGE, $OUTPUT;
   
    header($_SERVER['SERVER_PROTOCOL'] . ' 503 Moodle under maintenance');
    header('Status: 503 Moodle under maintenance');
    header('Retry-After: 300');
   
    $PAGE->set_pagetype('maintenance-message');
    $PAGE->set_pagelayout('columns1');
    $PAGE->set_title(strip_tags($SITE->fullname));
    $PAGE->set_heading($fullname);
    echo $OUTPUT->header();
    echo $OUTPUT->heading("Course Maintenance");
        echo $OUTPUT->box_start('coursemaintenance_message generalbox boxwidthwide boxaligncenter');
          echo $message;
        echo $OUTPUT->box_end();
    echo $OUTPUT->footer();
    die;
}


Picture of Roel Cantada
Re: Request for help in implementing a maintenance mode setting for the course context
 

The exception that I was getting when I inserted the following PHP code generated by XMLDB in lib/db/upgrade.php is:

Exception - Call to a member function field_exists() on null (Exception - Call to a member function field_exists() on null)

I may be doing something wrong or missing a step somewhere. So I just did a fresh install with install.xml.

If anyone has any ideas about this exception I'd appreciate some help.

An example of the php script to add course maintenance is:

    if ($oldversion < 2017111302.10) {

        // Define field coursemaintenance to be added to course.
        $table = new xmldb_table('course');
        $field = new xmldb_field('coursemaintenance', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0', 'visibleold');

        // Conditionally launch add field coursemaintenance.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // Main savepoint reached.
        upgrade_main_savepoint(true, 2017111302.10);
    }

 
Average of ratings: -
Picture of Roel Cantada
Re: Request for help in implementing a maintenance mode setting for the course context
 

Another thing that I could not figure out is how to use an editor instead of textarea for the "Course maintenance message" setting. It would have been nice if the teacher can embed or attach files like in the course summary fields but the code for that seems quite complex.

 
Average of ratings: -
Picture of Roel Cantada
Re: Request for help in implementing a maintenance mode setting for the course context
 

I assume there are a lot more missing in the proof of concept like code for events and backup.  I've seen code for course request in course/lib.php that seems relevant as well. Anyways this is all I can share for now.

 
Average of ratings: -