mirror of
https://github.com/catalyst/moodle-auth_outage.git
synced 2026-05-17 05:48:43 +02:00
Compare commits
12 Commits
admin-mess
...
MOODLE_32_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fb8f2f186 | ||
|
|
907cf73e54 | ||
|
|
c6c0382eab | ||
|
|
7bf8b9a748 | ||
|
|
99e43b6c76 | ||
|
|
1d1fb94142 | ||
|
|
2366b3ea18 | ||
|
|
a252f55bdf | ||
|
|
f72a03aa5a | ||
|
|
a42ad4141a | ||
|
|
4ce9f05ebf | ||
|
|
bdf158a677 |
20
.github/workflows/moodle-release.yml
vendored
Normal file
20
.github/workflows/moodle-release.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Whenever version.php is changed, add the latest version
|
||||
# to the Moodle Plugins directory at https://moodle.org/plugins
|
||||
#
|
||||
name: Releasing in the Plugins directory
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- MOODLE_32_STABLE
|
||||
paths:
|
||||
- 'version.php'
|
||||
|
||||
jobs:
|
||||
workflow_group_27_to_32_release:
|
||||
uses: catalyst/catalyst-moodle-workflows/.github/workflows/group-27-to-32-release.yml@main
|
||||
with:
|
||||
plugin_name: auth_outage
|
||||
secrets:
|
||||
moodle_org_token: ${{ secrets.MOODLE_ORG_TOKEN }}
|
||||
75
.travis.yml
75
.travis.yml
@@ -1,75 +0,0 @@
|
||||
language: php
|
||||
|
||||
sudo: true
|
||||
|
||||
services:
|
||||
- mysql
|
||||
|
||||
addons:
|
||||
firefox: "47.0.1"
|
||||
postgresql: "9.6"
|
||||
apt:
|
||||
packages:
|
||||
- openjdk-8-jre
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
- $HOME/.npm
|
||||
|
||||
php:
|
||||
- 7.2
|
||||
|
||||
env:
|
||||
- DB=pgsql MOODLE_BRANCH=MOODLE_36_STABLE NODEJS=8
|
||||
- DB=mysqli MOODLE_BRANCH=MOODLE_36_STABLE NODEJS=8
|
||||
- DB=pgsql MOODLE_BRANCH=MOODLE_37_STABLE
|
||||
- DB=pgsql MOODLE_BRANCH=MOODLE_38_STABLE
|
||||
- DB=pgsql MOODLE_BRANCH=MOODLE_39_STABLE
|
||||
- DB=mysqli MOODLE_BRANCH=MOODLE_39_STABLE
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- php: 5.6
|
||||
env: DB=pgsql MOODLE_BRANCH=MOODLE_33_STABLE NODEJS=8
|
||||
- php: 7.0
|
||||
env: DB=mysqli MOODLE_BRANCH=MOODLE_35_STABLE
|
||||
- php: 7.1
|
||||
env: DB=mysqli MOODLE_BRANCH=MOODLE_33_STABLE NODEJS=8
|
||||
- php: 7.4
|
||||
env: DB=mysqli MOODLE_BRANCH=master
|
||||
- php: 7.4
|
||||
env: DB=pgsql MOODLE_BRANCH=master
|
||||
|
||||
before_install:
|
||||
- export MOODLE_VERSION=$(echo "$MOODLE_BRANCH" | cut -d'_' -f 2)
|
||||
- phpenv config-rm xdebug.ini
|
||||
- if [ "$NODEJS" = 8 ]; then
|
||||
nvm install 8.9;
|
||||
nvm use 8.9;
|
||||
else
|
||||
nvm install 14.0.0;
|
||||
nvm use 14.0.0;
|
||||
fi
|
||||
- cd ../..
|
||||
- composer selfupdate
|
||||
- composer create-project -n --no-dev --prefer-dist blackboard-open-source/moodle-plugin-ci ci ^2
|
||||
- export PATH="$(cd ci/bin; pwd):$(cd ci/vendor/bin; pwd):$PATH"
|
||||
|
||||
install:
|
||||
- moodle-plugin-ci install
|
||||
|
||||
script:
|
||||
- moodle-plugin-ci phplint
|
||||
- moodle-plugin-ci phpcpd
|
||||
- moodle-plugin-ci phpmd
|
||||
- moodle-plugin-ci codechecker
|
||||
- moodle-plugin-ci validate
|
||||
- moodle-plugin-ci savepoints
|
||||
- moodle-plugin-ci mustache
|
||||
- moodle-plugin-ci grunt
|
||||
- moodle-plugin-ci phpunit
|
||||
# Behat tests are failing due to issue:
|
||||
# https://github.com/blackboard-open-source/moodle-plugin-ci/issues/70
|
||||
# Commenting it out until the issue is fixed.
|
||||
# - moodle-plugin-ci behat
|
||||
29
README.md
29
README.md
@@ -1,14 +1,11 @@
|
||||
<a href="https://travis-ci.org/catalyst/moodle-auth_outage">
|
||||
<img src="https://travis-ci.org/catalyst/moodle-auth_outage.svg?branch=master">
|
||||
</a>
|
||||
(https://github.com/catalyst/moodle-auth_outage/actions)
|
||||
|
||||
# Moodle Outage manager plugin
|
||||
* [Version Support](#version-support)
|
||||
|
||||
* [What is this?](#what-is-this)
|
||||
* [Moodle Requirements](#moodle-requirements)
|
||||
* [Screenshots](#screenshots)
|
||||
* [Installation](#installation)
|
||||
* [Theme configuration](#theme-configuration)
|
||||
* [How to use](#how-to-use)
|
||||
* [Quick Guide](#quick-guide)
|
||||
* [Why is it an auth plugin?](#why-it-is-an-auth-plugin)
|
||||
@@ -40,14 +37,6 @@ If you have an older version of Moodle you can still make it work but you will
|
||||
need to manually add one extra plugin, please check:
|
||||
* https://github.com/catalyst/moodle-local_outage
|
||||
|
||||
Branches
|
||||
--------
|
||||
| Moodle version | Branch | PHP |
|
||||
| ----------------- | ----------- | ---- |
|
||||
| Moodle 2.7 to 3.2 | MOODLE_32_STABLE | 5.5+ |
|
||||
| Totara up to 10 | TOTARA_10 | 5.5+ |
|
||||
| Moodle 3.3+ | master | 7.0+ |
|
||||
| Totara 11+ | master | 7.0+ |
|
||||
|
||||
Screenshots
|
||||
-----------
|
||||
@@ -92,20 +81,6 @@ if (file_exists(__DIR__.'/auth/outage/bootstrap.php')) {
|
||||
}
|
||||
```
|
||||
|
||||
Theme configuration
|
||||
-------------------
|
||||
|
||||
This plugin must work gracefully with your theme, but every theme can be different so it's impossible to get this right out of the box (other than with the default moodle theme Boost).
|
||||
|
||||
There is an admin setting which allows you to add or override and css to fix css issues. Typically these include properly pushing the page down when the outage notification bar is visible, including making this work with fixed headers and when the hamburger menu is open / closed and at different responsive breakpoints.
|
||||
|
||||
This can be found at:
|
||||
|
||||
`Dashboard / Site administration / Plugins / Authentication / Outage manager / Settings`
|
||||
|
||||
|
||||
|
||||
|
||||
How to use
|
||||
----------
|
||||
|
||||
|
||||
@@ -67,19 +67,9 @@ if (is_callable('auth_outage_bootstrap_callback')) {
|
||||
}
|
||||
|
||||
// 3) Check for allowed scripts or IPs during outages.
|
||||
if (!empty($_SERVER['REQUEST_URI'])) {
|
||||
$rooturl = parse_url($CFG->wwwroot);
|
||||
$path = '';
|
||||
if (array_key_exists('path', $rooturl) && !empty($rooturl['path'])) {
|
||||
$path = $rooturl['url'];
|
||||
}
|
||||
$url = $path.'/auth/outage/info.php';
|
||||
$outageinfo = strpos($_SERVER['REQUEST_URI'], $url) === 0 ? true : false;
|
||||
}
|
||||
$allowed = !file_exists($CFG->dataroot.'/climaintenance.php') // Not in maintenance mode.
|
||||
|| (defined('ABORT_AFTER_CONFIG') && ABORT_AFTER_CONFIG) // Only config requested.
|
||||
|| (defined('CLI_SCRIPT') && CLI_SCRIPT) // Allow CLI scripts.
|
||||
|| $outageinfo; // Allow outage info requests.
|
||||
|| (defined('CLI_SCRIPT') && CLI_SCRIPT); // Allow CLI scripts.
|
||||
if (!$allowed) {
|
||||
// Call the climaintenance.php which will check for allowed IPs.
|
||||
$CFG->dirroot = dirname(dirname(dirname(__FILE__))); // It is not defined yet but the script below needs it.
|
||||
|
||||
@@ -65,7 +65,7 @@ class calendar {
|
||||
debugging('Cannot update calendar entry for outage #'.$outage->id.', event not found. Creating it...');
|
||||
self::create($outage);
|
||||
} else {
|
||||
$event->update(self::create_data($outage), false);
|
||||
$event->update(self::create_data($outage));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,79 +96,6 @@ class outagedb {
|
||||
return new outage($outage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Also sends all admins the event as a message
|
||||
*
|
||||
* @param $outage
|
||||
* @param $event
|
||||
*/
|
||||
private static function notify($outage, $event) {
|
||||
|
||||
$admins = get_admins();
|
||||
|
||||
foreach ($admins as $admin) {
|
||||
self::notify_user($outage, $event, $admin);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Send outage info to one user
|
||||
*
|
||||
* @param $outage outage
|
||||
* @param $event event
|
||||
* @param $to user object
|
||||
*/
|
||||
private static function notify_user($outage, $event, $to) {
|
||||
|
||||
global $SITE, $CFG;
|
||||
|
||||
$from = \core_user::get_user($event->userid);
|
||||
$fields = [
|
||||
'site_shortname' => $SITE->shortname,
|
||||
'site_fullname' => $SITE->fullname,
|
||||
'site_wwwroot' => $CFG->wwwroot,
|
||||
|
||||
'outage_id' => $outage->id,
|
||||
'outage_title' => $outage->get_title(),
|
||||
'outage_desc' => $outage->get_description(),
|
||||
'outage_start' => userdate($outage->starttime, get_string('datetimeformat', 'auth_outage')),
|
||||
'outage_stop' => userdate($outage->stoptime, get_string('datetimeformat', 'auth_outage')),
|
||||
'outage_duration' => format_time($outage->get_duration_planned()),
|
||||
|
||||
'event_name' => $event->get_name(),
|
||||
'event_desc' => $event->get_description(),
|
||||
'event_link' => $event->get_url()->out(),
|
||||
|
||||
'from_name' => fullname($from),
|
||||
'to_name' => fullname($to),
|
||||
'prefs_link' => (new \moodle_url('/message/notificationpreferences.php'))->out(),
|
||||
|
||||
];
|
||||
|
||||
$message = new \core\message\message();
|
||||
$message->component = 'auth_outage';
|
||||
$message->name = 'updatenotify';
|
||||
$message->userto = $to;
|
||||
$message->subject = get_string('messagesubject', 'auth_outage', $fields);
|
||||
$message->fullmessage = get_string('messagetext', 'auth_outage', $fields);
|
||||
$message->fullmessagehtml = get_string('messagehtml', 'auth_outage', $fields);
|
||||
$message->fullmessageformat = FORMAT_HTML;
|
||||
|
||||
$threadid = generate_email_messageid('outage' . $outage->id);
|
||||
$message->userfrom = $from;
|
||||
$message->userfrom->customheaders = [
|
||||
"In-Reply-To: $threadid",
|
||||
"References: $threadid",
|
||||
"Thread-Topic: " . $message->subject,
|
||||
"Thread-Index: $threadid",
|
||||
];
|
||||
|
||||
$message->notification = '1';
|
||||
$messageid = message_send($message);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves an outage to the database.
|
||||
*
|
||||
@@ -190,42 +117,25 @@ class outagedb {
|
||||
$outage->createdby = $USER->id;
|
||||
// Then create it, log it and adjust its id.
|
||||
$outage->id = $DB->insert_record('auth_outage', $outage, true);
|
||||
|
||||
$other = (array) $outage;
|
||||
$other['title'] = $outage->get_title();
|
||||
$event = outage_created::create([
|
||||
'objectid' => $outage->id,
|
||||
'other' => $other,
|
||||
]);
|
||||
$event->add_record_snapshot('auth_outage', (object)(array) $outage);
|
||||
$event->trigger();
|
||||
self::notify($outage, $event);
|
||||
|
||||
outage_created::create(
|
||||
['objectid' => $outage->id, 'other' => (array)$outage]
|
||||
)->trigger();
|
||||
// Create calendar entry.
|
||||
calendar::create($outage);
|
||||
} else {
|
||||
|
||||
$other = (array) $outage;
|
||||
$other['title'] = $outage->get_title();
|
||||
$event = outage_updated::create([
|
||||
'objectid' => $outage->id,
|
||||
'other' => $other,
|
||||
]);
|
||||
|
||||
$event->add_record_snapshot('auth_outage', (object)(array) $outage);
|
||||
$event->trigger();
|
||||
self::notify($outage, $event);
|
||||
|
||||
// Remove the createdby field so it does not get updated.
|
||||
unset($outage->createdby);
|
||||
$DB->update_record('auth_outage', $outage);
|
||||
|
||||
// Log it.
|
||||
outage_updated::create(
|
||||
['objectid' => $outage->id, 'other' => (array)$outage]
|
||||
)->trigger();
|
||||
// Update calendar entry.
|
||||
calendar::update($outage);
|
||||
}
|
||||
|
||||
// Trigger outages modified events.
|
||||
outagelib::prepare_next_outage(true);
|
||||
outagelib::prepare_next_outage();
|
||||
|
||||
// All done, return the id.
|
||||
return $outage->id;
|
||||
@@ -246,19 +156,9 @@ class outagedb {
|
||||
|
||||
// Log it.
|
||||
$previous = $DB->get_record('auth_outage', ['id' => $id], '*', MUST_EXIST);
|
||||
|
||||
$outage = new outage($previous);
|
||||
|
||||
$other = (array) $outage;
|
||||
$other['title'] = $outage->get_title();
|
||||
$event = outage_deleted::create([
|
||||
'objectid' => $id,
|
||||
'other' => $other,
|
||||
]);
|
||||
|
||||
$event = outage_deleted::create(['objectid' => $id, 'other' => (array)$previous]);
|
||||
$event->add_record_snapshot('auth_outage', $previous);
|
||||
$event->trigger();
|
||||
self::notify($outage, $event);
|
||||
|
||||
// Delete it and remove from calendar.
|
||||
$DB->delete_records('auth_outage', ['id' => $id]);
|
||||
|
||||
@@ -39,23 +39,14 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class outage_created extends base {
|
||||
|
||||
/**
|
||||
* Return localised event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('eventoutagecreated', 'auth_outage');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised event description with id's for admin use only.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return "The user with the id '{$this->userid}' scheduled outage {$this->other['id']} '{$this->other['title']}'";
|
||||
return "The user with the id '{$this->userid}' created a new outage title '{$this->other['title']}' ".
|
||||
" with id '{$this->other['id']}'.";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,7 +54,7 @@ class outage_created extends base {
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_url() {
|
||||
return new moodle_url('/auth/outage/edit.php', ['edit' => $this->other['id']]);
|
||||
return new moodle_url('/auth/outage/list.php#auth_outage_id_'.$this->other['id']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,23 +38,14 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class outage_deleted extends base {
|
||||
|
||||
/**
|
||||
* Return localised event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('eventoutagedeleted', 'auth_outage');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised event description with id's for admin use only.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return "The user with the id '{$this->userid}' deleted outage {$this->other['id']} '{$this->other['title']}'";
|
||||
return "The user with the id '{$this->userid}' deleted the outage titled '{$this->other['title']}' ".
|
||||
"with id '{$this->other['id']}'.";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,7 +53,7 @@ class outage_deleted extends base {
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_url() {
|
||||
return new moodle_url('/auth/outage/manage.php');
|
||||
return new moodle_url('/auth/outage/list.php#auth_outage_id_'.$this->other['id']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -39,23 +39,14 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class outage_updated extends base {
|
||||
|
||||
/**
|
||||
* Return localised event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('eventoutageupdated', 'auth_outage');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised event description with id's for admin use only.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return "The user with the id '{$this->userid}' updated outage {$this->other['id']} '{$this->other['title']}'";
|
||||
return "The user with the id '{$this->userid}' updated the outage title '{$this->other['title']}' ".
|
||||
"with id '{$this->other['id']}'.";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,7 +54,7 @@ class outage_updated extends base {
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_url() {
|
||||
return new moodle_url('/auth/outage/edit.php', ['edit' => $this->other['id']]);
|
||||
return new moodle_url('/auth/outage/list.php');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -82,7 +82,6 @@ class edit extends moodleform {
|
||||
$mform->addHelpButton('description', 'description', 'auth_outage');
|
||||
|
||||
$mform->addElement('static', 'usagehints', '', get_string('textplaceholdershint', 'auth_outage'));
|
||||
$mform->addElement('static', 'warningreenablemaintenancemode', '');
|
||||
|
||||
$this->add_action_buttons();
|
||||
}
|
||||
@@ -147,9 +146,6 @@ class edit extends moodleform {
|
||||
* @throws coding_exception
|
||||
*/
|
||||
public function set_data($outage) {
|
||||
global $OUTPUT;
|
||||
$mform = $this->_form;
|
||||
|
||||
// Cannot change method signature, check type.
|
||||
if ($outage instanceof outage) {
|
||||
$this->_form->setDefaults([
|
||||
@@ -161,12 +157,6 @@ class edit extends moodleform {
|
||||
'title' => $outage->title,
|
||||
'description' => ['text' => $outage->description, 'format' => '1'],
|
||||
]);
|
||||
|
||||
if (!empty($outage->id) && $outage->autostart && $outage->starttime < time() && $outage->stoptime > time()) {
|
||||
$warning = $mform->getElement('warningreenablemaintenancemode');
|
||||
$warning->setValue($OUTPUT->notification(get_string('warningreenablemaintenancemode', 'auth_outage'),
|
||||
'notifywarning'));
|
||||
}
|
||||
} else {
|
||||
throw new coding_exception('$outage must be an outage object.', $outage);
|
||||
}
|
||||
|
||||
@@ -147,6 +147,5 @@ abstract class clibase {
|
||||
$long = '--'.$long;
|
||||
printf(" %-4s %-20s %s\n", $short, $long, $text);
|
||||
}
|
||||
printf("\n%s\n\n", get_string('cli'.$cliname.'examples', 'auth_outage'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ class create extends clibase {
|
||||
private function clone_defaults() {
|
||||
$id = $this->options['clone'];
|
||||
if (!is_number($id) || ($id <= 0)) {
|
||||
throw new cli_exception(get_string('clierrorinvalidvaluenotid', 'auth_outage', ['param' => 'clone']),
|
||||
throw new cli_exception(get_string('clierrorinvalidvalue', 'auth_outage', ['param' => 'clone']),
|
||||
cli_exception::ERROR_PARAMETER_INVALID);
|
||||
}
|
||||
|
||||
@@ -245,12 +245,12 @@ class create extends clibase {
|
||||
*/
|
||||
private function merge_options_check_parameters_int_nonnegative($option, $param) {
|
||||
if (!is_number($option)) {
|
||||
throw new cli_exception(get_string('clierrorinvalidvaluenotnumber', 'auth_outage', ['param' => $param]),
|
||||
throw new cli_exception(get_string('clierrorinvalidvalue', 'auth_outage', ['param' => $param]),
|
||||
cli_exception::ERROR_PARAMETER_INVALID);
|
||||
}
|
||||
$option = (int)$option;
|
||||
if ($option < 0) {
|
||||
throw new cli_exception(get_string('clierrorinvalidvaluenegativenumber', 'auth_outage', ['param' => $param]),
|
||||
throw new cli_exception(get_string('clierrorinvalidvalue', 'auth_outage', ['param' => $param]),
|
||||
cli_exception::ERROR_PARAMETER_INVALID);
|
||||
}
|
||||
return $option;
|
||||
@@ -265,12 +265,12 @@ class create extends clibase {
|
||||
*/
|
||||
private function merge_options_check_parameters_string_nonempty($option, $param) {
|
||||
if (!is_string($option)) {
|
||||
throw new cli_exception(get_string('clierrorinvalidvaluenotstring', 'auth_outage', ['param' => $param]),
|
||||
throw new cli_exception(get_string('clierrorinvalidvalue', 'auth_outage', ['param' => $param]),
|
||||
cli_exception::ERROR_PARAMETER_INVALID);
|
||||
}
|
||||
$option = trim($option);
|
||||
if (strlen($option) == 0) {
|
||||
throw new cli_exception(get_string('clierrorinvalidvalueemptystring', 'auth_outage', ['param' => $param]),
|
||||
throw new cli_exception(get_string('clierrorinvalidvalue', 'auth_outage', ['param' => $param]),
|
||||
cli_exception::ERROR_PARAMETER_INVALID);
|
||||
}
|
||||
return $option;
|
||||
@@ -298,7 +298,7 @@ class create extends clibase {
|
||||
}
|
||||
}
|
||||
|
||||
throw new cli_exception(get_string('clierrorinvalidvaluenotbool', 'auth_outage', ['param' => $param]),
|
||||
throw new cli_exception(get_string('clierrorinvalidvalue', 'auth_outage', ['param' => $param]),
|
||||
cli_exception::ERROR_PARAMETER_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,11 +53,6 @@ class infopage {
|
||||
* @param array $params Parameters to use or null to get from Moodle API (request).
|
||||
*/
|
||||
public function __construct(array $params = null) {
|
||||
global $CFG;
|
||||
// Enable SVG support here to make sure all SVG files
|
||||
// used in the current theme are served properly.
|
||||
$CFG->svgicons = true;
|
||||
|
||||
if (is_null($params)) {
|
||||
$params = [
|
||||
'id' => optional_param('id', null, PARAM_INT),
|
||||
|
||||
@@ -57,7 +57,7 @@ class maintenance_static_page {
|
||||
|
||||
if (is_null($outage)) {
|
||||
$html = null;
|
||||
} else if (PHPUNIT_TEST || defined('BEHAT_SITE_RUNNING')) {
|
||||
} else if (PHPUNIT_TEST) {
|
||||
$html = '<html></html>';
|
||||
} else {
|
||||
$data = maintenance_static_page_io::file_get_data(
|
||||
|
||||
@@ -30,7 +30,6 @@ use coding_exception;
|
||||
use DOMDocument;
|
||||
use DOMElement;
|
||||
use invalid_state_exception;
|
||||
use moodle_url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
@@ -128,7 +127,7 @@ class maintenance_static_page_generator {
|
||||
continue;
|
||||
}
|
||||
$saved = $this->io->save_url_file($href);
|
||||
if (empty($saved['url'])) {
|
||||
if (is_null($saved['url'])) {
|
||||
$url = $href; // Skipped, use original URL.
|
||||
} else {
|
||||
$this->update_link_stylesheet_parse($saved['file'], dirname($href));
|
||||
@@ -138,17 +137,6 @@ class maintenance_static_page_generator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all URLs from file content using regular expressions.
|
||||
*
|
||||
* @param string $contents Content of the file
|
||||
* @return array Array of all matches in multi-dimensional array
|
||||
*/
|
||||
public function get_urls_from_stylesheet($contents) {
|
||||
preg_match_all('#url\([\'"]?(?!data:)([^\'"\)]+)#', $contents, $matches);
|
||||
return $matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for urls inside filename.
|
||||
*
|
||||
@@ -159,15 +147,15 @@ class maintenance_static_page_generator {
|
||||
global $CFG;
|
||||
|
||||
$contents = file_get_contents($filename);
|
||||
$matches = $this->get_urls_from_stylesheet($contents);
|
||||
|
||||
if (!preg_match_all('#url\([\'"]?([^\'"\)]+)#', $contents, $matches)) {
|
||||
return;
|
||||
}
|
||||
foreach ($matches[1] as $originalurl) {
|
||||
// Allow incomplete URLs in CSS, assume it is from moodle root.
|
||||
if (maintenance_static_page_io::is_url($originalurl)) {
|
||||
$fullurl = $originalurl;
|
||||
} else if ($originalurl[0] == '/') {
|
||||
$rooturl = parse_url($CFG->wwwroot);
|
||||
$fullurl = $rooturl['scheme'].'://'.$rooturl['host'].$originalurl;
|
||||
$fullurl = $CFG->wwwroot.$originalurl;
|
||||
} else {
|
||||
$fullurl = $baseref.'/'.$originalurl;
|
||||
}
|
||||
@@ -191,12 +179,10 @@ class maintenance_static_page_generator {
|
||||
foreach ($links as $link) {
|
||||
$rel = $link->getAttribute("rel");
|
||||
$href = $link->getAttribute("href");
|
||||
if (($rel == 'shortcut icon') && ($href != '')) {
|
||||
if (!maintenance_static_page_io::is_url($href)) {
|
||||
$href = (string) new moodle_url($href);
|
||||
}
|
||||
$link->setAttribute('href', $this->io->generate_file_url($href)); // Works for most image formats.
|
||||
if (($rel != 'shortcut icon') || ($href == '')) {
|
||||
continue;
|
||||
}
|
||||
$link->setAttribute('href', $this->io->generate_file_url($href)); // Works for most image formats.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,12 +194,10 @@ class maintenance_static_page_generator {
|
||||
|
||||
foreach ($links as $link) {
|
||||
$src = $link->getAttribute("src");
|
||||
if ($src != '') {
|
||||
if (!maintenance_static_page_io::is_url($src)) {
|
||||
$src = (string) new moodle_url($src);
|
||||
}
|
||||
$link->setAttribute('src', $this->io->generate_file_url($src)); // Works for most image formats.
|
||||
if ($src == '') {
|
||||
continue;
|
||||
}
|
||||
$link->setAttribute('src', $this->io->generate_file_url($src)); // Works for most image formats.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ class maintenance_static_page_io {
|
||||
/**
|
||||
* Saves the content of the URL into a file, returning the local filename.
|
||||
* @param string $url Input URL.
|
||||
* @return array|null Output an array with the filename and url or null if skipped.
|
||||
* @return string|null Output filename or null if skipped.
|
||||
*/
|
||||
public function save_url_file($url) {
|
||||
global $CFG;
|
||||
|
||||
@@ -281,17 +281,7 @@ class outage {
|
||||
*/
|
||||
private function adjust_field_types() {
|
||||
// Adjust int fields.
|
||||
$fs = [
|
||||
'id',
|
||||
'starttime',
|
||||
'stoptime',
|
||||
'warntime',
|
||||
'finished',
|
||||
'createdby',
|
||||
'lastmodified',
|
||||
'modifiedby',
|
||||
];
|
||||
|
||||
$fs = ['createdby', 'id', 'lastmodified', 'modifiedby', 'starttime', 'stoptime', 'warntime', 'finished'];
|
||||
foreach ($fs as $f) {
|
||||
$this->$f = ($this->$f === null) ? null : (int)$this->$f;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ use auth_outage\dml\outagedb;
|
||||
use auth_outage\local\controllers\maintenance_static_page;
|
||||
use auth_outage\output\renderer;
|
||||
use coding_exception;
|
||||
use curl;
|
||||
use Exception;
|
||||
use file_exception;
|
||||
use invalid_parameter_exception;
|
||||
@@ -48,25 +47,22 @@ require_once(__DIR__.'/../../lib.php');
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class outagelib {
|
||||
|
||||
const OUTAGE_START = '<!-- OUTAGESTART -->';
|
||||
|
||||
const OUTAGE_END = '<!-- OUTAGEEND -->';
|
||||
|
||||
/**
|
||||
* @var bool Flags in the injection function was already called.
|
||||
*/
|
||||
private static $injectcalled = false;
|
||||
|
||||
public static function fetch_page($file) {
|
||||
$curl = new curl();
|
||||
$contents = $curl->get($file);
|
||||
$info = $curl->get_info();
|
||||
if (!empty($info['content_type'])) {
|
||||
$mime = $info['content_type'];
|
||||
} else {
|
||||
$mime = '';
|
||||
}
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, $file);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5); // It is localhost, time to connect is enough.
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, 15); // It is localhost, time to fetch index is enough.
|
||||
$contents = curl_exec($curl);
|
||||
$mime = curl_getinfo($curl, CURLINFO_CONTENT_TYPE);
|
||||
curl_close($curl);
|
||||
return compact('contents', 'mime');
|
||||
}
|
||||
|
||||
@@ -78,26 +74,6 @@ class outagelib {
|
||||
self::inject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a time, usually now, when is the next outage window?
|
||||
*/
|
||||
public static function get_next_window($time = null) {
|
||||
|
||||
$config = self::get_config();
|
||||
|
||||
if (!$time) {
|
||||
$time = time();
|
||||
}
|
||||
|
||||
$default = $config->default_time;
|
||||
if ($default) {
|
||||
// First try natural language parsing.
|
||||
$time = strtotime($default, $time);
|
||||
}
|
||||
return $time;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Will check for ongoing or warning outages and will attach the message bar as required.
|
||||
*/
|
||||
@@ -111,8 +87,6 @@ class outagelib {
|
||||
return;
|
||||
}
|
||||
|
||||
self::clean_outages();
|
||||
|
||||
// Check for a previewing outage, then for an active outage.
|
||||
$previewid = optional_param('auth_outage_preview', null, PARAM_INT);
|
||||
$time = time();
|
||||
@@ -171,7 +145,6 @@ class outagelib {
|
||||
return [
|
||||
'allowedips' => '',
|
||||
'css' => '',
|
||||
'default_time' => '',
|
||||
'default_autostart' => '0',
|
||||
'default_duration' => (string)(60 * 60),
|
||||
'default_warning_duration' => (string)(60 * 60),
|
||||
@@ -183,25 +156,16 @@ class outagelib {
|
||||
|
||||
/**
|
||||
* Executed when outages are modified (created, updated or deleted).
|
||||
*
|
||||
* @param bool $reenablemaint should we re-enable maintenance mode for ongoing outage
|
||||
* @throws coding_exception
|
||||
* @throws file_exception
|
||||
*/
|
||||
public static function prepare_next_outage($reenablemaint = false) {
|
||||
public static function prepare_next_outage() {
|
||||
// If there is an ongoing outage, prepare it instead.
|
||||
$outage = outagedb::get_ongoing();
|
||||
if (is_null($outage)) {
|
||||
$outage = outagedb::get_next_starting();
|
||||
$ongoingoutage = false;
|
||||
} else {
|
||||
$ongoingoutage = true;
|
||||
}
|
||||
maintenance_static_page::create_from_outage($outage)->generate();
|
||||
self::update_climaintenance_code($outage);
|
||||
if (!$ongoingoutage || $reenablemaint || is_null($outage)) {
|
||||
self::update_maintenance_later($outage);
|
||||
}
|
||||
self::update_maintenance_later($outage);
|
||||
}
|
||||
|
||||
private static function check_wwwroot_accessible() {
|
||||
@@ -282,16 +246,13 @@ class outagelib {
|
||||
}
|
||||
// I know Moodle validation would clean up this field, but just in case, let's ensure no
|
||||
// single-quotes (and double for the sake of it) are present otherwise it would break the code.
|
||||
$allowedips = addslashes($allowedips);
|
||||
$allowedips = str_replace('\'"', '', $allowedips);
|
||||
|
||||
$code = <<<'EOT'
|
||||
<?php
|
||||
if ((time() >= {{STARTTIME}}) && (time() < {{STOPTIME}})) {
|
||||
define('MOODLE_INTERNAL', true);
|
||||
require_once($CFG->dirroot.'/lib/moodlelib.php');
|
||||
if (file_exists($CFG->dirroot.'/lib/classes/ip_utils.php')) {
|
||||
require_once($CFG->dirroot.'/lib/classes/ip_utils.php');
|
||||
}
|
||||
if (!remoteip_in_list('{{ALLOWEDIPS}}')) {
|
||||
header($_SERVER['SERVER_PROTOCOL'] . ' 503 Moodle under maintenance');
|
||||
header('Status: 503 Moodle under maintenance');
|
||||
@@ -304,7 +265,6 @@ if ((time() >= {{STARTTIME}}) && (time() < {{STOPTIME}})) {
|
||||
header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||
header('Accept-Ranges: none');
|
||||
header('X-Moodle-Maintenance: manager');
|
||||
if ((defined('AJAX_SCRIPT') && AJAX_SCRIPT) || (defined('WS_SERVER') && WS_SERVER)) {
|
||||
exit(0);
|
||||
}
|
||||
@@ -366,11 +326,11 @@ EOT;
|
||||
* @internal bootstrap_renderer $OUTPUT
|
||||
*/
|
||||
public static function generate_plugin_configuration_warning() {
|
||||
global $CFG, $OUTPUT, $PAGE;
|
||||
global $CFG, $OUTPUT;
|
||||
|
||||
$message = [];
|
||||
|
||||
if (trim(self::get_config()->allowedips) != '' && (!isset($CFG->auth_outage_bootstrap_loaded) || !$CFG->auth_outage_bootstrap_loaded)) {
|
||||
if (!isset($CFG->auth_outage_bootstrap_loaded) || !$CFG->auth_outage_bootstrap_loaded) {
|
||||
$message[] = get_string('configurationwarning', 'auth_outage');
|
||||
}
|
||||
|
||||
@@ -378,10 +338,8 @@ EOT;
|
||||
$message[] = get_string('configurationdisabled', 'auth_outage');
|
||||
}
|
||||
|
||||
if ($PAGE->pagetype == "admin-setting-auth_outage" || $PAGE->pagetype == "admin-setting-authsettingoutage") {
|
||||
if (!self::check_wwwroot_accessible()) {
|
||||
$message[] = get_string('configurationinaccessiblewwwroot', 'auth_outage', ['wwwroot' => $CFG->wwwroot]);
|
||||
}
|
||||
if (!self::check_wwwroot_accessible()) {
|
||||
$message[] = get_string('configurationinaccessiblewwwroot', 'auth_outage', ['wwwroot' => $CFG->wwwroot]);
|
||||
}
|
||||
|
||||
if (count($message) == 0) {
|
||||
@@ -396,26 +354,4 @@ EOT;
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks $CFG->additionalhtmltopofbody for saved outages and removes them.
|
||||
* We should only be temporarily injecting into that variable and not saving them to the database.
|
||||
*
|
||||
* @return string the cleaned content
|
||||
*/
|
||||
public static function clean_outages() {
|
||||
global $CFG;
|
||||
|
||||
// Replace the content to clean up pages that do not have the injection.
|
||||
$re = '/' . self::OUTAGE_START . '[\s\S]*' . self::OUTAGE_END . '/m';
|
||||
$replaced = preg_replace($re, '', $CFG->additionalhtmltopofbody);
|
||||
|
||||
// We have removed the outages and any duplicates as it should be injected and not saved to $CFG.
|
||||
if ($CFG->additionalhtmltopofbody != $replaced) {
|
||||
set_config('additionalhtmltopofbody', $replaced);
|
||||
return $replaced;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ class base_table extends flexible_table {
|
||||
$buttons .= html_writer::link(
|
||||
new moodle_url('/auth/outage/info.php', ['id' => $outage->id]),
|
||||
html_writer::empty_tag('img', [
|
||||
'src' => $OUTPUT->image_url('t/preview'),
|
||||
'src' => $OUTPUT->pix_url('t/preview'),
|
||||
'alt' => get_string('view'),
|
||||
'class' => 'iconsmall',
|
||||
|
||||
@@ -100,7 +100,7 @@ class base_table extends flexible_table {
|
||||
$buttons .= html_writer::link(
|
||||
new moodle_url('/auth/outage/edit.php', ['edit' => $outage->id]),
|
||||
html_writer::empty_tag('img', [
|
||||
'src' => $OUTPUT->image_url('t/edit'),
|
||||
'src' => $OUTPUT->pix_url('t/edit'),
|
||||
'alt' => get_string('edit'),
|
||||
'class' => 'iconsmall',
|
||||
]),
|
||||
@@ -112,7 +112,7 @@ class base_table extends flexible_table {
|
||||
$buttons .= html_writer::link(
|
||||
new moodle_url('/auth/outage/edit.php', ['clone' => $outage->id]),
|
||||
html_writer::empty_tag('img', [
|
||||
'src' => $OUTPUT->image_url('t/copy'),
|
||||
'src' => $OUTPUT->pix_url('t/copy'),
|
||||
'alt' => get_string('clone', 'auth_outage'),
|
||||
'class' => 'iconsmall',
|
||||
|
||||
@@ -125,7 +125,7 @@ class base_table extends flexible_table {
|
||||
$buttons .= html_writer::link(
|
||||
new moodle_url('/auth/outage/finish.php', ['id' => $outage->id]),
|
||||
html_writer::empty_tag('img', [
|
||||
'src' => $OUTPUT->image_url('t/check'),
|
||||
'src' => $OUTPUT->pix_url('t/check'),
|
||||
'alt' => get_string('finish', 'auth_outage'),
|
||||
'class' => 'iconsmall',
|
||||
]),
|
||||
@@ -138,7 +138,7 @@ class base_table extends flexible_table {
|
||||
$buttons .= html_writer::link(
|
||||
new moodle_url('/auth/outage/delete.php', ['id' => $outage->id]),
|
||||
html_writer::empty_tag('img', [
|
||||
'src' => $OUTPUT->image_url('t/delete'),
|
||||
'src' => $OUTPUT->pix_url('t/delete'),
|
||||
'alt' => get_string('delete'),
|
||||
'class' => 'iconsmall',
|
||||
]),
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
namespace auth_outage\output;
|
||||
|
||||
use auth_outage\local\outage;
|
||||
use auth_outage\local\outagelib;
|
||||
use coding_exception;
|
||||
use core_user;
|
||||
use html_writer;
|
||||
@@ -179,14 +178,14 @@ class renderer extends plugin_renderer_base {
|
||||
$url = new moodle_url('/auth/outage/edit.php', ['edit' => $outage->id]);
|
||||
$img = html_writer::empty_tag(
|
||||
'img',
|
||||
['src' => $OUTPUT->image_url('t/edit'), 'alt' => get_string('edit'), 'class' => 'iconsmall']
|
||||
['src' => $OUTPUT->pix_url('t/edit'), 'alt' => get_string('edit'), 'class' => 'iconsmall']
|
||||
);
|
||||
$linkedit = html_writer::link($url, $img, ['title' => get_string('edit')]);
|
||||
|
||||
$url = new moodle_url('/auth/outage/delete.php', ['id' => $outage->id]);
|
||||
$img = html_writer::empty_tag(
|
||||
'img',
|
||||
['src' => $OUTPUT->image_url('t/delete'), 'alt' => get_string('delete'), 'class' => 'iconsmall']
|
||||
['src' => $OUTPUT->pix_url('t/delete'), 'alt' => get_string('delete'), 'class' => 'iconsmall']
|
||||
);
|
||||
$linkdelete = html_writer::link($url, $img, ['title' => get_string('delete')]);
|
||||
|
||||
@@ -197,38 +196,35 @@ class renderer extends plugin_renderer_base {
|
||||
$finished = userdate($finished, get_string('datetimeformat', 'auth_outage'));
|
||||
}
|
||||
|
||||
$start = outagelib::OUTAGE_START;
|
||||
$end = outagelib::OUTAGE_END;
|
||||
$outagehtml = html_writer::div(
|
||||
return html_writer::div(
|
||||
html_writer::tag('blockquote',
|
||||
html_writer::div(html_writer::tag('b', $outage->get_title(), ['data-id' => $outage->id])).
|
||||
html_writer::div(html_writer::tag('i', $outage->get_description())).
|
||||
html_writer::div(
|
||||
html_writer::tag('b', get_string('tableheaderwarnbefore', 'auth_outage').': ').
|
||||
format_time($outage->get_warning_duration())
|
||||
).
|
||||
html_writer::div(
|
||||
html_writer::tag('b', get_string('tableheaderstarttime', 'auth_outage').': ').
|
||||
userdate($outage->starttime, get_string('datetimeformat', 'auth_outage'))
|
||||
).
|
||||
html_writer::div(
|
||||
html_writer::tag('b', get_string('tableheaderdurationplanned', 'auth_outage').': ').
|
||||
format_time($outage->get_duration_planned())
|
||||
).
|
||||
html_writer::div(
|
||||
html_writer::tag('b', get_string('tableheaderdurationactual', 'auth_outage').': ').
|
||||
$finished
|
||||
).
|
||||
html_writer::div(
|
||||
html_writer::tag('small',
|
||||
'Created by '.$created.
|
||||
', modified by '.$modified.' on '.
|
||||
userdate($outage->lastmodified, get_string('datetimeformat', 'auth_outage'))
|
||||
)
|
||||
).
|
||||
($buttons ? html_writer::div($linkedit.$linkdelete) : '')
|
||||
html_writer::div(html_writer::tag('b', $outage->get_title(), ['data-id' => $outage->id])).
|
||||
html_writer::div(html_writer::tag('i', $outage->get_description())).
|
||||
html_writer::div(
|
||||
html_writer::tag('b', get_string('tableheaderwarnbefore', 'auth_outage').': ').
|
||||
format_time($outage->get_warning_duration())
|
||||
).
|
||||
html_writer::div(
|
||||
html_writer::tag('b', get_string('tableheaderstarttime', 'auth_outage').': ').
|
||||
userdate($outage->starttime, get_string('datetimeformat', 'auth_outage'))
|
||||
).
|
||||
html_writer::div(
|
||||
html_writer::tag('b', get_string('tableheaderdurationplanned', 'auth_outage').': ').
|
||||
format_time($outage->get_duration_planned())
|
||||
).
|
||||
html_writer::div(
|
||||
html_writer::tag('b', get_string('tableheaderdurationactual', 'auth_outage').': ').
|
||||
$finished
|
||||
).
|
||||
html_writer::div(
|
||||
html_writer::tag('small',
|
||||
'Created by '.$created.
|
||||
', modified by '.$modified.' on '.
|
||||
userdate($outage->lastmodified, get_string('datetimeformat', 'auth_outage'))
|
||||
)
|
||||
).
|
||||
($buttons ? html_writer::div($linkedit.$linkdelete) : '')
|
||||
)
|
||||
);
|
||||
return $start . $outagehtml . $end;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +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/>.
|
||||
|
||||
/**
|
||||
* Defines capabilities
|
||||
*
|
||||
* @package auth_outage
|
||||
* @copyright 2020 Brendan Heywood <brendan@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$capabilities = [
|
||||
'auth/outage:updatenotify' => [
|
||||
'captype' => 'write',
|
||||
'riskbitmask' => RISK_XSS,
|
||||
'contextlevel' => CONTEXT_SYSTEM,
|
||||
'archetypes' => [
|
||||
'manager' => CAP_ALLOW,
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
@@ -1,32 +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/>.
|
||||
|
||||
/**
|
||||
* Defines message providers for outage
|
||||
*
|
||||
* @package auth_outage
|
||||
* @copyright 2020 Brendan Heywood <brendan@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$messageproviders = [
|
||||
'updatenotify' => [
|
||||
'capability' => 'auth/outage:updatenotify',
|
||||
]
|
||||
];
|
||||
|
||||
8
edit.php
8
edit.php
@@ -42,12 +42,11 @@ if ($mform->is_cancelled()) {
|
||||
redirect(new moodle_url('/auth/outage/manage.php'));
|
||||
} else if ($outage = $mform->get_data()) {
|
||||
$id = outagedb::save($outage);
|
||||
redirect(new moodle_url('/auth/outage/manage.php'));
|
||||
redirect($CFG->wwwroot. '/auth/outage/manage.php#auth_outage_id_'.$id);
|
||||
}
|
||||
|
||||
$clone = optional_param('clone', 0, PARAM_INT);
|
||||
$edit = optional_param('edit', 0, PARAM_INT);
|
||||
$time = optional_param('starttime', 0, PARAM_INT);
|
||||
if ($clone && $edit) {
|
||||
throw new invalid_parameter_exception('Cannot provide both clone and edit ids.');
|
||||
}
|
||||
@@ -61,10 +60,7 @@ if ($clone) {
|
||||
$action = 'outageedit';
|
||||
} else {
|
||||
$config = outagelib::get_config();
|
||||
if (empty($time)) {
|
||||
$time = outagelib::get_next_window();
|
||||
}
|
||||
|
||||
$time = time();
|
||||
$outage = new outage([
|
||||
'autostart' => $config->default_autostart,
|
||||
'starttime' => $time,
|
||||
|
||||
@@ -27,7 +27,6 @@ $string['auth_outagedescription'] = 'Auxiliary plugin that warns users about a f
|
||||
$string['autostart'] = 'Auto start maintenance mode.';
|
||||
$string['autostart_help'] = 'If selected, when the outage starts it will automatically turn on Moodle maintenance mode.';
|
||||
$string['clicreatehelp'] = 'Creates a new outage.';
|
||||
$string['clicreateexamples'] = "Create an outage starting in 10 seconds\n\n> php create.php -s=10";
|
||||
$string['clicreateparamautostart'] = 'must be Y or N, sets if the outage automatically triggers maintenance mode.';
|
||||
$string['clicreateparamblock'] = 'blocks until outage starts.';
|
||||
$string['clicreateparamclone'] = 'clone another outage except for the start time.';
|
||||
@@ -39,7 +38,6 @@ $string['clicreateparamstart'] = 'in how many seconds should this outage start o
|
||||
$string['clicreateparamtitle'] = 'the title of the outage.';
|
||||
$string['clicreateparamwarn'] = 'how many seconds before it starts to display a warning.';
|
||||
$string['clifinishhelp'] = 'Finishes an ongoing outage.';
|
||||
$string['clifinishexamples'] = '';
|
||||
$string['clifinishnotongoing'] = 'Outage is not ongoing.';
|
||||
$string['clifinishparamhelp'] = 'shows parameters help.';
|
||||
$string['clifinishparamactive'] = 'finishes the currently active outage.';
|
||||
@@ -47,7 +45,6 @@ $string['clifinishparamoutageid'] = 'the id of the outage to finish.';
|
||||
$string['cliinmaintenancemode'] = 'Moodle maintenance mode is on. Use "php admin/cli/maintenance.php --disable" to disable it before finishing the outage.';
|
||||
$string['cliwaitforiterroridxoractive'] = 'You must use --outageid=# or --active parameter but not both.';
|
||||
$string['cliwaitforithelp'] = 'Waits until an outage starts.';
|
||||
$string['cliwaitforitexamples'] = '';
|
||||
$string['cliwaitforitoutagestarted'] = 'Outage started!';
|
||||
$string['cliwaitforitoutagestartingin'] = 'Outage starting in {$a->countdown}.';
|
||||
$string['cliwaitforitparamactive'] = 'wait for the currently active outage.';
|
||||
@@ -56,12 +53,6 @@ $string['cliwaitforitparamoutageid'] = 'the id of the outage to wait until it st
|
||||
$string['cliwaitforitparamsleep'] = 'maximum amount of seconds before status output.';
|
||||
$string['cliwaitforitparamverbose'] = 'enable verbose mode.';
|
||||
$string['clierrorinvalidvalue'] = 'Invalid value for parameter: {$a->param}';
|
||||
$string['clierrorinvalidvaluenotid'] = 'Param --{$a->param} must be an id number';
|
||||
$string['clierrorinvalidvaluenotbool'] = 'Param --{$a->param} must be set to either Y or N';
|
||||
$string['clierrorinvalidvaluenotnumber'] = 'Param --{$a->param} must be a number';
|
||||
$string['clierrorinvalidvaluenegativenumber'] = 'Param --{$a->param} must be a positive number';
|
||||
$string['clierrorinvalidvaluenotstring'] = 'Param --{$a->param} must be a string';
|
||||
$string['clierrorinvalidvalueemptystring'] = 'Param --{$a->param} must not be an empty string';
|
||||
$string['clierrormissingparamaters'] = 'You must specify the start time, use --help for more information.';
|
||||
$string['clierroroutagechanged'] = 'Outage was changed while waiting.';
|
||||
$string['clierroroutageended'] = 'Outage has already ended.';
|
||||
@@ -80,19 +71,14 @@ $string['defaultoutageduration'] = 'Outage duration';
|
||||
$string['defaultoutagedurationdescription'] = 'Default duration (in minutes) of an outage.';
|
||||
$string['defaultwarningduration'] = 'Warning duration';
|
||||
$string['defaultwarningdurationdescription'] = 'Default warning time (in minutes) for outages.';
|
||||
$string['defaulttime'] = 'Default time';
|
||||
$string['defaulttimedescription'] = 'The default time for the next outage, expressed in natural language eg "next Thursday 7pm". See <a target=_blank href="https://www.php.net/manual/en/datetime.formats.relative.php">PHP relative dates</a>';
|
||||
$string['defaulttitle'] = 'Title';
|
||||
$string['defaulttitledescription'] = 'Default title for outages. Use {{start}} and {{stop}} placeholders as required.';
|
||||
$string['defaulttitlevalue'] = 'System down from {{start}} for {{duration}}';
|
||||
$string['defaulttitlevalue'] = 'System down from {{start}} for {{duration}}.';
|
||||
$string['defaultdescription'] = 'Description';
|
||||
$string['defaultdescriptiondescription'] = 'Default warning message for outages. Use {{start}} and {{stop}} placeholders as required.';
|
||||
$string['defaultdescriptionvalue'] = 'There is an scheduled maintenance from {{start}} to {{stop}} and our system will not be available during that time.';
|
||||
$string['description'] = 'Public Description';
|
||||
$string['description_help'] = 'A full description of the outage, publicly visible by all users.';
|
||||
$string['eventoutagecreated'] = 'Outage scheduled';
|
||||
$string['eventoutagedeleted'] = 'Outage cancelled';
|
||||
$string['eventoutageupdated'] = 'Outage updated';
|
||||
$string['finish'] = 'Finish';
|
||||
$string['info15secondsbefore'] = '15 seconds before';
|
||||
$string['infoendofoutage'] = 'end of outage';
|
||||
@@ -108,50 +94,11 @@ $string['allowedipshasmyip'] = 'Your IP (<i>{$a->ip}</i>) is in the list and you
|
||||
$string['allowedipshasntmyip'] = 'Your IP (<i>{$a->ip}</i>) is not in the list and you will be blocked out during an outage.';
|
||||
$string['allowedipsnoconfig'] = 'Your config.php does not have the extra setup to allow blocking via IP.<br />Please refer to our <a href="https://github.com/catalyst/moodle-auth_outage#installation" target="_blank">README.md</a> file for more information.';
|
||||
$string['menusettings'] = 'Settings';
|
||||
$string['menumanage'] = 'Manage outages';
|
||||
$string['menumanage'] = 'Manage';
|
||||
$string['messageoutagebackonline'] = 'We are back online!';
|
||||
$string['messageoutagebackonlinedescription'] = 'You may resume browsing safely.';
|
||||
$string['messageoutageongoing'] = 'Back online at {$a->stop}.';
|
||||
$string['messageoutagewarning'] = 'Shutting down in {{countdown}}';
|
||||
$string['messageprovider:updatenotify'] = 'Changes to planned outages';
|
||||
$string['messagesubject'] = '[{$a->site_shortname}] {$a->event_name} #{$a->outage_id}: {$a->outage_start}';
|
||||
$string['messagetext'] = '{$a->event_name}
|
||||
|
||||
{$a->site_fullname} ({$a->site_wwwroot})
|
||||
|
||||
{$a->event_link}
|
||||
|
||||
ID: {$a->outage_id}
|
||||
NAME: {$a->outage_title}
|
||||
START: {$a->outage_start}
|
||||
DURATION: {$a->outage_duration}
|
||||
DESCRIPTION:
|
||||
{$a->outage_desc}
|
||||
|
||||
--
|
||||
|
||||
To unsubscribe visit:
|
||||
{$a->prefs_link}';
|
||||
$string['messagehtml'] = '
|
||||
<h3>{$a->event_name}</h3>
|
||||
|
||||
<p>{$a->site_fullname} (<a href="{$a->site_wwwroot}">{$a->site_wwwroot}</a>)</p>
|
||||
|
||||
<p><a href="{$a->event_link}">{$a->event_link}</a></p>
|
||||
|
||||
<h4>Name:</h4>
|
||||
<p>{$a->outage_title}</p>
|
||||
<h4>Start:</h4>
|
||||
<p>{$a->outage_start}</p>
|
||||
<h4>Duration:</h4>
|
||||
<p>{$a->outage_duration}</p>
|
||||
<h4>Description:</h4>
|
||||
<p>{$a->outage_desc}</p>
|
||||
|
||||
<hr>
|
||||
<p>To unsubscribe visit:<br>
|
||||
<a href="{$a->prefs_link}">{$a->prefs_link}</a></p>
|
||||
';
|
||||
$string['na'] = 'n/a';
|
||||
$string['notfound'] = 'No outages found.';
|
||||
$string['outageedit'] = 'Edit outage';
|
||||
@@ -169,7 +116,6 @@ $string['outagefinish'] = 'Finish outage';
|
||||
$string['outagefinishwarning'] = 'You are about to mark this outage as finished. The system will be immediately back online.';
|
||||
$string['outageslistfuture'] = 'Planned outages';
|
||||
$string['outageslistpast'] = 'Outage history';
|
||||
$string['outage:updatenotify'] = '';
|
||||
$string['pluginname'] = 'Outage manager';
|
||||
$string['removeselectors'] = 'Remove selectors';
|
||||
$string['removeselectorsdescription'] = 'CSS selectors to remove when rendering a static themed maintenance page. One selector per line.';
|
||||
@@ -197,7 +143,6 @@ $string['title_help'] = 'A short title to for this outage. It will be displayed
|
||||
$string['warningdurationerrorinvalid'] = 'Warning duration must be positive.';
|
||||
$string['warningduration'] = 'Warning duration';
|
||||
$string['warningduration_help'] = 'How long before the start of the outage should the warning be displayed.';
|
||||
$string['warningreenablemaintenancemode'] = 'Please note that saving this outage will re-enable maintenance mode.<br />Untick "Auto start maintenance mode" if you want to prevent this.';
|
||||
|
||||
/*
|
||||
* Privacy provider (GDPR)
|
||||
|
||||
13
lib.php
13
lib.php
@@ -75,7 +75,7 @@ function auth_outage_get_climaintenance_resource_file($file) {
|
||||
|
||||
// Protect against path traversal attacks.
|
||||
$basename = basename($file);
|
||||
if ($basename !== $file && $file !== 'preview/' . $basename) {
|
||||
if ($basename !== $file) {
|
||||
// @codingStandardsIgnoreStart
|
||||
if (!PHPUNIT_TEST) {
|
||||
error_log('Possible attempt for Path Traversal Attack (only filename expected): '.$file);
|
||||
@@ -87,14 +87,3 @@ function auth_outage_get_climaintenance_resource_file($file) {
|
||||
$realpath = realpath($resourcedir.'/'.$file);
|
||||
return ($realpath == false) ? null : $realpath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display required icon for the calendar events.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function auth_outage_get_fontawesome_icon_map() {
|
||||
return [
|
||||
'core:i/auth_outageevent' => 'fa-power-off',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -59,13 +59,6 @@ if ($hassiteconfig && is_enabled_auth('outage')) {
|
||||
$defaults['default_duration'],
|
||||
60
|
||||
));
|
||||
$settings->add(new admin_setting_configtext(
|
||||
'auth_outage/default_time',
|
||||
get_string('defaulttime', 'auth_outage'),
|
||||
get_string('defaulttimedescription', 'auth_outage'),
|
||||
'',
|
||||
PARAM_TEXT
|
||||
));
|
||||
$settings->add(new admin_setting_configtext(
|
||||
'auth_outage/default_title',
|
||||
get_string('defaulttitle', 'auth_outage'),
|
||||
|
||||
@@ -11,8 +11,9 @@ Feature: Change the default settings
|
||||
Given the authentication plugin "outage" is enabled
|
||||
And I am an administrator
|
||||
|
||||
|
||||
Scenario Outline: Check if I can save the default settings.
|
||||
When I navigate to "Plugins > Authentication > Outage manager > Settings" in site administration
|
||||
When I navigate to "Settings" node in "Site administration > Plugins > Authentication > Outage manager"
|
||||
And I set the following fields to these values:
|
||||
| s_auth_outage_default_autostart | <autostart> |
|
||||
| s_auth_outage_default_warning_duration[v] | <warning> |
|
||||
|
||||
@@ -8,11 +8,14 @@ Feature: IP Blocker
|
||||
- An ongoing outage does not block Moodle execution, although it can trigger maintenance mode.
|
||||
- Maintenance mode completely blocks Moodle and can only be deactivated using the CLI.
|
||||
|
||||
|
||||
Background:
|
||||
Given the authentication plugin "outage" is enabled
|
||||
|
||||
|
||||
Scenario: Default IP Whitelist Settings
|
||||
Given I am an administrator
|
||||
When I navigate to "Plugins > Authentication > Outage manager > Settings" in site administration
|
||||
And I am on homepage
|
||||
When I navigate to "Settings" node in "Site administration > Plugins > Authentication > Outage manager"
|
||||
Then I should see "Allowed IP list"
|
||||
And I should see an empty settings text area "allowedips"
|
||||
|
||||
@@ -11,19 +11,22 @@ Feature: Manage outages
|
||||
- finished is an outage that has explicitly been marked as finished.
|
||||
- stopped is an outage that has already ended but not explicitly marked as finished.
|
||||
|
||||
|
||||
Background: Always login as admin, enable the auth_outage plugin and go to the outage management page.
|
||||
Given the authentication plugin "outage" is enabled
|
||||
And I log in as "admin"
|
||||
And I wait "1" seconds
|
||||
|
||||
|
||||
Scenario: Check if I can navigate to management page.
|
||||
Given I am on homepage
|
||||
When I navigate to "Plugins > Authentication > Outage manager > Manage outages" in site administration
|
||||
When I navigate to "Manage" node in "Site administration > Plugins > Authentication > Outage manager"
|
||||
Then I should see "Planned outages"
|
||||
And I should see "No outages found." in the "#section_planned_outages" "css_element"
|
||||
And I should see "Outage history"
|
||||
And I should see "No outages found." in the "#section_outage_history" "css_element"
|
||||
|
||||
|
||||
Scenario Outline: Planned outages should include all outages not finished or stopped.
|
||||
Given there is a "<type>" outage
|
||||
When I am on Outage Management Page
|
||||
@@ -37,6 +40,7 @@ Feature: Manage outages
|
||||
| finished | outage_history |
|
||||
| stopped | outage_history |
|
||||
|
||||
|
||||
Scenario Outline: Planned and history outages have different actions.
|
||||
Given there is a "<type>" outage
|
||||
When I am on Outage Management Page
|
||||
@@ -55,12 +59,14 @@ Feature: Manage outages
|
||||
| finished | see | see | not see | not see | not see |
|
||||
| stopped | see | see | not see | not see | not see |
|
||||
|
||||
Scenario: Create an outage using defaults.
|
||||
Given I am on Outage Management Page
|
||||
When I press "Create outage"
|
||||
And I press "Save changes"
|
||||
And I should not see "No outages found." in the "#section_planned_outages" "css_element"
|
||||
And I should see "No outages found." in the "#section_outage_history" "css_element"
|
||||
|
||||
# Scenario: Create an outage using defaults.
|
||||
# Given I am on Outage Management Page
|
||||
# When I press "Create outage"
|
||||
# And I press "Save changes"
|
||||
# And I should not see "No outages found." in the "#section_planned_outages" "css_element"
|
||||
# And I should see "No outages found." in the "#section_outage_history" "css_element"
|
||||
|
||||
|
||||
Scenario: View an outage which should open in a new window or tab.
|
||||
Given there is a "waiting" outage
|
||||
@@ -69,26 +75,29 @@ Feature: Manage outages
|
||||
Then I should be in a new window
|
||||
And I should see "Example of waiting outage"
|
||||
|
||||
Scenario: Clone an outage.
|
||||
Given there is a "waiting" outage
|
||||
And I am on Outage Management Page
|
||||
When I click on the "Clone" action button
|
||||
Then I should see "Clone outage"
|
||||
And I set the field "title" to "My cloned outage"
|
||||
And I press "Save changes"
|
||||
Then I should see "Example of waiting outage"
|
||||
And I should see "My cloned outage"
|
||||
|
||||
Scenario: Edit an outage.
|
||||
Given there is a "warning" outage
|
||||
And I am on Outage Management Page
|
||||
And I should see "Example of warning outage"
|
||||
When I click on the "Edit" action button
|
||||
Then I should see "Edit outage"
|
||||
And I set the field "title" to "My previous warning outage"
|
||||
And I press "Save changes"
|
||||
Then I should not see "Example of warning outage"
|
||||
And I should see "My previous warning outage"
|
||||
# Scenario: Clone an outage.
|
||||
# Given there is a "waiting" outage
|
||||
# And I am on Outage Management Page
|
||||
# When I click on the "Clone" action button
|
||||
# Then I should see "Clone outage"
|
||||
# And I set the field "title" to "My cloned outage"
|
||||
# And I press "Save changes"
|
||||
# Then I should see "Example of waiting outage"
|
||||
# And I should see "My cloned outage"
|
||||
|
||||
|
||||
# Scenario: Edit an outage.
|
||||
# Given there is a "warning" outage
|
||||
# And I am on Outage Management Page
|
||||
# And I should see "Example of warning outage"
|
||||
# When I click on the "Edit" action button
|
||||
# Then I should see "Edit outage"
|
||||
# And I set the field "title" to "My previous warning outage"
|
||||
# And I press "Save changes"
|
||||
# Then I should not see "Example of warning outage"
|
||||
# And I should see "My previous warning outage"
|
||||
|
||||
|
||||
Scenario: Delete an outage
|
||||
Given there is a "warning" outage
|
||||
@@ -100,6 +109,7 @@ Feature: Manage outages
|
||||
Then I press "Delete"
|
||||
And I should not see "Example of warning outage"
|
||||
|
||||
|
||||
Scenario: Finish an outage
|
||||
Given there is a "ongoing" outage
|
||||
And I am on Outage Management Page
|
||||
|
||||
@@ -11,45 +11,46 @@ Feature: Warning bar
|
||||
- finished is an outage that has explicitly been marked as finished.
|
||||
- stopped is an outage that has already ended but not explicitly marked as finished.
|
||||
|
||||
|
||||
Background:
|
||||
Given the authentication plugin "outage" is enabled
|
||||
|
||||
Scenario: This is how an outage should happen without maintenance mode and manual finish.
|
||||
Given there is the following outage:
|
||||
| warnbefore | startsin | stopsafter |
|
||||
| 10 | 20 | 10 |
|
||||
When I am on homepage
|
||||
Then I should not see the warning bar
|
||||
When I wait until the outage warns
|
||||
And I reload the page
|
||||
Then I should see "Shutting down in" in the warning bar
|
||||
When I wait until the outage starts
|
||||
And I reload the page
|
||||
Then I should see "Back online at" in the warning bar
|
||||
When I wait until the outage stops
|
||||
Then I should see "We are back online!" in the warning bar
|
||||
When I reload the page
|
||||
Then I should not see the warning bar
|
||||
#
|
||||
#
|
||||
# Scenario Outline: Some stages should show its own warning message.
|
||||
# Given there is a "<type>" outage
|
||||
# When I am on homepage
|
||||
# Then I should see "<see>" in the warning bar
|
||||
#
|
||||
# Examples:
|
||||
# | type | see |
|
||||
# | warning | Shutting down in |
|
||||
# | ongoing | Back online at |
|
||||
#
|
||||
#
|
||||
# Scenario Outline: Some stages should not have a warning bar.
|
||||
# Given there is a "<type>" outage
|
||||
|
||||
# Scenario: This is how an outage should happend without maintenance mode and manual finish.
|
||||
# Given there is the following outage:
|
||||
# | warnbefore | startsin | stopsafter |
|
||||
# | 10 | 20 | 10 |
|
||||
# When I am on homepage
|
||||
# Then I should not see the warning bar
|
||||
#
|
||||
# Examples:
|
||||
# | type |
|
||||
# | waiting |
|
||||
# | finished |
|
||||
# | stopped |
|
||||
# When I wait until the outage warns
|
||||
# And I reload the page
|
||||
# Then I should see "Shutting down in" in the warning bar
|
||||
# When I wait until the outage starts
|
||||
# Then I should see "Back online at" in the warning bar
|
||||
# When I wait until the outage stops
|
||||
# Then I should see "We are back online!" in the warning bar
|
||||
# When I reload the page
|
||||
# Then I should not see the warning bar
|
||||
|
||||
|
||||
Scenario Outline: Some stages should show its own warning message.
|
||||
Given there is a "<type>" outage
|
||||
When I am on homepage
|
||||
Then I should see "<see>" in the warning bar
|
||||
|
||||
Examples:
|
||||
| type | see |
|
||||
| warning | Shutting down in |
|
||||
| ongoing | Back online at |
|
||||
|
||||
|
||||
Scenario Outline: Some stages should not have a warning bar.
|
||||
Given there is a "<type>" outage
|
||||
When I am on homepage
|
||||
Then I should not see the warning bar
|
||||
|
||||
Examples:
|
||||
| type |
|
||||
| waiting |
|
||||
| finished |
|
||||
| stopped |
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use auth_outage\dml\outagedb;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
@@ -71,13 +69,9 @@ abstract class auth_outage_base_testcase extends advanced_testcase {
|
||||
|
||||
parent::setUp();
|
||||
$this->resetAfterTest(true);
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
global $DB;
|
||||
|
||||
foreach (outagedb::get_all() as $i => $outage) {
|
||||
$DB->delete_records('auth_outage', ['id' => $outage->id]);
|
||||
}
|
||||
// Do not use https.
|
||||
$CFG->wwwroot = 'http://www.example.com/moodle';
|
||||
$CFG->httpswwwroot = $CFG->wwwroot;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,8 +49,8 @@ class calendar_test extends advanced_testcase {
|
||||
* Creates an outage and checks if its in the calendar.
|
||||
*/
|
||||
public function test_create() {
|
||||
$this->resetAfterTest(true);
|
||||
self::setAdminUser();
|
||||
$this->resetAfterTest(false);
|
||||
|
||||
$time = time();
|
||||
self::$outage = new outage([
|
||||
@@ -70,20 +70,8 @@ class calendar_test extends advanced_testcase {
|
||||
* Updates an outage and checks the calendar.
|
||||
*/
|
||||
public function test_update() {
|
||||
$this->resetAfterTest(true);
|
||||
self::setAdminUser();
|
||||
|
||||
$time = time();
|
||||
self::$outage = new outage([
|
||||
'id' => 1,
|
||||
'autostart' => false,
|
||||
'warntime' => $time - 100,
|
||||
'starttime' => $time,
|
||||
'stoptime' => $time + (2 * 60 * 60),
|
||||
'title' => 'Title',
|
||||
'description' => 'Description',
|
||||
]);
|
||||
calendar::create(self::$outage);
|
||||
$this->resetAfterTest(false);
|
||||
|
||||
self::$outage->title = 'New Title';
|
||||
calendar::update(self::$outage);
|
||||
@@ -94,22 +82,8 @@ class calendar_test extends advanced_testcase {
|
||||
* Deletes an outage and checks the calendar.
|
||||
*/
|
||||
public function test_delete() {
|
||||
$this->resetAfterTest(true);
|
||||
self::setAdminUser();
|
||||
|
||||
$time = time();
|
||||
self::$outage = new outage([
|
||||
'id' => 1,
|
||||
'autostart' => false,
|
||||
'warntime' => $time - 100,
|
||||
'starttime' => $time,
|
||||
'stoptime' => $time + (2 * 60 * 60),
|
||||
'title' => 'Title',
|
||||
'description' => 'Description',
|
||||
]);
|
||||
calendar::create(self::$outage);
|
||||
|
||||
$this->check_calendar();
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
calendar::delete(self::$outage->id);
|
||||
self::assertNull(calendar::load(self::$outage->id));
|
||||
@@ -119,8 +93,8 @@ class calendar_test extends advanced_testcase {
|
||||
* Try to update a non existing outage.
|
||||
*/
|
||||
public function test_update_notfound() {
|
||||
$this->resetAfterTest(true);
|
||||
self::setAdminUser();
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$time = time();
|
||||
$outage = new outage([
|
||||
@@ -142,9 +116,8 @@ class calendar_test extends advanced_testcase {
|
||||
* Try to delete a non existing outage.
|
||||
*/
|
||||
public function test_delete_notfound() {
|
||||
$this->resetAfterTest(true);
|
||||
self::setAdminUser();
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
calendar::delete(1);
|
||||
self::assertCount(1, phpunit_util::get_debugging_messages());
|
||||
phpunit_util::reset_debugging();
|
||||
|
||||
@@ -57,7 +57,7 @@ class events_test extends advanced_testcase {
|
||||
public function test_save() {
|
||||
global $DB;
|
||||
self::setAdminUser();
|
||||
$this->resetAfterTest(true);
|
||||
$this->resetAfterTest(false);
|
||||
|
||||
// Save new outage.
|
||||
$now = time();
|
||||
@@ -90,20 +90,7 @@ class events_test extends advanced_testcase {
|
||||
global $DB;
|
||||
|
||||
self::setAdminUser();
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
// Save new outage.
|
||||
$now = time();
|
||||
$outage = new outage([
|
||||
'autostart' => false,
|
||||
'warntime' => $now - 60,
|
||||
'starttime' => 60,
|
||||
'stoptime' => 120,
|
||||
'title' => 'Title',
|
||||
'description' => 'Description',
|
||||
]);
|
||||
$outage->id = outagedb::save($outage);
|
||||
self::$outage = $outage;
|
||||
$this->resetAfterTest(false);
|
||||
|
||||
self::$outage->starttime += 10;
|
||||
outagedb::save(self::$outage);
|
||||
@@ -130,19 +117,6 @@ class events_test extends advanced_testcase {
|
||||
self::setAdminUser();
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
// Save new outage.
|
||||
$now = time();
|
||||
$outage = new outage([
|
||||
'autostart' => false,
|
||||
'warntime' => $now - 60,
|
||||
'starttime' => 60,
|
||||
'stoptime' => 120,
|
||||
'title' => 'Title',
|
||||
'description' => 'Description',
|
||||
]);
|
||||
$outage->id = outagedb::save($outage);
|
||||
self::$outage = $outage;
|
||||
|
||||
outagedb::delete(self::$outage->id);
|
||||
|
||||
// Should not exist.
|
||||
|
||||
@@ -3,5 +3,5 @@ a {
|
||||
}
|
||||
|
||||
div {
|
||||
background-image: url('/moodle/auth/outage/tests/phpunit/local/controllers/fixtures/catalyst.png');
|
||||
background-image: url('/auth/outage/tests/phpunit/local/controllers/fixtures/catalyst.png');
|
||||
}
|
||||
@@ -3,5 +3,5 @@ a {
|
||||
}
|
||||
|
||||
div {
|
||||
background-image: url(/moodle/auth/outage/tests/phpunit/local/controllers/fixtures/catalyst.png);
|
||||
background-image: url(/auth/outage/tests/phpunit/local/controllers/fixtures/catalyst.png);
|
||||
}
|
||||
@@ -106,14 +106,4 @@ class infopagecontroller_test extends auth_outage_base_testcase {
|
||||
$output = $info->get_output();
|
||||
self::assertContains('auth_outage_info', $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the constructor enables SVG support.
|
||||
*/
|
||||
public function test_svgicons_is_true() {
|
||||
global $CFG;
|
||||
$CFG->svgicons = false;
|
||||
new infopage();
|
||||
self::assertTrue($CFG->svgicons);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
use auth_outage\local\controllers\maintenance_static_page;
|
||||
use auth_outage\local\controllers\maintenance_static_page_io;
|
||||
use auth_outage\local\controllers\maintenance_static_page_generator;
|
||||
use auth_outage\task\update_static_page;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
@@ -88,7 +87,7 @@ class maintenance_static_page_test extends auth_outage_base_testcase {
|
||||
'<body>Content<link rel="stylesheet" href="'.$externalcsslink.'"></body></html>';
|
||||
$generated = $this->generated_page_html($html);
|
||||
|
||||
self::assertContains('www.example.com/moodle/auth/outage/file.php?file=', $generated);
|
||||
self::assertContains('http://www.example.com/moodle/auth/outage/file.php?file=', $generated);
|
||||
self::assertNotContains($localcsslink, $generated);
|
||||
self::assertContains($externalcsslink, $generated);
|
||||
}
|
||||
@@ -102,7 +101,7 @@ class maintenance_static_page_test extends auth_outage_base_testcase {
|
||||
$page->generate();
|
||||
|
||||
// Check for css file.
|
||||
self::assertFileExists($page->get_io()->get_resources_folder().'/d8643101d96b093e642b15544e4d1f7815b5ba55.dGV4dC9wbGFpbg');
|
||||
self::assertFileExists($page->get_io()->get_resources_folder().'/622ef6e83acfcb274cdf37bdb3bffa0923f9a7ad.dGV4dC9wbGFpbg');
|
||||
|
||||
// Check for catalyst.png file referenced in url(..) of css.
|
||||
self::assertFileExists($page->get_io()->get_resources_folder().'/ff7f7f87a26a908fc72930eaefb6b57306361d16.aW1hZ2UvcG5n');
|
||||
@@ -117,7 +116,7 @@ class maintenance_static_page_test extends auth_outage_base_testcase {
|
||||
$page->generate();
|
||||
|
||||
// Check for css file.
|
||||
self::assertFileExists($page->get_io()->get_resources_folder().'/9fe2374b03953e1949d54ab750be2d8706891c03.dGV4dC9wbGFpbg');
|
||||
self::assertFileExists($page->get_io()->get_resources_folder().'/1d84b6d321fef780237f84834b7316c079221a31.dGV4dC9wbGFpbg');
|
||||
|
||||
// Check for catalyst.png file referenced in url(..) of css.
|
||||
self::assertFileExists($page->get_io()->get_resources_folder().'/ff7f7f87a26a908fc72930eaefb6b57306361d16.aW1hZ2UvcG5n');
|
||||
@@ -146,7 +145,7 @@ class maintenance_static_page_test extends auth_outage_base_testcase {
|
||||
'<body><img src="'.$localimglink.'">Content<img src="'.$externalimglink.'" /></body></html>';
|
||||
$generated = $this->generated_page_html($html);
|
||||
|
||||
self::assertContains('www.example.com/moodle/auth/outage/file.php?file=', $generated);
|
||||
self::assertContains('http://www.example.com/moodle/auth/outage/file.php?file=', $generated);
|
||||
self::assertNotContains($localimglink, $generated);
|
||||
self::assertContains($externalimglink, $generated);
|
||||
}
|
||||
@@ -159,7 +158,7 @@ class maintenance_static_page_test extends auth_outage_base_testcase {
|
||||
$generated = $this->generated_page_html($html);
|
||||
|
||||
self::assertNotContains($link, $generated);
|
||||
self::assertContains('www.example.com/moodle/auth/outage/file.php?file=', $generated);
|
||||
self::assertContains('http://www.example.com/moodle/auth/outage/file.php?file=', $generated);
|
||||
}
|
||||
|
||||
public function test_previewpath() {
|
||||
@@ -173,7 +172,7 @@ class maintenance_static_page_test extends auth_outage_base_testcase {
|
||||
$generated = trim(file_get_contents($page->get_io()->get_template_file()));
|
||||
|
||||
self::assertNotContains($link, $generated);
|
||||
self::assertContains('www.example.com/moodle/auth/outage/file.php?file=preview%2F', $generated);
|
||||
self::assertContains('http://www.example.com/moodle/auth/outage/file.php?file=preview%2F', $generated);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -257,7 +256,7 @@ class maintenance_static_page_test extends auth_outage_base_testcase {
|
||||
|
||||
public function test_get_url_for_file() {
|
||||
$io = new maintenance_static_page_io();
|
||||
self::assertContains('www.example.com/moodle/auth/outage/file.php?file=img.png', $io->get_url_for_file('img.png'));
|
||||
self::assertSame('http://www.example.com/moodle/auth/outage/file.php?file=img.png', $io->get_url_for_file('img.png'));
|
||||
}
|
||||
|
||||
public function test_is_url() {
|
||||
@@ -396,45 +395,4 @@ class maintenance_static_page_test extends auth_outage_base_testcase {
|
||||
|
||||
self::assertContains('<meta http-equiv="refresh" content="5">', $generated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_get_urls_from_stylesheet
|
||||
* @return array
|
||||
*/
|
||||
public function test_get_urls_from_stylesheet_provider() {
|
||||
return [
|
||||
// Empty string.
|
||||
["", 0],
|
||||
// URLs that should be retrieved.
|
||||
["background:url(/theme/image.php/_s/boost/core/1581292565/t/expanded)", 1],
|
||||
["background:url('/theme/image.php/_s/boost/core/1581292565/t/expanded')", 1],
|
||||
["src:url(\"/theme/font.php/boost/core/1581292565/fontawesome-webfont.eot?#iefix&v=4.7.0\")", 1],
|
||||
["background-image:url(pix/vline-rtl.gif)", 1],
|
||||
// URLs that should not be retrieved.
|
||||
["background-image:url(data:image/gif;base64,R0lGODlhYADIAP=)", 0],
|
||||
["background-image:url('data:image/gif;base64,R0lGODlhYADIAP=')", 0],
|
||||
["background-image:url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns=\'http://www.w3.org/2000/svg\'\")", 0],
|
||||
// Combination of URLs used above.
|
||||
["background-image:url(pix/vline-rtl.gif) background:url(/theme/image.php/_s/boost/core/158/t/expanded)", 2],
|
||||
["background-image:url(data:image/gif;base64,R0lG=)src:url(\"/theme/font.php/fontawesome-webfont.eot\")", 1],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests get_urls_from_stylesheet() method to get all appropriate URLS from the file.
|
||||
*
|
||||
* @dataProvider test_get_urls_from_stylesheet_provider
|
||||
* @param string $filecontent Content of the file
|
||||
* @param int $count Expected quantity of found URLs
|
||||
* @throws coding_exception
|
||||
*/
|
||||
public function test_get_urls_from_stylesheet($filecontent, $count) {
|
||||
$this->resetAfterTest(true);
|
||||
$generator = new maintenance_static_page_generator(new DOMDocument(), new maintenance_static_page_io());
|
||||
$matches = $generator->get_urls_from_stylesheet($filecontent);
|
||||
|
||||
self::assertInternalType('array', $matches);
|
||||
self::assertCount(2, $matches);
|
||||
self::assertCount($count, $matches[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once(__DIR__.'/../base_testcase.php');
|
||||
|
||||
/**
|
||||
* outagelib_test test class.
|
||||
@@ -42,7 +41,7 @@ require_once(__DIR__.'/../base_testcase.php');
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @SuppressWarnings(public) Allow as many methods as needed.
|
||||
*/
|
||||
class outagelib_test extends auth_outage_base_testcase {
|
||||
class outagelib_test extends advanced_testcase {
|
||||
/**
|
||||
* Check if maintenance message is disabled as needed.
|
||||
*/
|
||||
@@ -106,6 +105,8 @@ class outagelib_test extends auth_outage_base_testcase {
|
||||
$size = strlen($CFG->additionalhtmltopofbody);
|
||||
outagelib::inject();
|
||||
self::assertSame($size, strlen($CFG->additionalhtmltopofbody));
|
||||
|
||||
$this->resetDebugging(); // Function pix_url deprecated in Moodle 33+.
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,6 +142,8 @@ class outagelib_test extends auth_outage_base_testcase {
|
||||
outagelib::reinject();
|
||||
self::assertContains('<style>', $CFG->additionalhtmltopofbody);
|
||||
self::assertContains('<script>', $CFG->additionalhtmltopofbody);
|
||||
|
||||
$this->resetDebugging(); // Function pix_url deprecated in Moodle 33+.
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -290,10 +293,7 @@ class outagelib_test extends auth_outage_base_testcase {
|
||||
if ((time() >= 123) && (time() < 456)) {
|
||||
define('MOODLE_INTERNAL', true);
|
||||
require_once($CFG->dirroot.'/lib/moodlelib.php');
|
||||
if (file_exists($CFG->dirroot.'/lib/classes/ip_utils.php')) {
|
||||
require_once($CFG->dirroot.'/lib/classes/ip_utils.php');
|
||||
}
|
||||
if (!remoteip_in_list('hey\'\"you
|
||||
if (!remoteip_in_list('heyyou
|
||||
a.b.c.d
|
||||
e.e.e.e/20')) {
|
||||
header($_SERVER['SERVER_PROTOCOL'] . ' 503 Moodle under maintenance');
|
||||
@@ -307,7 +307,6 @@ e.e.e.e/20')) {
|
||||
header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||
header('Accept-Ranges: none');
|
||||
header('X-Moodle-Maintenance: manager');
|
||||
if ((defined('AJAX_SCRIPT') && AJAX_SCRIPT) || (defined('WS_SERVER') && WS_SERVER)) {
|
||||
exit(0);
|
||||
}
|
||||
@@ -334,9 +333,6 @@ EOT;
|
||||
if ((time() >= 123) && (time() < 456)) {
|
||||
define('MOODLE_INTERNAL', true);
|
||||
require_once($CFG->dirroot.'/lib/moodlelib.php');
|
||||
if (file_exists($CFG->dirroot.'/lib/classes/ip_utils.php')) {
|
||||
require_once($CFG->dirroot.'/lib/classes/ip_utils.php');
|
||||
}
|
||||
if (!remoteip_in_list('127.0.0.1')) {
|
||||
header($_SERVER['SERVER_PROTOCOL'] . ' 503 Moodle under maintenance');
|
||||
header('Status: 503 Moodle under maintenance');
|
||||
@@ -349,7 +345,6 @@ if ((time() >= 123) && (time() < 456)) {
|
||||
header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||
header('Accept-Ranges: none');
|
||||
header('X-Moodle-Maintenance: manager');
|
||||
if ((defined('AJAX_SCRIPT') && AJAX_SCRIPT) || (defined('WS_SERVER') && WS_SERVER)) {
|
||||
exit(0);
|
||||
}
|
||||
@@ -508,6 +503,8 @@ EOT;
|
||||
outagelib::reinject();
|
||||
|
||||
self::assertNotEmpty($CFG->additionalhtmltopofbody);
|
||||
|
||||
$this->resetDebugging(); // Function pix_url deprecated in Moodle 33+.
|
||||
}
|
||||
|
||||
private function create_outage() {
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->component = "auth_outage";
|
||||
$plugin->version = 2020032500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->release = 2020032500; // Human-readable release information.
|
||||
$plugin->requires = 2017051500; // Requires 3.3 and higher.
|
||||
$plugin->version = 2018062502; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->release = '1.0.9'; // Human-readable release information.
|
||||
$plugin->requires = 2014051200; // Requires Moodle 2.7 or later. Moodle 3.0 or later recommended.
|
||||
$plugin->maturity = MATURITY_STABLE; // Suitable for PRODUCTION environments!
|
||||
$plugin->supported = [27, 32]; // A range of branch numbers of supported moodle versions.
|
||||
|
||||
@@ -26,12 +26,9 @@
|
||||
use auth_outage\output\manage\history_table;
|
||||
use auth_outage\output\manage\planned_table;
|
||||
use auth_outage\output\renderer;
|
||||
use auth_outage\dml\outagedb;
|
||||
use auth_outage\local\outagelib;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $OUTPUT;
|
||||
$urlnew = new moodle_url('/auth/outage/edit.php');
|
||||
|
||||
echo $viewbag['warning'];
|
||||
@@ -50,23 +47,9 @@ echo $viewbag['warning'];
|
||||
$table->finish_output();
|
||||
?>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
$outage = outagedb::get_ongoing();
|
||||
if (is_null($outage)) :
|
||||
$config = outagelib::get_config();
|
||||
$default = $config->default_time;
|
||||
$max = $default ? 3 : 1;
|
||||
$next = time();
|
||||
for ($c = 0; $c < $max; $c++) {
|
||||
echo '<p>';
|
||||
$next = outagelib::get_next_window($next);
|
||||
$urlnew->param('starttime', $next);
|
||||
echo $OUTPUT->single_button($urlnew, get_string('outagecreate', 'auth_outage'));
|
||||
if ($default) {
|
||||
echo ' ' . userdate( $next, get_string('datetimeformat', 'auth_outage'));
|
||||
}
|
||||
}
|
||||
endif; ?>
|
||||
<input type="button" class="form-submit"
|
||||
value="<?php echo get_string('outagecreate', 'auth_outage'); ?>"
|
||||
onclick="location.href='<?php echo $urlnew; ?>';"/>
|
||||
</section>
|
||||
|
||||
<section id="section_outage_history">
|
||||
|
||||
@@ -7,7 +7,7 @@ If you need to make changes here, remember to update your settings inside Moodle
|
||||
background-color: red;
|
||||
box-sizing: content-box;
|
||||
color: white;
|
||||
height: 100px;
|
||||
height: 90px;
|
||||
left: 0;
|
||||
padding: 0;
|
||||
position: fixed;
|
||||
@@ -19,51 +19,47 @@ If you need to make changes here, remember to update your settings inside Moodle
|
||||
}
|
||||
|
||||
#auth_outage_warningbar_box.auth_outage_warning_period {
|
||||
background:
|
||||
repeating-linear-gradient(
|
||||
background: repeating-linear-gradient(
|
||||
-45deg,
|
||||
#ff7c00,
|
||||
#ff7c00 10px,
|
||||
#ff6c00 10px,
|
||||
#ff6c00 20px
|
||||
);
|
||||
);
|
||||
background-color: #ff7c00;
|
||||
}
|
||||
|
||||
#auth_outage_warningbar_box.auth_outage_imminent_period {
|
||||
background:
|
||||
repeating-linear-gradient(
|
||||
background: repeating-linear-gradient(
|
||||
-45deg,
|
||||
#a000a0,
|
||||
#a000a0 10px,
|
||||
#800080 10px,
|
||||
#800080 20px
|
||||
);
|
||||
);
|
||||
background-color: #800080;
|
||||
}
|
||||
|
||||
#auth_outage_warningbar_box.auth_outage_ongoing_period {
|
||||
background:
|
||||
repeating-linear-gradient(
|
||||
background: repeating-linear-gradient(
|
||||
-45deg,
|
||||
#e00,
|
||||
#e00 10px,
|
||||
#c00 10px,
|
||||
#c00 20px
|
||||
);
|
||||
background-color: #e00;
|
||||
#ee0000,
|
||||
#ee0000 10px,
|
||||
#cc0000 10px,
|
||||
#cc0000 20px
|
||||
);
|
||||
background-color: #ee0000;
|
||||
}
|
||||
|
||||
#auth_outage_warningbar_box.auth_outage_finished_period {
|
||||
background:
|
||||
repeating-linear-gradient(
|
||||
background: repeating-linear-gradient(
|
||||
-45deg,
|
||||
#0a0,
|
||||
#0a0 10px,
|
||||
#090 10px,
|
||||
#090 20px
|
||||
);
|
||||
background-color: #090;
|
||||
#00aa00,
|
||||
#00aa00 10px,
|
||||
#009900 10px,
|
||||
#009900 20px
|
||||
);
|
||||
background-color: #009900;
|
||||
}
|
||||
|
||||
.auth_outage_warningbar_center {
|
||||
@@ -99,14 +95,10 @@ a.auth_outage_warningbar_box_finish:hover {
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
.navbar.navbar-fixed-top {
|
||||
top: 90px;
|
||||
}
|
||||
|
||||
.auth_outage_warningbar_spacer {
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
body.auth_outage #nav-drawer {
|
||||
top: 150px;
|
||||
}
|
||||
|
||||
body.auth_outage nav.fixed-top.navbar {
|
||||
top: 100px;
|
||||
}
|
||||
@@ -114,10 +114,8 @@ var authOutageWarningBar = {
|
||||
seconds2hms: function(seconds) {
|
||||
var minutes = Math.floor(seconds / 60);
|
||||
var hours = Math.floor(minutes / 60);
|
||||
var days = Math.floor(hours / 24);
|
||||
seconds %= 60;
|
||||
minutes %= 60;
|
||||
hours %= 24;
|
||||
// Cross-browser simple solution for padding zeroes.
|
||||
if (minutes < 10) {
|
||||
minutes = "0" + minutes;
|
||||
@@ -125,15 +123,6 @@ var authOutageWarningBar = {
|
||||
if (seconds < 10) {
|
||||
seconds = "0" + seconds;
|
||||
}
|
||||
if (days > 0) {
|
||||
if (days > 1) {
|
||||
days = days + ' days ';
|
||||
} else {
|
||||
days = days + ' day ';
|
||||
}
|
||||
} else {
|
||||
days = '';
|
||||
}
|
||||
return days + hours + ':' + minutes + ':' + seconds;
|
||||
return hours + ':' + minutes + ':' + seconds;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -48,7 +48,7 @@ if (!$viewbag['static']) {
|
||||
if (is_siteadmin()) {
|
||||
$url = new moodle_url('/auth/outage/finish.php', ['id' => $viewbag['outage']->id]);
|
||||
$text = html_writer::empty_tag('img', [
|
||||
'src' => $OUTPUT->image_url('t/check'),
|
||||
'src' => $OUTPUT->pix_url('t/check'),
|
||||
'alt' => get_string('finish', 'auth_outage'),
|
||||
'class' => 'iconsmall',
|
||||
]).' '.get_string('finish', 'auth_outage');
|
||||
|
||||
Reference in New Issue
Block a user