Merge branch 'issue27-cli'

This commit is contained in:
Daniel Thee Roperto
2016-09-19 16:02:30 +10:00
15 changed files with 1398 additions and 15 deletions

View File

@@ -24,17 +24,14 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
*/
if (!defined('MOODLE_INTERNAL')) {
die('Direct access to this script is forbidden.'); // It must be included from a Moodle page.
}
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/authlib.php');
/**
* Class auth_plugin_outage
*/
class auth_plugin_outage extends auth_plugin_base
{
class auth_plugin_outage extends auth_plugin_base {
/**
* Constructor.
*/

133
classes/cli/clibase.php Normal file
View File

@@ -0,0 +1,133 @@
<?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/>.
namespace auth_outage\cli;
use core\session\manager;
use InvalidArgumentException;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/clilib.php');
/**
* Outage CLI base class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class clibase {
/**
* @var array Options passed as parameters to the CLI.
*/
protected $options;
/**
* @var int The reference time to use when creating an outage.
*/
protected $time;
/**
* clibase constructor.
* @param array|null $options The parameters to use or null to read from the command line.
* @throws cliexception
*/
public function __construct(array $options = null) {
$this->becomeadmin();
if (is_null($options)) {
// Using Moodle CLI API to read the parameters.
list($options, $unrecognized) = cli_get_params($this->generateoptions(), $this->generateshortcuts());
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
throw new cliexception(get_string('cliunknowoption', 'admin', $unrecognized));
}
} else {
// If not using Moodle CLI API to read parameters, ensure all keys exist.
$default = $this->generateoptions();
foreach ($options as $k => $v) {
if (!array_key_exists($k, $default)) {
throw new cliexception(get_string('cliunknowoption', 'admin', $k));
}
$default[$k] = $v;
}
$options = $default;
}
$this->options = $options;
$this->time = time();
}
/**
* Sets the reference time for creating outages.
* @param int $time Timestamp for the reference time.
*/
public function set_referencetime($time) {
if (!is_int($time) || ($time <= 0)) {
throw new InvalidArgumentException('$time must be a positive int.');
}
$this->time = $time;
}
/**
* Generates all options (parameters) available for the CLI command.
* @return array Options.
*/
public abstract function generateoptions();
/**
* Generate all short forms for the available options.
* @return array Short form options.
*/
public abstract function generateshortcuts();
/**
* Executes the CLI script.
*/
public abstract function execute();
/**
* Change session to admin user.
*/
protected function becomeadmin() {
global $DB;
$user = $DB->get_record('user', array('id' => 2));
unset($user->description);
unset($user->access);
unset($user->preference);
manager::init_empty_session();
manager::set_user($user);
}
/**
* Outputs a help message.
* @param string $cliname Name of CLI used in the language file.
*/
protected function showhelp($cliname) {
$options = $this->generateoptions();
$shorts = array_flip($this->generateshortcuts());
printf("%s\n\n", get_string('cli' . $cliname . 'help', 'auth_outage'));
foreach (array_keys($options) as $long) {
$text = get_string('cli' . $cliname . 'param' . $long, 'auth_outage');
$short = isset($shorts[$long]) ? ('-' . $shorts[$long] . ',') : '';
$long = '--' . $long;
printf(" %-4s %-20s %s\n", $short, $long, $text);
}
}
}

View File

