General developer forum

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

 
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: -