Merge branch 'MDL-34498-master' of git://github.com/damyon/moodle
authorJun Pataleta <jun@moodle.com>
Thu, 6 Jun 2019 02:50:56 +0000 (10:50 +0800)
committerJun Pataleta <jun@moodle.com>
Thu, 6 Jun 2019 02:50:56 +0000 (10:50 +0800)
26 files changed:
grade/grading/form/rubric/edit.php
lang/en/error.php
lang/en/moodle.php
lib/ajax/service.php
lib/amd/build/ajax.min.js
lib/amd/build/network.min.js [new file with mode: 0644]
lib/amd/build/page_global.min.js
lib/amd/src/ajax.js
lib/amd/src/network.js [new file with mode: 0644]
lib/amd/src/page_global.js
lib/classes/session/external.php [new file with mode: 0644]
lib/classes/session/manager.php
lib/db/services.php
lib/outputrequirementslib.php
lib/sessionkeepalive_ajax.php [deleted file]
lib/upgrade.txt
lib/yui/build/moodle-core-checknet/assets/checknet.txt [deleted file]
lib/yui/build/moodle-core-checknet/moodle-core-checknet-debug.js [deleted file]
lib/yui/build/moodle-core-checknet/moodle-core-checknet-min.js [deleted file]
lib/yui/build/moodle-core-checknet/moodle-core-checknet.js [deleted file]
lib/yui/src/checknet/assets/checknet.txt [deleted file]
lib/yui/src/checknet/build.json [deleted file]
lib/yui/src/checknet/js/checknet.js [deleted file]
lib/yui/src/checknet/meta/checknet.json [deleted file]
mod/scorm/player.php
version.php

index c1849f2..15bda1e 100644 (file)
@@ -65,6 +65,10 @@ if ($mform->is_cancelled()) {
     redirect($returnurl, $warning, null, \core\output\notification::NOTIFY_ERROR);
 }
 
+// Try to keep the session alive on this page as it may take some time
+// before significant interaction happens with the server.
+\core\session\manager::keepalive();
+
 echo $OUTPUT->header();
 $mform->display();
-echo $OUTPUT->footer();
\ No newline at end of file
+echo $OUTPUT->footer();
index 825a6b3..e0b5519 100644 (file)
@@ -496,6 +496,7 @@ $string['sendmessage'] = 'Send message';
 $string['serverconnection'] = 'Error connecting to the server';
 $string['servicedonotexist'] = 'The service does not exist';
 $string['sessionwaiterr'] = 'Timed out while waiting for session lock.<br />Wait for your current requests to finish and try again later.';
+$string['sessionexpired'] = 'Session expired';
 $string['sessioncookiesdisable'] = 'Incorrect use of require_key_login() - session cookies must be disabled!';
 $string['sessiondiskfull'] = 'The session partition is full. It is not possible to log in at this time. Please notify the server administrator.';
 $string['sessionhandlerproblem'] = 'Session handler is misconfigured';
index df841d6..6c3294b 100644 (file)
@@ -802,6 +802,7 @@ $string['existingcoursedeleting'] = 'Existing course, deleting it first';
 $string['existingcreators'] = 'Existing course creators';
 $string['existingstudents'] = 'Enrolled students';
 $string['existingteachers'] = 'Existing teachers';
+$string['extendsession'] = 'Extend session';
 $string['expand'] = 'Expand';
 $string['expandall'] = 'Expand all';
 $string['expandcategory'] = 'Expand {$a}';
@@ -1807,7 +1808,8 @@ $string['separateandconnected'] = 'Separate and Connected ways of knowing';
 $string['separateandconnectedinfo'] = 'The scale based on the theory of separate and connected knowing. This theory describes two different ways that we can evaluate and learn about the things we see and hear.<ul><li><strong>Separate knowers</strong> remain as objective as possible without including feelings and emotions. In a discussion with other people, they like to defend their own ideas, using logic to find holes in opponent\'s ideas.</li><li><strong>Connected knowers</strong> are more sensitive to other people. They are skilled at empathy and tend to listen and ask questions until they feel they can connect and "understand things from their point of view". They learn by trying to share the experiences that led to the knowledge they find in other people.</li></ul>';
 $string['servererror'] = 'An error occurred whilst communicating with the server';
 $string['serverlocaltime'] = 'Server\'s local time';