@@ -0,0 +1,30 @@
<?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/>.
namespace auth_outage\cli;
use Exception;
/**
* Exception executing CLI.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cliexception extends Exception {
}

208
classes/cli/create.php Normal file
View File

@@ -0,0 +1,208 @@
<?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/>.
namespace auth_outage\cli;
use auth_outage\models\outage;
use auth_outage\outagedb;
defined('MOODLE_INTERNAL') || die();
/**
* Outage CLI to create outage.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class create extends clibase {
/**
* @var array Defaults to use if given option is null.
*/
private $defaults;
/**
* Generates all options (parameters) available for the CLI command.
* @return array Options.
*/
public function generateoptions() {
// Do not provide some defaults, if cloning an outage we need to know which parameters were provided.
$options = [
'help' => false,
'clone' => null,
'warn' => null,
'start' => null,
'duration' => null,
'title' => null,
'description' => null,
'onlyid' => false,
'block' => false,
];
return $options;
}
/**
* Generate all short forms for the available options.
* @return array Short form options.
*/
public function generateshortcuts() {
return [
'b' => 'block',
'c' => 'clone',
'd' => 'duration',
'e' => 'description',
'h' => 'help',
's' => 'start',
't' => 'title',
'w' => 'warn',
];
}
/**
* Sets the default values for options.
* @param array $defaults Defaults.
*/
public function set_defaults(array $defaults) {
$this->defaults = $defaults;
}
/**
* Executes the CLI.
*/
public function execute() {
// Help always overrides any other parameter.
if ($this->options['help']) {
$this->showhelp('create');
return;
}
// If not help mode, 'start' is required and cannot use default.
if (is_null($this->options['start'])) {
throw new cliexception(get_string('clierrormissingparamaters', 'auth_outage'));
}
// If cloning, set defaults to outage being cloned.
if (!is_null($this->options['clone'])) {
$this->clonedefaults();
}
// Merge provided parameters with defaults then create outage.
$options = $this->mergeoptions();
$id = $this->createoutage($options);
if ($options['block']) {
$block = new waitforit(['outageid' => $id]);
$block->execute();
}
}
/**
* Merges provided options with defaults, checking and converting types as needed.
* @return array Parameters to use.
* @throws cliexception
*/
private function mergeoptions() {
$options = $this->options;
// Merge with defaults.
if (!is_null($this->defaults)) {
foreach ($options as $k => $v) {
if (is_null($v) && array_key_exists($k, $this->defaults)) {
$options[$k] = $this->defaults[$k];
}
}
}
return $this->mergeoptions_checkparameters($options);
}
/**
* Creates an outages based on the provided options.
* @param array $options Options used to create the outage.
* @return int Id of the new outage.
*/
private function createoutage(array $options) {
// We need to become an admin to avoid permission problems.
$this->becomeadmin();
// Create the outage.
$start = $this->time + $options['start'];
$outage = new outage([
'warntime' => $start - $options['warn'],
'starttime' => $start,
'stoptime' => $start + $options['duration'],
'title' => $options['title'],
'description' => $options['description'],
]);
$id = outagedb::save($outage);
// All done!
if ($options['onlyid']) {
printf("%d\n", $id);
} else {
printf("%s\n", get_string('clioutagecreated', 'auth_outage', ['id' => $id]));
}
return $id;
}
private function clonedefaults() {
$id = $this->options['clone'];
if (!is_number($id) || ($id <= 0)) {
throw new cliexception(get_string('clierrorinvalidvalue', 'auth_outage', ['param' => 'clone']));
}
$outage = outagedb::get_by_id((int)$id);
$this->set_defaults([
'warn' => $outage->get_warning_duration(),
'duration' => $outage->get_duration(),
'title' => $outage->title,
'description' => $outage->description,
]);
}
/**
* Check parameters converting their type as needed.
* @param array $options Input options.
* @return array Output options.
* @throws cliexception
*/
private function mergeoptions_checkparameters(array $options) {
// Check parameters that must be a non-negative int while converting their type to int.
foreach (['start', 'warn', 'duration'] as $param) {
if (!is_number($options[$param])) {
throw new cliexception(get_string('clierrorinvalidvalue', 'auth_outage', ['param' => $param]));
}
$options[$param] = (int)$options[$param];
if ($options[$param] < 0) {
throw new cliexception(get_string('clierrorinvalidvalue', 'auth_outage', ['param' => $param]));
}
}
// Check parameters that must be a non empty string.
foreach (['title', 'description'] as $param) {
if (!is_string($options[$param])) {
throw new cliexception(get_string('clierrorinvalidvalue', 'auth_outage', ['param' => $param]));
}
$options[$param] = trim($options[$param]);
if (strlen($options[$param]) == 0) {
throw new cliexception(get_string('clierrorinvalidvalue', 'auth_outage', ['param' => $param]));
}
}
return $options;
}
}

106
classes/cli/finish.php Normal file
View File

