MDL-53566 core: Add UI for context locking
authorAndrew Nicols <andrew@nicols.co.uk>
Fri, 8 Jun 2018 03:37:43 +0000 (11:37 +0800)
committerAndrew Nicols <andrew@nicols.co.uk>
Tue, 13 Nov 2018 13:17:40 +0000 (21:17 +0800)
admin/lock.php [new file with mode: 0644]
admin/settings/development.php
course/classes/management/helper.php
lang/en/admin.php
lib/blocklib.php
lib/navigationlib.php

diff --git a/admin/lock.php b/admin/lock.php
new file mode 100644 (file)
index 0000000..3041ded
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file is used to display a categories sub categories, external pages, and settings.
+ *
+ * @package    admin
+ * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once('../config.php');
+require_once("{$CFG->libdir}/adminlib.php");
+
+$contextid = required_param('id', PARAM_INT);
+$confirm = optional_param('confirm', null, PARAM_INT);
+$returnurl = optional_param('returnurl', null, PARAM_LOCALURL);
+
+$PAGE->set_url('/admin/lock.php', ['id' => $contextid]);
+
+list($context, $course, $cm) = get_context_info_array($contextid);
+
+$parentcontext = $context->get_parent_context();
+if ($parentcontext && !empty($parentcontext->locked)) {
+    // Can't make changes to a context whose parent is locked.
+    throw new \coding_exception('Not sure how you got here');
+}
+
+if ($course) {
+    $isfrontpage = ($course->id == SITEID);
+} else {
+    $isfrontpage = false;
+    $course = $SITE;
+}
+
+require_login($course, false, $cm);
+require_capability('moodle/site:managecontextlocks', $context);
+
+$PAGE->set_pagelayout('admin');
+$PAGE->navigation->clear_cache();
+
+$a = (object) [
+    'contextname' => $context->get_context_name(),
+];
+
+if (null !== $confirm && confirm_sesskey()) {
+    $context->set_locked(!empty($confirm));
+
+    if ($context->locked) {
+        $lockmessage = get_string('managecontextlocklocked', 'admin', $a);
+    } else {
+        $lockmessage = get_string('managecontextlockunlocked', 'admin', $a);
+    }
+
+    if (empty($returnurl)) {
+        $returnurl = $context->get_url();
+    } else {
+        $returnurl = new moodle_url($returnurl);
+    }
+    redirect($returnurl, $lockmessage);
+}
+
+$heading = get_string('managecontextlock', 'admin');
+$PAGE->set_title($heading);
+$PAGE->set_heading($heading);
+
+echo $OUTPUT->header();
+
+if ($context->locked) {
+    $confirmstring = get_string('confirmcontextunlock', 'admin', $a);
+    $target = 0;
+} else {
+    $confirmstring = get_string('confirmcontextlock', 'admin', $a);
+    $target = 1;
+}
+
+$confirmurl = new \moodle_url($PAGE->url, ['confirm' => $target]);
+if (!empty($returnurl)) {
+    $confirmurl->param('returnurl', $returnurl);
+}
+
+echo $OUTPUT->confirm($confirmstring, $confirmurl, $context->get_url());
+echo $OUTPUT->footer();
index cc2a620..54fe94b 100644 (file)
@@ -16,6 +16,9 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
 
     $temp->add(new admin_setting_configexecutable('pathtosassc', new lang_string('pathtosassc', 'admin'), new lang_string('pathtosassc_help', 'admin'), ''));
 
+    $temp->add(new admin_setting_configcheckbox('contextlocking', new lang_string('contextlocking', 'core_admin'),
+        new lang_string('contextlocking_desc', 'core_admin'), 0));
+
     $temp->add(new admin_setting_configcheckbox('forceclean', new lang_string('forceclean', 'core_admin'),
         new lang_string('forceclean_desc', 'core_admin'), 0));
 