-$string['sessionforceclean'] = 'As a security precaution, user-generated scripts have been disabled within this session.';
+$string['sessionforceclean'] = 'As a security precaution, user-generated scripts have been disabled within this session';
+$string['sessiontimeoutsoon'] = 'Your session is about to timeout. Do you want to extend your current session?';
 $string['setcategorytheme'] = 'Set category theme';
 $string['setpassword'] = 'Set password';
 $string['setpasswordinstructions'] = 'Please enter your new password below, then save changes.';
index 3298c0e..caaf86c 100644 (file)
 
 define('AJAX_SCRIPT', true);
 
+if (!empty($_GET['nosessionupdate'])) {
+    define('NO_SESSION_UPDATE', true);
+}
+
 require_once(__DIR__ . '/../../config.php');
 require_once($CFG->libdir . '/externallib.php');
 
@@ -63,5 +67,4 @@ foreach ($requests as $request) {
         break;
     }
 }
-
 echo json_encode($responses);
index f8c5453..adc66eb 100644 (file)
Binary files a/lib/amd/build/ajax.min.js and b/lib/amd/build/ajax.min.js differ
diff --git a/lib/amd/build/network.min.js b/lib/amd/build/network.min.js
new file mode 100644 (file)
index 0000000..435d017
Binary files /dev/null and b/lib/amd/build/network.min.js differ
index 838ab91..a02a46c 100644 (file)
Binary files a/lib/amd/build/page_global.min.js and b/lib/amd/build/page_global.min.js differ
index a13cbcf..98e982c 100644 (file)
@@ -40,11 +40,12 @@ define(['jquery', 'core/config', 'core/log', 'core/url'], function($, config, Lo
      */
     var requestSuccess = function(responses) {
         // Call each of the success handlers.
-        var requests = this;
-        var exception = null;
-        var i = 0;
-        var request;
-        var response;
+        var requests = this,
+            exception = null,
+            i = 0,
+            request,
+            response,
+            nosessionupdate;
 
         if (responses.error) {
             // There was an error with the request as a whole.
@@ -69,6 +70,7 @@ define(['jquery', 'core/config', 'core/log', 'core/url'], function($, config, Lo
                     request.deferred.resolve(response.data);
                 } else {
                     exception = response.exception;
+                    nosessionupdate = requests[i].nosessionupdate;
                     break;
                 }
             } else {
@@ -80,7 +82,7 @@ define(['jquery', 'core/config', 'core/log', 'core/url'], function($, config, Lo
         // Something failed, reject the remaining promises.
         if (exception !== null) {
             // Redirect to the login page.
-            if (exception.errorcode === "servicerequireslogin") {
+            if (exception.errorcode === "servicerequireslogin" && !nosessionupdate) {
                 window.location = URL.relativeUrl("/login/index.php");
             } else {
                 requests.forEach(function(request) {
@@ -132,9 +134,12 @@ define(['jquery', 'core/config', 'core/log', 'core/url'], function($, config, Lo
          *                  If false - this function will call the faster nologin ajax script - but
          *                  will fail unless all functions have been marked as 'loginrequired' => false
          *                  in services.php
+         * @param {Boolean} nosessionupdate Optional, defaults to false.
+         *                  If true, the timemodified for the session will not be updated.
+         * @param {Integer} timeout number of milliseconds to wait for a response. Defaults to no limit.
          * @return {Promise[]} Array of promises that will be resolved when the ajax call returns.
          */
-        call: function(requests, async, loginrequired) {
+        call: function(requests, async, loginrequired, nosessionupdate, timeout) {
             $(window).bind('beforeunload', function() {
                 unloading = true;
             });
@@ -150,6 +155,13 @@ define(['jquery', 'core/config', 'core/log', 'core/url'], function($, config, Lo
             if (typeof async === "undefined") {
                 async = true;
             }
+            if (typeof timeout === 'undefined') {
+                timeout = 0;
+            }
+
+            if (typeof nosessionupdate === "undefined") {
+                nosessionupdate = false;
+            }
             for (i = 0; i < requests.length; i++) {
                 var request = requests[i];
                 ajaxRequestData.push({
@@ -157,6 +169,7 @@ define(['jquery', 'core/config', 'core/log', 'core/url'], function($, config, Lo
                     methodname: request.methodname,
                     args: request.args
                 });
+                request.nosessionupdate = nosessionupdate;
                 request.deferred = $.Deferred();
                 promises.push(request.deferred.promise());
                 // Allow setting done and fail handlers as arguments.
@@ -185,7 +198,8 @@ define(['jquery', 'core/config', 'core/log', 'core/url'], function($, config, Lo
                 dataType: 'json',
                 processData: false,
                 async: async,
-                contentType: "application/json"
+                contentType: "application/json",
+                timeout: timeout
             };
 
             var script = 'service.php';
@@ -195,6 +209,10 @@ define(['jquery', 'core/config', 'core/log', 'core/url'], function($, config, Lo
             var url = config.wwwroot + '/lib/ajax/' + script +
                     '?sesskey=' + config.sesskey + '&info=' + requestInfo;
 
+            if (nosessionupdate) {
+                url += '&nosessionupdate=true';
+            }
+
             // Jquery deprecated done and fail with async=false so we need to do this 2 ways.
             if (async) {
                 $.ajax(url, settings)
diff --git a/lib/amd/src/network.js b/lib/amd/src/network.js
new file mode 100644 (file)
index 0000000..5e21a6a
--- /dev/null
@@ -0,0 +1,196 @@
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Poll the server to keep the session alive.
+ *
+ * @module     core/network
+ * @package    core
+ * @copyright  2019 Damyon Wiese
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define(['jquery', 'core/ajax', 'core/config', 'core/notification', 'core/str'],
+        function($, Ajax, Config, Notification, Str) {
+
+    var started = false;
+    var warningDisplayed = false;
+    var keepAliveFrequency = 0;
+    var requestTimeout = 0;
+    var keepAliveMessage = false;
+    var sessionTimeout = false;
+    // 1/10 of session timeout, max of 10 minutes.
+    var checkFrequency = Math.min((Config.sessiontimeout / 10), 600) * 1000;
+    // 1/5 of sessiontimeout.
+    var warningLimit = checkFrequency * 2;
+
+    /**
+     * The session time has expired - we can't extend it now.
+     */
+    var timeoutSessionExpired = function() {
+        sessionTimeout = true;
+    };
+
+    /**
+     * Ping the server to keep the session alive.
+     *
+     * @return {Promise}
+     */
+    var touchSession = function() {
+        var request = {
+            methodname: 'core_session_touch',
+            args: { }
+        };
+
+        if (sessionTimeout) {
+            // We timed out before we extended the session.
+            return Str.get_strings([
+                {key: 'sessionexpired', component: 'error'},
+                {key: 'sessionerroruser', component: 'error'}
+            ]).then(function(strings) {
+                Notification.alert(
+                    strings[0], // Title.
+                    strings[1] // Message.
+                );
+                return true;
+            }).fail(Notification.exception);
+        } else {
+            return Ajax.call([request], true, true, false, requestTimeout)[0].then(function() {
+                if (keepAliveFrequency > 0) {
+                    setTimeout(touchSession, keepAliveFrequency);
+                }
+                return true;
+            }).fail(function() {
+                Notification.alert('', keepAliveMessage);
+            });
+        }
+    };
+
+    /**
+     * Ask the server how much time is remaining in this session and
+     * show confirm/cancel notifications if the session is about to run out.
+     *
+     * @return {Promise}
+     */
+    var checkSession = function() {
+        var request = {
+            methodname: 'core_session_time_remaining',
+            args: { }
+        };
+
+        sessionTimeout = false;
+        return Ajax.call([request], true, true, true)[0].then(function(args) {
+            if (args.userid <= 0) {
+                return false;
+            }
+            if (args.timeremaining < 0) {
+                Str.get_strings([
+                    {key: 'sessionexpired', component: 'error'},
+                    {key: 'sessionerroruser', component: 'error'}
+                ]).then(function(strings) {
+                    Notification.alert(
+                        strings[0], // Title.
+                        strings[1] // Message.
+                    );
+                    return true;
+                }).fail(Notification.exception);
+
+            } else if (args.timeremaining * 1000 < warningLimit && !warningDisplayed) {
+                // If we don't extend the session before the timeout - warn.
+                setTimeout(timeoutSessionExpired, args.timeremaining * 1000);
+                warningDisplayed = true;
+                Str.get_strings([
+                    {key: 'norecentactivity', component: 'moodle'},
+                    {key: 'sessiontimeoutsoon', component: 'moodle'},
+                    {key: 'extendsession', component: 'moodle'},
+                    {key: 'cancel', component: 'moodle'}
+                ]).then(function(strings) {
+                    Notification.confirm(
+                        strings[0], // Title.
+                        strings[1], // Message.
+                        strings[2], // Extend session.
+                        strings[3], // Cancel.
+                        function() {
+                            touchSession();
+                            warningDisplayed = false;
+                            // First wait is half the session timeout.
+                            setTimeout(checkSession, checkFrequency * 5);
+                            return true;
+                        },
+                        function() {
+                            warningDisplayed = false;
+                            setTimeout(checkSession, checkFrequency);
+                        }
+                    );
+                    return true;
+                }).fail(Notification.exception);
+            } else {
+                setTimeout(checkSession, checkFrequency);
+            }
+            return true;
+        });
+        // We do not catch the fails from the above ajax call because they will fail when
+        // we are not logged in - we don't need to take any action then.
+    };
+
+    /**
+     * Start calling a function to check if the session is still alive.
+     */
+    var start = function() {
+        if (keepAliveFrequency > 0) {
+            setTimeout(touchSession, keepAliveFrequency);
+        } else {
+            // First wait is half the session timeout.
+            setTimeout(checkSession, checkFrequency * 5);
+        }
+    };
+
+    /**
+     * Don't allow more than one of these polling loops in a single page.
+     */
+    var init = function() {
+        // We only allow one concurrent instance of this checker.
+        if (started) {
+            return;
+        }
+        started = true;
+
+        start();
+    };
+
+    /**
+     * Start polling with more specific values for the frequency, timeout and message.
+     *
+     * @param {number} freq How ofter to poll the server.
+     * @param {number} timeout The time to wait for each request to the server.
+     * @param {string} message The message to display if the session is going to time out.
+     */
+    var keepalive = function(freq, timeout, message) {
+        // We only allow one concurrent instance of this checker.
+        if (started) {
+            return;
+        }
+        started = true;
+
+        keepAliveFrequency = freq * 1000;
+        keepAliveMessage = message;
+        requestTimeout = timeout * 1000;
+        start();
+    };
+
+    return {
+        keepalive: keepalive,
+        init: init
+    };
+});
index 88360b8..b92c97d 100644 (file)
@@ -26,11 +26,13 @@ define(
     'jquery',
     'core/custom_interaction_events',
     'core/str',
+    'core/network'
 ],
 function(
     $,
     CustomEvents,
-    Str
+    Str,
+    Network
 ) {
 
     /**
@@ -127,6 +129,7 @@ function(
      */
     var init = function() {
         initActionOptionDropdownHandler();
+        Network.init();
     };
 
     return {
diff --git a/lib/classes/session/external.php b/lib/classes/session/external.php
new file mode 100644 (file)
index 0000000..e6e0f0e
--- /dev/null
@@ -0,0 +1,95 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This class contains a list of webservice functions related to session.
+ *
+ * @package    core
+ * @copyright  2019 Damyon Wiese
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core\session;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * This class contains a list of webservice functions related to session.
+ *
+ * @copyright  2019 Damyon Wiese
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since      2.9
+ */
+class external extends \external_api {
+
+    /**
+     * Returns description of touch_session() parameters.
+     *
+     * @return external_function_parameters
+     */
+    public static function touch_session_parameters() {
+        return new \external_function_parameters([]);
+    }
+
+    /**
+     * Extend the current session.
+     *
+     * @return array the mapping
+     */
+    public static function touch_session() {
+        \core\session\manager::touch_session(session_id());
+        return true;
+    }
+
+    /**
+     * Returns description of touch_session() result value.
+     *
+     * @return external_description
+     */
+    public static function touch_session_returns() {
+        return new \external_value(PARAM_BOOL, 'result');
+    }
+
+    /**
+     * Returns description of time_remaining() parameters.
+     *
+     * @return external_function_parameters
+     */
+    public static function time_remaining_parameters() {
+        return new \external_function_parameters([]);
+    }
+
+    /**
+     * Extend the current session.
+     *
+     * @return array the mapping
+     */
+    public static function time_remaining() {
+        return \core\session\manager::time_remaining(session_id());
+    }
+
+    /**
+     * Returns description of touch_session() result value.
+     *
+     * @return external_description
+     */
+    public static function time_remaining_returns() {
+        return new \external_single_structure(array (
+                'userid' => new \external_value(PARAM_INTEGER, 'The current user id.'),
+                'timeremaining' => new \external_value(PARAM_INTEGER, 'The number of seconds remaining in this session.')
+        ));
+    }
+}
index 36083dd..47c5df9 100644 (file)
@@ -364,6 +364,9 @@ class manager {
             }
 
             if ($timeout) {
+                if (defined('NO_SESSION_UPDATE') && NO_SESSION_UPDATE) {
+                    return;
+                }
                 session_regenerate_id(true);
                 $_SESSION = array();
                 $DB->delete_records('sessions', array('id'=>$record->id));
@@ -398,7 +401,7 @@ class manager {
                     $updated = true;
                 }
 
-                if ($updated) {
+                if ($updated && (!defined('NO_SESSION_UPDATE') || !NO_SESSION_UPDATE)) {
                     $update->id = $record->id;
                     $DB->update_record('sessions', $update);
                 }
@@ -632,6 +635,31 @@ class manager {
         return self::$handler->session_exists($sid);
     }
 
+    /**
+     * Return the number of seconds remaining in the current session.
+     * @param string $sid
+     */
+    public static function time_remaining($sid) {
+        global $DB, $CFG;
+
+        if (empty($CFG->version)) {
+            // Not installed yet, do not try to access database.
+            return ['userid' => 0, 'timeremaining' => $CFG->sessiontimeout];
+        }
+
+        // Note: add sessions->state checking here if it gets implemented.
+        if (!$record = $DB->get_record('sessions', array('sid' => $sid), 'id, userid, timemodified')) {
+            return ['userid' => 0, 'timeremaining' => $CFG->sessiontimeout];
+        }
+
+        if (empty($record->userid) or isguestuser($record->userid)) {
+            // Ignore guest and not-logged-in timeouts, there is very little risk here.
+            return ['userid' => 0, 'timeremaining' => $CFG->sessiontimeout];
+        } else {
+            return ['userid' => $record->userid, 'timeremaining' => $CFG->sessiontimeout - (time() - $record->timemodified)];
+        }
+    }
+
     /**
      * Fake last access for given session, this prevents session timeout.
      * @param string $sid
@@ -955,9 +983,10 @@ class manager {
      * @param string $identifier The string identifier for the message to show on failure.
      * @param string $component The string component for the message to show on failure.
      * @param int $frequency The update frequency in seconds.
+     * @param int $timeout The timeout of each request in seconds.
      * @throws coding_exception IF the frequency is longer than the session lifetime.
      */
-    public static function keepalive($identifier = 'sessionerroruser', $component = 'error', $frequency = null) {
+    public static function keepalive($identifier = 'sessionerroruser', $component = 'error', $frequency = null, $timeout = 0) {
         global $CFG, $PAGE;
 
         if ($frequency) {
@@ -966,19 +995,15 @@ class manager {
                 throw new \coding_exception('Keepalive frequency is longer than the session lifespan.');
             }
         } else {
-            // A frequency of sessiontimeout / 3 allows for one missed request whilst still preserving the session.
-            $frequency = $CFG->sessiontimeout / 3;
-        }
-
-        // Add the session keepalive script to the list of page output requirements.
-        $sessionkeepaliveurl = new \moodle_url('/lib/sessionkeepalive_ajax.php');
-        $PAGE->requires->string_for_js($identifier, $component);
-        $PAGE->requires->yui_module('moodle-core-checknet', 'M.core.checknet.init', array(array(
-            // The JS config takes this is milliseconds rather than seconds.
-            'frequency' => $frequency * 1000,
-            'message' => array($identifier, $component),
-            'uri' => $sessionkeepaliveurl->out(),
-        )));
+            // A frequency of sessiontimeout / 10 matches the timeouts in core/network amd module.
+            $frequency = $CFG->sessiontimeout / 10;
+        }
+
+        $PAGE->requires->js_call_amd('core/network', 'keepalive', array(
+                $frequency,
+                $timeout,
+                get_string($identifier, $component)
+            ));
     }
 
     /**
index 708f2cc..ce63f3d 100644 (file)
@@ -677,6 +677,22 @@ $functions = array(
         'loginrequired' => false,
         'ajax' => true,
     ),
+    'core_session_touch' => array(
+        'classname' => 'core\session\external',
+        'methodname' => 'touch_session',
+        'description' => 'Keep the users session alive',
+        'type' => 'read',
+        'loginrequired' => true,
+        'ajax' => true,
+    ),
+    'core_session_time_remaining' => array(
+        'classname' => 'core\session\external',
+        'methodname' => 'time_remaining',
+        'description' => 'Count the seconds remaining in this session',
+        'type' => 'read',
+        'loginrequired' => true,
+        'ajax' => true,
+    ),
     'core_files_get_files' => array(
         'classname' => 'core_files_external',
         'methodname' => 'get_files',
index c7c0aa1..f299050 100644 (file)
@@ -321,6 +321,7 @@ class page_requirements_manager {
             $this->M_cfg = array(
                 'wwwroot'             => $CFG->wwwroot,
                 'sesskey'             => sesskey(),
+                'sessiontimeout'      => $CFG->sessiontimeout,
                 'themerev'            => theme_get_revision(),
                 'slasharguments'      => (int)(!empty($CFG->slasharguments)),
                 'theme'               => $page->theme->name,
diff --git a/lib/sessionkeepalive_ajax.php b/lib/sessionkeepalive_ajax.php
deleted file mode 100644 (file)
index 65d1acf..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
-
-/**
- * Ensure that session is kept alive.
- *
- * @copyright 2014 Andrew Nicols
- * @package   core
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-define('AJAX_SCRIPT', true);
-require_once(__DIR__ . '/../config.php');
-
-// Require the session key - want to make sure that this isn't called
-// maliciously to keep a session alive longer than intended.
-if (!confirm_sesskey()) {
-    header('HTTP/1.1 403 Forbidden');
-    print_error('invalidsesskey');
-}
-
-// Update the session.
-\core\session\manager::touch_session(session_id());
index 30dbd05..631f3e6 100644 (file)
@@ -1,6 +1,9 @@
 This files describes API changes in core libraries and APIs,
 information provided here is intended especially for developers.
 
+=== 3.8 ===
+* The yui checknet module is removed. Call \core\session\manager::keepalive instead.
+
 === 3.7 ===
 * Nodes in the navigation api can have labels for each group. See set/get_collectionlabel().
 * The method core_user::is_real_user() now returns false for userid = 0 parameter
diff --git a/lib/yui/build/moodle-core-checknet/assets/checknet.txt b/lib/yui/build/moodle-core-checknet/assets/checknet.txt
deleted file mode 100644 (file)
index d00491f..0000000
Binary files a/lib/yui/build/moodle-core-checknet/assets/checknet.txt and /dev/null differ
diff --git a/lib/yui/build/moodle-core-checknet/moodle-core-checknet-debug.js b/lib/yui/build/moodle-core-checknet/moodle-core-checknet-debug.js
deleted file mode 100644 (file)
index 3ee6b81..0000000
Binary files a/lib/yui/build/moodle-core-checknet/moodle-core-checknet-debug.js and /dev/null differ
diff --git a/lib/yui/build/moodle-core-checknet/moodle-core-checknet-min.js b/lib/yui/build/moodle-core-checknet/moodle-core-checknet-min.js
deleted file mode 100644 (file)
index 0fe879b..0000000
Binary files a/lib/yui/build/moodle-core-checknet/moodle-core-checknet-min.js and /dev/null differ
diff --git a/lib/yui/build/moodle-core-checknet/moodle-core-checknet.js b/lib/yui/build/moodle-core-checknet/moodle-core-checknet.js
deleted file mode 100644 (file)
index 52d5b54..0000000
Binary files a/lib/yui/build/moodle-core-checknet/moodle-core-checknet.js and /dev/null differ
diff --git a/lib/yui/src/checknet/assets/checknet.txt b/lib/yui/src/checknet/assets/checknet.txt
deleted file mode 100644 (file)
index d00491f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/lib/yui/src/checknet/build.json b/lib/yui/src/checknet/build.json
deleted file mode 100644 (file)
index 406832d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "name": "moodle-core-checknet",
-    "builds": {
-        "moodle-core-checknet": {
-            "jsfiles": [
-                "checknet.js"
-            ]
-        }
-    }
-}
diff --git a/lib/yui/src/checknet/js/checknet.js b/lib/yui/src/checknet/js/checknet.js
deleted file mode 100644 (file)
index 595620e..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
-
-/**
- * A utility to check whether the connection to the Moodle server is still
- * active.
- *
- * @module     moodle-core-checknet
- * @package    core
- * @copyright  2014 Andrew Nicols <andrew@nicols.co.uk>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- * @main       moodle-core-checknet
- */
-
-/**
- * @namespace M.core
- * @class checknet
- */
-
-function CheckNet() {
-    CheckNet.superclass.constructor.apply(this, arguments);
-}
-
-Y.extend(CheckNet, Y.Base, {
-    /**
-     * Zero-based count of alerts displayed.
-     *
-     * @property _alertCount
-     * @type Number
-     * @private
-     * @default 0
-     */
-    _alertCount: 0,
-
-    /**
-     * A link to the warning dialogue.
-     *
-     * @property _alertDialogue
-     * @type M.core.dialogue
-     * @private
-     * @default null
-     */
-    _alertDialogue: null,
-
-    /**
-     * Setup the checking mechanism.
-     *
-     * @method initializer
-     */
-    initializer: function() {
-        // Perform our first check.
-        this._scheduleCheck();
-    },
-
-    /**
-     * Schedule a check of the checknet file.
-     *
-     * @method _scheduleCheck
-     * @chainable
-     * @private
-     */
-    _scheduleCheck: function() {
-        // Schedule the next check after five seconds.
-        Y.later(this.get('frequency'), this, this._performCheck);
-        return this;
-    },
-
-    /**
-     * Perform an immediate check of the checknet file.
-     *
-     * @method _performCheck
-     * @private
-     */
-    _performCheck: function() {
-        Y.io(this.get('uri'), {
-            data: {
-                // Add the session key.
-                sesskey: M.cfg.sesskey,
-                // Add a query string to prevent older versions of IE from using the cache.
-                time: new Date().getTime()
-            },
-            timeout: this.get('timeout'),
-            headers: {
-                'Cache-Control': 'no-cache',
-                'Expires': '-1'
-            },
-            context: this,
-            on: {
-                complete: function(tid, response) {
-                    // Check for failure conditions.
-                    // We check for a valid status here because if the user is moving away from the page at the time we
-                    // run this callback we do not want to display the error.
-                    if (response && typeof response.status !== "undefined") {
-                        var code = parseInt(response.status, 10);
-
-                        if (code === 200) {
-                            // This is a valid attempt - clear any existing warning dialogue and destroy it.
-                            if (this._alertDialogue) {
-                                this._alertDialogue.destroy();
-                                this._alertDialogue = null;
-                            }
-                        } else if (code >= 300 && code <= 399) {
-                            // This is a cached status - warn developers, but otherwise ignore.
-                            Y.log("A cached copy of the checknet status file was returned so it's reliablity cannot be guaranteed",
-                                'warn',
-                                'moodle-mod_scorm-checknet');
-                        } else {
-                            if (this._alertDialogue === null || this._alertDialogue.get('destroyed')) {
-                                // Only create a new dialogue if it isn't already displayed.
-                                this._alertDialogue = new M.core.alert({
-                                    message: M.util.get_string.apply(this, this.get('message'))
-                                });
-                            } else {
-                                this._alertDialogue.show();
-                            }
-                            this._alertCount++;
-                        }
-                    }
-                    // If max alert not modified in args, check indefinitely.
-                    // Once max alert count iteration is reached, stop checking.
-                    if (this.get('maxalerts') === -1 || (this.get('maxalerts') - 1) >= this._alertCount) {
-                        // Start the next check.
-                        this._scheduleCheck();
-                    }
-                }
-            }
-        });
-    }
-}, {
-    NAME: 'checkNet',
-    ATTRS: {
-        /**
-         * The file to check access against.
-         *
-         * @attribute uri
-         * @type String
-         * @default M.cfg.wwwroot + '/lib/yui/build/moodle-core-checknet/assets/checknet.txt'
-         */
-        uri: {
-            value: M.cfg.wwwroot + '/lib/yui/build/moodle-core-checknet/assets/checknet.txt'
-        },
-
-        /**
-         * The timeout (in milliseconds) before the checker should give up and display a warning.
-         *
-         * @attribute timeout
-         * @type Number
-         * @value 4000
-         */
-        timeout: {
-            value: 4000
-        },
-
-        /**
-         * The frequency (in milliseconds) that checks should be run.
-         * A new check is not begun until the previous check has completed.
-         *
-         * @attribute frequency
-         * @writeOnce
-         * @type Number
-         * @value 10000
-         */
-        frequency: {
-            value: 10000
-        },
-
-        /**
-         * The message which should be displayed upon a test failure.
-         *
-         * The array values are passed directly to M.util.get_string() and arguments should match accordingly.
-         *
-         * @attribute message
-         * @type Array
-         * @value [
-         *  'networkdropped',
-         *  'moodle'
-         * ]
-         */
-        message: {
-            value: [
-                'networkdropped',
-                'moodle'
-            ]
-        },
-
-        /**
-         * Maxiumum count (not zero-based) of alerts to display for a single page load.
-         *
-         * @attribute maxalerts
-         * @type Number
-         * @value -1
-         */
-        maxalerts: {
-            value: -1
-        }
-    }
-});
-
-M.core = M.core || {};
-M.core.checknet = M.core.checknet || {};
-M.core.checknet.init = function(config) {
-    return new CheckNet(config);
-};
diff --git a/lib/yui/src/checknet/meta/checknet.json b/lib/yui/src/checknet/meta/checknet.json
deleted file mode 100644 (file)
index a63efb0..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "moodle-core-checknet": {
-        "requires": [
-            "base-base",
-            "moodle-core-notification-alert",
-            "io-base"
-        ]
-    }
-}
index 07bf5b5..f0cc78e 100644 (file)
@@ -282,16 +282,9 @@ if (file_exists($CFG->dirroot.'/mod/scorm/datamodels/'.$scorm->version.'.php'))
     include_once($CFG->dirroot.'/mod/scorm/datamodels/scorm_12.php');
 }
 
-// Add the checknet system to keep checking for a connection.
-$PAGE->requires->string_for_js('networkdropped', 'mod_scorm');
-// Build arguments to send to checknet JS.
-$args = array(
-    'message' => array('networkdropped', 'mod_scorm'),
-    'frequency' => 30000, // Frequency of network check.
-    'timeout' => 10000, // Timeout of network check.
-    'maxalerts' => 1 // Max number of alerts to be thrown.
-);
-$PAGE->requires->yui_module('moodle-core-checknet', 'M.core.checknet.init', array($args));
+// Add the keepalive system to keep checking for a connection.
+\core\session\manager::keepalive('networkdropped', 'mod_scorm', 30, 10);
+
 echo $OUTPUT->footer();
 
 // Set the start time of this SCO.
index d62f6f0..acea8f1 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2019053000.00;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2019060600.00;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.