@@ -0,0 +1,106 @@
<?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/>.
namespace auth_outage\cli;
use auth_outage\models\outage;
use auth_outage\outagedb;
defined('MOODLE_INTERNAL') || die();
/**
* Outage CLI to finish an outage.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class finish extends clibase {
/**
* Generates all options (parameters) available for the CLI command.
* @return array Options.
*/
public function generateoptions() {
// Do not provide some defaults, if cloning an outage we need to know which parameters were provided.
$options = [
'help' => false,
'outageid' => null,
'active' => false,
];
return $options;
}
/**
* Generate all short forms for the available options.
* @return array Short form options.
*/
public function generateshortcuts() {
return [
'h' => 'help',
'id' => 'outageid',
'a' => 'active',
];
}
/**
* Executes the CLI.
*/
public function execute() {
// Help always overrides any other parameter.
if ($this->options['help']) {
$this->showhelp('finish');
return;
}
// Requires outageid or active but not both at the same time.
$byid = !is_null($this->options['outageid']);
$byactive = $this->options['active'];
if ($byid == $byactive) {
throw new cliexception(get_string('cliwaitforiterroridxoractive', 'auth_outage'));
}
$outage = $this->get_outage();
if (!$outage->is_ongoing()) {
throw new cliexception(get_string('clifinishnotongoing', 'auth_outage'));
}
outagedb::finish($outage->id, $this->time);
}
/**
* Gets the outage to finish.
* @return outage|null The outage to wait for.
* @throws cliexception
*/
private function get_outage() {
if ($this->options['active']) {
$outage = outagedb::get_active();
} else {
$id = $this->options['outageid'];
if (!is_number($id) || ($id <= 0)) {
throw new cliexception(get_string('clierrorinvalidvalue', 'auth_outage', ['param' => 'outageid']));
}
$outage = outagedb::get_by_id((int)$id);
}
if (is_null($outage)) {
throw new cliexception(get_string('clierroroutagenotfound', 'auth_outage'));
}
return $outage;
}
}

178
classes/cli/waitforit.php Normal file
View File

@@ -0,0 +1,178 @@
<?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/>.
namespace auth_outage\cli;
use auth_outage\models\outage;
use auth_outage\outagedb;
defined('MOODLE_INTERNAL') || die();
/**
* Outage CLI to wait for an outage to start.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class waitforit extends clibase {
/**
* Default value if --sleep no provided.
*/
const DEFAULT_SLEEP_SECONDS = 300;
/**
* @var callable Alternative callback for sleeping thread, must return the new reference timestamp.
*/
private $sleepcallback = null;
/**
* Generates all options (parameters) available for the CLI command.
* @return array Options.
*/
public function generateoptions() {
// Do not provide some defaults, if cloning an outage we need to know which parameters were provided.
$options = [
'help' => false,
'outageid' => null,
'active' => false,
'verbose' => false,
'sleep' => self::DEFAULT_SLEEP_SECONDS,
];
return $options;
}
/**
* Generate all short forms for the available options.
* @return array Short form options.
*/
public function generateshortcuts() {
return [
'h' => 'help',
'id' => 'outageid',
'a' => 'active',
'v' => 'verbose',
's' => 'sleep',
];
}
/**
* Sets a callback to be used instead of the sleep method.
* @param callable $callback Callback function.
*/
public function set_sleepcallback(callable $callback) {
$this->sleepcallback = $callback;
}
/**
* Executes the CLI.
*/
public function execute() {
// Help always overrides any other parameter.
if ($this->options['help']) {
$this->showhelp('waitforit');
return;
}
// Requires outageid or active but not both at the same time.
$byid = !is_null($this->options['outageid']);
$byactive = $this->options['active'];
if ($byid == $byactive) {
throw new cliexception(get_string('cliwaitforiterroridxoractive', 'auth_outage'));
}
$this->verbose('Verbose mode activated.');
$outage = $this->get_outage();
while ($sleep = $this->waitforoutagestart($outage)) {
if (is_null($this->sleepcallback)) {
$this->verbose('Sleeping for ' . $sleep . ' second(s).');
sleep($sleep);
$this->time = time();
} else {
$this->verbose('Calling callback to sleep ' . $sleep . ' second(s).');
$callback = $this->sleepcallback;
$this->time = $callback($sleep);
}
}
}
/**
* Shows a message if in verbose mode.
* @param string $message Message.
*/
private function verbose($message) {
if (!$this->options['verbose']) {
return;
}
$time = strftime('%F %T %Z');
printf("[%s] %s\n", $time, $message);
}
/**
* Gets the outage to wait for.
* @return outage|null The outage to wait for.
* @throws cliexception
*/
private function get_outage() {
if ($this->options['active']) {
$this->verbose('Querying database for active outage...');
$outage = outagedb::get_active();
} else {
$id = $this->options['outageid'];
if (!is_number($id) || ($id <= 0)) {
throw new cliexception(get_string('clierrorinvalidvalue', 'auth_outage', ['param' => 'outageid']));
}
$this->verbose('Querying database for outage #' . $id . '...');
$outage = outagedb::get_by_id((int)$id);
}
if (is_null($outage)) {
throw new cliexception(get_string('clierroroutagenotfound', 'auth_outage'));
}
$this->verbose('Found outage #' . $outage->id . ': ' . $outage->get_title());
return $outage;
}
private function waitforoutagestart(outage $outage) {
$this->verbose('Checking outage status...');
// Outage should not change while waiting to start.
if (outagedb::get_by_id($outage->id) != $outage) {
throw new cliexception(get_string('clierroroutagechanged', 'auth_outage'));
}
// Outage cannot have already ended.
if ($outage->has_ended($this->time)) {
throw new cliexception(get_string('clierroroutageended', 'auth_outage'));
}
// If outage has started, do not wait.
if ($outage->is_ongoing($this->time)) {
printf("%s\n", get_string('cliwaitforitoutagestarted', 'auth_outage'));
return 0;
}
// Outage nas not started yet.
$countdown = $outage->starttime - $this->time;
printf("%s\n", get_string(
'cliwaitforitoutagestartingin',
'auth_outage',
['countdown' => format_time($countdown)]
));
return min($countdown, $this->options['sleep']);
}
}