index 2374883..0befd64 100644 (file)
@@ -168,6 +168,8 @@ class helper {
      * @return array
      */
     public static function get_category_listitem_actions(\core_course_category $category) {
+        global $CFG;
+
         $manageurl = new \moodle_url('/course/management.php', array('categoryid' => $category->id));
         $baseurl = new \moodle_url($manageurl, array('sesskey' => \sesskey()));
         $actions = array();
@@ -280,6 +282,28 @@ class helper {
             );
         }
 
+        // Context locking.
+        if (!empty($CFG->contextlocking) && has_capability('moodle/site:managecontextlocks', $category->get_context())) {
+            $parentcontext = $category->get_context()->get_parent_context();
+            if (empty($parentcontext) || !$parentcontext->locked) {
+                if ($category->get_context()->locked) {
+                    $lockicon = 'i/unlock';
+                    $lockstring = get_string('managecontextunlock', 'admin');
+                } else {
+                    $lockicon = 'i/lock';
+                    $lockstring = get_string('managecontextlock', 'admin');
+                }
+                $actions['managecontextlock'] = [
+                    'url' => new \moodle_url('/admin/lock.php', [
+                            'id' => $category->get_context()->id,
+                            'returnurl' => $manageurl->out_as_local_url(false),
+                        ]),
+                    'icon' => new \pix_icon($lockicon, $lockstring),
+                    'string' => $lockstring,
+                ];
+            }
+        }
+
         // Cohorts.
         if ($category->can_review_cohorts()) {
             $actions['cohorts'] = array(
index 11d79f3..4160854 100644 (file)
@@ -379,8 +379,12 @@ $string['configvisiblecourses'] = 'Display courses in hidden categories normally
 $string['configwarning'] = 'Be careful modifying these settings - strange values could cause problems.';
 $string['configyuicomboloading'] = 'This options enables combined file loading optimisation for YUI libraries. This setting should be enabled on production sites for performance reasons.';
 $string['confirmation'] = 'Confirmation';
+$string['confirmcontextlock'] = '{$a->contextname} is currently unlocked. Locking it will prevent any further changes. Are you sure you wish to continue?';
+$string['confirmcontextunlock'] = '{$a->contextname} is currently locked. Unlocking it will allow users to make changes. Are you sure you wish to continue?';
 $string['confirmdeletecomments'] = 'You are about to delete comments, are you sure?';
 $string['confirmed'] = 'Confirmed';
+$string['contextlocking'] = 'Context locking';
+$string['contextlocking_desc'] = 'This setting allows you to lock categories, courses, activites, and blocks within the site by removing all write-access to those locations.';
 $string['cookiehttponly'] = 'Only http cookies';
 $string['cookiesecure'] = 'Secure cookies only';
 $string['country'] = 'Default country';
@@ -718,6 +722,10 @@ $string['maintenancemodeisscheduled'] = 'This site will be switched to maintenan
 $string['maintenancemodeisscheduledlong'] = 'This site will be switched to maintenance mode in {$a->hour} hours {$a->min} mins {$a->sec} secs';
 $string['maintfileopenerror'] = 'Error opening maintenance files!';
 $string['maintinprogress'] = 'Maintenance is in progress...';
+$string['managecontextlock'] = 'Lock this context';
+$string['managecontextlocklocked'] = '{$a->contextname}, and all of its children are now locked.';
+$string['managecontextlockunlocked'] = '{$a->contextname}, and all of its children are now unlocked.';
+$string['managecontextunlock'] = 'Unlock this context';
 $string['manageformats'] = 'Manage course formats';
 $string['manageformatsgotosettings'] = 'Default format can be changed in {$a}';
 $string['managelang'] = 'Manage';
index feaefb3..18172c2 100644 (file)
@@ -1378,6 +1378,30 @@ class block_manager {
             );
         }
 
+        if (!empty($CFG->contextlocking) && has_capability('moodle/site:managecontextlocks', $block->context)) {
+            $parentcontext = $block->context->get_parent_context();
+            if (empty($parentcontext) || empty($parentcontext->locked)) {
+                if ($block->context->locked) {
+                    $lockicon = 'i/unlock';
+                    $lockstring = get_string('managecontextunlock', 'admin');
+                } else {
+                    $lockicon = 'i/lock';
+                    $lockstring = get_string('managecontextlock', 'admin');
+                }
+                $controls[] = new action_menu_link_secondary(
+                    new moodle_url(
+                        '/admin/lock.php',
+                        [
+                            'id' => $block->context->id,
+                        ]
+                    ),
+                    new pix_icon($lockicon, $lockstring, 'moodle', array('class' => 'iconsmall', 'title' => '')),
+                    $lockstring,
+                    ['class' => 'editing_lock']
+                );
+            }
+        }
+
         return $controls;
     }
 
index 94f995d..93d32b5 100644 (file)
@@ -834,6 +834,43 @@ class navigation_node implements renderable {
         }
         return $this->action;
     }
