From e6a2231ba11c29b5b62db944210d3fa2bb95ff33 Mon Sep 17 00:00:00 2001 From: Daniel Thee Roperto Date: Tue, 20 Sep 2016 20:00:33 +1000 Subject: [PATCH] Issue #33 - Refactored code, created infopage_controller to control the display of an info page. --- classes/infopage_controller.php | 224 ++++++++++++++++++ classes/outagedb.php | 4 +- classes/outagelib.php | 79 ------ info.php | 29 +-- renderer.php | 71 ------ ...b_test.php => infopagecontroller_test.php} | 55 +++-- tests/renderer_test.php | 54 ----- views/{infopage.php => info/content.php} | 40 +++- views/{infopagestatic.php => info/static.php} | 15 +- views/warningbar.php | 2 +- 10 files changed, 315 insertions(+), 258 deletions(-) create mode 100644 classes/infopage_controller.php rename tests/{cli/outagelib_test.php => infopagecontroller_test.php} (55%) delete mode 100644 tests/renderer_test.php rename views/{infopage.php => info/content.php} (50%) rename views/{infopagestatic.php => info/static.php} (81%) diff --git a/classes/infopage_controller.php b/classes/infopage_controller.php new file mode 100644 index 0000000..548e65b --- /dev/null +++ b/classes/infopage_controller.php @@ -0,0 +1,224 @@ +. + +namespace auth_outage; + +use auth_outage\models\outage; +use coding_exception; +use context_system; +use Exception; +use InvalidArgumentException; +use moodle_url; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Controller for the info page. + * + * @package auth_outage + * @author Daniel Thee Roperto + * @copyright 2016 Catalyst IT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class infopage_controller { + /** + * @var outage|null The outage to display or null if none found. + */ + private $outage; + + /** + * @var bool Flags if a static version of this page should be displayed (maintenance mode). + */ + private $static; + + /** + * infopage_controller constructor. + * @param array|null $params Parameters to use or null to get from Moodle API (request). + */ + public function __construct(array $params = null) { + if (is_null($params)) { + $params = [ + 'id' => optional_param('id', null, PARAM_INT), + 'static' => optional_param('static', false, PARAM_BOOL), + 'outage' => null, + ]; + } else { + $defaults = [ + 'id' => null, + 'outage' => null, + 'static' => false, + ]; + $params = array_merge($defaults, $params); + } + + $this->set_parameters($params); + } + + /** + * Given the HTML code for the static page, find the outage id for that page. + * @param string $html Static info page HTML. + * @return int|null Outage id or null if not found. + */ + public static function find_outageid_from_infopage($html) { + if (!is_string($html)) { + throw new InvalidArgumentException('$html must be a string.'); + } + + $output = []; + if (preg_match('/data-outage-id="(?P\d+)"/', $html, $output)) { + return (int)$output['id']; + } + return null; + } + + /** + * Saves a static info page for the given outage. + * @param outage $outage Outage to generate the info page. + * @param string $file File to save the static info page. + * @throws Exception + */ + public static function save_static_page(outage $outage, $file) { + if (!is_string($file)) { + throw new InvalidArgumentException('$file is not a string.'); + } + + $info = new infopage_controller(['outage' => $outage, 'static' => true]); + $html = $info->get_output(); + + // Sanity check before writing/overwriting old file. + if (!is_string($html) || ($html == '') || (html_to_text($html) == '')) { + throw new Exception('Sanity check failed. Invalid contents on $html.'); + } + + $dir = dirname($file); + if (!file_exists($dir) || !is_dir($dir)) { + throw new Exception('Directory must exists: ' . $dir); + } + file_put_contents($file, $html); + } + + /** + * Updates the static info page by (re)creating or deleting it as needed. + * @param null $file + * @throws Exception + */ + public static function update_static_page($file = null) { + if (is_null($file)) { + $file = self::get_defaulttemplatefile(); + } + if (!is_string($file)) { + throw new InvalidArgumentException('$file is not a string.'); + } + + $outage = outagedb::get_next_starting(); + if (is_null($outage)) { + if (file_exists($file)) { + if (is_file($file) && is_writable($file)) { + unlink($file); + } else { + throw new Exception('Cannot remove: ' . $file); + } + } + } else { + self::save_static_page($outage, $file); + } + } + + /** + * @return string The default template file to use for static info page. + */ + public static function get_defaulttemplatefile() { + global $CFG; + return $CFG->dataroot . '/climaintenance.template.html'; + } + + /** + * Generates and returns the HTML for the info page. + * @return string HTML for the info page. + */ + public function get_output() { + ob_start(); + try { + $this->output(); + return ob_get_contents(); + } finally { + ob_end_clean(); + } + } + + /** + * Checks if this page should have admin options, taking in consideration it should happen if generating a static page. + * @return bool True if it should display admin options. + */ + public function has_admin_options() { + return (!$this->static && is_siteadmin()); + } + + /** + * Generates and outputs the HTML for the info page. + * @uses redirect + */ + public function output() { + global $PAGE, $CFG, $OUTPUT; + + if (is_null($this->outage)) { + if ($this->static) { + throw new coding_exception('Cannot render a static info page without an outage.'); + } else { + redirect(new moodle_url('/')); + } + } + + $PAGE->set_context(context_system::instance()); + if ($this->static) { + require($CFG->dirroot . '/auth/outage/views/info/static.php'); + } else { + $PAGE->set_title($this->outage->get_title()); + $PAGE->set_heading($this->outage->get_title()); + $PAGE->set_url(new moodle_url('/auth/outage/info.php')); + + // No hooks injecting into this page, do it manually. + outagelib::inject(); + + echo $OUTPUT->header(); + require($CFG->dirroot . '/auth/outage/views/info/content.php'); + echo $OUTPUT->footer(); + } + } + + /** + * Adjusts the fields according to the given parameters. + * @param array $params + */ + private function set_parameters(array $params) { + if (!is_null($params['outage']) && !($params['outage'] instanceof outage)) { + throw new InvalidArgumentException('Provided outage is not a valid outage object.'); + } + + if (!is_null($params['id']) && !is_null($params['outage']) && ($params['id'] !== $params['outage']->id)) { + throw new InvalidArgumentException('Provided id and outage->id do not match.'); + } + + if (is_null($params['id']) && is_null($params['outage'])) { + $params['outage'] = outagedb::get_active(); + } else if (is_null($params['outage'])) { + $params['outage'] = outagedb::get_by_id($params['id']); + } + + $this->outage = $params['outage']; + $this->static = (bool)$params['static']; + } +} diff --git a/classes/outagedb.php b/classes/outagedb.php index 23fd9cc..3ab7d78 100644 --- a/classes/outagedb.php +++ b/classes/outagedb.php @@ -121,7 +121,7 @@ class outagedb { } // Trigger static page update. - outagelib::updatestaticinfopagefile(); + infopage_controller::update_static_page(); // All done, return the id. return $outage->id; @@ -154,7 +154,7 @@ class outagedb { self::calendar_delete($id); // Trigger static page update. - outagelib::updatestaticinfopagefile(); + infopage_controller::update_static_page(); } /** diff --git a/classes/outagelib.php b/classes/outagelib.php index 5a84b44..4ee3275 100644 --- a/classes/outagelib.php +++ b/classes/outagelib.php @@ -16,10 +16,8 @@ namespace auth_outage; -use auth_outage\models\outage; use auth_outage_renderer; use Exception; -use InvalidArgumentException; use moodle_url; defined('MOODLE_INTERNAL') || die(); @@ -120,81 +118,4 @@ class outagelib { 'css' => file_get_contents($CFG->dirroot . '/auth/outage/views/warningbar.css'), ]; } - - /** - * Saves a static info page for the given outage. - * @param outage $outage Outage to generate the info page. - * @param string $file File to save the static info page. - * @throws Exception - */ - public static function savestaticinfopage(outage $outage, $file) { - if (!is_string($file)) { - throw new InvalidArgumentException('$file is not a string.'); - } - - $html = self::get_renderer()->renderoutagepagestatic($outage); - - // Sanity check before writing/overwriting old file. - if (!is_string($html) || ($html == '')) { - throw new Exception('Sanity check failed. Invalid contents on $html.'); - } - - $dir = dirname($file); - if (!file_exists($dir) || !is_dir($dir)) { - throw new Exception('Directory must exists: ' . $dir); - } - file_put_contents($file, $html); - } - - /** - * Updates the static info page by (re)creating or deleting it as needed. - * @param null $file - * @throws Exception - */ - public static function updatestaticinfopagefile($file = null) { - if (is_null($file)) { - $file = self::get_defaulttemplatefile(); - } - if (!is_string($file)) { - throw new InvalidArgumentException('$file is not a string.'); - } - - $outage = outagedb::get_next_starting(); - if (is_null($outage)) { - if (file_exists($file)) { - if (is_file($file)) { - unlink($file); - } else { - throw new Exception('Cannot remove non-file: ' . $file); - } - } - } else { - self::savestaticinfopage($outage, $file); - } - } - - /** - * Given the HTML code for the static page, find the outage id for that page. - * @param $html Static info page HTML. - * @return int|null Outage id or null if not found. - */ - public static function get_outageidfrominfopage($html) { - if (!is_string($html)) { - throw new InvalidArgumentException('$html must be a string.'); - } - - $output = []; - if (preg_match('/data-outage-id="(?P\d+)"/', $html, $output)) { - return (int)$output['id']; - } - return null; - } - - /** - * @return string The default template file to use for static info page. - */ - public static function get_defaulttemplatefile() { - global $CFG; - return $CFG->dataroot . '/climaintenance.template.html'; - } } diff --git a/info.php b/info.php index 7862f79..5739523 100644 --- a/info.php +++ b/info.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * List outages + * Shows the information about an outage. * * @package auth_outage * @author Daniel Thee Roperto @@ -23,30 +23,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -use auth_outage\outagedb; -use auth_outage\outagelib; +use auth_outage\infopage_controller; require_once('../../config.php'); -$id = optional_param('id', null, PARAM_INT); -$outage = is_null($id) ? outagedb::get_active() : outagedb::get_by_id($id); -if (is_null($outage)) { - redirect(new moodle_url('/')); -} - -if (optional_param('static', false, PARAM_BOOL)) { - echo outagelib::get_renderer()->renderoutagepagestatic($outage); -} else { - $PAGE->set_title($outage->get_title()); - $PAGE->set_heading($outage->get_title()); - $PAGE->set_url(new \moodle_url('/auth/outage/info.php')); - - // No hooks injecting into this page, do it manually. - outagelib::inject(); - - echo $OUTPUT->header(); - - echo outagelib::get_renderer()->renderoutagepage($outage); - - echo $OUTPUT->footer(); -} +$info = new infopage_controller(); +$info->output(); diff --git a/renderer.php b/renderer.php index dd319c7..c5a88da 100644 --- a/renderer.php +++ b/renderer.php @@ -185,77 +185,6 @@ class auth_outage_renderer extends plugin_renderer_base { ); } - /** - * Renders the outage page. - * @param outage $outage Outage to be rendered. - * @param null $time Time to use as refence. Null for current time. - * @return string - * @SuppressWarnings("unused") because $admineditlink is used inside require(...) - */ - public function renderoutagepage(outage $outage, $time = null) { - global $CFG; - - if (is_null($time)) { - $time = time(); - } - if (!is_int($time) || ($time <= 0)) { - throw new InvalidArgumentException('$time is not an positive int or null.'); - } - - $adminlinks = []; - foreach ([ - 'startofwarning' => -$outage->get_warning_duration(), - '15secondsbefore' => -15, - 'start' => 0, - 'endofoutage' => $outage->get_duration_planned(), - ] as $title => $delta) { - $adminlinks[] = html_writer::link( - new moodle_url( - '/auth/outage/info.php', - [ - 'id' => $outage->id, - 'auth_outage_preview' => $outage->id, - 'auth_outage_delta' => $delta, - ] - ), - get_string('info' . $title, 'auth_outage') - ); - } - - $admineditlink = html_writer::link( - new moodle_url('/auth/outage/edit.php', ['id' => $outage->id]), - get_string('outageedit', 'auth_outage') - ); - - $static = false; - - ob_start(); - require($CFG->dirroot . '/auth/outage/views/infopage.php'); - $html = ob_get_contents(); - ob_end_clean(); - return $html; - } - - /** - * Generates the HTML for a static info page. - * @param outage $outage Outage to generate the page. - * @return string The HTML code. - * @SuppressWarnings("unused") because variables are used in require(...) - */ - public function renderoutagepagestatic(outage $outage) { - global $PAGE, $CFG; - $PAGE->set_context(context_system::instance()); - - $static = true; - $time = $outage->starttime; - - ob_start(); - require($CFG->dirroot . '/auth/outage/views/infopagestatic.php'); - $html = ob_get_contents(); - ob_end_clean(); - return $html; - } - /** * Renders the warning bar. * @param outage $outage The outage to show in the warning bar. diff --git a/tests/cli/outagelib_test.php b/tests/infopagecontroller_test.php similarity index 55% rename from tests/cli/outagelib_test.php rename to tests/infopagecontroller_test.php index 2b43f19..50d4805 100644 --- a/tests/cli/outagelib_test.php +++ b/tests/infopagecontroller_test.php @@ -14,29 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +use auth_outage\infopage_controller; use auth_outage\models\outage; use auth_outage\outagelib; defined('MOODLE_INTERNAL') || die(); /** - * Tests performed on outage class. + * Tests performed on infopage_controller class. * * @package auth_outage * @author Daniel Thee Roperto * @copyright Catalyst IT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @covers \auth_outage\outagelib + * @covers \auth_outage\infopage_controller */ -class outagelib_test extends advanced_testcase { - /** - * Gets a temp file to use in the test. Deleted every time a test starts. - * @return string A temporary file name. - */ - public function get_file() { - return sys_get_temp_dir() . '/phpunit_authoutage.tmp'; - } - +class infopagecontroller_test extends advanced_testcase { public function setUp() { if (file_exists($this->get_file())) { if (is_file($this->get_file())) { @@ -47,7 +40,39 @@ class outagelib_test extends advanced_testcase { } } - public function test_staticpage() { + /** + * Return a temporary file name to use for this test. + * @return string Default file. + */ + public function get_file() { + return sys_get_temp_dir() . '/phpunit_authoutage.tmp'; + } + + public function test_staticpage_output() { + global $PAGE; + $this->resetAfterTest(true); + + $PAGE->set_context(context_system::instance()); + $renderer = outagelib::get_renderer(); + $now = time(); + $outage = new outage([ + 'id' => 1, + 'starttime' => $now + (60 * 60), + 'warntime' => $now - (60 * 60), + 'stoptime' => $now + (2 * 60 * 60), + 'title' => 'Outage Title at {{start}}', + 'description' => 'This is an important outage, starting at {{start}}.', + ]); + $info = new infopage_controller(['static' => true, 'outage' => $outage]); + $html = $info->get_output(); + self::assertContains('', $html); + self::assertContains('', $html); + self::assertContains($outage->get_title(), $html); + self::assertContains($outage->get_description(), $html); + self::assertSame($outage->id, infopage_controller::find_outageid_from_infopage($html)); + } + + public function test_staticpage_file() { $now = time(); $outage = new outage([ 'id' => 1, @@ -57,17 +82,17 @@ class outagelib_test extends advanced_testcase { 'title' => 'Title', 'description' => 'Description', ]); - outagelib::savestaticinfopage($outage, $this->get_file()); + infopage_controller::save_static_page($outage, $this->get_file()); self::assertFileExists($this->get_file()); - $id = outagelib::get_outageidfrominfopage(file_get_contents($this->get_file())); + $id = infopage_controller::find_outageid_from_infopage(file_get_contents($this->get_file())); self::assertSame($outage->id, $id); unlink($this->get_file()); } public function test_getdefaulttemplatefile() { - $file = outagelib::get_defaulttemplatefile(); + $file = infopage_controller::get_defaulttemplatefile(); self::assertTrue(is_string($file)); self::assertContains('template', $file); } diff --git a/tests/renderer_test.php b/tests/renderer_test.php deleted file mode 100644 index 996a5d7..0000000 --- a/tests/renderer_test.php +++ /dev/null @@ -1,54 +0,0 @@ -. - -use auth_outage\models\outage; -use auth_outage\outagelib; - -defined('MOODLE_INTERNAL') || die(); - -/** - * Tests performed on outage class. - * - * @package auth_outage - * @author Daniel Thee Roperto - * @copyright Catalyst IT - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @covers \auth_outage_renderer - */ -class renderer_test extends advanced_testcase { - public function test_staticpage() { - global $PAGE; - $this->resetAfterTest(true); - - $PAGE->set_context(context_system::instance()); - $renderer = outagelib::get_renderer(); - $now = time(); - $outage = new outage([ - 'id' => 1, - 'starttime' => $now + (60 * 60), - 'warntime' => $now - (60 * 60), - 'stoptime' => $now + (2 * 60 * 60), - 'title' => 'Outage Title at {{start}}', - 'description' => 'This is an important outage, starting at {{start}}.', - ]); - $html = $renderer->renderoutagepagestatic($outage); - self::assertContains('', $html); - self::assertContains('', $html); - self::assertContains($outage->get_title(), $html); - self::assertContains($outage->get_description(), $html); - self::assertSame($outage->id, outagelib::get_outageidfrominfopage($html)); - } -} diff --git a/views/infopage.php b/views/info/content.php similarity index 50% rename from views/infopage.php rename to views/info/content.php index fc2ae51..9524d8e 100644 --- a/views/infopage.php +++ b/views/info/content.php @@ -23,26 +23,52 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -if (!defined('MOODLE_INTERNAL')) { - die('Direct access to this script is forbidden.'); // It must be included from a Moodle page. +defined('MOODLE_INTERNAL') || die(); + +if ($this->has_admin_options()) { + $adminlinks = []; + foreach ([ + 'startofwarning' => -$this->outage->get_warning_duration(), + '15secondsbefore' => -15, + 'start' => 0, + 'endofoutage' => $this->outage->get_duration_planned(), + ] as $title => $delta) { + $adminlinks[] = html_writer::link( + new moodle_url( + '/auth/outage/info.php', + [ + 'id' => $this->outage->id, + 'auth_outage_preview' => $this->outage->id, + 'auth_outage_delta' => $delta, + ] + ), + get_string('info'.$title, 'auth_outage') + ); + } + + $admineditlink = html_writer::link( + new moodle_url('/auth/outage/edit.php', ['id' => $this->outage->id]), + get_string('outageedit', 'auth_outage') + ); } ?>
+
- starttime, get_string('datetimeformat', 'auth_outage')); ?> + outage->starttime, get_string('datetimeformat', 'auth_outage')); ?>
- stoptime, get_string('datetimeformat', 'auth_outage')); ?> + outage->stoptime, get_string('datetimeformat', 'auth_outage')); ?>
-
get_description(); ?>
+
outage->get_description(); ?>
- + has_admin_options()): ?> diff --git a/views/infopagestatic.php b/views/info/static.php similarity index 81% rename from views/infopagestatic.php rename to views/info/static.php index cb022ce..8178635 100644 --- a/views/infopagestatic.php +++ b/views/info/static.php @@ -28,7 +28,7 @@ defined('MOODLE_INTERNAL') || die(); global $SITE; ?> - + <?php echo strip_tags($SITE->fullname); ?> @@ -41,15 +41,22 @@ global $SITE; - +outage; +$static = true; +require($CFG->dirroot.'/auth/outage/views/warningbar.php'); +?>

fullname); ?>

-

get_title(); ?>

- +

outage->get_title(); ?>

+