48
cli/create.php Normal file
View File

@@ -0,0 +1,48 @@
<?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/>.
/**
* CLI for creating outages.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use auth_outage\cli\cliexception;
use auth_outage\cli\create;
define('CLI_SCRIPT', true);
require('../../config.php');
$cli = new create();
$config = get_config('auth_outage');
$cli->set_defaults([
'help' => false,
'warn' => (int)($config->warning_duration),
'start' => null,
'duration' => (int)($config->default_duration),
'title' => $config->warning_title,
'description' => $config->warning_description,
]);
try {
$cli->execute();
} catch (cliexception $e) {
cli_error($e->getMessage());
}

39
cli/finish.php Normal file
View File

@@ -0,0 +1,39 @@
<?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/>.
/**
* CLI for finishing an outage.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use auth_outage\cli\cliexception;
use auth_outage\cli\finish;
define('CLI_SCRIPT', true);
require('../../config.php');
$cli = new finish();
try {
$cli->execute();
} catch (cliexception $e) {
cli_error($e->getMessage());
}

39
cli/waitforit.php Normal file
View File

@@ -0,0 +1,39 @@
<?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/>.
/**
* CLI for waiting (blocking) until an outage starts.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use auth_outage\cli\cliexception;
use auth_outage\cli\waitforit;
define('CLI_SCRIPT', true);
require('../../config.php');
$cli = new waitforit();
try {
$cli->execute();
} catch (cliexception $e) {
cli_error($e->getMessage());
}

View File

@@ -24,6 +24,36 @@
*/
$string['auth_outagedescription'] = 'Auxiliary plugin that warns users about a future outage and prevents them from logging in once the outage starts.';
$string['clicreatehelp'] = 'Creates a new outage.';
$string['clicreateparamblock'] = 'blocks until outage starts.';
$string['clicreateparamclone'] = 'clone another outage except for the start time.';
$string['clicreateparamdescription'] = 'the description of the outage.';
$string['clicreateparamduration'] = 'how many seconds should the outage last.';
$string['clicreateparamhelp'] = 'shows parameters help.';
$string['clicreateparamonlyid'] = 'only outputs the new outage id, useful for scripts.';
$string['clicreateparamstart'] = 'in how many seconds should this outage start. Required.';
$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['clifinishnotongoing'] = 'Outage is not ongoing.';
$string['clifinishparamhelp'] = 'shows parameters help.';
$string['clifinishparamactive'] = 'finishes the currently active outage.';
$string['clifinishparamoutageid'] = 'the id of the outage to finish.';
$string['cliwaitforiterroridxoractive'] = 'You must use --outageid=# or --active parameter but not both.';
$string['cliwaitforithelp'] = 'Waits until an outage starts.';
$string['cliwaitforitoutagestarted'] = 'Outage started!';
$string['cliwaitforitoutagestartingin'] = 'Outage starting in {$a->countdown}.';
$string['cliwaitforitparamactive'] = 'wait for the currently active outage.';
$string['cliwaitforitparamhelp'] = 'shows parameters help.';
$string['cliwaitforitparamoutageid'] = 'the id of the outage to wait until it starts.';
$string['cliwaitforitparamsleep'] = 'maximum amount of seconds before status output.';
$string['cliwaitforitparamverbose'] = 'enable verbose mode.';
$string['clierrorinvalidvalue'] = 'Invalid value for parameter: {$a->param}';
$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.';
$string['clierroroutagenotfound'] = 'Outage not found.';
$string['clioutagecreated'] = 'Outage created, id: {$a->id}';
$string['clone'] = 'Clone';
$string['datetimeformat'] = '%a %d %h %Y at %I:%M%P %Z';
$string['defaultlayoutcss'] = 'Layout CSS';
@@ -51,6 +81,7 @@ $string['menudefaults'] = 'Default Settings';
$string['menumanage'] = 'Manage';
$string['messageoutageongoing'] = 'Back online at {$a->stop}.';
$string['messageoutagewarning'] = 'Shutting down in {{countdown}}';
$string['na'] = 'n/a';
$string['notfound'] = 'No outages found.';
$string['outageedit'] = 'Edit Outage';
$string['outageclone'] = 'Clone Outage';