+
+    /**
+     * Add the menu item to handle locking and unlocking of a conext.
+     *
+     * @param \navigation_node $node Node to add
+     * @param \context $context The context to be locked
+     */
+    protected function add_context_locking_node(\navigation_node $node, \context $context) {
+        global $CFG;
+        // Manage context locking.
+        if (!empty($CFG->contextlocking) && has_capability('moodle/site:managecontextlocks', $context)) {
+            $parentcontext = $context->get_parent_context();
+            if (empty($parentcontext) || !$parentcontext->locked) {
+                if ($context->locked) {
+                    $lockicon = 'i/unlock';
+                    $lockstring = get_string('managecontextunlock', 'admin');
+                } else {
+                    $lockicon = 'i/lock';
+                    $lockstring = get_string('managecontextlock', 'admin');
+                }
+                $node->add(
+                    $lockstring,
+                    new moodle_url(
+                        '/admin/lock.php',
+                        [
+                            'id' => $context->id,
+                        ]
+                    ),
+                    self::TYPE_SETTING,
+                    null,
+                    'contextlocking',
+                     new pix_icon($lockicon, '')
+                );
+            }
+        }
+
+    }
 }
 
 /**
@@ -4371,6 +4408,9 @@ class settings_navigation extends navigation_node {
                 null, 'gradebooksetup', new pix_icon('i/settings', ''));
         }
 
+        // Add the context locking node.
+        $this->add_context_locking_node($coursenode, $coursecontext);
+
         //  Add outcome if permitted
         if ($adminoptions->outcomes) {
             $url = new moodle_url('/grade/edit/outcome/course.php', array('id'=>$course->id));
@@ -4507,6 +4547,10 @@ class settings_navigation extends navigation_node {
             $url = new moodle_url('/'.$CFG->admin.'/roles/check.php', array('contextid'=>$this->page->cm->context->id));
             $modulenode->add(get_string('checkpermissions', 'role'), $url, self::TYPE_SETTING, null, 'rolecheck');
         }
+
+        // Add the context locking node.
+        $this->add_context_locking_node($modulenode, $this->page->cm->context);
+
         // Manage filters
         if (has_capability('moodle/filter:manage', $this->page->cm->context) && count(filter_get_available_in_context($this->page->cm->context))>0) {
             $url = new moodle_url('/filter/manage.php', array('contextid'=>$this->page->cm->context->id));
@@ -5087,6 +5131,9 @@ class settings_navigation extends navigation_node {
                 'checkpermissions', new pix_icon('i/checkpermissions', ''));
         }
 
+        // Add the context locking node.
+        $this->add_context_locking_node($blocknode, $this->context);
+
         return $blocknode;
     }
 
@@ -5149,6 +5196,9 @@ class settings_navigation extends navigation_node {
             $categorynode->add(get_string('checkpermissions', 'role'), $url, self::TYPE_SETTING, null, 'checkpermissions', new pix_icon('i/checkpermissions', ''));
         }
 
+        // Add the context locking node.
+        $this->add_context_locking_node($categorynode, $catcontext);
+
         // Cohorts
         if (has_any_capability(array('moodle/cohort:view', 'moodle/cohort:manage'), $catcontext)) {
             $categorynode->add(get_string('cohorts', 'cohort'), new moodle_url('/cohort/index.php',