View File

@@ -111,17 +111,25 @@ class auth_outage_renderer extends plugin_renderer_base {
private function renderoutage(outage $outage, $buttons) {
global $OUTPUT;
$created = core_user::get_user($outage->createdby, 'firstname,lastname', MUST_EXIST);
$created = html_writer::link(
new moodle_url('/user/profile.php', ['id' => $outage->createdby]),
trim($created->firstname . ' ' . $created->lastname)
);
if ($outage->createdby == 0) {
$created = get_string('na', 'auth_outage');
} else {
$created = core_user::get_user($outage->createdby, 'firstname,lastname', MUST_EXIST);
$created = html_writer::link(
new moodle_url('/user/profile.php', ['id' => $outage->createdby]),
trim($created->firstname . ' ' . $created->lastname)
);
}
$modified = core_user::get_user($outage->modifiedby, 'firstname,lastname', MUST_EXIST);
$modified = html_writer::link(
new moodle_url('/user/profile.php', ['id' => $outage->modifiedby]),
trim($modified->firstname . ' ' . $modified->lastname)
);
if ($outage->modifiedby == 0) {
$modified = get_string('na', 'auth_outage');
} else {
$modified = core_user::get_user($outage->modifiedby, 'firstname,lastname', MUST_EXIST);
$modified = html_writer::link(
new moodle_url('/user/profile.php', ['id' => $outage->modifiedby]),
trim($modified->firstname . ' ' . $modified->lastname)
);
}
$url = new moodle_url('/auth/outage/edit.php', ['id' => $outage->id]);
$img = html_writer::empty_tag(

View File

@@ -0,0 +1,61 @@
<?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/>.
use auth_outage\cli\clibase;
defined('MOODLE_INTERNAL') || die();
/**
* Tests performed on CLIs.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cli_testcase extends advanced_testcase {
public function setUp() {
$this->resetAfterTest(true);
$this->set_parameters([]);
parent::setUp();
}
/**
* Mocks the command line parameters.
* @param array $options Options to use as parameters.
*/
protected function set_parameters(array $options) {
array_unshift($options, 'cli.php');
$_SERVER['argv'] = $options;
$_SERVER['argc'] = count($options);
}
/**
* Executes the CLI.
* @param clibase $cli CLI to execute.
* @return string The output text.
*/
protected function execute(clibase $cli) {
ob_start();
try {
$cli->execute();
$text = ob_get_contents();
return $text;
} finally {
ob_end_clean();
}
}
}

270
tests/cli/create_test.php Normal file
View File

@@ -0,0 +1,270 @@
<?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/>.
use auth_outage\cli\cliexception;
use auth_outage\cli\create;
use auth_outage\models\outage;
use auth_outage\outagedb;
defined('MOODLE_INTERNAL') || die();
require_once('cli_testcase.php');
/**
* Tests performed on CLI create class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @SuppressWarnings("public")
*/
class create_test extends cli_testcase {
public function test_noarguments() {
$cli = new create();
$this->setExpectedException(cliexception::class);
$this->execute($cli);
}
public function test_invalidargumentparam() {
$this->set_parameters(['--aninvalidparameter']);
$this->setExpectedException(cliexception::class);
new create();
}
public function test_invalidargumentgiven() {
$this->setExpectedException(cliexception::class);
new create(['anotherinvalidparameter']);
}
public function test_invalidparam_notanumber() {
$cli = new create(['start' => 'some day']);
$cli->set_defaults([
'warn' => 50,
'start' => 200,
'duration' => 300,
'title' => 'Default Title',
'description' => 'Default Description',
]);
$this->setExpectedException(cliexception::class);
$this->execute($cli);
}
public function test_invalidparam_negative() {
$cli = new create(['start' => -1]);
$cli->set_defaults([
'warn' => 50,
'start' => 200,
'duration' => 300,
'title' => 'Default Title',
'description' => 'Default Description',
]);
$this->setExpectedException(cliexception::class);
$this->execute($cli);
}
public function test_invalidparam_emptystring() {
$cli = new create(['start' => 0, 'title' => '']);
$cli->set_defaults([
'warn' => 50,
'start' => 200,
'duration' => 300,
'title' => 'Default Title',
'description' => 'Default Description',
]);
$this->setExpectedException(cliexception::class);
$this->execute($cli);
}
public function test_invalidparam_notastring() {
$cli = new create(['start' => 0, 'title' => true]);
$cli->set_defaults([
'warn' => 50,
'start' => 200,
'duration' => 300,
'title' => 'Default Title',
'description' => 'Default Description',
]);
$this->setExpectedException(cliexception::class);
$this->execute($cli);
}
public function test_setreferencetime_invalid() {
$cli = new create(['start' => 0]);
$this->setExpectedException(InvalidArgumentException::class);
$cli->set_referencetime(-1);
}
public function test_help() {
$this->set_parameters(['--help']);
$cli = new create();
$output = $this->execute($cli);
self::assertContains('Creates', $output);
self::assertContains('--help', $output);
}
public function test_options() {
$cli = new create();
$options = $cli->generateoptions();
foreach (array_keys($options) as $k) {
self::assertTrue(is_string($k));
}
$shorts = $cli->generateshortcuts();
foreach ($shorts as $s) {
self::assertArrayHasKey($s, $options);
}
}
public function test_create_withoptions() {
$this->set_parameters([
'--warn=10',
'--start=0',
'--duration=30',
'--title=A Title',
'--description=A Description',
]);
$now = time();
$cli = new create();
$cli->set_referencetime($now);
$text = $this->execute($cli);
self::assertContains('created', $text);
// Check creted outage.
list(, $id) = explode(':', $text);
$id = (int)$id;
$outage = outagedb::get_by_id($id);
self::assertSame($now, $outage->starttime);
self::assertSame(10, $outage->get_warning_duration());
self::assertSame(30, $outage->get_duration());
self::assertNull($outage->finished);
self::assertSame('A Title', $outage->title);
self::assertSame('A Description', $outage->description);
}
public function test_create_onlyid() {
$this->set_parameters([
'--onlyid',
'--warn=10',
'--start=0',
'--duration=30',
'--title=Title',
'--description=Description',
]);
$now = time();
$cli = new create();
$cli->set_referencetime($now);
$id = $this->execute($cli);
// Check if the id contains is only a number (parameter onlyid).
$id = trim($id);
self::assertTrue(is_number($id));
$id = (int)$id;
// Check creted outage.
$outage = outagedb::get_by_id($id);
self::assertSame($now, $outage->starttime);
self::assertSame($outage->starttime - 10, $outage->warntime);
self::assertSame($outage->starttime + 30, $outage->stoptime);
self::assertNull($outage->finished);
self::assertSame('Title', $outage->title);
self::assertSame('Description', $outage->description);
}
public function test_create_withdefaults() {
$this->set_parameters([
'--warn=100',
'--start=50',
]);
$now = time();
$cli = new create();
$cli->set_referencetime($now);
$cli->set_defaults([
'warn' => 50,
'start' => 200,
'duration' => 300,
'title' => 'Default Title',
'description' => 'Default Description',
]);
$text = $this->execute($cli);
self::assertContains('created', $text);
// Check creted outage.
list(, $id) = explode(':', $text);
$id = (int)$id;
$outage = outagedb::get_by_id($id);
self::assertSame($now + 50, $outage->starttime, 'Wrong starttime.');
self::assertSame($outage->starttime - 100, $outage->warntime, 'Wrong warntime.');
self::assertSame($outage->starttime + 300, $outage->stoptime, 'Wrong stoptime.');
self::assertNull($outage->finished);
self::assertSame('Default Title', $outage->title);
self::assertSame('Default Description', $outage->description);
}
public function test_create_withclone() {
$this->setAdminUser();
$now = time();
// Create the outage to clone.
$original = new outage([
'warntime' => $now - 120,
'starttime' => $now,
'stoptime' => $now + 120,
'title' => 'Title',
'description' => 'Description',
]);
$id = outagedb::save($original);
// Clone it using CLI.
$this->set_parameters([
'--onlyid',
'--start=60',
'--clone=' . $id,
]);
$cli = new create();
$cli->set_referencetime($now);
$id = trim($this->execute($cli));
// Check cloned data.
$cloned = outagedb::get_by_id((int)$id);
self::assertSame($now + 60, $cloned->starttime);
self::assertSame($original->get_warning_duration(), $cloned->get_warning_duration());
self::assertSame($original->get_duration(), $cloned->get_duration());
self::assertSame($original->title, $cloned->title);
self::assertSame($original->description, $cloned->description);
}
public function test_create_withclone_invalid() {
$this->setExpectedException(cliexception::class);
$this->set_parameters([
'--start=60',
'--clone=-1',
]);
$cli = new create();
$this->execute($cli);
}
public function test_create_withblock() {
// Not an extensive test in the blocking API, cliwaitforit tests should cover them deeper.
$this->set_parameters([
'--block',
'--warn=60',
'--start=0',
'--duration=600',
'--title=Title',
'--description=Description',
]);
$now = time();
$cli = new create();
$cli->set_referencetime($now);
$text = $this->execute($cli);
self::assertContains('created', $text);
self::assertContains('started', $text);
}
}

64
tests/cli/finish_test.php Normal file
View File

@@ -0,0 +1,64 @@
<?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/>.
use auth_outage\cli\cliexception;
use auth_outage\cli\finish;
defined('MOODLE_INTERNAL') || die();
require_once('cli_testcase.php');
/**
* Tests performed on CLI finish class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class finish_test extends cli_testcase {
public function test_constructor() {
$cli = new finish();
self::assertNotNull($cli);
}
public function test_options() {
$cli = new finish();
$options = $cli->generateoptions();
foreach (array_keys($options) as $k) {
self::assertTrue(is_string($k));
}
$shorts = $cli->generateshortcuts();
foreach ($shorts as $s) {
self::assertArrayHasKey($s, $options);
}
}
public function test_help() {
$this->set_parameters(['--help']);
$cli = new finish();
$text = $this->execute($cli);
self::assertContains('Finishes', $text);
self::assertContains('--help', $text);
}
public function test_noarguments() {
$cli = new finish();
$this->setExpectedException(cliexception::class);
$this->execute($cli);
}
}

View File

@@ -0,0 +1,171 @@
<?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/>.
use auth_outage\cli\cliexception;
use auth_outage\cli\waitforit;
use auth_outage\models\outage;
use auth_outage\outagedb;
defined('MOODLE_INTERNAL') || die();
require_once('cli_testcase.php');
/**
* Tests performed on CLI waitforit class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @SuppressWarnings("public")
*/
class waitforit_test extends cli_testcase {
public function test_constructor() {
$cli = new waitforit();
self::assertNotNull($cli);
}
public function test_generateoptions() {
$cli = new waitforit();
$options = $cli->generateoptions();
foreach (array_keys($options) as $k) {
self::assertTrue(is_string($k));
}
}
public function test_generateshortcuts() {
$cli = new waitforit();
$options = $cli->generateoptions();
$shorts = $cli->generateshortcuts();
foreach ($shorts as $s) {
self::assertArrayHasKey($s, $options);
}
}
public function test_help() {
$this->set_parameters(['--help']);
$cli = new waitforit();
$text = $this->execute($cli);
self::assertContains('Waits', $text);
self::assertContains('--help', $text);
}
public function test_bothparams() {
$this->set_parameters(['--outageid=1', '--active']);
$cli = new waitforit();
$this->setExpectedException(cliexception::class);
$cli->execute();
}
public function test_invalidoutageid() {
$this->set_parameters(['-id=-1']);
$cli = new waitforit();
$this->setExpectedException(cliexception::class);
$this->execute($cli);
}
public function test_outagenotfound() {
$this->set_parameters(['-a']);
$cli = new waitforit();
$this->setExpectedException(cliexception::class);
$this->execute($cli);
}
public function test_endedoutage() {
$this->setAdminUser();
$now = time();
$id = outagedb::save(new outage([
'warntime' => $now - 200,
'starttime' => $now - 100,
'stoptime' => $now - 50,
'title' => 'Title',
'description' => 'Description',
]));
$this->set_parameters(['-id=' . $id]);
$cli = new waitforit();
$cli->set_referencetime($now);
$this->setExpectedException(cliexception::class);
$this->execute($cli);
}
public function test_activeverbose() {
$this->setAdminUser();
$now = time();
outagedb::save(new outage([
'warntime' => $now - 10,
'starttime' => $now + 1,
'stoptime' => $now + 10,
'title' => 'Title',
'description' => 'Description',
]));
$this->set_parameters(['-v', '--active']);
$cli = new waitforit();
$cli->set_referencetime($now);
$output = $this->execute($cli);
self::assertContains('Verbose mode', $output);
self::assertContains('starting in 1 sec', $output);
self::assertContains('started', $output);
}
public function test_countdown() {
$this->setAdminUser();
$now = time();
outagedb::save(new outage([
'warntime' => $now,
'starttime' => $now + 45,
'stoptime' => $now + (60 * 60),
'title' => 'Title',
'description' => 'Description',
]));
$this->set_parameters(['-v', '--active', '--sleep=30']);
$cli = new waitforit();
$cli->set_referencetime($now);
$cli->set_sleepcallback(function ($sleep) use (&$now) {
$now += $sleep;
return $now;
});
$output = $this->execute($cli);
self::assertContains("starting in 45", $output);
self::assertContains("sleep 30 second", $output);
self::assertContains("starting in 15", $output);
self::assertContains("sleep 15 second", $output);
self::assertContains("started!", $output);
}
public function test_outagechanged() {
$this->setAdminUser();
$now = time();
$id = outagedb::save(new outage([
'warntime' => $now,
'starttime' => $now + (2 * 60 * 60),
'stoptime' => $now + (60 * 60),
'title' => 'Title',
'description' => 'Description',
]));
$this->set_parameters(['-v', '--active', '--sleep=30']);
$cli = new waitforit();
$cli->set_referencetime($now);
$cli->set_sleepcallback(function () use ($id) {
// Change outage when not expected to.
$outage = outagedb::get_by_id($id);
$outage->title = 'New title!';
outagedb::save($outage);
// Pretend it is time to start, but it should get an error instead.
return $outage->starttime;
});
$this->setExpectedException(cliexception::class);
$this->execute($cli);
}
}