Merge branch 'MDL-40386' of https://github.com/prateeksachan/moodle
authorDamyon Wiese <damyon@moodle.com>
Tue, 9 Jul 2013 04:34:31 +0000 (12:34 +0800)
committerDamyon Wiese <damyon@moodle.com>
Tue, 9 Jul 2013 04:34:31 +0000 (12:34 +0800)
324 files changed:
admin/blocks.php
admin/cli/install.php
admin/cli/install_database.php
admin/cli/upgrade.php
admin/courseformats.php
admin/editors.php
admin/enrol.php
admin/environment.xml
admin/index.php
admin/localplugins.php
admin/modules.php
admin/plagiarism.php
admin/plugins.php
admin/renderer.php
admin/reports.php
admin/roles/admins.php
admin/roles/allow.php
admin/roles/assign.php
admin/roles/check.php
admin/roles/classes/admins_existing_selector.php [new file with mode: 0644]
admin/roles/classes/admins_potential_selector.php [new file with mode: 0644]
admin/roles/classes/allow_assign_page.php [new file with mode: 0644]
admin/roles/classes/allow_override_page.php [new file with mode: 0644]
admin/roles/classes/allow_role_page.php [new file with mode: 0644]
admin/roles/classes/allow_switch_page.php [new file with mode: 0644]
admin/roles/classes/assign_user_selector_base.php [new file with mode: 0644]
admin/roles/classes/capability_table_base.php [new file with mode: 0644]
admin/roles/classes/capability_table_with_risks.php [new file with mode: 0644]
admin/roles/classes/check_capability_table.php [new file with mode: 0644]
admin/roles/classes/check_users_selector.php [new file with mode: 0644]
admin/roles/classes/define_role_table_advanced.php [new file with mode: 0644]
admin/roles/classes/define_role_table_basic.php [new file with mode: 0644]
admin/roles/classes/existing_role_holders.php [new file with mode: 0644]
admin/roles/classes/override_permissions_table_advanced.php [new file with mode: 0644]
admin/roles/classes/permission_allow_form.php [new file with mode: 0644]
admin/roles/classes/permission_prohibit_form.php [new file with mode: 0644]
admin/roles/classes/permissions_table.php [new file with mode: 0644]
admin/roles/classes/potential_assignees_below_course.php [new file with mode: 0644]
admin/roles/classes/potential_assignees_course_and_above.php [new file with mode: 0644]
admin/roles/classes/preset.php [new file with mode: 0644]
admin/roles/classes/preset_form.php [new file with mode: 0644]
admin/roles/classes/view_role_definition_table.php [new file with mode: 0644]
admin/roles/define.php
admin/roles/lib.php
admin/roles/manage.php
admin/roles/managetabs.php
admin/roles/override.php
admin/roles/permissions.php
admin/roles/permissions_forms.php [deleted file]
admin/roles/role_schema.xml [new file with mode: 0644]
admin/roles/tests/preset_test.php [new file with mode: 0644]
admin/roles/usersroles.php
admin/settings/courses.php
admin/settings/development.php
admin/settings/security.php
admin/settings/users.php
admin/tool/behat/cli/init.php
admin/tool/behat/tests/behat/data_generators.feature
admin/tool/capability/classes/settings_form.php [new file with mode: 0644]
admin/tool/capability/index.php
admin/tool/capability/lang/en/tool_capability.php
admin/tool/capability/locallib.php [new file with mode: 0644]
admin/tool/capability/module.js [deleted file]
admin/tool/capability/renderer.php [new file with mode: 0644]
admin/tool/capability/settings.php
admin/tool/capability/styles.css [new file with mode: 0644]
admin/tool/capability/version.php
admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-debug.js [new file with mode: 0644]
admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js [new file with mode: 0644]
admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search.js [new file with mode: 0644]
admin/tool/capability/yui/src/search/build.json [new file with mode: 0644]
admin/tool/capability/yui/src/search/js/search.js [new file with mode: 0644]
admin/tool/capability/yui/src/search/meta/search.json [new file with mode: 0644]
admin/tool/customlang/edit.php
admin/tool/customlang/index.php
admin/tool/generator/index.php
admin/tool/langimport/lang/en/tool_langimport.php
admin/tool/phpunit/cli/init.php
admin/tool/profiling/export.php [new file with mode: 0644]
admin/tool/profiling/import.php [new file with mode: 0644]
admin/tool/profiling/import_form.php [new file with mode: 0644]
admin/tool/profiling/index.php
admin/tool/profiling/lang/en/tool_profiling.php
admin/tool/profiling/version.php
admin/tools.php
admin/user/user_bulk_cohortadd.php
admin/user/user_bulk_display.php
auth/ldap/auth.php
auth/mnet/auth.php
auth/tests/behat/behat_auth.php
auth/tests/behat/login.feature
backup/moodle2/backup_final_task.class.php
backup/moodle2/backup_root_task.class.php
backup/moodle2/backup_settingslib.php
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_final_task.class.php
backup/moodle2/restore_root_task.class.php
backup/moodle2/restore_settingslib.php
backup/moodle2/restore_stepslib.php
backup/util/dbops/backup_controller_dbops.class.php
backup/util/helper/backup_cron_helper.class.php
badges/award.php
badges/index.php
badges/renderer.php
blocks/badges/db/access.php
blocks/badges/version.php
blocks/completionstatus/details.php
blocks/moodleblock.class.php
blocks/navigation/renderer.php
cache/locallib.php
calendar/lib.php
course/editcategory.php
course/editcategory_form.php
enrol/externallib.php
enrol/flatfile/lib.php
enrol/flatfile/tests/flatfile_test.php
enrol/self/lang/en/enrol_self.php
enrol/self/lib.php
enrol/self/locallib.php
enrol/self/tests/self_test.php
enrol/self/version.php
enrol/tests/externallib_role_test.php
enrol/upgrade.txt
error/index.php
files/externallib.php
files/tests/externallib_test.php [new file with mode: 0644]
grade/grading/lib.php
grade/report/grader/lib.php
grade/report/grader/styles.css
group/index.php
group/overview.php
install.php
install/lang/pan/langconfig.php [new file with mode: 0644]
lang/README.txt
lang/en/admin.php
lang/en/auth.php
lang/en/backup.php
lang/en/badges.php
lang/en/cache.php
lang/en/editor.php
lang/en/enrol.php
lang/en/error.php
lang/en/moodle.php
lang/en/plagiarism.php
lang/en/plugin.php
lang/en/portfolio.php
lang/en/role.php
lib/accesslib.php
lib/adminlib.php
lib/ajax/getnavbranch.php
lib/badgeslib.php
lib/behat/behat_files.php
lib/classes/collator.php [new file with mode: 0644]
lib/classes/component.php
lib/classes/text.php [new file with mode: 0644]
lib/conditionlib.php
lib/coursecatlib.php
lib/csslib.php
lib/datalib.php
lib/db/access.php
lib/db/install.php
lib/db/install.xml
lib/db/upgrade.php
lib/deprecatedlib.php
lib/dml/mssql_native_moodle_database.php
lib/dml/mysqli_native_moodle_database.php
lib/dml/sqlsrv_native_moodle_database.php
lib/editor/tinymce/adminlib.php
lib/editor/tinymce/lang/en/editor_tinymce.php
lib/editor/tinymce/subplugins.php
lib/editor/tinymce/yui/build/moodle-editor_tinymce-collapse/moodle-editor_tinymce-collapse-debug.js
lib/editor/tinymce/yui/build/moodle-editor_tinymce-collapse/moodle-editor_tinymce-collapse-min.js
lib/editor/tinymce/yui/build/moodle-editor_tinymce-collapse/moodle-editor_tinymce-collapse.js
lib/editor/tinymce/yui/src/collapse/js/collapse.js
lib/enrollib.php
lib/filelib.php
lib/form/form.js
lib/formslib.php
lib/html2text.php
lib/html2text_readme.txt
lib/modinfolib.php
lib/moodlelib.php
lib/navigationlib.php
lib/outputcomponents.php
lib/outputlib.php
lib/pagelib.php
lib/phpunit/bootstrap.php
lib/phpunit/classes/autoloader.php [new file with mode: 0644]
lib/phpunit/classes/util.php
lib/phpunit/tests/advanced_test.php
lib/pluginlib.php
lib/setup.php
lib/tablelib.php
lib/testing/generator/data_generator.php
lib/tests/accesslib_test.php
lib/tests/behat/behat_general.php
lib/tests/collator_test.php [new file with mode: 0644]
lib/tests/component_test.php
lib/tests/csslib_test.php
lib/tests/html2text_test.php
lib/tests/moodlelib_test.php
lib/tests/text_test.php [new file with mode: 0644]
lib/tests/textlib_test.php [deleted file]
lib/textlib.class.php
lib/upgrade.txt
lib/upgradelib.php
lib/weblib.php
lib/xhprof/readme_moodle.txt
lib/xhprof/xhprof_moodle.php
local/readme.txt
login/index_form.html
login/token.php
mnet/service/enrol/index.php
mnet/service/enrol/locallib.php
mod/assign/adminmanageplugins.php
mod/assign/feedback/offline/locallib.php
mod/assign/locallib.php
mod/assign/submissionplugin.php
mod/assign/tests/locallib_test.php
mod/chat/gui_sockets/index.php
mod/data/db/upgrade.php
mod/data/lib.php
mod/data/tests/search_test.php
mod/data/view.php
mod/feedback/delete_template.php
mod/feedback/edit.php
mod/feedback/edit_form.php
mod/feedback/item/label/lib.php
mod/feedback/lib.php
mod/forum/lang/en/forum.php
mod/forum/lib.php
mod/forum/tests/behat/behat_mod_forum.php
mod/forum/tests/behat/edit_post_student.feature
mod/forum/user.php
mod/lesson/pagetypes/matching.php
mod/lti/mod_form.js
mod/lti/mod_form.php
mod/quiz/renderer.php
mod/quiz/report/attemptsreport_table.php
mod/scorm/report/basic/report.php
mod/scorm/report/interactions/report.php
mod/workshop/allocation/manual/lib.php
mod/workshop/locallib.php
phpunit.xml.dist
portfolio/add.php
question/type/calculatedmulti/question.php
question/type/essay/question.php
question/type/essay/tests/question_test.php
question/type/shortanswer/db/upgrade.php
question/type/upgrade.txt
report/log/locallib.php
repository/draftfiles_ajax.php
repository/filepicker.php
repository/filesystem/lang/en/repository_filesystem.php
repository/filesystem/lib.php
repository/flickr_public/lib.php
repository/googledocs/lib.php
repository/lib.php
repository/recent/tests/behat/behat_repository_recent.php
repository/repository_ajax.php
repository/tests/behat/behat_filepicker.php
repository/tests/repository_test.php
repository/upload/tests/behat/behat_repository_upload.php
rss/file.php
tag/coursetags_more.php
tag/coursetagslib.php
theme/base/style/admin.css
theme/base/style/core.css
theme/bootstrapbase/layout/columns1.php
theme/bootstrapbase/layout/columns2.php
theme/bootstrapbase/layout/columns3.php
theme/bootstrapbase/less/moodle/core.less
theme/bootstrapbase/less/moodle/grade.less
theme/bootstrapbase/less/moodle/responsive.less
theme/bootstrapbase/style/moodle.css
theme/boxxie/layout/frontpage.php
theme/boxxie/layout/general.php
theme/clean/layout/columns1.php
theme/clean/layout/columns2.php
theme/clean/layout/columns3.php
theme/formal_white/config.php
theme/formal_white/db/upgrade.php
theme/formal_white/lang/en/theme_formal_white.php
theme/formal_white/layout/embedded.php
theme/formal_white/layout/frontpage.php
theme/formal_white/layout/general.php
theme/formal_white/layout/report.php
theme/formal_white/lib.php
theme/formal_white/settings.php
theme/formal_white/style/course.css
theme/formal_white/style/formal_white.css
theme/formal_white/version.php
theme/formfactor/config.php
theme/formfactor/lang/en/theme_formfactor.php
theme/formfactor/layout/embedded.php
theme/formfactor/layout/frontpage.php
theme/formfactor/layout/general.php
theme/formfactor/style/blocks.css
theme/formfactor/style/core.css
theme/formfactor/style/course.css
theme/formfactor/style/editor.css
theme/formfactor/style/mods.css
theme/formfactor/style/pagelayout.css
theme/formfactor/style/selected.css
theme/mymobile/style/core.css
theme/styles.php
user/edit.php
user/editadvanced.php
user/editadvanced_form.php
user/editlib.php
user/externallib.php
user/index.php
user/lib.php
user/messageselect.php
user/profile.php
user/selector/lib.php
user/tests/externallib_test.php
version.php
webservice/amf/server.php
webservice/amf/simpleserver.php
webservice/soap/server.php
webservice/soap/simpleserver.php
webservice/xmlrpc/server.php
webservice/xmlrpc/simpleserver.php

index f2017b9..2ad0a0e 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 
-    // Allows the admin to configure blocks (hide/show, delete and configure)
+    // Allows the admin to configure blocks (hide/show, uninstall and configure)
 
     require_once('../config.php');
     require_once($CFG->libdir.'/adminlib.php');
     $confirm  = optional_param('confirm', 0, PARAM_BOOL);
     $hide     = optional_param('hide', 0, PARAM_INT);
     $show     = optional_param('show', 0, PARAM_INT);
-    $delete   = optional_param('delete', 0, PARAM_INT);
     $unprotect = optional_param('unprotect', 0, PARAM_INT);
     $protect = optional_param('protect', 0, PARAM_INT);
 
 /// Print headings
 
     $strmanageblocks = get_string('manageblocks');
-    $strdelete = get_string('delete');
+    $struninstall = get_string('uninstallplugin', 'core_admin');
     $strversion = get_string('version');
     $strhide = get_string('hide');
     $strshow = get_string('show');
         admin_get_root(true, false);  // settings not required - only pages
     }
 
-    if (!empty($delete) && confirm_sesskey()) {
-        echo $OUTPUT->header();
-        echo $OUTPUT->heading($strmanageblocks);
-
-        if (!$block = blocks_get_record($delete)) {
-            print_error('blockdoesnotexist', 'error');
-        }
-
-        if (get_string_manager()->string_exists('pluginname', "block_$block->name")) {
-            $strblockname = get_string('pluginname', "block_$block->name");
-        } else {
-            $strblockname = $block->name;
-        }
-
-        if (!$confirm) {
-            echo $OUTPUT->confirm(get_string('blockdeleteconfirm', '', $strblockname), 'blocks.php?delete='.$block->id.'&confirm=1', 'blocks.php');
-            echo $OUTPUT->footer();
-            exit;
-
-        } else {
-            uninstall_plugin('block', $block->name);
-
-            $a = new stdClass();
-            $a->block = $strblockname;
-            $a->directory = $CFG->dirroot.'/blocks/'.$block->name;
-            notice(get_string('blockdeletefiles', '', $a), 'blocks.php');
-        }
-    }
-
     echo $OUTPUT->header();
     echo $OUTPUT->heading($strmanageblocks);
 
 
     $table = new flexible_table('admin-blocks-compatible');
 
-    $table->define_columns(array('name', 'instances', 'version', 'hideshow', 'undeletable', 'delete', 'settings'));
-    $table->define_headers(array($strname, $strcourses, $strversion, $strhide.'/'.$strshow, $strprotecthdr, $strdelete, $strsettings));
+    $table->define_columns(array('name', 'instances', 'version', 'hideshow', 'undeletable', 'uninstall', 'settings'));
+    $table->define_headers(array($strname, $strcourses, $strversion, $strhide.'/'.$strshow, $strprotecthdr, $struninstall, $strsettings));
     $table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/blocks.php');
     $table->set_attribute('class', 'admintable blockstable generaltable');
     $table->set_attribute('id', 'compatibleblockstable');
             }
         }
 
-        $delete = '<a href="blocks.php?delete='.$blockid.'&amp;sesskey='.sesskey().'">'.$strdelete.'</a>';
+        if ($uninstallurl = plugin_manager::instance()->get_uninstall_url('block_'.$blockname)) {
+            $uninstall = html_writer::link($uninstallurl, $struninstall);
+        } else {
+            $uninstall = '';
+        }
 
         $settings = ''; // By default, no configuration
         if ($blockobject and $blockobject->has_config()) {
             '<span'.$class.'>'.$version.'</span>',
             $visible,
             $undeletable,
-            $delete,
+            $uninstall,
             $settings
         );
         $table->add_data($row);
 
         $table = new flexible_table('admin-blocks-incompatible');
 
-        $table->define_columns(array('block', 'delete'));
-        $table->define_headers(array($strname, $strdelete));
+        $table->define_columns(array('block', 'uninstall'));
+        $table->define_headers(array($strname, $struninstall));
         $table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/blocks.php');
 
         $table->set_attribute('class', 'incompatibleblockstable generaltable');
         $table->setup();
 
         foreach ($incompatible as $block) {
+            if ($uninstallurl = plugin_manager::instance()->get_uninstall_url('block_'.$block->name)) {
+                $uninstall = html_writer::link($uninstallurl, $struninstall);
+            } else {
+                $uninstall = '';
+            }
             $table->add_data(array(
                 $block->name,
-                '<a href="blocks.php?delete='.$block->id.'&amp;sesskey='.sesskey().'">'.$strdelete.'</a>',
+                $uninstall,
             ));
         }
         $table->print_html();
index 684acb5..f0bee31 100644 (file)
@@ -36,6 +36,12 @@ if (isset($_SERVER['REMOTE_ADDR'])) {
     exit(1);
 }
 
+// Force OPcache reset if used, we do not want any stale caches
+// when preparing test environment.
+if (function_exists('opcache_reset')) {
+    opcache_reset();
+}
+
 $help =
 "Command line Moodle installer, creates config.php and initializes database.
 Please note you must execute this script with the same uid as apache
@@ -163,10 +169,10 @@ $CFG->admin                = array_pop($parts);
 ini_set('include_path', $CFG->libdir.'/pear' . PATH_SEPARATOR . ini_get('include_path'));
 
 require_once($CFG->libdir.'/classes/component.php');
+require_once($CFG->libdir.'/classes/text.php');
 require_once($CFG->libdir.'/installlib.php');
 require_once($CFG->libdir.'/clilib.php');
 require_once($CFG->libdir.'/setuplib.php');
-require_once($CFG->libdir.'/textlib.class.php');
 require_once($CFG->libdir.'/weblib.php');
 require_once($CFG->libdir.'/dmllib.php');
 require_once($CFG->libdir.'/moodlelib.php');
index dfc7a42..7a4f288 100644 (file)
@@ -36,6 +36,12 @@ if (isset($_SERVER['REMOTE_ADDR'])) {
     exit(1);
 }
 
+// Force OPcache reset if used, we do not want any stale caches
+// when preparing test environment.
+if (function_exists('opcache_reset')) {
+    opcache_reset();
+}
+
 $help =
 "Advanced command line Moodle database installer.
 Please note you must execute this script with the same uid as apache.
index ca6ef6a..98e8726 100644 (file)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+// Force OPcache reset if used, we do not want any stale caches
+// when detecting if upgrade necessary or when running upgrade.
+if (function_exists('opcache_reset') and !isset($_SERVER['REMOTE_ADDR'])) {
+    opcache_reset();
+}
+
 define('CLI_SCRIPT', true);
 define('CACHE_DISABLE_ALL', true);
 
index fddcdda..7ea15e8 100644 (file)
@@ -28,7 +28,6 @@ require_once($CFG->libdir.'/pluginlib.php');
 
 $action  = required_param('action', PARAM_ALPHANUMEXT);
 $formatname   = required_param('format', PARAM_PLUGIN);
-$confirm = optional_param('confirm', 0, PARAM_BOOL);
 
 $syscontext = context_system::instance();
 $PAGE->set_url('/admin/courseformats.php');
@@ -79,52 +78,5 @@ switch ($action) {
             set_config('format_plugins_sortorder', implode(',', $seq));
         }
         break;
-    case 'uninstall':
-        echo $OUTPUT->header();
-        echo $OUTPUT->heading(get_string('courseformats', 'moodle'));
-
-        $coursecount = $DB->count_records('course', array('format' => $formatname));
-        if ($coursecount) {
-            // Check that default format is set. It will be used to convert courses
-            // using this format
-            $defaultformat = get_config('moodlecourse', 'format');
-            $defaultformat = $formatplugins[get_config('moodlecourse', 'format')];
-            if (!$defaultformat) {
-                echo $OUTPUT->error_text(get_string('defaultformatnotset', 'admin'));
-                echo $OUTPUT->footer();
-                exit;
-            }
-        }
-
-        $format = $formatplugins[$formatname];
-        $deleteurl = $format->get_uninstall_url();
-        if (!$deleteurl) {
-            // somebody was trying to cheat and type non-existing link
-            echo $OUTPUT->error_text(get_string('cannotuninstall', 'admin', $format->displayname));
-            echo $OUTPUT->footer();
-            exit;
-        }
-
-        if (!$confirm) {
-            if ($coursecount) {
-                $message = get_string('formatuninstallwithcourses', 'admin',
-                        (object)array('count' => $coursecount, 'format' => $format->displayname,
-                            'defaultformat' => $defaultformat->displayname));
-            } else {
-                $message = get_string('formatuninstallconfirm', 'admin', $format->displayname);
-            }
-            $deleteurl->param('confirm', 1);
-            echo $OUTPUT->confirm($message, $deleteurl, $return);
-        } else {
-            $a = new stdClass();
-            $a->plugin = $format->displayname;
-            $a->directory = $format->rootdir;
-            uninstall_plugin('format', $formatname);
-            echo $OUTPUT->notification(get_string('formatuninstalled', 'admin', $a), 'notifysuccess');
-            echo $OUTPUT->continue_button($return);
-        }
-
-        echo $OUTPUT->footer();
-        exit;
 }
 redirect($return);
index f6e68ff..da846fa 100644 (file)
@@ -83,47 +83,6 @@ switch ($action) {
         }
         break;
 
-    case 'uninstall':
-        if ($editor === 'textarea') {
-            redirect($returnurl);
-        }
-        if (get_string_manager()->string_exists('pluginname', 'editor_'.$editor)) {
-            $strplugin = get_string('pluginname', 'editor_'.$editor);
-        } else {
-            $strplugin = $editor;
-        }
-
-        $PAGE->set_title($strplugin);
-        echo $OUTPUT->header();
-
-        if (!$confirm) {
-            echo $OUTPUT->heading(get_string('editors', 'core_editor'));
-
-            $deleteurl = new moodle_url('/admin/editors.php', array('action'=>'uninstall', 'editor'=>$editor, 'sesskey'=>sesskey(), 'confirm'=>1));
-
-            echo $OUTPUT->confirm(get_string('editordeleteconfirm', 'core_editor', $strplugin),
-                $deleteurl, $returnurl);
-            echo $OUTPUT->footer();
-            die();
-
-        } else {
-            // Remove from enabled list.
-            $key = array_search($editor, $active_editors);
-            unset($active_editors[$key]);
-            set_config('texteditors', implode(',', $active_editors));
-
-            // Delete everything!!
-            uninstall_plugin('editor', $editor);
-
-            $a = new stdClass();
-            $a->name = $strplugin;
-            $a->directory = "$CFG->dirroot/lib/editor/$editor";
-            echo $OUTPUT->notification(get_string('plugindeletefiles', '', $a), 'notifysuccess');
-            echo $OUTPUT->continue_button($returnurl);
-            echo $OUTPUT->footer();
-            die();
-        }
-
     default:
         break;
 }
index 10062a1..59f77c5 100644 (file)
@@ -31,7 +31,6 @@ require_once($CFG->libdir.'/adminlib.php');
 $action  = required_param('action', PARAM_ALPHANUMEXT);
 $enrol   = required_param('enrol', PARAM_PLUGIN);
 $confirm = optional_param('confirm', 0, PARAM_BOOL);
-$migrate = optional_param('migrate', 0, PARAM_BOOL);
 
 $PAGE->set_url('/admin/enrol.php');
 $PAGE->set_context(context_system::instance());
@@ -96,7 +95,7 @@ switch ($action) {
         set_config('enrol_plugins_enabled', implode(',', $enabled));
         break;
 
-    case 'uninstall':
+    case 'migrate':
         if (get_string_manager()->string_exists('pluginname', 'enrol_'.$enrol)) {
             $strplugin = get_string('pluginname', 'enrol_'.$enrol);
         } else {
@@ -106,58 +105,26 @@ switch ($action) {
         $PAGE->set_title($strplugin);
         echo $OUTPUT->header();
 
-        if (!$confirm) {
-            echo $OUTPUT->heading(get_string('enrolments', 'enrol'));
+        // This may take a long time.
+        set_time_limit(0);
 
-            $deleteurl = new moodle_url('/admin/enrol.php', array('action'=>'uninstall', 'enrol'=>$enrol, 'sesskey'=>sesskey(), 'confirm'=>1, 'migrate'=>0));
-            $migrateurl = new moodle_url('/admin/enrol.php', array('action'=>'uninstall', 'enrol'=>$enrol, 'sesskey'=>sesskey(), 'confirm'=>1, 'migrate'=>1));
-
-            $migrate = new single_button($migrateurl, get_string('uninstallmigrate', 'enrol'));
-            $delete = new single_button($deleteurl, get_string('uninstalldelete', 'enrol'));
-            $cancel = new single_button($return, get_string('cancel'), 'get');
-
-            $buttons = $OUTPUT->render($delete) . $OUTPUT->render($cancel);
-            if ($enrol !== 'manual') {
-                $buttons = $OUTPUT->render($migrate) . $buttons;
-            }
-
-            echo $OUTPUT->box_start('generalbox', 'notice');
-            echo html_writer::tag('p', markdown_to_html(get_string('uninstallconfirm', 'enrol', $strplugin)));
-            echo html_writer::tag('div', $buttons, array('class' => 'buttons'));
-            echo $OUTPUT->box_end();
-
-            echo $OUTPUT->footer();
-            exit;
-
-        } else {
-            // This may take a long time.
-            set_time_limit(0);
-
-            // Disable plugin to prevent concurrent cron execution.
-            unset($enabled[$enrol]);
-            set_config('enrol_plugins_enabled', implode(',', array_keys($enabled)));
-
-            if ($migrate) {
-                echo $OUTPUT->heading(get_string('uninstallmigrating', 'enrol', 'enrol_'.$enrol));
+        // Disable plugin to prevent concurrent cron execution.
+        unset($enabled[$enrol]);
+        set_config('enrol_plugins_enabled', implode(',', array_keys($enabled)));
 
-                require_once("$CFG->dirroot/enrol/manual/locallib.php");
-                enrol_manual_migrate_plugin_enrolments($enrol);
+        echo $OUTPUT->heading(get_string('uninstallmigrating', 'enrol', 'enrol_'.$enrol));
 
-                echo $OUTPUT->notification(get_string('success'), 'notifysuccess');
-            }
+        require_once("$CFG->dirroot/enrol/manual/locallib.php");
+        enrol_manual_migrate_plugin_enrolments($enrol);
 
-            // Delete everything!!
-            uninstall_plugin('enrol', $enrol);
-            $syscontext->mark_dirty(); // Resets all enrol caches.
+        echo $OUTPUT->notification(get_string('success'), 'notifysuccess');
 
-            $a = new stdClass();
-            $a->plugin = $strplugin;
-            $a->directory = "$CFG->dirroot/enrol/$enrol";
-            echo $OUTPUT->notification(get_string('uninstalldeletefiles', 'enrol', $a), 'notifysuccess');
-            echo $OUTPUT->continue_button($return);
-            echo $OUTPUT->footer();
-            exit;
+        if (!$return = plugin_manager::instance()->get_uninstall_url('enrol_'.$enrol)) {
+            $return = new moodle_url('/admin/plugins.php');
         }
+        echo $OUTPUT->continue_button($return);
+        echo $OUTPUT->footer();
+        exit;
 }
 
 
index 61af243..19997a4 100644 (file)
       </PHP_SETTING>
     </PHP_SETTINGS>
   </MOODLE>
+  <MOODLE version="2.6" requires="2.2">
+    <UNICODE level="required">
+      <FEEDBACK>
+        <ON_ERROR message="unicoderequired" />
+      </FEEDBACK>
+    </UNICODE>
+    <DATABASE level="required">
+      <VENDOR name="mysql" version="5.1.33" />
+      <VENDOR name="postgres" version="8.3" />
+      <VENDOR name="mssql" version="9.0" />
+      <VENDOR name="oracle" version="10.2" />
+    </DATABASE>
+    <PHP version="5.3.3" level="required">
+    </PHP>
+    <PCREUNICODE level="optional">
+      <FEEDBACK>
+        <ON_CHECK message="pcreunicodewarning" />
+      </FEEDBACK>
+    </PCREUNICODE>
+    <PHP_EXTENSIONS>
+      <PHP_EXTENSION name="iconv" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="iconvrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="mbstring" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="mbstringrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="curl" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="curlrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="openssl" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="opensslrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="tokenizer" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="tokenizerrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="xmlrpc" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="xmlrpcrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="soap" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="soaprecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="ctype" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="ctyperequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="zip" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="ziprequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="gd" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="gdrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="simplexml" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="simplexmlrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="spl" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="splrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="pcre" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="dom" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="xml" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="intl" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="intlrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="json" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="hash" level="required"/>
+    </PHP_EXTENSIONS>
+    <PHP_SETTINGS>
+      <PHP_SETTING name="memory_limit" value="64M" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="settingmemorylimit" />
+        </FEEDBACK>
+      </PHP_SETTING>
+      <PHP_SETTING name="safe_mode" value="0" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="settingsafemode" />
+        </FEEDBACK>
+      </PHP_SETTING>
+      <PHP_SETTING name="file_uploads" value="1" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="settingfileuploads" />
+        </FEEDBACK>
+      </PHP_SETTING>
+    </PHP_SETTINGS>
+  </MOODLE>
 </COMPATIBILITY_MATRIX>
index c54e838..9acf551 100644 (file)
@@ -52,6 +52,12 @@ if (empty($_GET['cache']) and empty($_POST['cache'])) {
     // we redirect to self once we known no upgrades are necessary.
     // Note: $_GET and $_POST are used here intentionally because our param cleaning is not loaded yet.
     define('CACHE_DISABLE_ALL', true);
+
+    // Force OPcache reset if used, we do not want any stale caches
+    // when detecting if upgrade necessary or when running upgrade.
+    if (function_exists('opcache_reset')) {
+        opcache_reset();
+    }
 }
 
 require('../config.php');
index cd2f26e..12672b2 100644 (file)
@@ -33,48 +33,14 @@ require_once($CFG->libdir.'/tablelib.php');
 
 admin_externalpage_setup('managelocalplugins');
 
-$delete  = optional_param('delete', '', PARAM_PLUGIN);
-$confirm = optional_param('confirm', '', PARAM_BOOL);
-
-/// If data submitted, then process and store.
-
-if (!empty($delete) and confirm_sesskey()) {
-    echo $OUTPUT->header();
-    echo $OUTPUT->heading(get_string('localplugins'));
-
-    if (!$confirm) {
-        if (get_string_manager()->string_exists('pluginname', 'local_' . $delete)) {
-            $strpluginname = get_string('pluginname', 'local_' . $delete);
-        } else {
-            $strpluginname = $delete;
-        }
-        echo $OUTPUT->confirm(get_string('localplugindeleteconfirm', '', $strpluginname),
-                                new moodle_url($PAGE->url, array('delete' => $delete, 'confirm' => 1)),
-                                $PAGE->url);
-        echo $OUTPUT->footer();
-        die();
-
-    } else {
-        uninstall_plugin('local', $delete);
-        $a = new stdclass();
-        $a->name = $delete;
-        $pluginlocation = get_plugin_types();
-        $a->directory = $pluginlocation['local'] . '/' . $delete;
-        echo $OUTPUT->notification(get_string('plugindeletefiles', '', $a), 'notifysuccess');
-        echo $OUTPUT->continue_button($PAGE->url);
-        echo $OUTPUT->footer();
-        die();
-    }
-}
-
 echo $OUTPUT->header();
 echo $OUTPUT->heading(get_string('localplugins'));
 
 /// Print the table of all installed local plugins
 
 $table = new flexible_table('localplugins_administration_table');
-$table->define_columns(array('name', 'version', 'delete'));
-$table->define_headers(array(get_string('plugin'), get_string('version'), get_string('delete')));
+$table->define_columns(array('name', 'version', 'uninstall'));
+$table->define_headers(array(get_string('plugin'), get_string('version'), get_string('uninstallplugin', 'core_admin')));
 $table->define_baseurl($PAGE->url);
 $table->set_attribute('id', 'localplugins');
 $table->set_attribute('class', 'admintable generaltable');
@@ -92,8 +58,10 @@ foreach (get_plugin_list('local') as $plugin => $plugindir) {
 collatorlib::asort($plugins);
 
 foreach ($plugins as $plugin => $name) {
-    $delete = new moodle_url($PAGE->url, array('delete' => $plugin, 'sesskey' => sesskey()));
-    $delete = html_writer::link($delete, get_string('delete'));
+    $uninstall = '';
+    if ($uninstallurl = plugin_manager::instance()->get_uninstall_url('local_'.$plugin)) {
+        $uninstall = html_writer::link($uninstallurl, get_string('uninstallplugin', 'core_admin'));
+    }
 
     $version = get_config('local_' . $plugin);
     if (!empty($version->version)) {
@@ -102,7 +70,7 @@ foreach ($plugins as $plugin => $name) {
         $version = '?';
     }
 
-    $table->add_data(array($name, $version, $delete));
+    $table->add_data(array($name, $version, $uninstall));
 }
 
 $table->print_html();
index 33d2fbb..8eab4bc 100644 (file)
 
     $show    = optional_param('show', '', PARAM_PLUGIN);
     $hide    = optional_param('hide', '', PARAM_PLUGIN);
-    $delete  = optional_param('delete', '', PARAM_PLUGIN);
-    $confirm = optional_param('confirm', '', PARAM_BOOL);
 
 
 /// Print headings
 
     $stractivities = get_string("activities");
-    $strdelete = get_string("delete");
+    $struninstall = get_string('uninstallplugin', 'core_admin');
     $strversion = get_string("version");
     $strhide = get_string("hide");
     $strshow = get_string("show");
@@ -46,7 +44,7 @@
                  WHERE module=?";
         $DB->execute($sql, array($module->id));
         // clear the course modinfo cache for courses
-        // where we just deleted something
+        // where we just uninstalld something
         $sql = "UPDATE {course}
                    SET modinfo=''
                  WHERE id IN (SELECT DISTINCT course
         admin_get_root(true, false);  // settings not required - only pages
     }
 
-    if (!empty($delete) and confirm_sesskey()) {
-        echo $OUTPUT->header();
-        echo $OUTPUT->heading($stractivities);
-
-        if (get_string_manager()->string_exists('modulename', $delete)) {
-            $strmodulename = get_string('modulename', $delete);
-        } else {
-            $strmodulename = $delete;
-        }
-
-        if (!$confirm) {
-            echo $OUTPUT->confirm(get_string("moduledeleteconfirm", "", $strmodulename), "modules.php?delete=$delete&confirm=1", "modules.php");
-            echo $OUTPUT->footer();
-            exit;
-
-        } else {  // Delete everything!!
-
-            if ($delete == "forum") {
-                print_error("cannotdeleteforummodule", 'forum');
-            }
-
-            uninstall_plugin('mod', $delete);
-            $a = new stdClass();
-            $a->module = $strmodulename;
-            $a->directory = "$CFG->dirroot/mod/$delete";
-            echo $OUTPUT->notification(get_string("moduledeletefiles", "", $a), 'notifysuccess');
-            echo $OUTPUT->continue_button("modules.php");
-            echo $OUTPUT->footer();
-            exit;
-        }
-    }
-
     echo $OUTPUT->header();
     echo $OUTPUT->heading($stractivities);
 
 /// Print the table of all modules
     // construct the flexible table ready to display
     $table = new flexible_table(MODULE_TABLE);
-    $table->define_columns(array('name', 'instances', 'version', 'hideshow', 'delete', 'settings'));
-    $table->define_headers(array($stractivitymodule, $stractivities, $strversion, "$strhide/$strshow", $strdelete, $strsettings));
+    $table->define_columns(array('name', 'instances', 'version', 'hideshow', 'uninstall', 'settings'));
+    $table->define_headers(array($stractivitymodule, $stractivities, $strversion, "$strhide/$strshow", $struninstall, $strsettings));
     $table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/modules.php');
     $table->set_attribute('id', 'modules');
     $table->set_attribute('class', 'generaltable');
             $missing = false;
         }
 
-        $delete = "<a href=\"modules.php?delete=$module->name&amp;sesskey=".sesskey()."\">$strdelete</a>";
+        $uninstall = '';
+        if ($uninstallurl = plugin_manager::instance()->get_uninstall_url('mod_'.$module->name)) {
+            $uninstall = html_writer::link($uninstallurl, $struninstall);
+        }
 
         if (file_exists("$CFG->dirroot/mod/$module->name/settings.php") ||
                 file_exists("$CFG->dirroot/mod/$module->name/settingstree.php")) {
             $class =   ' class="dimmed_text"';
         }
         if ($module->name == "forum") {
-            $delete = "";
+            $uninstall = "";
             $visible = "";
             $class = "";
         }
             $countlink,
             '<span'.$class.'>'.$module->version.'</span>',
             $visible,
-            $delete,
+            $uninstall,
             $settings
         ));
     }
index 40ed3ae..db2cd2f 100644 (file)
@@ -18,7 +18,7 @@
  * Provides an overview of installed plagiarism plugins
  *
  * Displays the list of found plagiarism plugins, their version (if found) and
- * a link to delete the plagiarism plugin.
+ * a link to uninstall the plagiarism plugin.
  *
  * @see       http://docs.moodle.org/dev/Plagiarism_API
  * @package   admin
@@ -32,43 +32,12 @@ require_once($CFG->libdir.'/tablelib.php');
 
 admin_externalpage_setup('manageplagiarismplugins');
 
-$delete  = optional_param('delete', '', PARAM_PLUGIN);
-$confirm = optional_param('confirm', false, PARAM_BOOL);
-
-if (!empty($delete) and confirm_sesskey()) { // If data submitted, then process and store.
-    echo $OUTPUT->header();
-    echo $OUTPUT->heading(get_string('manageplagiarism', 'plagiarism'));
-
-    if (!$confirm) {
-        if (get_string_manager()->string_exists('pluginname', 'plagiarism_' . $delete)) {
-            $strpluginname = get_string('pluginname', 'plagiarism_' . $delete);
-        } else {
-            $strpluginname = $delete;
-        }
-        echo $OUTPUT->confirm(get_string('plagiarismplugindeleteconfirm', 'plagiarism', $strpluginname),
-            new moodle_url($PAGE->url, array('delete' => $delete, 'confirm' => 1)),
-            $PAGE->url);
-        echo $OUTPUT->footer();
-        die();
-
-    } else {
-        uninstall_plugin('plagiarism', $delete);
-        $a = new stdclass();
-        $a->name = $delete;
-        $pluginlocation = get_plugin_types();
-        $a->directory = $pluginlocation['plagiarism'] . '/' . $delete;
-        echo $OUTPUT->notification(get_string('plugindeletefiles', '', $a), 'notifysuccess');
-        echo $OUTPUT->continue_button($PAGE->url);
-        echo $OUTPUT->footer();
-        die();
-    }
-}
-
 echo $OUTPUT->header();
 
 // Print the table of all installed plagiarism plugins.
 
-$txt = get_strings(array('settings', 'name', 'version', 'delete'));
+$txt = get_strings(array('settings', 'name', 'version'));
+$txt->uninstall = get_string('uninstallplugin', 'core_admin');
 
 $plagiarismplugins = get_plugin_list('plagiarism');
 if (empty($plagiarismplugins)) {
@@ -81,7 +50,7 @@ echo $OUTPUT->heading(get_string('availableplugins', 'plagiarism'), 3, 'main');
 echo $OUTPUT->box_start('generalbox authsui');
 
 $table = new html_table();
-$table->head  = array($txt->name, $txt->version, $txt->delete, $txt->settings);
+$table->head  = array($txt->name, $txt->version, $txt->uninstall, $txt->settings);
 $table->colclasses = array('mdl-left', 'mdl-align', 'mdl-align', 'mdl-align');
 $table->data  = array();
 $table->attributes['class'] = 'manageplagiarismtable generaltable';
@@ -101,10 +70,12 @@ foreach ($plagiarismplugins as $plugin => $dir) {
         } else {
             $version = '?';
         }
-        // Delete link.
-        $delete = new moodle_url($PAGE->url, array('delete' => $plugin, 'sesskey' => sesskey()));
-        $delete = html_writer::link($delete, get_string('delete'));
-        $table->data[] = array($displayname, $version, $delete, $settings);
+        // uninstall link.
+        $uninstall = '';
+        if ($uninstallurl = plugin_manager::instance()->get_uninstall_url('plagiarism_'.$plugin)) {
+            $uninstall = html_writer::link($uninstallurl, $txt->uninstall);
+        }
+        $table->data[] = array($displayname, $version, $uninstall, $settings);
     }
 }
 echo html_writer::table($table);
index 08157df..8ceba12 100644 (file)
@@ -85,10 +85,18 @@ if ($uninstall) {
         if ($pluginman->is_plugin_folder_removable($pluginfo->component)) {
             $continueurl = new moodle_url($PAGE->url, array('delete' => $pluginfo->component, 'sesskey' => sesskey(), 'confirm' => 1));
             echo $output->plugin_uninstall_results_removable_page($pluginman, $pluginfo, $progress, $continueurl);
+            // Reset op code caches.
+            if (function_exists('opcache_reset')) {
+                opcache_reset();
+            }
             exit();
 
         } else {
             echo $output->plugin_uninstall_results_page($pluginman, $pluginfo, $progress);
+            // Reset op code caches.
+            if (function_exists('opcache_reset')) {
+                opcache_reset();
+            }
             exit();
         }
     }
@@ -131,7 +139,10 @@ if ($delete and $confirmed) {
 
     // So long, and thanks for all the bugs.
     fulldelete($pluginfo->rootdir);
-    cache::make('core', 'pluginlist')->purge();
+    // Reset op code caches.
+    if (function_exists('opcache_reset')) {
+        opcache_reset();
+    }
     redirect($PAGE->url);
 }
 
index e708152..68cdb49 100644 (file)
@@ -375,7 +375,7 @@ class core_admin_renderer extends plugin_renderer_base {
      * Display a page to confirm the plugin uninstallation.
      *
      * @param plugin_manager $pluginman
-     * @param plugin_info $pluginfo
+     * @param plugininfo_base $pluginfo
      * @param moodle_url $continueurl URL to continue after confirmation
      * @return string
      */
@@ -384,10 +384,14 @@ class core_admin_renderer extends plugin_renderer_base {
 
         $pluginname = $pluginman->plugin_name($pluginfo->component);
 
+        $confirm = '<p>' . get_string('uninstallconfirm', 'core_plugin', array('name' => $pluginname)) . '</p>';
+        if ($extraconfirm = $pluginfo->get_uninstall_extra_warning()) {
+            $confirm .= $extraconfirm;
+        }
+
         $output .= $this->output->header();
         $output .= $this->output->heading(get_string('uninstalling', 'core_plugin', array('name' => $pluginname)));
-        $output .= $this->output->confirm(get_string('uninstallconfirm', 'core_plugin', array('name' => $pluginname)),
-            $continueurl, $this->page->url);
+        $output .= $this->output->confirm($confirm, $continueurl, $this->page->url);
         $output .= $this->output->footer();
 
         return $output;
@@ -397,7 +401,7 @@ class core_admin_renderer extends plugin_renderer_base {
      * Display a page with results of plugin uninstallation and offer removal of plugin files.
      *
      * @param plugin_manager $pluginman
-     * @param plugin_info $pluginfo
+     * @param plugininfo_base $pluginfo
      * @param progress_trace_buffer $progress
      * @param moodle_url $continueurl URL to continue to remove the plugin folder
      * @return string
@@ -431,7 +435,7 @@ class core_admin_renderer extends plugin_renderer_base {
      * Display a page with results of plugin uninstallation and inform about the need to remove plugin files manually.
      *
      * @param plugin_manager $pluginman
-     * @param plugin_info $pluginfo
+     * @param plugininfo_base $pluginfo
      * @param progress_trace_buffer $progress
      * @return string
      */
index e03c928..19fafdb 100644 (file)
@@ -18,7 +18,7 @@
  * Provides an overview of installed reports
  *
  * Displays the list of found reports, their version (if found) and
- * a link to delete the report.
+ * a link to uninstall the report.
  *
  * The code is based on admin/localplugins.php by David Mudrak.
  *
@@ -33,48 +33,16 @@ require_once($CFG->libdir.'/tablelib.php');
 
 admin_externalpage_setup('managereports');
 
-$delete  = optional_param('delete', '', PARAM_PLUGIN);
-$confirm = optional_param('confirm', '', PARAM_BOOL);
-
-/// If data submitted, then process and store.
-
-if (!empty($delete) and confirm_sesskey()) {
-    echo $OUTPUT->header();
-    echo $OUTPUT->heading(get_string('reports'));
-
-    if (!$confirm) {
-        if (get_string_manager()->string_exists('pluginname', 'report_' . $delete)) {
-            $strpluginname = get_string('pluginname', 'report_' . $delete);
-        } else {
-            $strpluginname = $delete;
-        }
-        echo $OUTPUT->confirm(get_string('reportsdeleteconfirm', 'admin', $strpluginname),
-                                new moodle_url($PAGE->url, array('delete' => $delete, 'confirm' => 1)),
-                                $PAGE->url);
-        echo $OUTPUT->footer();
-        die();
-
-    } else {
-        uninstall_plugin('report', $delete);
-        $a = new stdclass();
-        $a->name = $delete;
-        $pluginlocation = get_plugin_types();
-        $a->directory = $pluginlocation['report'] . '/' . $delete;
-        echo $OUTPUT->notification(get_string('plugindeletefiles', '', $a), 'notifysuccess');
-        echo $OUTPUT->continue_button($PAGE->url);
-        echo $OUTPUT->footer();
-        die();
-    }
-}
-
 echo $OUTPUT->header();
 echo $OUTPUT->heading(get_string('reports'));
 
 /// Print the table of all installed report plugins
 
+$struninstall = get_string('uninstallplugin', 'core_admin');
+
 $table = new flexible_table('reportplugins_administration_table');
-$table->define_columns(array('name', 'version', 'delete'));
-$table->define_headers(array(get_string('plugin'), get_string('version'), get_string('delete')));
+$table->define_columns(array('name', 'version', 'uninstall'));
+$table->define_headers(array(get_string('plugin'), get_string('version'), $struninstall));
 $table->define_baseurl($PAGE->url);
 $table->set_attribute('id', 'reportplugins');
 $table->set_attribute('class', 'generaltable generalbox boxaligncenter boxwidthwide');
@@ -104,8 +72,10 @@ foreach ($installed as $config) {
 }
 
 foreach ($plugins as $plugin => $name) {
-    $delete = new moodle_url($PAGE->url, array('delete' => $plugin, 'sesskey' => sesskey()));
-    $delete = html_writer::link($delete, get_string('delete'));
+    $uninstall = '';
+    if ($uninstallurl = plugin_manager::instance()->get_uninstall_url('report_'.$plugin)) {
+        $uninstall = html_writer::link($uninstallurl, $struninstall);
+    }
 
     if (!isset($versions[$plugin])) {
         if (file_exists("$CFG->dirroot/report/$plugin/version.php")) {
@@ -126,7 +96,7 @@ foreach ($plugins as $plugin => $name) {
         }
     }
 
-    $table->add_data(array($name, $version, $delete));
+    $table->add_data(array($name, $version, $uninstall));
 }
 
 $table->print_html();
index 1f5a8fe..57833b6 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-
 // This file is part of Moodle - http://moodle.org/
 //
 // Moodle is free software: you can redistribute it and/or modify
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * Lets you site administrators
+ * Select site administrators.
  *
- * @package    core
- * @subpackage role
- * @copyright  2010 Petr Skoda (skodak) http://skodak.org
+ * @package    core_role
+ * @copyright  2010 Petr Skoda {@link http://skodak.org}
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-require_once(dirname(__FILE__) . '/../../config.php');
-require_once($CFG->dirroot . '/' . $CFG->admin . '/roles/lib.php');
+require_once(__DIR__ . '/../../config.php');
+require_once($CFG->libdir.'/adminlib.php');
 
 $confirmadd = optional_param('confirmadd', 0, PARAM_INT);
 $confirmdel = optional_param('confirmdel', 0, PARAM_INT);
@@ -37,10 +35,10 @@ if (!is_siteadmin()) {
     die;
 }
 
-$admisselector = new admins_existing_selector();
+$admisselector = new core_role_admins_existing_selector();
 $admisselector->set_extra_fields(array('username', 'email'));
 
-$potentialadmisselector = new admins_potential_selector();
+$potentialadmisselector = new core_role_admins_potential_selector();
 $potentialadmisselector->set_extra_fields(array('username', 'email'));
 
 if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
@@ -48,7 +46,8 @@ if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
         $user = reset($userstoadd);
         $username = fullname($user) . " ($user->username, $user->email)";
         echo $OUTPUT->header();
-        echo $OUTPUT->confirm(get_string('confirmaddadmin', 'role', $username), new moodle_url('/admin/roles/admins.php', array('confirmadd'=>$user->id, 'sesskey'=>sesskey())), $PAGE->url);
+        $yesurl = new moodle_url('/admin/roles/admins.php', array('confirmadd'=>$user->id, 'sesskey'=>sesskey()));
+        echo $OUTPUT->confirm(get_string('confirmaddadmin', 'core_role', $username), $yesurl, $PAGE->url);
         echo $OUTPUT->footer();
         die;
     }
@@ -57,11 +56,12 @@ if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
     if ($userstoremove = $admisselector->get_selected_users()) {
         $user = reset($userstoremove);
         if ($USER->id == $user->id) {
-            //can not remove self
+            // Can not remove self.
         } else {
             $username = fullname($user) . " ($user->username, $user->email)";
             echo $OUTPUT->header();
-            echo $OUTPUT->confirm(get_string('confirmdeladmin', 'role', $username), new moodle_url('/admin/roles/admins.php', array('confirmdel'=>$user->id, 'sesskey'=>sesskey())), $PAGE->url);
+            $yesurl = new moodle_url('/admin/roles/admins.php', array('confirmdel'=>$user->id, 'sesskey'=>sesskey()));
+            echo $OUTPUT->confirm(get_string('confirmdeladmin', 'core_role', $username), $yesurl, $PAGE->url);
             echo $OUTPUT->footer();
             die;
         }
@@ -72,7 +72,7 @@ if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
         $newmain = reset($newmain);
         $newmain = $newmain->id;
         $admins = array();
-        foreach(explode(',', $CFG->siteadmins) as $admin) {
+        foreach (explode(',', $CFG->siteadmins) as $admin) {
             $admin = (int)$admin;
             if ($admin) {
                 $admins[$admin] = $admin;
@@ -89,7 +89,7 @@ if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
 
 } else if ($confirmadd and confirm_sesskey()) {
     $admins = array();
-    foreach(explode(',', $CFG->siteadmins) as $admin) {
+    foreach (explode(',', $CFG->siteadmins) as $admin) {
         $admin = (int)$admin;
         if ($admin) {
             $admins[$admin] = $admin;
@@ -101,7 +101,7 @@ if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
 
 } else if ($confirmdel and confirm_sesskey() and $confirmdel != $USER->id) {
     $admins = array();
-    foreach(explode(',', $CFG->siteadmins) as $admin) {
+    foreach (explode(',', $CFG->siteadmins) as $admin) {
         $admin = (int)$admin;
         if ($admin) {
             $admins[$admin] = $admin;
@@ -112,12 +112,12 @@ if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
     redirect($PAGE->url);
 }
 
-/// Print header
+// Print header.
 echo $OUTPUT->header();
 ?>
 
 <div id="addadmisform">
-    <h3 class="main"><?php print_string('manageadmins', 'role'); ?></h3>
+    <h3 class="main"><?php print_string('manageadmins', 'core_role'); ?></h3>
 
     <form id="assignform" method="post" action="<?php echo $PAGE->url ?>">
     <div>
@@ -127,18 +127,18 @@ echo $OUTPUT->header();
     <tr>
       <td id='existingcell'>
           <p>
-            <label for="removeselect"><?php print_string('existingadmins', 'role'); ?></label>
+            <label for="removeselect"><?php print_string('existingadmins', 'core_role'); ?></label>
           </p>
           <?php $admisselector->display(); ?>
           </td>
-      <td id='buttonscell'>
+      <td id="buttonscell">
         <p class="arrow_button">
             <input name="add" id="add" type="submit" value="<?php echo $OUTPUT->larrow().'&nbsp;'.get_string('add'); ?>" title="<?php print_string('add'); ?>" /><br />
             <input name="remove" id="remove" type="submit" value="<?php echo get_string('remove').'&nbsp;'.$OUTPUT->rarrow(); ?>" title="<?php print_string('remove'); ?>" />
-            <input name="main" id="main" type="submit" value="<?php echo get_string('mainadminset', 'role'); ?>" title="<?php print_string('mainadminset', 'role'); ?>" />
+            <input name="main" id="main" type="submit" value="<?php echo get_string('mainadminset', 'core_role'); ?>" title="<?php print_string('mainadminset', 'core_role'); ?>" />
         </p>
       </td>
-      <td id='potentialcell'>
+      <td id="potentialcell">
           <p>
             <label for="addselect"><?php print_string('users'); ?></label>
           </p>
@@ -152,7 +152,4 @@ echo $OUTPUT->header();
 
 <?php
 
-//this must be after calling display() on the selectors so their setup JS executes first
-//////$PAGE->requires->js_function_call('init_add_remove_admis_page');
-
 echo $OUTPUT->footer();
index 37ac157..9b7e709 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-
 // This file is part of Moodle - http://moodle.org/
 //
 // Moodle is free software: you can redistribute it and/or modify
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * Allow overriding of roles by other roles
+ * Allow overriding of roles by other roles.
  *
- * @package    core
- * @subpackage role
+ * @package    core_role
  * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 require_once(dirname(__FILE__) . '/../../config.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->dirroot . '/' . $CFG->admin . '/roles/lib.php');
 
 $mode = required_param('mode', PARAM_ALPHANUMEXT);
 $classformode = array(
-    'assign' => 'role_allow_assign_page',
-    'override' => 'role_allow_override_page',
-    'switch' => 'role_allow_switch_page'
+    'assign' => 'core_role_allow_assign_page',
+    'override' => 'core_role_allow_override_page',
+    'switch' => 'core_role_allow_switch_page'
 );
 if (!isset($classformode[$mode])) {
     print_error('invalidmode', '', '', $mode);
@@ -48,7 +45,7 @@ $controller = new $classformode[$mode]();
 
 if (optional_param('submit', false, PARAM_BOOL) && data_submitted() && confirm_sesskey()) {
     $controller->process_submission();
-    mark_context_dirty($syscontext->path);
+    $syscontext->mark_dirty();
     add_to_log(SITEID, 'role', 'edit allow ' . $mode, str_replace($CFG->wwwroot . '/', '', $baseurl), '', '', $USER->id);
     redirect($baseurl);
 }
index 4b7cef8..ee212b1 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-
 // This file is part of Moodle - http://moodle.org/
 //
 // Moodle is free software: you can redistribute it and/or modify
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * Lets you assign roles to users in a particular context.
+ * Assign roles to users.
  *
- * @package    core
- * @subpackage role
+ * @package    core_role
  * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-require_once(dirname(__FILE__) . '/../../config.php');
+require_once(__DIR__ . '/../../config.php');
 require_once($CFG->dirroot . '/' . $CFG->admin . '/roles/lib.php');
 
 define("MAX_USERS_TO_LIST_PER_ROLE", 10);
 
-$contextid      = required_param('contextid',PARAM_INT);
-$roleid         = optional_param('roleid', 0, PARAM_INT);
+$contextid = required_param('contextid', PARAM_INT);
+$roleid    = optional_param('roleid', 0, PARAM_INT);
 
 list($context, $course, $cm) = get_context_info_array($contextid);
 
@@ -51,20 +49,20 @@ if ($course) {
 }
 
 
-// security
+// Security.
 require_login($course, false, $cm);
 require_capability('moodle/role:assign', $context);
 $PAGE->set_url($url);
 $PAGE->set_context($context);
 
-$contextname = print_context_name($context);
+$contextname = $context->get_context_name();
 $courseid = $course->id;
 
-// These are needed early because of tabs.php
+// These are needed early because of tabs.php.
 list($assignableroles, $assigncounts, $nameswithcounts) = get_assignable_roles($context, ROLENAME_BOTH, true);
 $overridableroles = get_overridable_roles($context, ROLENAME_BOTH);
 
-// Make sure this user can assign this role
+// Make sure this user can assign this role.
 if ($roleid && !isset($assignableroles[$roleid])) {
     $a = new stdClass;
     $a->roleid = $roleid;
@@ -77,12 +75,12 @@ if ($roleid) {
     $a = new stdClass;
     $a->role = $assignableroles[$roleid];
     $a->context = $contextname;
-    $title = get_string('assignrolenameincontext', 'role', $a);
+    $title = get_string('assignrolenameincontext', 'core_role', $a);
 } else {
     if ($isfrontpage) {
         $title = get_string('frontpageroles', 'admin');
     } else {
-        $title = get_string('assignrolesin', 'role', $contextname);
+        $title = get_string('assignrolesin', 'core_role', $contextname);
     }
 }
 
@@ -92,10 +90,10 @@ if ($roleid) {
     // Create the user selector objects.
     $options = array('context' => $context, 'roleid' => $roleid);
 
-    $potentialuserselector = roles_get_potential_user_selector($context, 'addselect', $options);
-    $currentuserselector = new existing_role_holders('removeselect', $options);
+    $potentialuserselector = core_role_get_potential_user_selector($context, 'addselect', $options);
+    $currentuserselector = new core_role_existing_role_holders('removeselect', $options);
 
-    // Process incoming role assignments
+    // Process incoming role assignments.
     $errors = array();
     if (optional_param('add', false, PARAM_BOOL) && confirm_sesskey()) {
         $userstoassign = $potentialuserselector->get_selected_users();
@@ -119,13 +117,13 @@ if ($roleid) {
         }
     }
 
-    // Process incoming role unassignments
+    // Process incoming role unassignments.
     if (optional_param('remove', false, PARAM_BOOL) && confirm_sesskey()) {
         $userstounassign = $currentuserselector->get_selected_users();
         if (!empty($userstounassign)) {
 
             foreach ($userstounassign as $removeuser) {
-                //unassign only roles that are added manually, no messing with other components!!!
+                // Unassign only roles that are added manually, no messing with other components!!!
                 role_unassign($roleid, $removeuser->id, $context->id, '');
             }
 
@@ -145,6 +143,7 @@ $PAGE->set_title($title);
 
 switch ($context->contextlevel) {
     case CONTEXT_SYSTEM:
+        require_once($CFG->libdir.'/adminlib.php');
         admin_externalpage_setup('assignroles', '', array('contextid' => $contextid, 'roleid' => $roleid));
         break;
     case CONTEXT_USER:
@@ -157,13 +156,14 @@ switch ($context->contextlevel) {
         break;
     case CONTEXT_COURSE:
         if ($isfrontpage) {
+            require_once($CFG->libdir.'/adminlib.php');
             admin_externalpage_setup('frontpageroles', '', array('contextid' => $contextid, 'roleid' => $roleid));
         } else {
             $PAGE->set_heading($course->fullname);
         }
         break;
     case CONTEXT_MODULE:
-        $PAGE->set_heading(print_context_name($context, false));
+        $PAGE->set_heading($context->get_context_name(false));
         $PAGE->set_cacheable(false);
         break;
     case CONTEXT_BLOCK:
@@ -174,17 +174,17 @@ switch ($context->contextlevel) {
 echo $OUTPUT->header();
 
 // Print heading.
-echo $OUTPUT->heading_with_help($title, 'assignroles', 'role');
+echo $OUTPUT->heading_with_help($title, 'assignroles', 'core_role');
 
 if ($roleid) {
     // Show UI for assigning a particular role to users.
     // Print a warning if we are assigning system roles.
     if ($context->contextlevel == CONTEXT_SYSTEM) {
-        echo $OUTPUT->box(get_string('globalroleswarning', 'role'));
+        echo $OUTPUT->box(get_string('globalroleswarning', 'core_role'));
     }
 
     // Print the form.
-$assignurl = new moodle_url($PAGE->url, array('roleid'=>$roleid));
+    $assignurl = new moodle_url($PAGE->url, array('roleid'=>$roleid));
 ?>
 <form id="assignform" method="post" action="<?php echo $assignurl ?>"><div>
   <input type="hidden" name="sesskey" value="<?php echo sesskey() ?>" />
@@ -192,7 +192,7 @@ $assignurl = new moodle_url($PAGE->url, array('roleid'=>$roleid));
   <table id="assigningrole" summary="" class="admintable roleassigntable generaltable" cellspacing="0">
     <tr>
       <td id="existingcell">
-          <p><label for="removeselect"><?php print_string('extusers', 'role'); ?></label></p>
+          <p><label for="removeselect"><?php print_string('extusers', 'core_role'); ?></label></p>
           <?php $currentuserselector->display() ?>
       </td>
       <td id="buttonscell">
@@ -205,7 +205,7 @@ $assignurl = new moodle_url($PAGE->url, array('roleid'=>$roleid));
           </div>
       </td>
       <td id="potentialcell">
-          <p><label for="addselect"><?php print_string('potusers', 'role'); ?></label></p>
+          <p><label for="addselect"><?php print_string('potusers', 'core_role'); ?></label></p>
           <?php $potentialuserselector->display() ?>
       </td>
     </tr>
@@ -230,31 +230,31 @@ $assignurl = new moodle_url($PAGE->url, array('roleid'=>$roleid));
     echo '<div class="backlink">';
 
     $select = new single_select($PAGE->url, 'roleid', $nameswithcounts, $roleid, null);
-    $select->label = get_string('assignanotherrole', 'role');
+    $select->label = get_string('assignanotherrole', 'core_role');
     echo $OUTPUT->render($select);
     $backurl = new moodle_url('/admin/roles/assign.php', array('contextid' => $contextid));
-    echo '<p><a href="' . $backurl->out() . '">' . get_string('backtoallroles', 'role') . '</a></p>';
+    echo '<p><a href="' . $backurl->out() . '">' . get_string('backtoallroles', 'core_role') . '</a></p>';
     echo '</div>';
 
 } else if (empty($assignableroles)) {
     // Print a message that there are no roles that can me assigned here.
-    echo $OUTPUT->heading(get_string('notabletoassignroleshere', 'role'), 3);
+    echo $OUTPUT->heading(get_string('notabletoassignroleshere', 'core_role'), 3);
 
 } else {
     // Show UI for choosing a role to assign.
 
     // Print a warning if we are assigning system roles.
     if ($context->contextlevel == CONTEXT_SYSTEM) {
-        echo $OUTPUT->box(get_string('globalroleswarning', 'role'));
+        echo $OUTPUT->box(get_string('globalroleswarning', 'core_role'));
     }
 
-    // Print instruction
-    echo $OUTPUT->heading(get_string('chooseroletoassign', 'role'), 3);
+    // Print instruction.
+    echo $OUTPUT->heading(get_string('chooseroletoassign', 'core_role'), 3);
 
     // Get the names of role holders for roles with between 1 and MAX_USERS_TO_LIST_PER_ROLE users,
     // and so determine whether to show the extra column.
     $roleholdernames = array();
-    $strmorethanmax = get_string('morethan', 'role', MAX_USERS_TO_LIST_PER_ROLE);
+    $strmorethanmax = get_string('morethan', 'core_role', MAX_USERS_TO_LIST_PER_ROLE);
     $showroleholders = false;
     foreach ($assignableroles as $roleid => $notused) {
         $roleusers = '';
@@ -276,10 +276,10 @@ $assignurl = new moodle_url($PAGE->url, array('roleid'=>$roleid));
         }
     }
 
-    // Print overview table
+    // Print overview table.
     $table = new html_table();
     $table->id = 'assignrole';
-    $table->head = array(get_string('role'), get_string('description'), get_string('userswiththisrole', 'role'));
+    $table->head = array(get_string('role'), get_string('description'), get_string('userswiththisrole', 'core_role'));
     $table->colclasses = array('leftalign role', 'leftalign', 'centeralign userrole');
     $table->attributes['class'] = 'admintable generaltable';
     if ($showroleholders) {
@@ -302,7 +302,7 @@ $assignurl = new moodle_url($PAGE->url, array('roleid'=>$roleid));
 
     if ($context->contextlevel > CONTEXT_USER) {
         echo html_writer::start_tag('div', array('class'=>'backlink'));
-        echo html_writer::tag('a', get_string('backto', '', $contextname), array('href'=>get_context_url($context)));
+        echo html_writer::tag('a', get_string('backto', '', $contextname), array('href'=>$context->get_url()));
         echo html_writer::end_tag('div');
     }
 }
index d3917b0..0590165 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-
 // This file is part of Moodle - http://moodle.org/
 //
 // Moodle is free software: you can redistribute it and/or modify
 /**
  * Shows the result of has_capability for every capability for a user in a context.
  *
- * @package    core
- * @subpackage role
+ * @package    core_role
  * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 require_once(dirname(__FILE__) . '/../../config.php');
-require_once($CFG->dirroot . '/' . $CFG->admin . '/roles/lib.php');
 
-$contextid = required_param('contextid',PARAM_INT);
+$contextid = required_param('contextid', PARAM_INT);
 
 list($context, $course, $cm) = get_context_info_array($contextid);
 
@@ -47,32 +44,33 @@ if ($course) {
     }
 }
 
-// security first
+// Security first.
 require_login($course, false, $cm);
 if (!has_any_capability(array('moodle/role:assign', 'moodle/role:safeoverride', 'moodle/role:override', 'moodle/role:manage'), $context)) {
-    print_error('nopermissions', 'error', '', get_string('checkpermissions', 'role'));
+    print_error('nopermissions', 'error', '', get_string('checkpermissions', 'core_role'));
 }
 $PAGE->set_url($url);
 $PAGE->set_context($context);
 
 $courseid = $course->id;
-$contextname = print_context_name($context);
+$contextname = $context->get_context_name();
 
 // Get the user_selector we will need.
 // Teachers within a course just get to see the same list of enrolled users.
 // Admins (people with moodle/role:manage) can run this report for any user.
 $options = array('accesscontext' => $context);
-$userselector = new role_check_users_selector('reportuser', $options);
+$userselector = new core_role_check_users_selector('reportuser', $options);
 $userselector->set_rows(20);
 
 // Work out an appropriate page title.
-$title = get_string('checkpermissionsin', 'role', $contextname);
+$title = get_string('checkpermissionsin', 'core_role', $contextname);
 
 $PAGE->set_pagelayout('admin');
 $PAGE->set_title($title);
 
 switch ($context->contextlevel) {
     case CONTEXT_SYSTEM:
+        require_once($CFG->libdir.'/adminlib.php');
         admin_externalpage_setup('checkpermissions', '', array('contextid' => $contextid));
         break;
     case CONTEXT_USER:
@@ -85,13 +83,14 @@ switch ($context->contextlevel) {
         break;
     case CONTEXT_COURSE:
         if ($isfrontpage) {
+            require_once($CFG->libdir.'/adminlib.php');
             admin_externalpage_setup('frontpageroles', '', array('contextid' => $contextid), $CFG->wwwroot . '/' . $CFG->admin . '/roles/check.php');
         } else {
             $PAGE->set_heading($course->fullname);
         }
         break;
     case CONTEXT_MODULE:
-        $PAGE->set_heading(print_context_name($context, false));
+        $PAGE->set_heading($context->get_context_name(false));
         $PAGE->set_cacheable(false);
         break;
     case CONTEXT_BLOCK:
@@ -117,7 +116,7 @@ if (!is_null($reportuser)) {
     echo $OUTPUT->box_start('generalbox boxaligncenter boxwidthwide');
 
     if (!empty($roleassignments)) {
-        echo $OUTPUT->heading(get_string('rolesforuser', 'role', fullname($reportuser)), 3);
+        echo $OUTPUT->heading(get_string('rolesforuser', 'core_role', fullname($reportuser)), 3);
         echo html_writer::start_tag('ul');
 
         $systemcontext = context_system::instance();
@@ -131,20 +130,20 @@ if (!is_null($reportuser)) {
                         array('action' => 'view', 'roleid' => $ra->roleid)), $rolename);
             }
 
-            echo html_writer::tag('li', get_string('roleincontext', 'role',
+            echo html_writer::tag('li', get_string('roleincontext', 'core_role',
                     array('role' => $rolename, 'context' => $link)));
         }
         echo html_writer::end_tag('ul');
     }
 
-    echo $OUTPUT->heading(get_string('permissionsforuser', 'role', fullname($reportuser)), 3);
-    $table = new check_capability_table($context, $reportuser, $contextname);
+    echo $OUTPUT->heading(get_string('permissionsforuser', 'core_role', fullname($reportuser)), 3);
+    $table = new core_role_check_capability_table($context, $reportuser, $contextname);
     $table->display();
     echo $OUTPUT->box_end();
 
-    $selectheading = get_string('selectanotheruser', 'role');
+    $selectheading = get_string('selectanotheruser', 'core_role');
 } else {
-    $selectheading = get_string('selectauser', 'role');
+    $selectheading = get_string('selectauser', 'core_role');
 }
 
 // Show UI for choosing a user to report on.
@@ -165,14 +164,14 @@ echo $OUTPUT->heading('<label for="reportuser">' . $selectheading . '</label>',
 $userselector->display();
 
 // Submit button and the end of the form.
-echo '<p id="chooseusersubmit"><input type="submit" value="' . get_string('showthisuserspermissions', 'role') . '" /></p>';
+echo '<p id="chooseusersubmit"><input type="submit" value="' . get_string('showthisuserspermissions', 'core_role') . '" /></p>';
 echo '</form>';
 echo $OUTPUT->box_end();
 
 // Appropriate back link.
 if ($context->contextlevel > CONTEXT_USER) {
     echo html_writer::start_tag('div', array('class'=>'backlink'));
-    echo html_writer::tag('a', get_string('backto', '', $contextname), array('href'=>get_context_url($context)));
+    echo html_writer::tag('a', get_string('backto', '', $contextname), array('href'=>$context->get_url()));
     echo html_writer::end_tag('div');
 }
 
diff --git a/admin/roles/classes/admins_existing_selector.php b/admin/roles/classes/admins_existing_selector.php
new file mode 100644 (file)
index 0000000..9389919
--- /dev/null
@@ -0,0 +1,98 @@
+<?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/>.
+
+/**
+ * Existing admin user selector.
+ *
+ * @package    core_role
+ * @copyright  2010 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->dirroot.'/user/selector/lib.php');
+
+class core_role_admins_existing_selector extends user_selector_base {
+    /**
+     * Create instance.
+     *
+     * @param string $name control name
+     * @param array $options should have two elements with keys groupid and courseid.
+     */
+    public function __construct($name = null, $options = array()) {
+        if (is_null($name)) {
+            $name = 'removeselect';
+        }
+        $options['multiselect'] = false;
+        parent::__construct($name, $options);
+    }
+
+    public function find_users($search) {
+        global $DB, $CFG;
+        list($wherecondition, $params) = $this->search_sql($search, '');
+
+        $fields      = 'SELECT ' . $this->required_fields_sql('');
+
+        if ($wherecondition) {
+            $wherecondition = "$wherecondition AND id IN ($CFG->siteadmins)";
+        } else {
+            $wherecondition = "id IN ($CFG->siteadmins)";
+        }
+        $sql = " FROM {user}
+                WHERE $wherecondition";
+
+        list($sort, $sortparams) = users_order_by_sql('', $search, $this->accesscontext);
+        $params = array_merge($params, $sortparams);
+        $order = ' ORDER BY ' . $sort;
+
+        $availableusers = $DB->get_records_sql($fields . $sql . $order, $params);
+
+        if (empty($availableusers)) {
+            return array();
+        }
+
+        $mainadmin = array();
+        $mainadminuser = get_admin();
+        if ($mainadminuser && isset($availableusers[$mainadminuser->id])) {
+            $mainadmin = array($mainadminuser->id => $availableusers[$mainadminuser->id]);
+            unset($availableusers[$mainadminuser->id]);
+        }
+
+        $result = array();
+        if ($mainadmin) {
+            $result[get_string('mainadmin', 'core_role')] = $mainadmin;
+        }
+
+        if ($availableusers) {
+            if ($search) {
+                $groupname = get_string('extusersmatching', 'core_role', $search);
+            } else {
+                $groupname = get_string('extusers', 'core_role');
+            }
+            $result[$groupname] = $availableusers;
+        }
+
+        return $result;
+    }
+
+    protected function get_options() {
+        global $CFG;
+        $options = parent::get_options();
+        $options['file'] = $CFG->admin . '/roles/lib.php';
+        return $options;
+    }
+}
diff --git a/admin/roles/classes/admins_potential_selector.php b/admin/roles/classes/admins_potential_selector.php
new file mode 100644 (file)
index 0000000..f80295d
--- /dev/null
@@ -0,0 +1,91 @@
+<?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/>.
+
+/**
+ * Potential admin user selector.
+ *
+ * @package    core_role
+ * @copyright  2010 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->dirroot.'/user/selector/lib.php');
+
+class core_role_admins_potential_selector extends user_selector_base {
+    /**
+     * Create instance.
+     *
+     * @param string $name control name
+     * @param array $options should have two elements with keys groupid and courseid.
+     */
+    public function __construct($name = null, $options = array()) {
+        global $CFG;
+        if (is_null($name)) {
+            $name = 'addselect';
+        }
+        $options['multiselect'] = false;
+        $options['exclude'] = explode(',', $CFG->siteadmins);
+        parent::__construct($name, $options);
+    }
+
+    public function find_users($search) {
+        global $CFG, $DB;
+        list($wherecondition, $params) = $this->search_sql($search, '');
+
+        $fields      = 'SELECT ' . $this->required_fields_sql('');
+        $countfields = 'SELECT COUNT(1)';
+
+        $sql = " FROM {user}
+                WHERE $wherecondition AND mnethostid = :localmnet";
+
+        // It could be dangerous to make remote users admins and also this could lead to other problems.
+        $params['localmnet'] = $CFG->mnet_localhost_id;
+
+        list($sort, $sortparams) = users_order_by_sql('', $search, $this->accesscontext);
+        $order = ' ORDER BY ' . $sort;
+
+        // Check to see if there are too many to show sensibly.
+        if (!$this->is_validating()) {
+            $potentialcount = $DB->count_records_sql($countfields . $sql, $params);
+            if ($potentialcount > $this->maxusersperpage) {
+                return $this->too_many_results($search, $potentialcount);
+            }
+        }
+
+        $availableusers = $DB->get_records_sql($fields . $sql . $order, array_merge($params, $sortparams));
+
+        if (empty($availableusers)) {
+            return array();
+        }
+
+        if ($search) {
+            $groupname = get_string('potusersmatching', 'core_role', $search);
+        } else {
+            $groupname = get_string('potusers', 'core_role');
+        }
+
+        return array($groupname => $availableusers);
+    }
+
+    protected function get_options() {
+        global $CFG;
+        $options = parent::get_options();
+        $options['file'] = $CFG->admin . '/roles/lib.php';
+        return $options;
+    }
+}
diff --git a/admin/roles/classes/allow_assign_page.php b/admin/roles/classes/allow_assign_page.php
new file mode 100644 (file)
index 0000000..8d31cc0
--- /dev/null
@@ -0,0 +1,49 @@
+<?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/>.
+
+/**
+ * Role assign matrix.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Subclass of role_allow_role_page for the Allow assigns tab.
+ */
+class core_role_allow_assign_page extends core_role_allow_role_page {
+    public function __construct() {
+        parent::__construct('role_allow_assign', 'allowassign');
+    }
+
+    protected function set_allow($fromroleid, $targetroleid) {
+        allow_assign($fromroleid, $targetroleid);
+    }
+
+    protected function get_cell_tooltip($fromrole, $targetrole) {
+        $a = new stdClass;
+        $a->fromrole = $fromrole->localname;
+        $a->targetrole = $targetrole->localname;
+        return get_string('allowroletoassign', 'core_role', $a);
+    }
+
+    public function get_intro_text() {
+        return get_string('configallowassign', 'core_admin');
+    }
+}
diff --git a/admin/roles/classes/allow_override_page.php b/admin/roles/classes/allow_override_page.php
new file mode 100644 (file)
index 0000000..a277abb
--- /dev/null
@@ -0,0 +1,49 @@
+<?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/>.
+
+/**
+ * Role override matrix.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Subclass of role_allow_role_page for the Allow overrides tab.
+ */
+class core_role_allow_override_page extends core_role_allow_role_page {
+    public function __construct() {
+        parent::__construct('role_allow_override', 'allowoverride');
+    }
+
+    protected function set_allow($fromroleid, $targetroleid) {
+        allow_override($fromroleid, $targetroleid);
+    }
+
+    protected function get_cell_tooltip($fromrole, $targetrole) {
+        $a = new stdClass;
+        $a->fromrole = $fromrole->localname;
+        $a->targetrole = $targetrole->localname;
+        return get_string('allowroletooverride', 'core_role', $a);
+    }
+
+    public function get_intro_text() {
+        return get_string('configallowoverride2', 'core_admin');
+    }
+}
diff --git a/admin/roles/classes/allow_role_page.php b/admin/roles/classes/allow_role_page.php
new file mode 100644 (file)
index 0000000..c84d01a
--- /dev/null
@@ -0,0 +1,164 @@
+<?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/>.
+
+/**
+ * Base class for allow matrices.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Base class for managing the data in the grid of checkboxes on the role allow
+ * allow/overrides/switch editing pages (allow.php).
+ */
+abstract class core_role_allow_role_page {
+    protected $tablename;
+    protected $targetcolname;
+    protected $roles;
+    protected $allowed = null;
+
+    /**
+     * Constructor.
+     *
+     * @param string $tablename the table where our data is stored.
+     * @param string $targetcolname the name of the target role id column.
+     */
+    public function __construct($tablename, $targetcolname) {
+        $this->tablename = $tablename;
+        $this->targetcolname = $targetcolname;
+        $this->load_required_roles();
+    }
+
+    /**
+     * Load information about all the roles we will need information about.
+     */
+    protected function load_required_roles() {
+        // Get all roles.
+        $this->roles = role_fix_names(get_all_roles(), context_system::instance(), ROLENAME_ORIGINAL);
+    }
+
+    /**
+     * Update the data with the new settings submitted by the user.
+     */
+    public function process_submission() {
+        global $DB;
+        // Delete all records, then add back the ones that should be allowed.
+        $DB->delete_records($this->tablename);
+        foreach ($this->roles as $fromroleid => $notused) {
+            foreach ($this->roles as $targetroleid => $alsonotused) {
+                if (optional_param('s_' . $fromroleid . '_' . $targetroleid, false, PARAM_BOOL)) {
+                    $this->set_allow($fromroleid, $targetroleid);
+                }
+            }
+        }
+    }
+
+    /**
+     * Set one allow in the database.
+     * @param int $fromroleid
+     * @param int $targetroleid
+     */
+    protected abstract function set_allow($fromroleid, $targetroleid);
+
+    /**
+     * Load the current allows from the database.
+     */
+    public function load_current_settings() {
+        global $DB;
+        // Load the current settings.
+        $this->allowed = array();
+        foreach ($this->roles as $role) {
+            // Make an array $role->id => false. This is probably too clever for its own good.
+            $this->allowed[$role->id] = array_combine(array_keys($this->roles), array_fill(0, count($this->roles), false));
+        }
+        $rs = $DB->get_recordset($this->tablename);
+        foreach ($rs as $allow) {
+            $this->allowed[$allow->roleid][$allow->{$this->targetcolname}] = true;
+        }
+        $rs->close();
+    }
+
+    /**
+     * Is target allowed?
+     *
+     * @param integer $targetroleid a role id.
+     * @return boolean whether the user should be allowed to select this role as a target role.
+     */
+    protected function is_allowed_target($targetroleid) {
+        return true;
+    }
+
+    /**
+     * Returns structure that can be passed to print_table,
+     * containing one cell for each checkbox.
+     * @return html_table a table
+     */
+    public function get_table() {
+        $table = new html_table();
+        $table->tablealign = 'center';
+        $table->cellpadding = 5;
+        $table->cellspacing = 0;
+        $table->width = '90%';
+        $table->align = array('left');
+        $table->rotateheaders = true;
+        $table->head = array('&#xa0;');
+        $table->colclasses = array('');
+
+        // Add role name headers.
+        foreach ($this->roles as $targetrole) {
+            $table->head[] = $targetrole->localname;
+            $table->align[] = 'left';
+            if ($this->is_allowed_target($targetrole->id)) {
+                $table->colclasses[] = '';
+            } else {
+                $table->colclasses[] = 'dimmed_text';
+            }
+        }
+
+        // Now the rest of the table.
+        foreach ($this->roles as $fromrole) {
+            $row = array($fromrole->localname);
+            foreach ($this->roles as $targetrole) {
+                $checked = '';
+                $disabled = '';
+                if ($this->allowed[$fromrole->id][$targetrole->id]) {
+                    $checked = 'checked="checked" ';
+                }
+                if (!$this->is_allowed_target($targetrole->id)) {
+                    $disabled = 'disabled="disabled" ';
+                }
+                $name = 's_' . $fromrole->id . '_' . $targetrole->id;
+                $tooltip = $this->get_cell_tooltip($fromrole, $targetrole);
+                $row[] = '<input type="checkbox" name="' . $name . '" id="' . $name .
+                    '" title="' . $tooltip . '" value="1" ' . $checked . $disabled . '/>' .
+                    '<label for="' . $name . '" class="accesshide">' . $tooltip . '</label>';
+            }
+            $table->data[] = $row;
+        }
+
+        return $table;
+    }
+
+    /**
+     * Snippet of text displayed above the table, telling the admin what to do.
+     * @return string
+     */
+    public abstract function get_intro_text();
+}
diff --git a/admin/roles/classes/allow_switch_page.php b/admin/roles/classes/allow_switch_page.php
new file mode 100644 (file)
index 0000000..934bda3
--- /dev/null
@@ -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/>.
+
+/**
+ * Role witch matrix.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Subclass of role_allow_role_page for the Allow switches tab.
+ */
+class core_role_allow_switch_page extends core_role_allow_role_page {
+    protected $allowedtargetroles;
+
+    public function __construct() {
+        parent::__construct('role_allow_switch', 'allowswitch');
+    }
+
+    protected function load_required_roles() {
+        global $DB;
+        parent::load_required_roles();
+        $this->allowedtargetroles = $DB->get_records_menu('role', null, 'id');
+    }
+
+    protected function set_allow($fromroleid, $targetroleid) {
+        allow_switch($fromroleid, $targetroleid);
+    }
+
+    protected function is_allowed_target($targetroleid) {
+        return isset($this->allowedtargetroles[$targetroleid]);
+    }
+
+    protected function get_cell_tooltip($fromrole, $targetrole) {
+        $a = new stdClass;
+        $a->fromrole = $fromrole->localname;
+        $a->targetrole = $targetrole->localname;
+        return get_string('allowroletoswitch', 'core_role', $a);
+    }
+
+    public function get_intro_text() {
+        return get_string('configallowswitch', 'core_admin');
+    }
+}
diff --git a/admin/roles/classes/assign_user_selector_base.php b/admin/roles/classes/assign_user_selector_base.php
new file mode 100644 (file)
index 0000000..e1fcf00
--- /dev/null
@@ -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/>.
+
+/**
+ * Library code used by the roles administration interfaces.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->dirroot.'/user/selector/lib.php');
+
+/**
+ * Base class to avoid duplicating code.
+ */
+abstract class core_role_assign_user_selector_base extends user_selector_base {
+    protected $roleid;
+    protected $context;
+
+    /**
+     * @param string $name control name
+     * @param array $options should have two elements with keys groupid and courseid.
+     */
+    public function __construct($name, $options) {
+        global $CFG;
+        if (isset($options['context'])) {
+            $this->context = $options['context'];
+        } else {
+            $this->context = context::instance_by_id($options['contextid']);
+        }
+        $options['accesscontext'] = $this->context;
+        parent::__construct($name, $options);
+        $this->roleid = $options['roleid'];
+        require_once($CFG->dirroot . '/group/lib.php');
+    }
+
+    protected function get_options() {
+        global $CFG;
+        $options = parent::get_options();
+        $options['file'] = $CFG->admin . '/roles/lib.php';
+        $options['roleid'] = $this->roleid;
+        $options['contextid'] = $this->context->id;
+        return $options;
+    }
+}
diff --git a/admin/roles/classes/capability_table_base.php b/admin/roles/classes/capability_table_base.php
new file mode 100644 (file)
index 0000000..9c9d7f9
--- /dev/null
@@ -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/>.
+
+/**
+ * Base capability table.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * This class represents a table with one row for each of a list of capabilities
+ * where the first cell in the row contains the capability name, and there is
+ * arbitrary stuff in the rest of the row. This class is used by
+ * admin/roles/manage.php, override.php and check.php.
+ *
+ * An ajaxy search UI shown at the top, if JavaScript is on.
+ */
+abstract class core_role_capability_table_base {
+    /** The context this table relates to. */
+    protected $context;
+
+    /** The capabilities to display. Initialised as fetch_context_capabilities($context). */
+    protected $capabilities = array();
+
+    /** Added as an id="" attribute to the table on output. */
+    protected $id;
+
+    /** Added to the class="" attribute on output. */
+    protected $classes = array('rolecap');
+
+    /** Default number of capabilities in the table for the search UI to be shown. */
+    const NUM_CAPS_FOR_SEARCH = 12;
+
+    /**
+     * Constructor.
+     * @param context $context the context this table relates to.
+     * @param string $id what to put in the id="" attribute.
+     */
+    public function __construct(context $context, $id) {
+        $this->context = $context;
+        $this->capabilities = $context->get_capabilities();
+        $this->id = $id;
+    }
+
+    /**
+     * Use this to add class="" attributes to the table. You get the rolecap by
+     * default.
+     * @param array $classnames of class names.
+     */
+    public function add_classes($classnames) {
+        $this->classes = array_unique(array_merge($this->classes, $classnames));
+    }
+
+    /**
+     * Display the table.
+     */
+    public function display() {
+        if (count($this->capabilities) > self::NUM_CAPS_FOR_SEARCH) {
+            global $PAGE;
+            $PAGE->requires->strings_for_js(array('filter', 'clear'), 'moodle');
+            $PAGE->requires->js_init_call('M.core_role.init_cap_table_filter', array($this->id, $this->context->id));
+        }
+        echo '<table class="' . implode(' ', $this->classes) . '" id="' . $this->id . '">' . "\n<thead>\n";
+        echo '<tr><th class="name" align="left" scope="col">' . get_string('capability', 'core_role') . '</th>';
+        $this->add_header_cells();
+        echo "</tr>\n</thead>\n<tbody>\n";
+
+        // Loop over capabilities.
+        $contextlevel = 0;
+        $component = '';
+        foreach ($this->capabilities as $capability) {
+            if ($this->skip_row($capability)) {
+                continue;
+            }
+
+            // Prints a breaker if component or name or context level has changed.
+            if (component_level_changed($capability, $component, $contextlevel)) {
+                $this->print_heading_row($capability);
+            }
+            $contextlevel = $capability->contextlevel;
+            $component = $capability->component;
+
+            // Start the row.
+            echo '<tr class="' . implode(' ', array_unique(array_merge(array('rolecap'),
+                    $this->get_row_classes($capability)))) . '">';
+
+            // Table cell for the capability name.
+            echo '<th scope="row" class="name"><span class="cap-desc">' . get_capability_docs_link($capability) .
+                '<span class="cap-name">' . $capability->name . '</span></span></th>';
+
+            // Add the cells specific to this table.
+            $this->add_row_cells($capability);
+
+            // End the row.
+            echo "</tr>\n";
+        }
+
+        // End of the table.
+        echo "</tbody>\n</table>\n";
+    }
+
+    /**
+     * Used to output a heading rows when the context level or component changes.
+     * @param stdClass $capability gives the new component and contextlevel.
+     */
+    protected function print_heading_row($capability) {
+        echo '<tr class="rolecapheading header"><td colspan="' . (1 + $this->num_extra_columns()) . '" class="header"><strong>' .
+            get_component_string($capability->component, $capability->contextlevel) .
+            '</strong></td></tr>';
+
+    }
+
+    /**
+     * For subclasses to override, output header cells, after the initial capability one.
+     */
+    protected abstract function add_header_cells();
+
+    /**
+     * For subclasses to override, return the number of cells that add_header_cells/add_row_cells output.
+     */
+    protected abstract function num_extra_columns();
+
+    /**
+     * For subclasses to override. Allows certain capabilties
+     * to be left out of the table.
+     *
+     * @param object $capability the capability this row relates to.
+     * @return boolean. If true, this row is omitted from the table.
+     */
+    protected function skip_row($capability) {
+        return false;
+    }
+
+    /**
+     * For subclasses to override. A change to reaturn class names that are added
+     * to the class="" attribute on the &lt;tr> for this capability.
+     *
+     * @param stdClass $capability the capability this row relates to.
+     * @return array of class name strings.
+     */
+    protected function get_row_classes($capability) {
+        return array();
+    }
+
+    /**
+     * For subclasses to override. Output the data cells for this capability. The
+     * capability name cell will already have been output.
+     *
+     * You can rely on get_row_classes always being called before add_row_cells.
+     *
+     * @param stdClass $capability the capability this row relates to.
+     */
+    protected abstract function add_row_cells($capability);
+}
diff --git a/admin/roles/classes/capability_table_with_risks.php b/admin/roles/classes/capability_table_with_risks.php
new file mode 100644 (file)
index 0000000..5fd57dd
--- /dev/null
@@ -0,0 +1,193 @@
+<?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/>.
+
+/**
+ * Capabilities table with risks.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * This subclass is the bases for both the define roles and override roles
+ * pages. As well as adding the risks columns, this also provides generic
+ * facilities for showing a certain number of permissions columns, and
+ * recording the current and submitted permissions for each capability.
+ */
+abstract class core_role_capability_table_with_risks extends core_role_capability_table_base {
+    protected $allrisks;
+    protected $allpermissions; // We don't need perms ourselves, but all our subclasses do.
+    protected $strperms; // Language string cache.
+    protected $risksurl; // URL in moodledocs about risks.
+    protected $riskicons = array(); // Cache to avoid regenerating the HTML for each risk icon.
+    /** @var array The capabilities to highlight as default/inherited. */
+    protected $parentpermissions;
+    protected $displaypermissions;
+    protected $permissions;
+    protected $changed;
+    protected $roleid;
+
+    public function __construct($context, $id, $roleid) {
+        parent::__construct($context, $id);
+
+        $this->allrisks = get_all_risks();
+        $this->risksurl = get_docs_url(s(get_string('risks', 'core_role')));
+
+        $this->allpermissions = array(
+            CAP_INHERIT => 'inherit',
+            CAP_ALLOW => 'allow',
+            CAP_PREVENT => 'prevent' ,
+            CAP_PROHIBIT => 'prohibit',
+        );
+
+        $this->strperms = array();
+        foreach ($this->allpermissions as $permname) {
+            $this->strperms[$permname] =  get_string($permname, 'core_role');
+        }
+
+        $this->roleid = $roleid;
+        $this->load_current_permissions();
+
+        // Fill in any blank permissions with an explicit CAP_INHERIT, and init a locked field.
+        foreach ($this->capabilities as $capid => $cap) {
+            if (!isset($this->permissions[$cap->name])) {
+                $this->permissions[$cap->name] = CAP_INHERIT;
+            }
+            $this->capabilities[$capid]->locked = false;
+        }
+    }
+
+    protected function load_current_permissions() {
+        global $DB;
+
+        // Load the overrides/definition in this context.
+        if ($this->roleid) {
+            $this->permissions = $DB->get_records_menu('role_capabilities', array('roleid' => $this->roleid,
+                'contextid' => $this->context->id), '', 'capability,permission');
+        } else {
+            $this->permissions = array();
+        }
+    }
+
+    protected abstract function load_parent_permissions();
+
+    /**
+     * Update $this->permissions based on submitted data, while making a list of
+     * changed capabilities in $this->changed.
+     */
+    public function read_submitted_permissions() {
+        $this->changed = array();
+
+        foreach ($this->capabilities as $cap) {
+            if ($cap->locked || $this->skip_row($cap)) {
+                // The user is not allowed to change the permission for this capability.
+                continue;
+            }
+
+            $permission = optional_param($cap->name, null, PARAM_PERMISSION);
+            if (is_null($permission)) {
+                // A permission was not specified in submitted data.
+                continue;
+            }
+
+            // If the permission has changed, update $this->permissions and
+            // Record the fact there is data to save.
+            if ($this->permissions[$cap->name] != $permission) {
+                $this->permissions[$cap->name] = $permission;
+                $this->changed[] = $cap->name;
+            }
+        }
+    }
+
+    /**
+     * Save the new values of any permissions that have been changed.
+     */
+    public function save_changes() {
+        // Set the permissions.
+        foreach ($this->changed as $changedcap) {
+            assign_capability($changedcap, $this->permissions[$changedcap],
+                $this->roleid, $this->context->id, true);
+        }
+
+        // Force accessinfo refresh for users visiting this context.
+        $this->context->mark_dirty();
+    }
+
+    public function display() {
+        $this->load_parent_permissions();
+        foreach ($this->capabilities as $cap) {
+            if (!isset($this->parentpermissions[$cap->name])) {
+                $this->parentpermissions[$cap->name] = CAP_INHERIT;
+            }
+        }
+        parent::display();
+    }
+
+    protected function add_header_cells() {
+        global $OUTPUT;
+        echo '<th colspan="' . count($this->displaypermissions) . '" scope="col">' .
+            get_string('permission', 'core_role') . ' ' . $OUTPUT->help_icon('permission', 'core_role') . '</th>';
+        echo '<th class="risk" colspan="' . count($this->allrisks) . '" scope="col">' . get_string('risks', 'core_role') . '</th>';
+    }
+
+    protected function num_extra_columns() {
+        return count($this->displaypermissions) + count($this->allrisks);
+    }
+
+    protected function get_row_classes($capability) {
+        $rowclasses = array();
+        foreach ($this->allrisks as $riskname => $risk) {
+            if ($risk & (int)$capability->riskbitmask) {
+                $rowclasses[] = $riskname;
+            }
+        }
+        return $rowclasses;
+    }
+
+    protected abstract function add_permission_cells($capability);
+
+    protected function add_row_cells($capability) {
+        $this->add_permission_cells($capability);
+        // One cell for each possible risk.
+        foreach ($this->allrisks as $riskname => $risk) {
+            echo '<td class="risk ' . str_replace('risk', '', $riskname) . '">';
+            if ($risk & (int)$capability->riskbitmask) {
+                echo $this->get_risk_icon($riskname);
+            }
+            echo '</td>';
+        }
+    }
+
+    /**
+     * Print a risk icon, as a link to the Risks page on Moodle Docs.
+     *
+     * @param string $type the type of risk, will be one of the keys from the
+     *      get_all_risks array. Must start with 'risk'.
+     */
+    public function get_risk_icon($type) {
+        global $OUTPUT;
+        if (!isset($this->riskicons[$type])) {
+            $iconurl = $OUTPUT->pix_url('i/' . str_replace('risk', 'risk_', $type));
+            $text = '<img src="' . $iconurl . '" alt="' . get_string($type . 'short', 'admin') . '" />';
+            $action = new popup_action('click', $this->risksurl, 'docspopup');
+            $this->riskicons[$type] = $OUTPUT->action_link($this->risksurl, $text, $action, array('title'=>get_string($type, 'admin')));
+        }
+        return $this->riskicons[$type];
+    }
+}
diff --git a/admin/roles/classes/check_capability_table.php b/admin/roles/classes/check_capability_table.php
new file mode 100644 (file)
index 0000000..de9eaae
--- /dev/null
@@ -0,0 +1,84 @@
+<?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/>.
+
+/**
+ * Library code used by the roles administration interfaces.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Subclass of core_role_capability_table_base for use on the Check permissions page.
+ *
+ * We have one additional column, Allowed, which contains yes/no.
+ */
+class core_role_check_capability_table extends core_role_capability_table_base {
+    protected $user;
+    protected $fullname;
+    protected $contextname;
+    protected $stryes;
+    protected $strno;
+    private $hascap;
+
+    /**
+     * Constructor
+     * @param object $context the context this table relates to.
+     * @param object $user the user we are generating the results for.
+     * @param string $contextname print_context_name($context) - to save recomputing.
+     */
+    public function __construct($context, $user, $contextname) {
+        parent::__construct($context, 'explaincaps');
+        $this->user = $user;
+        $this->fullname = fullname($user);
+        $this->contextname = $contextname;
+        $this->stryes = get_string('yes');
+        $this->strno = get_string('no');
+    }
+
+    protected function add_header_cells() {
+        echo '<th>' . get_string('allowed', 'core_role') . '</th>';
+    }
+
+    protected function num_extra_columns() {
+        return 1;
+    }
+
+    protected function get_row_classes($capability) {
+        $this->hascap = has_capability($capability->name, $this->context, $this->user->id);
+        if ($this->hascap) {
+            return array('yes');
+        } else {
+            return array('no');
+        }
+    }
+
+    protected function add_row_cells($capability) {
+        if ($this->hascap) {
+            $result = $this->stryes;
+        } else {
+            $result = $this->strno;
+        }
+        $a = new stdClass;
+        $a->fullname = $this->fullname;
+        $a->capability = $capability->name;
+        $a->context = $this->contextname;
+        echo '<td>' . $result . '</td>';
+    }
+}
diff --git a/admin/roles/classes/check_users_selector.php b/admin/roles/classes/check_users_selector.php
new file mode 100644 (file)
index 0000000..5ac4c26
--- /dev/null
@@ -0,0 +1,153 @@
+<?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/>.
+
+/**
+ * User selector.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->dirroot.'/user/selector/lib.php');
+
+/**
+ * User selector subclass for the selection of users in the check permissions page.
+ *
+ * @copyright 2012 Petr Skoda {@link http://skodak.org}
+ */
+class core_role_check_users_selector extends user_selector_base {
+    /** @var bool limit listing of users to enrolled only */
+    protected $onlyenrolled;
+
+    /**
+     * Constructor.
+     *
+     * @param string $name the control name/id for use in the HTML.
+     * @param array $options other options needed to construct this selector.
+     * You must be able to clone a userselector by doing new get_class($us)($us->get_name(), $us->get_options());
+     */
+    public function __construct($name, $options) {
+        if (!isset($options['multiselect'])) {
+            $options['multiselect'] = false;
+        }
+        parent::__construct($name, $options);
+
+        $coursecontext = $this->accesscontext->get_course_context(false);
+        if ($coursecontext and $coursecontext->id != SITEID and !has_capability('moodle/role:manage', $coursecontext)) {
+            // Prevent normal teachers from looking up all users.
+            $this->onlyenrolled = true;
+        } else {
+            $this->onlyenrolled = false;
+        }
+    }
+
+    public function find_users($search) {
+        global $DB;
+
+        list($wherecondition, $params) = $this->search_sql($search, 'u');
+
+        $fields      = 'SELECT ' . $this->required_fields_sql('u');
+        $countfields = 'SELECT COUNT(1)';
+
+        $coursecontext = $this->accesscontext->get_course_context(false);
+
+        if ($coursecontext and $coursecontext != SITEID) {
+            $sql1 = " FROM {user} u
+                      JOIN {user_enrolments} ue ON (ue.userid = u.id)
+                      JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid1)
+                     WHERE $wherecondition";
+            $params['courseid1'] = $coursecontext->instanceid;
+
+            if ($this->onlyenrolled) {
+                $sql2 = null;
+            } else {
+                $sql2 = " FROM {user} u
+                     LEFT JOIN ({user_enrolments} ue
+                                JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid2)) ON (ue.userid = u.id)
+                         WHERE $wherecondition
+                               AND ue.id IS NULL";
+                $params['courseid2'] = $coursecontext->instanceid;
+            }
+
+        } else {
+            if ($this->onlyenrolled) {
+                // Bad luck, current user may not view only enrolled users.
+                return array();
+            }
+            $sql1 = null;
+            $sql2 = " FROM {user} u
+                     WHERE $wherecondition";
+        }
+
+        $params['contextid'] = $this->accesscontext->id;
+
+        list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext);
+        $order = ' ORDER BY ' . $sort;
+
+        $result = array();
+
+        if ($search) {
+            $groupname1 = get_string('enrolledusersmatching', 'enrol', $search);
+            $groupname2 = get_string('potusersmatching', 'core_role', $search);
+        } else {
+            $groupname1 = get_string('enrolledusers', 'enrol');
+            $groupname2 = get_string('potusers', 'core_role');
+        }
+
+        if ($sql1) {
+            $enrolleduserscount = $DB->count_records_sql($countfields . $sql1, $params);
+            if (!$this->is_validating() and $enrolleduserscount > $this->maxusersperpage) {
+                $result[$groupname1] = array();
+                $toomany = $this->too_many_results($search, $enrolleduserscount);
+                $result[implode(' - ', array_keys($toomany))] = array();
+
+            } else {
+                $enrolledusers = $DB->get_records_sql($fields . $sql1 . $order, array_merge($params, $sortparams));
+                if ($enrolledusers) {
+                    $result[$groupname1] = $enrolledusers;
+                }
+            }
+            if ($sql2) {
+                $result[''] = array();
+            }
+        }
+        if ($sql2) {
+            $otheruserscount = $DB->count_records_sql($countfields . $sql2, $params);
+            if (!$this->is_validating() and $otheruserscount > $this->maxusersperpage) {
+                $result[$groupname2] = array();
+                $toomany = $this->too_many_results($search, $otheruserscount);
+                $result[implode(' - ', array_keys($toomany))] = array();
+            } else {
+                $otherusers = $DB->get_records_sql($fields . $sql2 . $order, array_merge($params, $sortparams));
+                if ($otherusers) {
+                    $result[$groupname2] = $otherusers;
+                }
+            }
+        }
+
+        return $result;
+    }
+
+    protected function get_options() {
+        global $CFG;
+        $options = parent::get_options();
+        $options['file'] = $CFG->admin . '/roles/lib.php';
+        return $options;
+    }
+}
diff --git a/admin/roles/classes/define_role_table_advanced.php b/admin/roles/classes/define_role_table_advanced.php
new file mode 100644 (file)
index 0000000..496df3e
--- /dev/null
@@ -0,0 +1,649 @@
+<?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/>.
+
+/**
+ * Advanced role definition form.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+
+/**
+ * As well as tracking the permissions information about the role we are creating
+ * or editing, we also track the other information about the role. (This class is
+ * starting to be more and more like a formslib form in some respects.)
+ */
+class core_role_define_role_table_advanced extends core_role_capability_table_with_risks {
+    /** @var stdClass Used to store other information (besides permissions) about the role we are creating/editing. */
+    protected $role;
+    /** @var array Used to store errors found when validating the data. */
+    protected $errors;
+    protected $contextlevels;
+    protected $allcontextlevels;
+    protected $disabled = '';
+
+    protected $allowassign;
+    protected $allowoverride;
+    protected $allowswitch;
+
+    public function __construct($context, $roleid) {
+        $this->roleid = $roleid;
+        parent::__construct($context, 'defineroletable', $roleid);
+        $this->displaypermissions = $this->allpermissions;
+        $this->strperms[$this->allpermissions[CAP_INHERIT]] = get_string('notset', 'core_role');
+
+        $this->allcontextlevels = array(
+            CONTEXT_SYSTEM => get_string('coresystem'),
+            CONTEXT_USER => get_string('user'),
+            CONTEXT_COURSECAT => get_string('category'),
+            CONTEXT_COURSE => get_string('course'),
+            CONTEXT_MODULE => get_string('activitymodule'),
+            CONTEXT_BLOCK => get_string('block')
+        );
+    }
+
+    protected function load_current_permissions() {
+        global $DB;
+        if ($this->roleid) {
+            if (!$this->role = $DB->get_record('role', array('id' => $this->roleid))) {
+                throw new moodle_exception('invalidroleid');
+            }
+            $contextlevels = get_role_contextlevels($this->roleid);
+            // Put the contextlevels in the array keys, as well as the values.
+            if (!empty($contextlevels)) {
+                $this->contextlevels = array_combine($contextlevels, $contextlevels);
+            } else {
+                $this->contextlevels = array();
+            }
+            $this->allowassign = array_keys($this->get_allow_roles_list('assign'));
+            $this->allowoverride = array_keys($this->get_allow_roles_list('override'));
+            $this->allowswitch = array_keys($this->get_allow_roles_list('switch'));
+
+        } else {
+            $this->role = new stdClass;
+            $this->role->name = '';
+            $this->role->shortname = '';
+            $this->role->description = '';
+            $this->role->archetype = '';
+            $this->contextlevels = array();
+            $this->allowassign = array();
+            $this->allowoverride = array();
+            $this->allowswitch = array();
+        }
+        parent::load_current_permissions();
+    }
+
+    public function read_submitted_permissions() {
+        global $DB;
+        $this->errors = array();
+
+        // Role short name. We clean this in a special way. We want to end up
+        // with only lowercase safe ASCII characters.
+        $shortname = optional_param('shortname', null, PARAM_RAW);
+        if (!is_null($shortname)) {
+            $this->role->shortname = $shortname;
+            $this->role->shortname = textlib::specialtoascii($this->role->shortname);
+            $this->role->shortname = textlib::strtolower(clean_param($this->role->shortname, PARAM_ALPHANUMEXT));
+            if (empty($this->role->shortname)) {
+                $this->errors['shortname'] = get_string('errorbadroleshortname', 'core_role');
+            }
+        }
+        if ($DB->record_exists_select('role', 'shortname = ? and id <> ?', array($this->role->shortname, $this->roleid))) {
+            $this->errors['shortname'] = get_string('errorexistsroleshortname', 'core_role');
+        }
+
+        // Role name.
+        $name = optional_param('name', null, PARAM_TEXT);
+        if (!is_null($name)) {
+            $this->role->name = $name;
+            // Hack: short names of standard roles are equal to archetypes, empty name means localised via lang packs.
+            $archetypes = get_role_archetypes();
+            if (!isset($archetypes[$shortname]) and html_is_blank($this->role->name)) {
+                $this->errors['name'] = get_string('errorbadrolename', 'core_role');
+            }
+        }
+        if ($this->role->name !== '' and $DB->record_exists_select('role', 'name = ? and id <> ?', array($this->role->name, $this->roleid))) {
+            $this->errors['name'] = get_string('errorexistsrolename', 'core_role');
+        }
+
+        // Description.
+        $description = optional_param('description', null, PARAM_RAW);
+        if (!is_null($description)) {
+            $this->role->description = $description;
+        }
+
+        // Legacy type.
+        $archetype = optional_param('archetype', null, PARAM_RAW);
+        if (isset($archetype)) {
+            $archetypes = get_role_archetypes();
+            if (isset($archetypes[$archetype])) {
+                $this->role->archetype = $archetype;
+            } else {
+                $this->role->archetype = '';
+            }
+        }
+
+        // Assignable context levels.
+        foreach ($this->allcontextlevels as $cl => $notused) {
+            $assignable = optional_param('contextlevel' . $cl, null, PARAM_BOOL);
+            if (!is_null($assignable)) {
+                if ($assignable) {
+                    $this->contextlevels[$cl] = $cl;
+                } else {
+                    unset($this->contextlevels[$cl]);
+                }
+            }
+        }
+
+        // Allowed roles.
+        $allow = optional_param_array('allowassign', null, PARAM_INT);
+        if (!is_null($allow)) {
+            $this->allowassign = $allow;
+        }
+        $allow = optional_param_array('allowoverride', null, PARAM_INT);
+        if (!is_null($allow)) {
+            $this->allowoverride = $allow;
+        }
+        $allow = optional_param_array('allowswitch', null, PARAM_INT);
+        if (!is_null($allow)) {
+            $this->allowswitch = $allow;
+        }
+
+        // Now read the permissions for each capability.
+        parent::read_submitted_permissions();
+    }
+
+    public function is_submission_valid() {
+        return empty($this->errors);
+    }
+
+    /**
+     * Call this after the table has been initialised,
+     * this resets everything to that role.
+     *
+     * @param int $roleid role id or 0 for no role
+     * @param array $options array with following keys:
+     *      'name', 'shortname', 'description', 'permissions', 'archetype',
+     *      'contextlevels', 'allowassign', 'allowoverride', 'allowswitch'
+     */
+    public function force_duplicate($roleid, array $options) {
+        global $DB;
+
+        if ($roleid == 0) {
+            // This means reset to nothing == remove everything.
+
+            if ($options['shortname']) {
+                $this->role->shortname = '';
+            }
+
+            if ($options['name']) {
+                $this->role->name = '';
+            }
+
+            if ($options['description']) {
+                $this->role->description = '';
+            }
+
+            if ($options['archetype']) {
+                $this->role->archetype = '';
+            }
+
+            if ($options['contextlevels']) {
+                $this->contextlevels = array();
+            }
+
+            if ($options['allowassign']) {
+                $this->allowassign = array();
+            }
+            if ($options['allowoverride']) {
+                $this->allowoverride = array();
+            }
+            if ($options['allowswitch']) {
+                $this->allowswitch = array();
+            }
+
+            if ($options['permissions']) {
+                foreach ($this->capabilities as $capid => $cap) {
+                    $this->permissions[$cap->name] = CAP_INHERIT;
+                }
+            }
+
+            return;
+        }
+
+        $role = $DB->get_record('role', array('id'=>$roleid), '*', MUST_EXIST);
+
+        if ($options['shortname']) {
+            $this->role->shortname = $role->shortname;
+        }
+
+        if ($options['name']) {
+            $this->role->name = $role->name;
+        }
+
+        if ($options['description']) {
+            $this->role->description = $role->description;
+        }
+
+        if ($options['archetype']) {
+            $this->role->archetype = $role->archetype;
+        }
+
+        if ($options['contextlevels']) {
+            $this->contextlevels = array();
+            $levels = get_role_contextlevels($roleid);
+            foreach ($levels as $cl) {
+                $this->contextlevels[$cl] = $cl;
+            }
+        }
+
+        if ($options['allowassign']) {
+            $this->allowassign = array_keys($this->get_allow_roles_list('assign', $roleid));
+        }
+        if ($options['allowoverride']) {
+            $this->allowoverride = array_keys($this->get_allow_roles_list('override', $roleid));
+        }
+        if ($options['allowswitch']) {
+            $this->allowswitch = array_keys($this->get_allow_roles_list('switch', $roleid));
+        }
+
+        if ($options['permissions']) {
+            $this->permissions = $DB->get_records_menu('role_capabilities',
+                array('roleid' => $roleid, 'contextid' => context_system::instance()->id),
+                '', 'capability,permission');
+
+            foreach ($this->capabilities as $capid => $cap) {
+                if (!isset($this->permissions[$cap->name])) {
+                    $this->permissions[$cap->name] = CAP_INHERIT;
+                }
+            }
+        }
+    }
+
+    /**
+     * Change the role definition to match given archetype.
+     *
+     * @param string $archetype
+     * @param array $options array with following keys:
+     *      'name', 'shortname', 'description', 'permissions', 'archetype',
+     *      'contextlevels', 'allowassign', 'allowoverride', 'allowswitch'
+     */
+    public function force_archetype($archetype, array $options) {
+        $archetypes = get_role_archetypes();
+        if (!isset($archetypes[$archetype])) {
+            throw new coding_exception('Unknown archetype: '.$archetype);
+        }
+
+        if ($options['shortname']) {
+            $this->role->shortname = '';
+        }
+
+        if ($options['name']) {
+            $this->role->name = '';
+        }
+
+        if ($options['description']) {
+            $this->role->description = '';
+        }
+
+        if ($options['archetype']) {
+            $this->role->archetype = $archetype;
+        }
+
+        if ($options['contextlevels']) {
+            $this->contextlevels = array();
+            $defaults = get_default_contextlevels($archetype);
+            foreach ($defaults as $cl) {
+                $this->contextlevels[$cl] = $cl;
+            }
+        }
+
+        if ($options['allowassign']) {
+            $this->allowassign = get_default_role_archetype_allows('assign', $archetype);
+        }
+        if ($options['allowoverride']) {
+            $this->allowoverride = get_default_role_archetype_allows('override', $archetype);
+        }
+        if ($options['allowswitch']) {
+            $this->allowswitch = get_default_role_archetype_allows('switch', $archetype);
+        }
+
+        if ($options['permissions']) {
+            $defaultpermissions = get_default_capabilities($archetype);
+            foreach ($this->permissions as $k => $v) {
+                if (isset($defaultpermissions[$k])) {
+                    $this->permissions[$k] = $defaultpermissions[$k];
+                    continue;
+                }
+                $this->permissions[$k] = CAP_INHERIT;
+            }
+        }
+    }
+
+    /**
+     * Change the role definition to match given preset.
+     *
+     * @param string $xml
+     * @param array $options array with following keys:
+     *      'name', 'shortname', 'description', 'permissions', 'archetype',
+     *      'contextlevels', 'allowassign', 'allowoverride', 'allowswitch'
+     */
+    public function force_preset($xml, array $options) {
+        if (!$info = core_role_preset::parse_preset($xml)) {
+            throw new coding_exception('Invalid role preset');
+        }
+
+        if ($options['shortname']) {
+            if (isset($info['shortname'])) {
+                $this->role->shortname = $info['shortname'];
+            }
+        }
+
+        if ($options['name']) {
+            if (isset($info['name'])) {
+                $this->role->name = $info['name'];
+            }
+        }
+
+        if ($options['description']) {
+            if (isset($info['description'])) {
+                $this->role->description = $info['description'];
+            }
+        }
+
+        if ($options['archetype']) {
+            if (isset($info['archetype'])) {
+                $this->role->archetype = $info['archetype'];
+            }
+        }
+
+        if ($options['contextlevels']) {
+            if (isset($info['contextlevels'])) {
+                $this->contextlevels = $info['contextlevels'];
+            }
+        }
+
+        foreach (array('assign', 'override', 'switch') as $type) {
+            if ($options['allow'.$type]) {
+                if (isset($info['allow'.$type])) {
+                    $this->{'allow'.$type} = $info['allow'.$type];
+                }
+            }
+        }
+
+        if ($options['permissions']) {
+            foreach ($this->permissions as $k => $v) {
+                // Note: do not set everything else to CAP_INHERIT here
+                //       because the xml file might not contain all capabilities.
+                if (isset($info['permissions'][$k])) {
+                    $this->permissions[$k] = $info['permissions'][$k];
+                }
+            }
+        }
+    }
+
+    public function get_role_name() {
+        return $this->role->name;
+    }
+
+    public function get_role_id() {
+        return $this->role->id;
+    }
+
+    public function get_archetype() {
+        return $this->role->archetype;
+    }
+
+    protected function load_parent_permissions() {
+        $this->parentpermissions = get_default_capabilities($this->role->archetype);
+    }
+
+    public function save_changes() {
+        global $DB;
+
+        if (!$this->roleid) {
+            // Creating role.
+            $this->role->id = create_role($this->role->name, $this->role->shortname, $this->role->description, $this->role->archetype);
+            $this->roleid = $this->role->id; // Needed to make the parent::save_changes(); call work.
+        } else {
+            // Updating role.
+            $DB->update_record('role', $this->role);
+        }
+
+        // Assignable contexts.
+        set_role_contextlevels($this->role->id, $this->contextlevels);
+
+        // Set allowed roles.
+        $this->save_allow('assign');
+        $this->save_allow('override');
+        $this->save_allow('switch');
+
+        // Permissions.
+        parent::save_changes();
+    }
+
+    protected function save_allow($type) {
+        global $DB;
+
+        $current = array_keys($this->get_allow_roles_list($type));
+        $wanted = $this->{'allow'.$type};
+
+        $addfunction = 'allow_'.$type;
+        $deltable = 'role_allow_'.$type;
+        $field = 'allow'.$type;
+
+        foreach ($current as $roleid) {
+            if (!in_array($roleid, $wanted)) {
+                $DB->delete_records($deltable, array('roleid'=>$this->roleid, $field=>$roleid));
+                continue;
+            }
+            $key = array_search($roleid, $wanted);
+            unset($wanted[$key]);
+        }
+
+        foreach ($wanted as $roleid) {
+            if ($roleid == -1) {
+                $roleid = $this->roleid;
+            }
+            $addfunction($this->roleid, $roleid);
+        }
+    }
+
+    protected function get_name_field($id) {
+        return '<input type="text" id="' . $id . '" name="' . $id . '" maxlength="254" value="' . s($this->role->name) . '" />';
+    }
+
+    protected function get_shortname_field($id) {
+        return '<input type="text" id="' . $id . '" name="' . $id . '" maxlength="254" value="' . s($this->role->shortname) . '" />';
+    }
+
+    protected function get_description_field($id) {
+        return print_textarea(true, 10, 50, 50, 10, 'description', $this->role->description, 0, true);
+    }
+
+    protected function get_archetype_field($id) {
+        $options = array();
+        $options[''] = get_string('none');
+        foreach (get_role_archetypes() as $type) {
+            $options[$type] = get_string('archetype'.$type, 'role');
+        }
+        return html_writer::select($options, 'archetype', $this->role->archetype, false);
+    }
+
+    protected function get_assignable_levels_control() {
+        $output = '';
+        foreach ($this->allcontextlevels as $cl => $clname) {
+            $extraarguments = $this->disabled;
+            if (in_array($cl, $this->contextlevels)) {
+                $extraarguments .= 'checked="checked" ';
+            }
+            if (!$this->disabled) {
+                $output .= '<input type="hidden" name="contextlevel' . $cl . '" value="0" />';
+            }
+            $output .= '<input type="checkbox" id="cl' . $cl . '" name="contextlevel' . $cl .
+                '" value="1" ' . $extraarguments . '/> ';
+            $output .= '<label for="cl' . $cl . '">' . $clname . "</label><br />\n";
+        }
+        return $output;
+    }
+
+    /**
+     * Returns an array of roles of the allowed type.
+     *
+     * @param string $type Must be one of: assign, switch, or override.
+     * @param int $roleid (null means current role)
+     * @return array
+     */
+    protected function get_allow_roles_list($type, $roleid = null) {
+        global $DB;
+
+        if ($type !== 'assign' and $type !== 'switch' and $type !== 'override') {
+            debugging('Invalid role allowed type specified', DEBUG_DEVELOPER);
+            return array();
+        }
+
+        if ($roleid === null) {
+            $roleid = $this->roleid;
+        }
+
+        if (empty($roleid)) {
+            return array();
+        }
+
+        $sql = "SELECT r.*
+                  FROM {role} r
+                  JOIN {role_allow_{$type}} a ON a.allow{$type} = r.id
+                 WHERE a.roleid = :roleid
+              ORDER BY r.sortorder ASC";
+        return $DB->get_records_sql($sql, array('roleid'=>$roleid));
+    }
+
+    /**
+     * Returns an array of roles with the allowed type.
+     *
+     * @param string $type Must be one of: assign, switch, or override.
+     * @return array Am array of role names with the allowed type
+     */
+    protected function get_allow_role_control($type) {
+        if ($type !== 'assign' and $type !== 'switch' and $type !== 'override') {
+            debugging('Invalid role allowed type specified', DEBUG_DEVELOPER);
+            return '';
+        }
+
+        $property = 'allow'.$type;
+        $selected = $this->$property;
+
+        $options = array();
+        foreach (role_get_names(null, ROLENAME_ALIAS) as $role) {
+            $options[$role->id] = $role->localname;
+        }
+        if ($this->roleid == 0) {
+            $options[-1] = get_string('thisnewrole', 'core_role');
+        }
+        return html_writer::select($options, 'allow'.$type.'[]', $selected, false, array('multiple'=>'multiple', 'size'=>10));
+    }
+
+    /**
+     * Returns information about the risks associated with a role.
+     *
+     * @return string
+     */
+    protected function get_role_risks_info() {
+        return '';
+    }
+
+    protected function print_field($name, $caption, $field) {
+        global $OUTPUT;
+        // Attempt to generate HTML like formslib.
+        echo '<div class="fitem">';
+        echo '<div class="fitemtitle">';
+        if ($name) {
+            echo '<label for="' . $name . '">';
+        }
+        echo $caption;
+        if ($name) {
+            echo "</label>\n";
+        }
+        echo '</div>';
+        if (isset($this->errors[$name])) {
+            $extraclass = ' error';
+        } else {
+            $extraclass = '';
+        }
+        echo '<div class="felement' . $extraclass . '">';
+        echo $field;
+        if (isset($this->errors[$name])) {
+            echo $OUTPUT->error_text($this->errors[$name]);
+        }
+        echo '</div>';
+        echo '</div>';
+    }
+
+    protected function print_show_hide_advanced_button() {
+        echo '<p class="definenotice">' . get_string('highlightedcellsshowdefault', 'core_role') . ' </p>';
+        echo '<div class="advancedbutton">';
+        echo '<input type="submit" name="toggleadvanced" value="' . get_string('hideadvanced', 'form') . '" />';
+        echo '</div>';
+    }
+
+    public function display() {
+        global $OUTPUT;
+        // Extra fields at the top of the page.
+        echo '<div class="topfields clearfix">';
+        $this->print_field('shortname', get_string('roleshortname', 'core_role').'&nbsp;'.$OUTPUT->help_icon('roleshortname', 'core_role'), $this->get_shortname_field('shortname'));
+        $this->print_field('name', get_string('customrolename', 'core_role').'&nbsp;'.$OUTPUT->help_icon('customrolename', 'core_role'), $this->get_name_field('name'));
+        $this->print_field('edit-description', get_string('customroledescription', 'core_role').'&nbsp;'.$OUTPUT->help_icon('customroledescription', 'core_role'),
+            $this->get_description_field('description'));
+        $this->print_field('menuarchetype', get_string('archetype', 'core_role').'&nbsp;'.$OUTPUT->help_icon('archetype', 'core_role'), $this->get_archetype_field('archetype'));
+        $this->print_field('', get_string('maybeassignedin', 'core_role'), $this->get_assignable_levels_control());
+        $this->print_field('menuallowassign', get_string('allowassign', 'core_role'), $this->get_allow_role_control('assign'));
+        $this->print_field('menuallowoverride', get_string('allowoverride', 'core_role'), $this->get_allow_role_control('override'));
+        $this->print_field('menuallowswitch', get_string('allowswitch', 'core_role'), $this->get_allow_role_control('switch'));
+        if ($risks = $this->get_role_risks_info()) {
+            $this->print_field('', get_string('rolerisks', 'core_role'), $risks);
+        }
+        echo "</div>";
+
+        $this->print_show_hide_advanced_button();
+
+        // Now the permissions table.
+        parent::display();
+    }
+
+    protected function add_permission_cells($capability) {
+        // One cell for each possible permission.
+        foreach ($this->displaypermissions as $perm => $permname) {
+            $strperm = $this->strperms[$permname];
+            $extraclass = '';
+            if ($perm == $this->parentpermissions[$capability->name]) {
+                $extraclass = ' capdefault';
+            }
+            $checked = '';
+            if ($this->permissions[$capability->name] == $perm) {
+                $checked = 'checked="checked" ';
+            }
+            echo '<td class="' . $permname . $extraclass . '">';
+            echo '<label><input type="radio" name="' . $capability->name .
+                '" value="' . $perm . '" ' . $checked . '/> ';
+            echo '<span class="note">' . $strperm . '</span>';
+            echo '</label></td>';
+        }
+    }
+}
diff --git a/admin/roles/classes/define_role_table_basic.php b/admin/roles/classes/define_role_table_basic.php
new file mode 100644 (file)
index 0000000..14393e7
--- /dev/null
@@ -0,0 +1,63 @@
+<?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/>.
+
+/**
+ * Library code used by the roles administration interfaces.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+class core_role_define_role_table_basic extends core_role_define_role_table_advanced {
+    protected $stradvmessage;
+    protected $strallow;
+
+    public function __construct($context, $roleid) {
+        parent::__construct($context, $roleid);
+        $this->displaypermissions = array(CAP_ALLOW => $this->allpermissions[CAP_ALLOW]);
+        $this->stradvmessage = get_string('useshowadvancedtochange', 'core_role');
+        $this->strallow = $this->strperms[$this->allpermissions[CAP_ALLOW]];
+    }
+
+    protected function print_show_hide_advanced_button() {
+        echo '<div class="advancedbutton">';
+        echo '<input type="submit" name="toggleadvanced" value="' . get_string('showadvanced', 'form') . '" />';
+        echo '</div>';
+    }
+
+    protected function add_permission_cells($capability) {
+        $perm = $this->permissions[$capability->name];
+        $permname = $this->allpermissions[$perm];
+        $defaultperm = $this->allpermissions[$this->parentpermissions[$capability->name]];
+        echo '<td class="' . $permname . '">';
+        if ($perm == CAP_ALLOW || $perm == CAP_INHERIT) {
+            $checked = '';
+            if ($perm == CAP_ALLOW) {
+                $checked = 'checked="checked" ';
+            }
+            echo '<input type="hidden" name="' . $capability->name . '" value="' . CAP_INHERIT . '" />';
+            echo '<label><input type="checkbox" name="' . $capability->name .
+                '" value="' . CAP_ALLOW . '" ' . $checked . '/> ' . $this->strallow . '</label>';
+        } else {
+            echo '<input type="hidden" name="' . $capability->name . '" value="' . $perm . '" />';
+            echo $this->strperms[$permname] . '<span class="note">' . $this->stradvmessage . '</span>';
+        }
+        echo '</td>';
+    }
+}
diff --git a/admin/roles/classes/existing_role_holders.php b/admin/roles/classes/existing_role_holders.php
new file mode 100644 (file)
index 0000000..c257a67
--- /dev/null
@@ -0,0 +1,144 @@
+<?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/>.
+
+/**
+ * Existing user selector.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * User selector subclass for the list of users who already have the role in
+ * question on the assign roles page.
+ */
+class core_role_existing_role_holders extends core_role_assign_user_selector_base {
+
+    public function find_users($search) {
+        global $DB;
+
+        list($wherecondition, $params) = $this->search_sql($search, 'u');
+        list($ctxcondition, $ctxparams) = $DB->get_in_or_equal($this->context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'ctx');
+        $params = array_merge($params, $ctxparams);
+        $params['roleid'] = $this->roleid;
+
+        list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext);
+        $params = array_merge($params, $sortparams);
+
+        $sql = "SELECT ra.id AS raid," . $this->required_fields_sql('u') . ",ra.contextid,ra.component
+                  FROM {role_assignments} ra
+                  JOIN {user} u ON u.id = ra.userid
+                  JOIN {context} ctx ON ra.contextid = ctx.id
+                 WHERE $wherecondition
+                       AND ctx.id $ctxcondition
+                       AND ra.roleid = :roleid
+              ORDER BY ctx.depth DESC, ra.component, $sort";
+        $contextusers = $DB->get_records_sql($sql, $params);
+
+        // No users at all.
+        if (empty($contextusers)) {
+            return array();
+        }
+
+        // We have users. Out put them in groups by context depth.
+        // To help the loop below, tack a dummy user on the end of the results
+        // array, to trigger output of the last group.
+        $dummyuser = new stdClass;
+        $dummyuser->contextid = 0;
+        $dummyuser->id = 0;
+        $dummyuser->component = '';
+        $contextusers[] = $dummyuser;
+        $results = array(); // The results array we are building up.
+        $doneusers = array(); // Ensures we only list each user at most once.
+        $currentcontextid = $this->context->id;
+        $currentgroup = array();
+        foreach ($contextusers as $user) {
+            if (isset($doneusers[$user->id])) {
+                continue;
+            }
+            $doneusers[$user->id] = 1;
+            if ($user->contextid != $currentcontextid) {
+                // We have got to the end of the previous group. Add it to the results array.
+                if ($currentcontextid == $this->context->id) {
+                    $groupname = $this->this_con_group_name($search, count($currentgroup));
+                } else {
+                    $groupname = $this->parent_con_group_name($search, $currentcontextid);
+                }
+                $results[$groupname] = $currentgroup;
+                // Get ready for the next group.
+                $currentcontextid = $user->contextid;
+                $currentgroup = array();
+            }
+            // Add this user to the group we are building up.
+            unset($user->contextid);
+            if ($currentcontextid != $this->context->id) {
+                $user->disabled = true;
+            }
+            if ($user->component !== '') {
+                // Bad luck, you can tweak only manual role assignments.
+                $user->disabled = true;
+            }
+            unset($user->component);
+            $currentgroup[$user->id] = $user;
+        }
+
+        return $results;
+    }
+
+    protected function this_con_group_name($search, $numusers) {
+        if ($this->context->contextlevel == CONTEXT_SYSTEM) {
+            // Special case in the System context.
+            if ($search) {
+                return get_string('extusersmatching', 'core_role', $search);
+            } else {
+                return get_string('extusers', 'core_role');
+            }
+        }
+        $contexttype = context_helper::get_level_name($this->context->contextlevel);
+        if ($search) {
+            $a = new stdClass;
+            $a->search = $search;
+            $a->contexttype = $contexttype;
+            if ($numusers) {
+                return get_string('usersinthisxmatching', 'core_role', $a);
+            } else {
+                return get_string('noneinthisxmatching', 'core_role', $a);
+            }
+        } else {
+            if ($numusers) {
+                return get_string('usersinthisx', 'core_role', $contexttype);
+            } else {
+                return get_string('noneinthisx', 'core_role', $contexttype);
+            }
+        }
+    }
+
+    protected function parent_con_group_name($search, $contextid) {
+        $context = context::instance_by_id($contextid);
+        $contextname = $context->get_context_name(true, true);
+        if ($search) {
+            $a = new stdClass;
+            $a->contextname = $contextname;
+            $a->search = $search;
+            return get_string('usersfrommatching', 'core_role', $a);
+        } else {
+            return get_string('usersfrom', 'core_role', $contextname);
+        }
+    }
+}
diff --git a/admin/roles/classes/override_permissions_table_advanced.php b/admin/roles/classes/override_permissions_table_advanced.php
new file mode 100644 (file)
index 0000000..7da1239
--- /dev/null
@@ -0,0 +1,102 @@
+<?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/>.
+
+/**
+ * override permissions table.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+class core_role_override_permissions_table_advanced extends core_role_capability_table_with_risks {
+    protected $strnotset;
+    protected $haslockedcapabilities = false;
+
+    /**
+     * Constructor.
+     *
+     * This method loads loads all the information about the current state of
+     * the overrides, then updates that based on any submitted data. It also
+     * works out which capabilities should be locked for this user.
+     *
+     * @param object $context the context this table relates to.
+     * @param integer $roleid the role being overridden.
+     * @param boolean $safeoverridesonly If true, the user is only allowed to override
+     *      capabilities with no risks.
+     */
+    public function __construct($context, $roleid, $safeoverridesonly) {
+        parent::__construct($context, 'overriderolestable', $roleid);
+        $this->displaypermissions = $this->allpermissions;
+        $this->strnotset = get_string('notset', 'core_role');
+
+        // Determine which capabilities should be locked.
+        if ($safeoverridesonly) {
+            foreach ($this->capabilities as $capid => $cap) {
+                if (!is_safe_capability($cap)) {
+                    $this->capabilities[$capid]->locked = true;
+                    $this->haslockedcapabilities = true;
+                }
+            }
+        }
+    }
+
+    protected function load_parent_permissions() {
+        // Get the capabilities from the parent context, so that can be shown in the interface.
+        $parentcontext = $this->context->get_parent_context();
+        $this->parentpermissions = role_context_capabilities($this->roleid, $parentcontext);
+    }
+
+    public function has_locked_capabilities() {
+        return $this->haslockedcapabilities;
+    }
+
+    protected function add_permission_cells($capability) {
+        $disabled = '';
+        if ($capability->locked || $this->parentpermissions[$capability->name] == CAP_PROHIBIT) {
+            $disabled = ' disabled="disabled"';
+        }
+
+        // One cell for each possible permission.
+        foreach ($this->displaypermissions as $perm => $permname) {
+            $strperm = $this->strperms[$permname];
+            $extraclass = '';
+            if ($perm != CAP_INHERIT && $perm == $this->parentpermissions[$capability->name]) {
+                $extraclass = ' capcurrent';
+            }
+            $checked = '';
+            if ($this->permissions[$capability->name] == $perm) {
+                $checked = 'checked="checked" ';
+            }
+            echo '<td class="' . $permname . $extraclass . '">';
+            echo '<label><input type="radio" name="' . $capability->name .
+                '" value="' . $perm . '" ' . $checked . $disabled . '/> ';
+            if ($perm == CAP_INHERIT) {
+                $inherited = $this->parentpermissions[$capability->name];
+                if ($inherited == CAP_INHERIT) {
+                    $inherited = $this->strnotset;
+                } else {
+                    $inherited = $this->strperms[$this->allpermissions[$inherited]];
+                }
+                $strperm .= ' (' . $inherited . ')';
+            }
+            echo '<span class="note">' . $strperm . '</span>';
+            echo '</label></td>';
+        }
+    }
+}
diff --git a/admin/roles/classes/permission_allow_form.php b/admin/roles/classes/permission_allow_form.php
new file mode 100644 (file)
index 0000000..1572c73
--- /dev/null
@@ -0,0 +1,66 @@
+<?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/>.
+
+/**
+ * Allow something form.
+ *
+ * @package    core_role
+ * @copyright  2009 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once("$CFG->libdir/formslib.php");
+
+class core_role_permission_allow_form extends moodleform {
+
+    /**
+     * Define the form.
+     */
+    protected function definition() {
+        global $CFG;
+
+        $mform = $this->_form;
+        list($context, $capability, $overridableroles) = $this->_customdata;
+
+        list($needed, $forbidden) = get_roles_with_cap_in_context($context, $capability->name);
+        foreach ($needed as $id => $unused) {
+            unset($overridableroles[$id]);
+        }
+        foreach ($forbidden as $id => $unused) {
+            unset($overridableroles[$id]);
+        }
+
+        $mform->addElement('header', 'allowheader', get_string('roleallowheader', 'core_role'));
+
+        $mform->addElement('select', 'roleid', get_string('roleselect', 'core_role'), $overridableroles);
+
+        $mform->addElement('hidden', 'capability');
+        $mform->setType('capability', PARAM_CAPABILITY);
+        $mform->setDefault('capability', $capability->name);
+
+        $mform->addElement('hidden', 'contextid');
+        $mform->setType('contextid', PARAM_INT);
+        $mform->setDefault('contextid', $context->id);
+
+        $mform->addElement('hidden', 'allow');
+        $mform->setType('allow', PARAM_INT);
+        $mform->setDefault('allow', 1);
+
+        $this->add_action_buttons(true, get_string('allow', 'core_role'));
+    }
+}
diff --git a/admin/roles/classes/permission_prohibit_form.php b/admin/roles/classes/permission_prohibit_form.php
new file mode 100644 (file)
index 0000000..ad07ad6
--- /dev/null
@@ -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/>.
+
+/**
+ * Prohibit something form.
+ *
+ * @package    core_role
+ * @copyright  2009 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once("$CFG->libdir/formslib.php");
+
+
+class core_role_permission_prohibit_form extends moodleform {
+
+    /**
+     * Define the form.
+     */
+    protected function definition() {
+        global $CFG;
+
+        $mform = $this->_form;
+        list($context, $capability, $overridableroles) = $this->_customdata;
+
+        list($needed, $forbidden) = get_roles_with_cap_in_context($context, $capability->name);
+        foreach ($forbidden as $id => $unused) {
+            unset($overridableroles[$id]);
+        }
+
+        $mform->addElement('header', 'ptohibitheader', get_string('roleprohibitheader', 'core_role'));
+
+        $mform->addElement('select', 'roleid', get_string('roleselect', 'core_role'), $overridableroles);
+
+        $mform->addElement('hidden', 'capability');
+        $mform->setType('capability', PARAM_CAPABILITY);
+        $mform->setDefault('capability', $capability->name);
+
+        $mform->addElement('hidden', 'contextid');
+        $mform->setType('contextid', PARAM_INT);
+        $mform->setDefault('contextid', $context->id);
+
+        $mform->addElement('hidden', 'prohibit');
+        $mform->setType('prohibit', PARAM_INT);
+        $mform->setDefault('prohibit', 1);
+
+        $this->add_action_buttons(true, get_string('prohibit', 'core_role'));
+    }
+}
diff --git a/admin/roles/classes/permissions_table.php b/admin/roles/classes/permissions_table.php
new file mode 100644 (file)
index 0000000..4d317f5
--- /dev/null
@@ -0,0 +1,150 @@
+<?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/>.
+
+/**
+ * Library code used by the roles administration interfaces.
+ *
+ * @package    core_role
+ * @copyright  2009 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Subclass of core_role_capability_table_base for use on the Permissions page.
+ */
+class core_role_permissions_table extends core_role_capability_table_base {
+    protected $contextname;
+    protected $allowoverrides;
+    protected $allowsafeoverrides;
+    protected $overridableroles;
+    protected $roles;
+    protected $icons = array();
+
+    /**
+     * Constructor.
+     * @param context $context the context this table relates to.
+     * @param string $contextname print_context_name($context) - to save recomputing.
+     * @param array $allowoverrides
+     * @param array $allowsafeoverrides
+     * @param array $overridableroles
+     */
+    public function __construct($context, $contextname, $allowoverrides, $allowsafeoverrides, $overridableroles) {
+        parent::__construct($context, 'permissions');
+        $this->contextname = $contextname;
+        $this->allowoverrides = $allowoverrides;
+        $this->allowsafeoverrides = $allowsafeoverrides;
+        $this->overridableroles = $overridableroles;
+
+        $roles = get_all_roles($context);
+        $this->roles = role_fix_names(array_reverse($roles, true), $context, ROLENAME_ALIAS, true);
+
+    }
+
+    protected function add_header_cells() {
+        echo '<th>' . get_string('risks', 'core_role') . '</th>';
+        echo '<th>' . get_string('neededroles', 'core_role') . '</th>';
+        echo '<th>' . get_string('prohibitedroles', 'core_role') . '</th>';
+    }
+
+    protected function num_extra_columns() {
+        return 3;
+    }
+
+    protected function add_row_cells($capability) {
+        global $OUTPUT, $PAGE;
+
+        $context = $this->context;
+        $contextid = $this->context->id;
+        $allowoverrides = $this->allowoverrides;
+        $allowsafeoverrides = $this->allowsafeoverrides;
+        $overridableroles = $this->overridableroles;
+        $roles = $this->roles;
+
+
+        list($needed, $forbidden) = get_roles_with_cap_in_context($context, $capability->name);
+        $neededroles    = array();
+        $forbiddenroles = array();
+        $allowable      = $overridableroles;
+        $forbitable     = $overridableroles;
+        foreach ($neededroles as $id => $unused) {
+            unset($allowable[$id]);
+        }
+        foreach ($forbidden as $id => $unused) {
+            unset($allowable[$id]);
+            unset($forbitable[$id]);
+        }
+
+        foreach ($roles as $id => $name) {
+            if (isset($needed[$id])) {
+                $neededroles[$id] = $roles[$id];
+                if (isset($overridableroles[$id]) and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability)))) {
+                    $preventurl = new moodle_url($PAGE->url, array('contextid'=>$contextid, 'roleid'=>$id, 'capability'=>$capability->name, 'prevent'=>1));
+                    $neededroles[$id] .= $OUTPUT->action_icon($preventurl, new pix_icon('t/delete', get_string('prevent', 'core_role')));
+                }
+            }
+        }
+        $neededroles = implode(', ', $neededroles);
+        foreach ($roles as $id => $name) {
+            if (isset($forbidden[$id])  and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability)))) {
+                $forbiddenroles[$id] = $roles[$id];
+                if (isset($overridableroles[$id]) and prohibit_is_removable($id, $context, $capability->name)) {
+                    $unprohibiturl = new moodle_url($PAGE->url, array('contextid'=>$contextid, 'roleid'=>$id, 'capability'=>$capability->name, 'unprohibit'=>1));
+                    $forbiddenroles[$id] .= $OUTPUT->action_icon($unprohibiturl, new pix_icon('t/delete', get_string('delete')));
+                }
+            }
+        }
+        $forbiddenroles = implode(', ', $forbiddenroles);
+
+        if ($allowable and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability)))) {
+            $allowurl = new moodle_url($PAGE->url, array('contextid'=>$contextid, 'capability'=>$capability->name, 'allow'=>1));
+            $neededroles .= '<div class="allowmore">'.$OUTPUT->action_icon($allowurl, new pix_icon('t/add', get_string('allow', 'core_role'))).'</div>';
+        }
+
+        if ($forbitable and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability)))) {
+            $prohibiturl = new moodle_url($PAGE->url, array('contextid'=>$contextid, 'capability'=>$capability->name, 'prohibit'=>1));
+            $forbiddenroles .= '<div class="prohibitmore">'.$OUTPUT->action_icon($prohibiturl, new pix_icon('t/add', get_string('prohibit', 'core_role'))).'</div>';
+        }
+
+        $risks = $this->get_risks($capability);
+
+        echo '<td>' . $risks . '</td>';
+        echo '<td>' . $neededroles . '</td>';
+        echo '<td>' . $forbiddenroles . '</td>';
+    }
+
+    protected function get_risks($capability) {
+        global $OUTPUT;
+
+        $allrisks = get_all_risks();
+        $risksurl = new moodle_url(get_docs_url(s(get_string('risks', 'core_role'))));
+
+        $return = '';
+
+        foreach ($allrisks as $type => $risk) {
+            if ($risk & (int)$capability->riskbitmask) {
+                if (!isset($this->icons[$type])) {
+                    $pixicon = new pix_icon('/i/' . str_replace('risk', 'risk_', $type), get_string($type . 'short', 'admin'));
+                    $this->icons[$type] = $OUTPUT->action_icon($risksurl, $pixicon, new popup_action('click', $risksurl));
+                }
+                $return .= $this->icons[$type];
+            }
+        }
+
+        return $return;
+    }
+}
diff --git a/admin/roles/classes/potential_assignees_below_course.php b/admin/roles/classes/potential_assignees_below_course.php
new file mode 100644 (file)
index 0000000..71664a1
--- /dev/null
@@ -0,0 +1,85 @@
+<?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/>.
+
+/**
+ * Library code used by the roles administration interfaces.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * User selector subclass for the list of potential users on the assign roles page,
+ * when we are assigning in a context below the course level. (CONTEXT_MODULE and
+ * some CONTEXT_BLOCK).
+ *
+ * This returns only enrolled users in this context.
+ */
+class core_role_potential_assignees_below_course extends core_role_assign_user_selector_base {
+    public function find_users($search) {
+        global $DB;
+
+        list($enrolsql, $eparams) = get_enrolled_sql($this->context);
+
+        // Now we have to go to the database.
+        list($wherecondition, $params) = $this->search_sql($search, 'u');
+        $params = array_merge($params, $eparams);
+
+        if ($wherecondition) {
+            $wherecondition = ' AND ' . $wherecondition;
+        }
+
+        $fields      = 'SELECT ' . $this->required_fields_sql('u');
+        $countfields = 'SELECT COUNT(u.id)';
+
+        $sql   = " FROM {user} u
+              LEFT JOIN {role_assignments} ra ON (ra.userid = u.id AND ra.roleid = :roleid AND ra.contextid = :contextid)
+                  WHERE u.id IN ($enrolsql)
+                        $wherecondition
+                        AND ra.id IS NULL";
+        $params['contextid'] = $this->context->id;
+        $params['roleid'] = $this->roleid;
+
+        list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext);
+        $order = ' ORDER BY ' . $sort;
+
+        // Check to see if there are too many to show sensibly.
+        if (!$this->is_validating()) {
+            $potentialmemberscount = $DB->count_records_sql($countfields . $sql, $params);
+            if ($potentialmemberscount > $this->maxusersperpage) {
+                return $this->too_many_results($search, $potentialmemberscount);
+            }
+        }
+
+        // If not, show them.
+        $availableusers = $DB->get_records_sql($fields . $sql . $order, array_merge($params, $sortparams));
+
+        if (empty($availableusers)) {
+            return array();
+        }
+
+        if ($search) {
+            $groupname = get_string('potusersmatching', 'core_role', $search);
+        } else {
+            $groupname = get_string('potusers', 'core_role');
+        }
+
+        return array($groupname => $availableusers);
+    }
+}
diff --git a/admin/roles/classes/potential_assignees_course_and_above.php b/admin/roles/classes/potential_assignees_course_and_above.php
new file mode 100644 (file)
index 0000000..ed3a184
--- /dev/null
@@ -0,0 +1,76 @@
+<?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/>.
+
+/**
+ * Library code used by the roles administration interfaces.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * User selector subclass for the list of potential users on the assign roles page,
+ * when we are assigning in a context at or above the course level. In this case we
+ * show all the users in the system who do not already have the role.
+ */
+class core_role_potential_assignees_course_and_above extends core_role_assign_user_selector_base {
+    public function find_users($search) {
+        global $DB;
+
+        list($wherecondition, $params) = $this->search_sql($search, '');
+
+        $fields      = 'SELECT ' . $this->required_fields_sql('');
+        $countfields = 'SELECT COUNT(1)';
+
+        $sql = " FROM {user}
+                WHERE $wherecondition
+                      AND id NOT IN (
+                         SELECT r.userid
+                           FROM {role_assignments} r
+                          WHERE r.contextid = :contextid
+                                AND r.roleid = :roleid)";
+
+        list($sort, $sortparams) = users_order_by_sql('', $search, $this->accesscontext);
+        $order = ' ORDER BY ' . $sort;
+
+        $params['contextid'] = $this->context->id;
+        $params['roleid'] = $this->roleid;
+
+        if (!$this->is_validating()) {
+            $potentialmemberscount = $DB->count_records_sql($countfields . $sql, $params);
+            if ($potentialmemberscount > $this->maxusersperpage) {
+                return $this->too_many_results($search, $potentialmemberscount);
+            }
+        }
+
+        $availableusers = $DB->get_records_sql($fields . $sql . $order, array_merge($params, $sortparams));
+
+        if (empty($availableusers)) {
+            return array();
+        }
+
+        if ($search) {
+            $groupname = get_string('potusersmatching', 'core_role', $search);
+        } else {
+            $groupname = get_string('potusers', 'core_role');
+        }
+
+        return array($groupname => $availableusers);
+    }
+}
diff --git a/admin/roles/classes/preset.php b/admin/roles/classes/preset.php
new file mode 100644 (file)
index 0000000..85904eb
--- /dev/null
@@ -0,0 +1,314 @@
+<?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/>.
+
+/**
+ * New role XML processing.
+ *
+ * @package    core_role
+ * @copyright  2013 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * XML role file manipulation class.
+ *
+ * @package    core_role
+ * @copyright  2013 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class core_role_preset {
+
+    /**
+     * Send role export xml file to browser.
+     *
+     * @param int $roleid
+     * @return void does not return, send the file to output
+     */
+    public static function send_export_xml($roleid) {
+        global $CFG, $DB;
+        require_once($CFG->libdir . '/filelib.php');
+
+        $role = $DB->get_record('role', array('id'=>$roleid), '*', MUST_EXIST);
+
+        if ($role->shortname) {
+            $filename = $role->shortname.'.xml';
+        } else {
+            $filename = 'role.xml';
+        }
+        $xml = self::get_export_xml($roleid);
+        send_file($xml, $filename, 0, false, true, true);
+        die();
+    }
+
+    /**
+     * Generate role export xml file.
+     *
+     * @param $roleid
+     * @return string
+     */
+    public static function get_export_xml($roleid) {
+        global $DB;
+
+        $role = $DB->get_record('role', array('id'=>$roleid), '*', MUST_EXIST);
+
+        $dom = new DOMDocument('1.0', 'UTF-8');
+        $top = $dom->createElement('role');
+        $dom->appendChild($top);
+
+        $top->appendChild($dom->createElement('shortname', $role->shortname));
+        $top->appendChild($dom->createElement('name', $role->name));
+        $top->appendChild($dom->createElement('description', $role->description));
+        $top->appendChild($dom->createElement('archetype', $role->archetype));
+
+        $contextlevels = $dom->createElement('contextlevels');
+        $top->appendChild($contextlevels);
+        foreach (get_role_contextlevels($roleid) as $level) {
+            $name = context_helper::get_class_for_level($level);
+            $name = preg_replace('/^context_/', '', $name);
+            $contextlevels->appendChild($dom->createElement('level', $name));
+        }
+
+        foreach (array('assign', 'override', 'switch') as $type) {
+            $allows = $dom->createElement('allow'.$type);
+            $top->appendChild($allows);
+            $records = $DB->get_records('role_allow_'.$type, array('roleid'=>$roleid), "allow$type ASC");
+            foreach ($records as $record) {
+                if (!$ar = $DB->get_record('role', array('id'=>$record->{'allow'.$type}))) {
+                    continue;
+                }
+                $allows->appendChild($dom->createElement('shortname', $ar->shortname));
+            }
+        }
+
+        $permissions = $dom->createElement('permissions');
+        $top->appendChild($permissions);
+
+        $capabilities = $DB->get_records_sql_menu(
+            "SELECT capability, permission
+               FROM {role_capabilities}
+              WHERE contextid = :syscontext AND roleid = :roleid
+           ORDER BY capability ASC",
+            array('syscontext'=>context_system::instance()->id, 'roleid'=>$roleid));
+
+        $allcapabilities = $DB->get_records('capabilities', array(), 'name ASC');
+        foreach ($allcapabilities as $cap) {
+            if (!isset($capabilities[$cap->name])) {
+                $permissions->appendChild($dom->createElement('inherit', $cap->name));
+            }
+        }
+
+        foreach ($capabilities as $capability => $permission) {
+            if ($permission == CAP_ALLOW) {
+                $permissions->appendChild($dom->createElement('allow', $capability));
+            }
+        }
+        foreach ($capabilities as $capability => $permission) {
+            if ($permission == CAP_PREVENT) {
+                $permissions->appendChild($dom->createElement('prevent', $capability));
+            }
+        }
+        foreach ($capabilities as $capability => $permission) {
+            if ($permission == CAP_PROHIBIT) {
+                $permissions->appendChild($dom->createElement('prohibit', $capability));
+            }
+        }
+
+        return $dom->saveXML();
+    }
+
+    /**
+     * Is this XML valid role preset?
+     *
+     * @param string $xml
+     * @return bool
+     */
+    public static function is_valid_preset($xml) {
+        $dom = new DOMDocument();
+        if (!$dom->loadXML($xml)) {
+            return false;
+        } else {
+            $val = @$dom->schemaValidate(__DIR__.'/../role_schema.xml');
+            if (!$val) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Parse role preset xml file.
+     *
+     * @param string $xml
+     * @return array role info, null on error
+     */
+    public static function parse_preset($xml) {
+        global $DB;
+
+        $info = array();
+
+        if (!self::is_valid_preset($xml)) {
+            return null;
+        }
+
+        $dom = new DOMDocument();
+        $dom->loadXML($xml);
+
+        $info['shortname'] = self::get_node_value($dom, '/role/shortname');
+        if (isset($info['shortname'])) {
+            $info['shortname'] = strtolower(clean_param($info['shortname'], PARAM_ALPHANUMEXT));
+        }
+
+        $info['name'] = self::get_node_value($dom, '/role/name');
+        if (isset($value)) {
+            $info['name'] = clean_param($info['name'], PARAM_TEXT);
+        }
+
+        $info['description'] = self::get_node_value($dom, '/role/description');
+        if (isset($value)) {
+            $info['description'] = clean_param($info['description'], PARAM_CLEANHTML);
+        }
+
+        $info['archetype'] = self::get_node_value($dom, '/role/archetype');
+        if (isset($value)) {
+            $archetypes = get_role_archetypes();
+            if (!isset($archetypes[$info['archetype']])) {
+                $info['archetype'] = null;
+            }
+        }
+
+        $values = self::get_node_children_values($dom, '/role/contextlevels', 'level');
+        if (isset($values)) {
+            $info['contextlevels'] = array();
+            $levelmap = array_flip(context_helper::get_all_levels());
+            foreach ($values as $value) {
+                $level = 'context_'.$value;
+                if (isset($levelmap[$level])) {
+                    $cl = $levelmap[$level];
+                    $info['contextlevels'][$cl] = $cl;
+                }
+            }
+        }
+
+        foreach (array('assign', 'override', 'switch') as $type) {
+            $values = self::get_node_children_values($dom, '/role/allow'.$type, 'shortname');
+            if (!isset($values)) {
+                $info['allow'.$type] = null;
+                continue;
+            }
+            $info['allow'.$type] = array();
+            foreach ($values as $value) {
+                if ($value === $info['shortname']) {
+                    array_unshift($info['allow'.$type], -1); // Means self.
+                }
+                if ($role = $DB->get_record('role', array('shortname'=>$value))) {
+                    $info['allow'.$type][] = $role->id;
+                    continue;
+                }
+            }
+        }
+
+        $info['permissions'] = array();
+        $values = self::get_node_children_values($dom, '/role/permissions', 'inherit');
+        if (isset($values)) {
+            foreach ($values as $value) {
+                if ($value = clean_param($value, PARAM_CAPABILITY)) {
+                    $info['permissions'][$value] = CAP_INHERIT;
+                }
+            }
+        }
+        $values = self::get_node_children_values($dom, '/role/permissions', 'allow');
+        if (isset($values)) {
+            foreach ($values as $value) {
+                if ($value = clean_param($value, PARAM_CAPABILITY)) {
+                    $info['permissions'][$value] = CAP_ALLOW;
+                }
+            }
+        }
+        $values = self::get_node_children_values($dom, '/role/permissions', 'prevent');
+        if (isset($values)) {
+            foreach ($values as $value) {
+                if ($value = clean_param($value, PARAM_CAPABILITY)) {
+                    $info['permissions'][$value] = CAP_PREVENT;
+                }
+            }
+        }
+        $values = self::get_node_children_values($dom, '/role/permissions', 'prohibit');
+        if (isset($values)) {
+            foreach ($values as $value) {
+                if ($value = clean_param($value, PARAM_CAPABILITY)) {
+                    $info['permissions'][$value] = CAP_PROHIBIT;
+                }
+            }
+        }
+
+        return $info;
+    }
+
+    protected static function get_node(DOMDocument $dom, $path) {
+        $parts = explode('/', $path);
+        $elname = end($parts);
+
+        $nodes = $dom->getElementsByTagName($elname);
+
+        if ($nodes->length == 0) {
+            return null;
+        }
+
+        foreach ($nodes as $node) {
+            if ($node->getNodePath() === $path) {
+                return $node;
+            }
+        }
+
+        return null;
+    }
+
+    protected static function get_node_value(DOMDocument $dom, $path) {
+        if (!$node = self::get_node($dom, $path)) {
+            return null;
+        }
+        return $node->nodeValue;
+    }
+
+    protected static function get_node_children(DOMDocument $dom, $path, $tagname) {
+        if (!$node = self::get_node($dom, $path)) {
+            return null;
+        }
+
+        $return = array();
+        foreach ($node->childNodes as $child) {
+            if ($child->nodeName === $tagname) {
+                $return[] = $child;
+            }
+        }
+        return $return;
+    }
+
+    protected static function get_node_children_values(DOMDocument $dom, $path, $tagname) {
+        $children = self::get_node_children($dom, $path, $tagname);
+
+        if ($children === null) {
+            return null;
+        }
+        $return = array();
+        foreach ($children as $child) {
+            $return[] = $child->nodeValue;
+        }
+        return $return;
+    }
+}
diff --git a/admin/roles/classes/preset_form.php b/admin/roles/classes/preset_form.php
new file mode 100644 (file)
index 0000000..ff2024d
--- /dev/null
@@ -0,0 +1,120 @@
+<?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/>.
+
+/**
+ * Role add/reset selection form.
+ *
+ * @package    core_role
+ * @copyright  2013 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once("$CFG->libdir/formslib.php");
+
+
+/**
+ * Role add/reset selection form.
+ *
+ * @package    core_role
+ * @copyright  2013 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class core_role_preset_form extends moodleform {
+
+    /**
+     * Definition of this form.
+     */
+    protected function definition() {
+        $mform = $this->_form;
+
+        $data = $this->_customdata;
+        $options = array();
+
+        $group = get_string('other');
+        $options[$group] = array();
+        $options[$group][0] = get_string('norole', 'core_role');
+
+        $group = get_string('role', 'core');
+        $options[$group] = array();
+        foreach (role_get_names(null, ROLENAME_BOTH) as $role) {
+            // Allow reset to self too, it may be useful when importing incomplete XML preset.
+            $options[$group][$role->id] = $role->localname;
+        }
+
+        $group = get_string('archetype', 'core_role');
+        $options[$group] = array();
+        foreach (get_role_archetypes() as $type) {
+            $options[$group][$type] = get_string('archetype'.$type, 'core_role');
+        }
+
+        $mform->addElement('header', 'presetheader', get_string('roleresetdefaults', 'core_role'));
+
+        $mform->addElement('selectgroups', 'resettype', get_string('roleresetrole', 'core_role'), $options);
+
+        $mform->addElement('filepicker', 'rolepreset', get_string('rolerepreset', 'core_role'));
+
+        if ($data['roleid']) {
+            $mform->addElement('header', 'resetheader', get_string('resetrole', 'core_role'));
+
+            $mform->addElement('advcheckbox', 'shortname', get_string('roleshortname', 'core_role'));
+            $mform->addElement('advcheckbox', 'name', get_string('customrolename', 'core_role'));
+            $mform->addElement('advcheckbox', 'description', get_string('customroledescription', 'core_role'));
+            $mform->addElement('advcheckbox', 'archetype', get_string('archetype', 'core_role'));
+            $mform->addElement('advcheckbox', 'contextlevels', get_string('maybeassignedin', 'core_role'));
+            $mform->addElement('advcheckbox', 'allowassign', get_string('allowassign', 'core_role'));
+            $mform->addElement('advcheckbox', 'allowoverride', get_string('allowoverride', 'core_role'));
+            $mform->addElement('advcheckbox', 'allowswitch', get_string('allowswitch', 'core_role'));
+            $mform->addElement('advcheckbox', 'permissions', get_string('permissions', 'core_role'));
+        }
+
+        $mform->addElement('hidden', 'roleid');
+        $mform->setType('roleid', PARAM_INT);
+
+        $mform->addElement('hidden', 'action');
+        $mform->setType('action', PARAM_ALPHA);
+
+        $mform->addElement('hidden', 'return');
+        $mform->setType('return', PARAM_ALPHA);
+
+        $this->add_action_buttons(true, get_string('continue', 'core'));
+
+        $this->set_data($data);
+    }
+
+    /**
+     * Validate this form.
+     *
+     * @param array $data submitted data
+     * @param array $files not used
+     * @return array errors
+     */
+    public function validation($data, $files) {
+        $errors = parent::validation($data, $files);
+
+        if ($files = $this->get_draft_files('rolepreset')) {
+            /** @var stored_file $file */
+            $file = reset($files);
+            $xml = $file->get_content();
+            if (!core_role_preset::is_valid_preset($xml)) {
+                $errors['rolepreset'] = get_string('invalidpresetfile', 'core_role');
+            }
+        }
+
+        return $errors;
+    }
+}
diff --git a/admin/roles/classes/view_role_definition_table.php b/admin/roles/classes/view_role_definition_table.php
new file mode 100644 (file)
index 0000000..a39ff0c
--- /dev/null
@@ -0,0 +1,136 @@
+<?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/>.
+
+/**
+ * Library code used by the roles administration interfaces.
+ *
+ * @package    core_role
+ * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+class core_role_view_role_definition_table extends core_role_define_role_table_advanced {
+    public function __construct($context, $roleid) {
+        parent::__construct($context, $roleid);
+        $this->displaypermissions = array(CAP_ALLOW => $this->allpermissions[CAP_ALLOW]);
+        $this->disabled = 'disabled="disabled" ';
+    }
+
+    public function save_changes() {
+        throw new moodle_exception('invalidaccess');
+    }
+
+    protected function get_name_field($id) {
+        return role_get_name($this->role);
+    }
+
+    protected function get_shortname_field($id) {
+        return $this->role->shortname;
+    }
+
+    protected function get_description_field($id) {
+        return role_get_description($this->role);
+    }
+
+    protected function get_archetype_field($id) {
+        if (empty($this->role->archetype)) {
+            return get_string('none');
+        } else {
+            return get_string('archetype'.$this->role->archetype, 'core_role');
+        }
+    }
+
+    protected function get_allow_role_control($type) {
+        if ($roles = $this->get_allow_roles_list($type)) {
+            $roles = role_fix_names($roles, null, ROLENAME_ORIGINAL, true);
+            return implode(', ', $roles);
+        } else {
+            return get_string('none');
+        }
+    }
+
+
+    protected function print_show_hide_advanced_button() {
+        // Do nothing.
+    }
+
+    /**
+     * Returns HTML risk icons.
+     *
+     * @return string
+     */
+    protected function get_role_risks_info() {
+        global $OUTPUT;
+
+        if (empty($this->roleid)) {
+            return '';
+        }
+
+        $risks = array();
+        $allrisks = get_all_risks();
+        foreach ($this->capabilities as $capability) {
+            $perm = $this->permissions[$capability->name];
+            if ($perm != CAP_ALLOW) {
+                continue;
+            }
+            foreach ($allrisks as $type => $risk) {
+                if ($risk & (int)$capability->riskbitmask) {
+                    $risks[$type] = $risk;
+                }
+            }
+        }
+
+        $risksurl = new moodle_url(get_docs_url(s(get_string('risks', 'core_role'))));
+        foreach ($risks as $type => $risk) {
+            $pixicon = new pix_icon('/i/' . str_replace('risk', 'risk_', $type), get_string($type . 'short', 'admin'));
+            $risks[$type] = $OUTPUT->action_icon($risksurl, $pixicon, new popup_action('click', $risksurl));
+        }
+
+        return implode(' ', $risks);
+    }
+
+    /**
+     * Returns true if the row should be skipped.
+     *
+     * @param string $capability
+     * @return bool
+     */
+    protected function skip_row($capability) {
+        $perm = $this->permissions[$capability->name];
+        if ($perm == CAP_INHERIT) {
+            // Do not print empty rows in role overview, admins need to know quickly what is allowed and prohibited,
+            // if they want to see the list of all capabilities they can go to edit role page.
+            return true;
+        }
+        parent::skip_row($capability);
+    }
+
+    protected function add_permission_cells($capability) {
+        $perm = $this->permissions[$capability->name];
+        $permname = $this->allpermissions[$perm];
+        $defaultperm = $this->allpermissions[$this->parentpermissions[$capability->name]];
+        if ($permname != $defaultperm) {
+            $default = get_string('defaultx', 'core_role', $this->strperms[$defaultperm]);
+        } else {
+            $default = "&#xa0;";
+        }
+        echo '<td class="' . $permname . '">' . $this->strperms[$permname] . '<span class="note">' .
+            $default . '</span></td>';
+
+    }
+}
index d889a10..f588d1a 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-
 // This file is part of Moodle - http://moodle.org/
 //
 // Moodle is free software: you can redistribute it and/or modify
  * Lets the user edit role definitions.
  *
  * Responds to actions:
- *   add       - add a new role
- *   duplicate - like add, only initialise the new role by using an existing one.
+ *   add       - add a new role (allows import, duplicate, archetype)
+ *   export    - save xml role definition
  *   edit      - edit the definition of a role
  *   view      - view the definition of a role
  *
- * @package    core
- * @subpackage role
+ * @package    core_role
  * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-    require_once(dirname(__FILE__) . '/../../config.php');
-    require_once($CFG->dirroot . '/' . $CFG->admin . '/roles/lib.php');
+require_once(dirname(__FILE__) . '/../../config.php');
+require_once($CFG->libdir.'/adminlib.php');
 
-    $action = required_param('action', PARAM_ALPHA);
-    if (!in_array($action, array('add', 'duplicate', 'edit', 'view'))) {
-        throw new moodle_exception('invalidaccess');
-    }
-    if ($action != 'add') {
-        $roleid = required_param('roleid', PARAM_INT);
-    } else {
-        $roleid = 0;
-    }
+$action = required_param('action', PARAM_ALPHA);
+if (!in_array($action, array('add', 'export', 'edit', 'reset', 'view'))) {
+    throw new moodle_exception('invalidaccess');
+}
+if ($action != 'add') {
+    $roleid = required_param('roleid', PARAM_INT);
+} else {
+    $roleid = 0;
+}
+$resettype = optional_param('resettype', '', PARAM_RAW);
+$return = optional_param('return', 'manage', PARAM_ALPHA);
 
-/// Get the base URL for this and related pages into a convenient variable.
-    $manageurl = $CFG->wwwroot . '/' . $CFG->admin . '/roles/manage.php';
-    $defineurl = $CFG->wwwroot . '/' . $CFG->admin . '/roles/define.php';
-    if ($action == 'duplicate') {
-        $baseurl = $defineurl . '?action=add';
-    } else {
-        $baseurl = $defineurl . '?action=' . $action;
-        if ($roleid) {
-            $baseurl .= '&amp;roleid=' . $roleid;
-        }
-    }
+// Get the base URL for this and related pages into a convenient variable.
+$baseurl = new moodle_url('/admin/roles/define.php', array('action'=>$action, 'roleid'=>$roleid));
+$manageurl = new moodle_url('/admin/roles/manage.php');
+if ($return === 'manage') {
+    $returnurl = $manageurl;
+} else {
+    $returnurl = new moodle_url('/admin/roles/define.php', array('action'=>'view', 'roleid'=>$roleid));;
+}
+
+// Check access permissions.
+$systemcontext = context_system::instance();
+require_login();
+require_capability('moodle/role:manage', $systemcontext);
+admin_externalpage_setup('defineroles', '', array('action' => $action, 'roleid' => $roleid), new moodle_url('/admin/roles/define.php'));
+
+// Export role.
+if ($action === 'export') {
+    core_role_preset::send_export_xml($roleid);
+    die;
+}
 
-/// Check access permissions.
-    $systemcontext = context_system::instance();
-    require_login();
-    require_capability('moodle/role:manage', $systemcontext);
-    admin_externalpage_setup('defineroles', '', array('action' => $action, 'roleid' => $roleid), $defineurl);
+// Handle the toggle advanced mode button.
+$showadvanced = get_user_preferences('definerole_showadvanced', false);
+if (optional_param('toggleadvanced', false, PARAM_BOOL)) {
+    $showadvanced = !$showadvanced;
+    set_user_preference('definerole_showadvanced', $showadvanced);
+}
 
-/// Handle the cancel button.
-    if (optional_param('cancel', false, PARAM_BOOL)) {
+// Get some basic data we are going to need.
+$roles = get_all_roles();
+$rolenames = role_fix_names($roles, $systemcontext, ROLENAME_ORIGINAL);
+$rolescount = count($roles);
+
+if ($action === 'add') {
+    $title = get_string('addinganewrole', 'core_role');
+} else if ($action == 'view') {
+    $title = get_string('viewingdefinitionofrolex', 'core_role', $rolenames[$roleid]->localname);
+} else if ($action == 'reset') {
+    $title = get_string('resettingrole', 'core_role', $rolenames[$roleid]->localname);
+} else {
+    $title = get_string('editingrolex', 'core_role', $rolenames[$roleid]->localname);
+}
+
+// Decide how to create new role.
+if ($action === 'add' and $resettype !== 'none') {
+    $mform = new core_role_preset_form(null, array('action'=>'add', 'roleid'=>0, 'resettype'=>'0', 'return'=>'manage'));
+    if ($mform->is_cancelled()) {
         redirect($manageurl);
-    }
 
-/// Handle the toggle advanced mode button.
-    $showadvanced = get_user_preferences('definerole_showadvanced', false);
-    if (optional_param('toggleadvanced', false, PARAM_BOOL)) {
-        $showadvanced = !$showadvanced;
-        set_user_preference('definerole_showadvanced', $showadvanced);
-    }
+    } else if ($data = $mform->get_data()) {
+        $resettype = $data->resettype;
+        $options = array(
+            'shortname'     => 1,
+            'name'          => 1,
+            'description'   => 1,
+            'permissions'   => 1,
+            'archetype'     => 1,
+            'contextlevels' => 1,
+            'allowassign'   => 1,
+            'allowoverride' => 1,
+            'allowswitch'   => 1);
+        if ($showadvanced) {
+            $definitiontable = new core_role_define_role_table_advanced($systemcontext, 0);
+        } else {
+            $definitiontable = new core_role_define_role_table_basic($systemcontext, 0);
+        }
+        if (is_number($resettype)) {
+            // Duplicate the role.
+            $definitiontable->force_duplicate($resettype, $options);
+        } else {
+            // Must be an archetype.
+            $definitiontable->force_archetype($resettype, $options);
+        }
 
-/// Get some basic data we are going to need.
-    $roles = get_all_roles();
-    $rolenames = role_fix_names($roles, $systemcontext, ROLENAME_ORIGINAL);
-    $rolescount = count($roles);
+        if ($xml = $mform->get_file_content('rolepreset')) {
+            $definitiontable->force_preset($xml, $options);
+        }
 
-/// Create the table object.
-    if ($action == 'view') {
-        $definitiontable = new view_role_definition_table($systemcontext, $roleid);
-    } else if ($showadvanced) {
-        $definitiontable = new define_role_table_advanced($systemcontext, $roleid);
     } else {
-        $definitiontable = new define_role_table_basic($systemcontext, $roleid);
-    }
-    $definitiontable->read_submitted_permissions();
-    if ($action == 'duplicate') {
-        $definitiontable->make_copy();
+        echo $OUTPUT->header();
+        echo $OUTPUT->heading_with_help($title, 'roles', 'core_role');
+        $mform->display();
+        echo $OUTPUT->footer();
+        die;
     }
 
-/// Process submission in necessary.
-    if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey() && $definitiontable->is_submission_valid()) {
-        $definitiontable->save_changes();
-        add_to_log(SITEID, 'role', $action, 'admin/roles/define.php?action=view&roleid=' .
-                $definitiontable->get_role_id(), $definitiontable->get_role_name(), '', $USER->id);
+} else if ($action === 'reset' and $resettype !== 'none') {
+    if (!$role = $DB->get_record('role', array('id'=>$roleid))) {
         redirect($manageurl);
     }
+    $resettype = empty($role->archetype) ? '0' : $role->archetype;
+    $mform = new core_role_preset_form(null,
+        array('action'=>'reset', 'roleid'=>$roleid, 'resettype'=>$resettype , 'permissions'=>1, 'archetype'=>1, 'contextlevels'=>1, 'return'=>$return));
+    if ($mform->is_cancelled()) {
+        redirect($returnurl);
 
-/// Print the page header and tabs.
-    echo $OUTPUT->header();
+    } else if ($data = $mform->get_data()) {
+        $resettype = $data->resettype;
+        $options = array(
+            'shortname'     => $data->shortname,
+            'name'          => $data->name,
+            'description'   => $data->description,
+            'permissions'   => $data->permissions,
+            'archetype'     => $data->archetype,
+            'contextlevels' => $data->contextlevels,
+            'allowassign'   => $data->allowassign,
+            'allowoverride' => $data->allowoverride,
+            'allowswitch'   => $data->allowswitch);
+        if ($showadvanced) {
+            $definitiontable = new core_role_define_role_table_advanced($systemcontext, $roleid);
+        } else {
+            $definitiontable = new core_role_define_role_table_basic($systemcontext, $roleid);
+        }
+        if (is_number($resettype)) {
+            // Duplicate the role.
+            $definitiontable->force_duplicate($resettype, $options);
+        } else {
+            // Must be an archetype.
+            $definitiontable->force_archetype($resettype, $options);
+        }
 
-    $currenttab = 'manage';
-    include('managetabs.php');
+        if ($xml = $mform->get_file_content('rolepreset')) {
+            $definitiontable->force_preset($xml, $options);
+        }
 
-    if ($action == 'add') {
-        $title = get_string('addinganewrole', 'role');
-    } else if ($action == 'duplicate') {
-        $title = get_string('addingrolebycopying', 'role', $rolenames[$roleid]->localname);
-    } else if ($action == 'view') {
-        $title = get_string('viewingdefinitionofrolex', 'role', $rolenames[$roleid]->localname);
-    } else if ($action == 'edit') {
-        $title = get_string('editingrolex', 'role', $rolenames[$roleid]->localname);
+    } else {
+        echo $OUTPUT->header();
+        echo $OUTPUT->heading_with_help($title, 'roles', 'core_role');
+        $mform->display();
+        echo $OUTPUT->footer();
+        die;
     }
-    echo $OUTPUT->heading_with_help($title, 'roles', 'role');
 
-/// Work out some button labels.
-    if ($action == 'add' || $action == 'duplicate') {
-        $submitlabel = get_string('createthisrole', 'role');
+} else {
+    // Create the table object.
+    if ($action === 'view') {
+        $definitiontable = new core_role_view_role_definition_table($systemcontext, $roleid);
+    } else if ($showadvanced) {
+        $definitiontable = new core_role_define_role_table_advanced($systemcontext, $roleid);
     } else {
-        $submitlabel = get_string('savechanges');
+        $definitiontable = new core_role_define_role_table_basic($systemcontext, $roleid);
     }
+    $definitiontable->read_submitted_permissions();
+}
 
-/// On the view page, show some extra controls at the top.
-    if ($action == 'view') {
-        echo $OUTPUT->container_start('buttons');
-        $options = array();
-        $options['roleid'] = $roleid;
-        $options['action'] = 'edit';
-        echo $OUTPUT->single_button(new moodle_url($defineurl, $options), get_string('edit'));
-        $options['action'] = 'reset';
-        if ($definitiontable->get_archetype()) {
-            echo $OUTPUT->single_button(new moodle_url($manageurl, $options), get_string('resetrole', 'role'));
-        } else {
-            echo $OUTPUT->single_button(new moodle_url($manageurl, $options), get_string('resetrolenolegacy', 'role'));
-        }
-        $options['action'] = 'duplicate';
-        echo $OUTPUT->single_button(new moodle_url($defineurl, $options), get_string('duplicaterole', 'role'));
-        echo $OUTPUT->single_button(new moodle_url($manageurl), get_string('listallroles', 'role'));
-        echo $OUTPUT->container_end();
-    }
+// Handle the cancel button.
+if (optional_param('cancel', false, PARAM_BOOL)) {
+    redirect($returnurl);
+}
 
-    // Start the form.
-    echo $OUTPUT->box_start('generalbox');
-    if ($action == 'view') {
-        echo '<div class="mform">';
+// Process submission in necessary.
+if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey() && $definitiontable->is_submission_valid()) {
+    $definitiontable->save_changes();
+    add_to_log(SITEID, 'role', $action, 'admin/roles/define.php?action=view&roleid=' .
+            $definitiontable->get_role_id(), $definitiontable->get_role_name(), '', $USER->id);
+    if ($action === 'add') {
+        redirect(new moodle_url('/admin/roles/define.php', array('action'=>'view', 'roleid'=>$definitiontable->get_role_id())));
     } else {
+        redirect($returnurl);
+    }
+}
+
+// Print the page header and tabs.
+echo $OUTPUT->header();
+
+$currenttab = 'manage';
+require('managetabs.php');
+
+echo $OUTPUT->heading_with_help($title, 'roles', 'core_role');
+
+// Work out some button labels.
+if ($action === 'add') {
+    $submitlabel = get_string('createthisrole', 'core_role');
+} else {
+    $submitlabel = get_string('savechanges');
+}
+
+// On the view page, show some extra controls at the top.
+if ($action === 'view') {
+    echo $OUTPUT->container_start('buttons');
+    $url = new moodle_url('/admin/roles/define.php', array('action'=>'edit', 'roleid'=>$roleid, 'return'=>'define'));
+    echo $OUTPUT->single_button(new moodle_url($url), get_string('edit'));
+    $url = new moodle_url('/admin/roles/define.php', array('action'=>'reset', 'roleid'=>$roleid, 'return'=>'define'));
+    echo $OUTPUT->single_button(new moodle_url($url), get_string('resetrole', 'core_role'));
+    $url = new moodle_url('/admin/roles/define.php', array('action'=>'export', 'roleid'=>$roleid));
+    echo $OUTPUT->single_button(new moodle_url($url), get_string('export', 'core_role'));
+    echo $OUTPUT->single_button($manageurl, get_string('listallroles', 'core_role'));
+    echo $OUTPUT->container_end();
+}
+
+// Start the form.
+echo $OUTPUT->box_start('generalbox');
+if ($action === 'view') {
+    echo '<div class="mform">';
+} else {
     ?>
-<form id="rolesform" class="mform" action="<?php echo $baseurl; ?>" method="post"><div>
+<form id="rolesform" class="mform" action="<?php p($baseurl->out(false)); ?>" method="post"><div>
 <input type="hidden" name="sesskey" value="<?php p(sesskey()) ?>" />
+<input type="hidden" name="return" value="<?php p($return); ?>" />
+<input type="hidden" name="resettype" value="none" />
 <div class="submit buttons">
-    <input type="submit" name="savechanges" value="<?php echo $submitlabel; ?>" />
+    <input type="submit" name="savechanges" value="<?php p($submitlabel); ?>" />
     <input type="submit" name="cancel" value="<?php print_string('cancel'); ?>" />
 </div>
     <?php
-    }
+}
 
-    // Print the form controls.
-    $definitiontable->display();
+// Print the form controls.
+$definitiontable->display();
 
-/// Close the stuff we left open above.
-    if ($action == 'view') {
-        echo '</div>';
-    } else {
-        ?>
+// Close the stuff we left open above.
+if ($action === 'view') {
+    echo '</div>';
+} else {
+    ?>
 <div class="submit buttons">
-    <input type="submit" name="savechanges" value="<?php echo $submitlabel; ?>" />
+    <input type="submit" name="savechanges" value="<?php p($submitlabel); ?>" />
     <input type="submit" name="cancel" value="<?php print_string('cancel'); ?>" />
 </div>
 </div></form>
-        <?php
-    }
-    echo $OUTPUT->box_end();
+<?php
+}
+echo $OUTPUT->box_end();
 
-/// Print a link back to the all roles list.
-    echo '<div class="backlink">';
-    echo '<p><a href="' . $manageurl . '">' . get_string('backtoallroles', 'role') . '</a></p>';
-    echo '</div>';
+// Print a link back to the all roles list.
+echo '<div class="backlink">';
+echo '<p><a href="' . s($manageurl->out(false)) . '">' . get_string('backtoallroles', 'core_role') . '</a></p>';
+echo '</div>';
 
-    echo $OUTPUT->footer();
+echo $OUTPUT->footer();
index 7473f86..b7c17da 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-
 // This file is part of Moodle - http://moodle.org/
 //
 // Moodle is free software: you can redistribute it and/or modify
 /**
  * Library code used by the roles administration interfaces.
  *
- * Responds to actions:
- *   add       - add a new role
- *   duplicate - like add, only initialise the new role by using an existing one.
- *   edit      - edit the definition of a role
- *   view      - view the definition of a role
- *
- * @package    core
- * @subpackage role
+ * @package    core_role
  * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-require_once($CFG->libdir.'/adminlib.php');
-require_once($CFG->dirroot.'/user/selector/lib.php');
-
-// Classes for producing tables with one row per capability ====================
-
-/**
- * This class represents a table with one row for each of a list of capabilities
- * where the first cell in the row contains the capability name, and there is
- * arbitrary stuff in the rest of the row. This class is used by
- * admin/roles/manage.php, override.php and check.php.
- *
- * An ajaxy search UI shown at the top, if JavaScript is on.
- */
-abstract class capability_table_base {
-    /** The context this table relates to. */
-    protected $context;
-
-    /** The capabilities to display. Initialised as fetch_context_capabilities($context). */
-    protected $capabilities = array();
-
-    /** Added as an id="" attribute to the table on output. */
-    protected $id;
-
-    /** Added to the class="" attribute on output. */
-    protected $classes = array('rolecap');
-
-    /** Default number of capabilities in the table for the search UI to be shown. */
-    const NUM_CAPS_FOR_SEARCH = 12;
-
-    /**
-     * Constructor
-     * @param object $context the context this table relates to.
-     * @param string $id what to put in the id="" attribute.
-     */
-    public function __construct($context, $id) {
-        $this->context = $context;
-        $this->capabilities = fetch_context_capabilities($context);
-        $this->id = $id;
-    }
-
-    /**
-     * Use this to add class="" attributes to the table. You get the rolecap by
-     * default.
-     * @param array $classnames of class names.
-     */
-    public function add_classes($classnames) {
-        $this->classes = array_unique(array_merge($this->classes, $classnames));
-    }
-
-    /**
-     * Display the table.
-     */
-    public function display() {
-        if (count($this->capabilities) > capability_table_base::NUM_CAPS_FOR_SEARCH) {
-            global $PAGE;
-            $PAGE->requires->strings_for_js(array('filter','clear'),'moodle');
-            $PAGE->requires->js_init_call('M.core_role.init_cap_table_filter', array($this->id, $this->context->id));
-        }
-        echo '<table class="' . implode(' ', $this->classes) . '" id="' . $this->id . '">' . "\n<thead>\n";
-        echo '<tr><th class="name" align="left" scope="col">' . get_string('capability','role') . '</th>';
-        $this->add_header_cells();
-        echo "</tr>\n</thead>\n<tbody>\n";
-
-    /// Loop over capabilities.
-        $contextlevel = 0;
-        $component = '';
-        foreach ($this->capabilities as $capability) {
-            if ($this->skip_row($capability)) {
-                continue;
-            }
-
-        /// Prints a breaker if component or name or context level has changed
-            if (component_level_changed($capability, $component, $contextlevel)) {
-                $this->print_heading_row($capability);
-            }
-            $contextlevel = $capability->contextlevel;
-            $component = $capability->component;
-
-        /// Start the row.
-            echo '<tr class="' . implode(' ', array_unique(array_merge(array('rolecap'),
-                    $this->get_row_classes($capability)))) . '">';
-
-        /// Table cell for the capability name.
-            echo '<th scope="row" class="name"><span class="cap-desc">' . get_capability_docs_link($capability) .
-                    '<span class="cap-name">' . $capability->name . '</span></span></th>';
-
-        /// Add the cells specific to this table.
-            $this->add_row_cells($capability);
-
-        /// End the row.
-            echo "</tr>\n";
-        }
-
-    /// End of the table.
-        echo "</tbody>\n</table>\n";
-    }
-
-    /**
-     * Used to output a heading rows when the context level or component changes.
-     * @param object $capability gives the new component and contextlevel.
-     */
-    protected function print_heading_row($capability) {
-        echo '<tr class="rolecapheading header"><td colspan="' . (1 + $this->num_extra_columns()) . '" class="header"><strong>' .
-                get_component_string($capability->component, $capability->contextlevel) .
-                '</strong></td></tr>';
-
-    }
-
-    /** For subclasses to override, output header cells, after the initial capability one. */
-    protected abstract function add_header_cells();
-
-    /** For subclasses to override, return the number of cells that add_header_cells/add_row_cells output. */
-    protected abstract function num_extra_columns();
-
-    /**
-     * For subclasses to override. Allows certain capabilties
-     * to be left out of the table.
-     *
-     * @param object $capability the capability this row relates to.
-     * @return boolean. If true, this row is omitted from the table.
-     */
-    protected function skip_row($capability) {
-        return false;
-    }
-
-    /**
-     * For subclasses to override. A change to reaturn class names that are added
-     * to the class="" attribute on the &lt;tr> for this capability.
-     *
-     * @param object $capability the capability this row relates to.
-     * @return array of class name strings.
-     */
-    protected function get_row_classes($capability) {
-        return array();
-    }
-
-    /**
-     * For subclasses to override. Output the data cells for this capability. The
-     * capability name cell will already have been output.
-     *
-     * You can rely on get_row_classes always being called before add_row_cells.
-     *
-     * @param object $capability the capability this row relates to.
-     */
-    protected abstract function add_row_cells($capability);
-}
-
-/**
- * Subclass of capability_table_base for use on the Check permissions page.
- *
- * We have one additional column, Allowed, which contains yes/no.
- */
-class check_capability_table extends capability_table_base {
-    protected $user;
-    protected $fullname;
-    protected $contextname;
-    protected $stryes;
-    protected $strno;
-    private $hascap;
-
-    /**
-     * Constructor
-     * @param object $context the context this table relates to.
-     * @param object $user the user we are generating the results for.
-     * @param string $contextname print_context_name($context) - to save recomputing.
-     */
-    public function __construct($context, $user, $contextname) {
-        global $CFG;
-        parent::__construct($context, 'explaincaps');
-        $this->user = $user;
-        $this->fullname = fullname($user);
-        $this->contextname = $contextname;
-        $this->stryes = get_string('yes');
-        $this->strno = get_string('no');
-    }
-
-    protected function add_header_cells() {
-        echo '<th>' . get_string('allowed', 'role') . '</th>';
-    }
-
-    protected function num_extra_columns() {
-        return 1;
-    }
-
-    protected function get_row_classes($capability) {
-        $this->hascap = has_capability($capability->name, $this->context, $this->user->id);
-        if ($this->hascap) {
-            return array('yes');
-        } else {
-            return array('no');
-        }
-    }
-
-    protected function add_row_cells($capability) {
-        global $OUTPUT;
-        if ($this->hascap) {
-            $result = $this->stryes;
-        } else {
-            $result = $this->strno;
-        }
-        $a = new stdClass;
-        $a->fullname = $this->fullname;
-        $a->capability = $capability->name;
-        $a->context = $this->contextname;
-        echo '<td>' . $result . '</td>';
-    }
-}
-
-
-/**
- * Subclass of capability_table_base for use on the Permissions page.
- */
-class permissions_table extends capability_table_base {
-    protected $contextname;
-    protected $allowoverrides;
-    protected $allowsafeoverrides;
-    protected $overridableroles;
-    protected $roles;
-    protected $icons = array();
-
-    /**
-     * Constructor
-     * @param object $context the context this table relates to.
-     * @param string $contextname print_context_name($context) - to save recomputing.
-     */
-    public function __construct($context, $contextname, $allowoverrides, $allowsafeoverrides, $overridableroles) {
-        parent::__construct($context, 'permissions');
-        $this->contextname = $contextname;
-        $this->allowoverrides = $allowoverrides;
-        $this->allowsafeoverrides = $allowsafeoverrides;
-        $this->overridableroles = $overridableroles;
-
-        $roles = get_all_roles($context);
-        $this->roles = role_fix_names(array_reverse($roles, true), $context, ROLENAME_ALIAS, true);
-
-    }
-
-    protected function add_header_cells() {
-        echo '<th>' . get_string('risks', 'role') . '</th>';
-        echo '<th>' . get_string('neededroles', 'role') . '</th>';
-        echo '<th>' . get_string('prohibitedroles', 'role') . '</th>';
-    }
-
-    protected function num_extra_columns() {
-        return 3;
-    }
-
-    protected function add_row_cells($capability) {
-        global $OUTPUT, $PAGE;
-
-        $context = $this->context;
-        $contextid = $this->context->id;
-        $allowoverrides = $this->allowoverrides;
-        $allowsafeoverrides = $this->allowsafeoverrides;
-        $overridableroles = $this->overridableroles;
-        $roles = $this->roles;
-
-
-        list($needed, $forbidden) = get_roles_with_cap_in_context($context, $capability->name);
-        $neededroles    = array();
-        $forbiddenroles = array();
-        $allowable      = $overridableroles;
-        $forbitable     = $overridableroles;
-        foreach ($neededroles as $id=>$unused) {
-            unset($allowable[$id]);
-        }
-        foreach ($forbidden as $id=>$unused) {
-            unset($allowable[$id]);
-            unset($forbitable[$id]);
-        }
-
-        foreach ($roles as $id=>$name) {
-            if (isset($needed[$id])) {
-                $neededroles[$id] = $roles[$id];
-                if (isset($overridableroles[$id]) and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability)))) {
-                    $preventurl = new moodle_url($PAGE->url, array('contextid'=>$contextid, 'roleid'=>$id, 'capability'=>$capability->name, 'prevent'=>1));
-                    $neededroles[$id] .= $OUTPUT->action_icon($preventurl, new pix_icon('t/delete', get_string('prevent', 'role')));
-                }
-            }
-        }
-        $neededroles = implode(', ', $neededroles);
-        foreach ($roles as $id=>$name) {
-            if (isset($forbidden[$id])  and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability)))) {
-                $forbiddenroles[$id] = $roles[$id];
-                if (isset($overridableroles[$id]) and prohibit_is_removable($id, $context, $capability->name)) {
-                    $unprohibiturl = new moodle_url($PAGE->url, array('contextid'=>$contextid, 'roleid'=>$id, 'capability'=>$capability->name, 'unprohibit'=>1));
-                    $forbiddenroles[$id] .= $OUTPUT->action_icon($unprohibiturl, new pix_icon('t/delete', get_string('delete')));
-                }
-            }
-        }
-        $forbiddenroles = implode(', ', $forbiddenroles);
-
-        if ($allowable and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability)))) {
-            $allowurl = new moodle_url($PAGE->url, array('contextid'=>$contextid, 'capability'=>$capability->name, 'allow'=>1));
-            $neededroles .= '<div class="allowmore">'.$OUTPUT->action_icon($allowurl, new pix_icon('t/add', get_string('allow', 'role'))).'</div>';
-        }
-
-        if ($forbitable and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability)))) {
-            $prohibiturl = new moodle_url($PAGE->url, array('contextid'=>$contextid, 'capability'=>$capability->name, 'prohibit'=>1));
-            $forbiddenroles .= '<div class="prohibitmore">'.$OUTPUT->action_icon($prohibiturl, new pix_icon('t/add', get_string('prohibit', 'role'))).'</div>';
-        }
-
-        $risks = $this->get_risks($capability);
-
-        echo '<td>' . $risks . '</td>';
-        echo '<td>' . $neededroles . '</td>';
-        echo '<td>' . $forbiddenroles . '</td>';
-    }
-
-    protected function get_risks($capability) {
-        global $OUTPUT;
-
-        $allrisks = get_all_risks();
-        $risksurl = new moodle_url(get_docs_url(s(get_string('risks', 'role'))));
-
-        $return = '';
-
-        foreach ($allrisks as $type=>$risk) {
-            if ($risk & (int)$capability->riskbitmask) {
-                if (!isset($this->icons[$type])) {
-                    $pixicon = new pix_icon('/i/' . str_replace('risk', 'risk_', $type), get_string($type . 'short', 'admin'));
-                    $this->icons[$type] = $OUTPUT->action_icon($risksurl, $pixicon, new popup_action('click', $risksurl));
-                }
-                $return .= $this->icons[$type];
-            }
-        }
-
-        return $return;
-    }
-}
-
-
-/**
- * This subclass is the bases for both the define roles and override roles
- * pages. As well as adding the risks columns, this also provides generic
- * facilities for showing a certain number of permissions columns, and
- * recording the current and submitted permissions for each capability.
- */
-abstract class capability_table_with_risks extends capability_table_base {
-    protected $allrisks;
-    protected $allpermissions; // We don't need perms ourselves, but all our subclasses do.
-    protected $strperms; // Language string cache.
-    protected $risksurl; // URL in moodledocs about risks.
-    protected $riskicons = array(); // Cache to avoid regenerating the HTML for each risk icon.
-    /** The capabilities to highlight as default/inherited. */
-    protected $parentpermissions;
-    protected $displaypermissions;
-    protected $permissions;
-    protected $changed;
-    protected $roleid;
-
-    public function __construct($context, $id, $roleid) {
-        parent::__construct($context, $id);
-
-        $this->allrisks = get_all_risks();
-        $this->risksurl = get_docs_url(s(get_string('risks', 'role')));
-
-        $this->allpermissions = array(
-            CAP_INHERIT => 'inherit',
-            CAP_ALLOW => 'allow',
-            CAP_PREVENT => 'prevent' ,
-            CAP_PROHIBIT => 'prohibit',
-        );
-
-        $this->strperms = array();
-        foreach ($this->allpermissions as $permname) {
-            $this->strperms[$permname] =  get_string($permname, 'role');
-        }
-
-        $this->roleid = $roleid;
-        $this->load_current_permissions();
-
-    /// Fill in any blank permissions with an explicit CAP_INHERIT, and init a locked field.
-        foreach ($this->capabilities as $capid => $cap) {
-            if (!isset($this->permissions[$cap->name])) {
-                $this->permissions[$cap->name] = CAP_INHERIT;
-            }
-            $this->capabilities[$capid]->locked = false;
-        }
-    }
-
-    protected function load_current_permissions() {
-        global $DB;
-
-    /// Load the overrides/definition in this context.
-        if ($this->roleid) {
-            $this->permissions = $DB->get_records_menu('role_capabilities', array('roleid' => $this->roleid,
-                    'contextid' => $this->context->id), '', 'capability,permission');
-        } else {
-            $this->permissions = array();
-        }
-    }
-
-    protected abstract function load_parent_permissions();
-
-    /**
-     * Update $this->permissions based on submitted data, while making a list of
-     * changed capabilities in $this->changed.
-     */
-    public function read_submitted_permissions() {
-        $this->changed = array();
-
-        foreach ($this->capabilities as $cap) {
-            if ($cap->locked || $this->skip_row($cap)) {
-            /// The user is not allowed to change the permission for this capability
-                continue;
-            }
-
-            $permission = optional_param($cap->name, null, PARAM_PERMISSION);
-            if (is_null($permission)) {
-            /// A permission was not specified in submitted data.
-                continue;
-            }
-
-        /// If the permission has changed, update $this->permissions and
-        /// Record the fact there is data to save.
-            if ($this->permissions[$cap->name] != $permission) {
-                $this->permissions[$cap->name] = $permission;
-                $this->changed[] = $cap->name;
-            }
-        }
-    }
-
-    /**
-     * Save the new values of any permissions that have been changed.
-     */
-    public function save_changes() {
-    /// Set the permissions.
-        foreach ($this->changed as $changedcap) {
-            assign_capability($changedcap, $this->permissions[$changedcap],
-                    $this->roleid, $this->context->id, true);
-        }
-
-    /// Force accessinfo refresh for users visiting this context.
-        mark_context_dirty($this->context->path);
-    }
-
-    public function display() {
-        $this->load_parent_permissions();
-        foreach ($this->capabilities as $cap) {
-            if (!isset($this->parentpermissions[$cap->name])) {
-                $this->parentpermissions[$cap->name] = CAP_INHERIT;
-            }
-        }
-        parent::display();
-    }
-
-    protected function add_header_cells() {
-        global $OUTPUT;
-        echo '<th colspan="' . count($this->displaypermissions) . '" scope="col">' .
-                get_string('permission', 'role') . ' ' . $OUTPUT->help_icon('permission', 'role') . '</th>';
-        echo '<th class="risk" colspan="' . count($this->allrisks) . '" scope="col">' . get_string('risks','role') . '</th>';
-    }
-
-    protected function num_extra_columns() {
-        return count($this->displaypermissions) + count($this->allrisks);
-    }
-
-    protected function get_row_classes($capability) {
-        $rowclasses = array();
-        foreach ($this->allrisks as $riskname => $risk) {
-            if ($risk & (int)$capability->riskbitmask) {
-                $rowclasses[] = $riskname;
-            }
-        }
-        return $rowclasses;
-    }
-
-    protected abstract function add_permission_cells($capability);
-
-    protected function add_row_cells($capability) {
-        $this->add_permission_cells($capability);
-    /// One cell for each possible risk.
-        foreach ($this->allrisks as $riskname => $risk) {
-            echo '<td class="risk ' . str_replace('risk', '', $riskname) . '">';
-            if ($risk & (int)$capability->riskbitmask) {
-                echo $this->get_risk_icon($riskname);
-            }
-            echo '</td>';
-        }
-    }
-
-    /**
-     * Print a risk icon, as a link to the Risks page on Moodle Docs.
-     *
-     * @param string $type the type of risk, will be one of the keys from the
-     *      get_all_risks array. Must start with 'risk'.
-     */
-    function get_risk_icon($type) {
-        global $OUTPUT;
-        if (!isset($this->riskicons[$type])) {
-            $iconurl = $OUTPUT->pix_url('i/' . str_replace('risk', 'risk_', $type));
-            $text = '<img src="' . $iconurl . '" alt="' . get_string($type . 'short', 'admin') . '" />';
-            $action = new popup_action('click', $this->risksurl, 'docspopup');
-            $this->riskicons[$type] = $OUTPUT->action_link($this->risksurl, $text, $action, array('title'=>get_string($type, 'admin')));
-        }
-        return $this->riskicons[$type];
-    }
-}
-
-/**
- * As well as tracking the permissions information about the role we are creating
- * or editing, we also track the other information about the role. (This class is
- * starting to be more and more like a formslib form in some respects.)
- */
-class define_role_table_advanced extends capability_table_with_risks {
-    /** Used to store other information (besides permissions) about the role we are creating/editing. */
-    protected $role;
-    /** Used to store errors found when validating the data. */
-    protected $errors;
-    protected $contextlevels;
-    protected $allcontextlevels;
-    protected $disabled = '';
-
-    public function __construct($context, $roleid) {
-        $this->roleid = $roleid;
-        parent::__construct($context, 'defineroletable', $roleid);
-        $this->displaypermissions = $this->allpermissions;
-        $this->strperms[$this->allpermissions[CAP_INHERIT]] = get_string('notset', 'role');
-
-        $this->allcontextlevels = array(
-            CONTEXT_SYSTEM => get_string('coresystem'),
-            CONTEXT_USER => get_string('user'),
-            CONTEXT_COURSECAT => get_string('category'),
-            CONTEXT_COURSE => get_string('course'),
-            CONTEXT_MODULE => get_string('activitymodule'),
-            CONTEXT_BLOCK => get_string('block')
-        );
-    }
-
-    protected function load_current_permissions() {
-        global $DB;
-        if ($this->roleid) {
-            if (!$this->role = $DB->get_record('role', array('id' => $this->roleid))) {
-                throw new moodle_exception('invalidroleid');
-            }
-            $contextlevels = get_role_contextlevels($this->roleid);
-            // Put the contextlevels in the array keys, as well as the values.
-            if (!empty($contextlevels)) {
-                $this->contextlevels = array_combine($contextlevels, $contextlevels);
-            } else {
-                $this->contextlevels = array();
-            }
-        } else {
-            $this->role = new stdClass;
-            $this->role->name = '';
-            $this->role->shortname = '';
-            $this->role->description = '';
-            $this->role->archetype = '';
-            $this->contextlevels = array();
-        }
-        parent::load_current_permissions();
-    }
-
-    public function read_submitted_permissions() {
-        global $DB;
-        $this->errors = array();
-
-        // Role short name. We clean this in a special way. We want to end up
-        // with only lowercase safe ASCII characters.
-        $shortname = optional_param('shortname', null, PARAM_RAW);
-        if (!is_null($shortname)) {
-            $this->role->shortname = $shortname;
-            $this->role->shortname = textlib::specialtoascii($this->role->shortname);
-            $this->role->shortname = textlib::strtolower(clean_param($this->role->shortname, PARAM_ALPHANUMEXT));
-            if (empty($this->role->shortname)) {
-                $this->errors['shortname'] = get_string('errorbadroleshortname', 'role');
-            }
-        }
-        if ($DB->record_exists_select('role', 'shortname = ? and id <> ?', array($this->role->shortname, $this->roleid))) {
-            $this->errors['shortname'] = get_string('errorexistsroleshortname', 'role');
-        }
-
-        // Role name.
-        $name = optional_param('name', null, PARAM_TEXT);
-        if (!is_null($name)) {
-            $this->role->name = $name;
-            // Hack: short names of standard roles are equal to archetypes, empty name means localised via lang packs.
-            $archetypes = get_role_archetypes();
-            if (!isset($archetypes[$shortname]) and html_is_blank($this->role->name)) {
-                $this->errors['name'] = get_string('errorbadrolename', 'role');
-            }
-        }
-        if ($this->role->name !== '' and $DB->record_exists_select('role', 'name = ? and id <> ?', array($this->role->name, $this->roleid))) {
-            $this->errors['name'] = get_string('errorexistsrolename', 'role');
-        }
-
-        // Description.
-        $description = optional_param('description', null, PARAM_RAW);
-        if (!is_null($description)) {
-            $this->role->description = $description;
-        }
-
-        // Legacy type.
-        $archetype = optional_param('archetype', null, PARAM_RAW);
-        if (isset($archetype)) {
-            $archetypes = get_role_archetypes();
-            if (isset($archetypes[$archetype])){
-                $this->role->archetype = $archetype;
-            } else {
-                $this->role->archetype = '';
-            }
-        }
-
-        // Assignable context levels.
-        foreach ($this->allcontextlevels as $cl => $notused) {
-            $assignable = optional_param('contextlevel' . $cl, null, PARAM_BOOL);
-            if (!is_null($assignable)) {
-                if ($assignable) {
-                    $this->contextlevels[$cl] = $cl;
-                } else {
-                    unset($this->contextlevels[$cl]);
-                }
-            }
-        }
-
-        // Now read the permissions for each capability.
-        parent::read_submitted_permissions();
-    }
-
-    public function is_submission_valid() {
-        return empty($this->errors);
-    }
-
-    /**
-     * Call this after the table has been initialised, so to indicate that
-     * when save is called, we want to make a duplicate role.
-     */
-    public function make_copy() {
-        $this->roleid = 0;
-        unset($this->role->id);
-        $this->role->name = role_get_name($this->role, null, ROLENAME_ORIGINAL) . ' ' . get_string('copyasnoun');
-        $this->role->shortname .= 'copy';
-    }
-
-    public function get_role_name() {
-        return $this->role->name;
-    }
-
-    public function get_role_id() {
-        return $this->role->id;
-    }
-
-    public function get_archetype() {
-        return $this->role->archetype;
-    }
-
-    protected function load_parent_permissions() {
-        $this->parentpermissions = get_default_capabilities($this->role->archetype);
-    }
-
-    public function save_changes() {
-        global $DB;
-
-        if (!$this->roleid) {
-            // Creating role
-            $this->role->id = create_role($this->role->name, $this->role->shortname, $this->role->description, $this->role->archetype);
-            $this->roleid = $this->role->id; // Needed to make the parent::save_changes(); call work.
-        } else {
-            // Updating role
-            $DB->update_record('role', $this->role);
-        }
-
-        // Assignable contexts.
-        set_role_contextlevels($this->role->id, $this->contextlevels);
-
-        // Permissions.
-        parent::save_changes();
-    }
-
-    protected function get_name_field($id) {
-        return '<input type="text" id="' . $id . '" name="' . $id . '" maxlength="254" value="' . s($this->role->name) . '" />';
-    }
-
-    protected function get_shortname_field($id) {
-        return '<input type="text" id="' . $id . '" name="' . $id . '" maxlength="254" value="' . s($this->role->shortname) . '" />';
-    }
-
-    protected function get_description_field($id) {
-        return print_textarea(true, 10, 50, 50, 10, 'description', $this->role->description, 0, true);
-    }
-
-    protected function get_archetype_field($id) {
-        $options = array();
-        $options[''] = get_string('none');
-        foreach(get_role_archetypes() as $type) {
-            $options[$type] = get_string('archetype'.$type, 'role');
-        }
-        return html_writer::select($options, 'archetype', $this->role->archetype, false);
-    }
-
-    protected function get_assignable_levels_control() {
-        $output = '';
-        foreach ($this->allcontextlevels as $cl => $clname) {
-            $extraarguments = $this->disabled;
-            if (in_array($cl, $this->contextlevels)) {
-                $extraarguments .= 'checked="checked" ';
-            }
-            if (!$this->disabled) {
-                $output .= '<input type="hidden" name="contextlevel' . $cl . '" value="0" />';
-            }
-            $output .= '<input type="checkbox" id="cl' . $cl . '" name="contextlevel' . $cl .
-                    '" value="1" ' . $extraarguments . '/> ';
-            $output .= '<label for="cl' . $cl . '">' . $clname . "</label><br />\n";
-        }
-        return $output;
-    }
-
-    /**
-     * Returns an array of roles of the allowed type.
-     *
-     * @param string $type Must be one of: assign, switch, or override.
-     * @return array
-     */
-    protected function get_allow_roles_list($type) {
-        global $DB;
-
-        if ($type !== 'assign' and $type !== 'switch' and $type !== 'override') {
-            debugging('Invalid role allowed type specified', DEBUG_DEVELOPER);
-            return array();
-        }
-
-        if (empty($this->roleid)) {
-            return array();
-        }
-
-        $sql = "SELECT r.*
-                  FROM {role} r
-                  JOIN {role_allow_{$type}} a ON a.allow{$type} = r.id
-                 WHERE a.roleid = :roleid
-              ORDER BY r.sortorder ASC";
-        return $DB->get_records_sql($sql, array('roleid'=>$this->roleid));
-    }
-
-    /**
-     * Returns an array of roles with the allowed type.
-     *
-     * @param string $type Must be one of: assign, switch, or override.
-     * @return array Am array of role names with the allowed type
-     */
-    protected function get_allow_role_control($type) {
-        if ($roles = $this->get_allow_roles_list($type)) {
-            $roles = role_fix_names($roles, null, ROLENAME_ORIGINAL, true);
-            return implode(', ', $roles);
-        } else {
-            return get_string('none');
-        }
-    }
-
-    /**
-     * Returns information about the risks associated with a role.
-     *
-     * @return string
-     */
-    protected function get_role_risks_info() {
-        return '';
-    }
-
-    protected function print_field($name, $caption, $field) {
-        global $OUTPUT;
-        // Attempt to generate HTML like formslib.
-        echo '<div class="fitem">';
-        echo '<div class="fitemtitle">';
-        if ($name) {
-            echo '<label for="' . $name . '">';
-        }
-        echo $caption;
-        if ($name) {
-            echo "</label>\n";
-        }
-        echo '</div>';
-        if (isset($this->errors[$name])) {
-            $extraclass = ' error';
-        } else {
-            $extraclass = '';
-        }
-        echo '<div class="felement' . $extraclass . '">';
-        if (isset($this->errors[$name])) {
-            echo $OUTPUT->error_text($this->errors[$name]);
-        }
-        echo $field;
-        echo '</div>';
-        echo '</div>';
-    }
-
-    protected function print_show_hide_advanced_button() {
-        echo '<p class="definenotice">' . get_string('highlightedcellsshowdefault', 'role') . ' </p>';
-        echo '<div class="advancedbutton">';
-        echo '<input type="submit" name="toggleadvanced" value="' . get_string('hideadvanced', 'form') . '" />';
-        echo '</div>';
-    }
-
-    public function display() {
-        global $OUTPUT;
-        // Extra fields at the top of the page.
-        echo '<div class="topfields clearfix">';
-        $this->print_field('shortname', get_string('roleshortname', 'role').'&nbsp;'.$OUTPUT->help_icon('roleshortname', 'role'), $this->get_shortname_field('shortname'));
-        $this->print_field('name', get_string('customrolename', 'role').'&nbsp;'.$OUTPUT->help_icon('customrolename', 'role'), $this->get_name_field('name'));
-        $this->print_field('edit-description', get_string('customroledescription', 'role').'&nbsp;'.$OUTPUT->help_icon('customroledescription', 'role'), $this->get_description_field('description'));
-        $this->print_field('menuarchetype', get_string('archetype', 'role').'&nbsp;'.$OUTPUT->help_icon('archetype', 'role'), $this->get_archetype_field('archetype'));
-        $this->print_field('', get_string('maybeassignedin', 'role'), $this->get_assignable_levels_control());
-        $this->print_field('', get_string('allowassign', 'role'), $this->get_allow_role_control('assign'));
-        $this->print_field('', get_string('allowoverride', 'role'), $this->get_allow_role_control('override'));
-        $this->print_field('', get_string('allowswitch', 'role'), $this->get_allow_role_control('switch'));
-        if ($risks = $this->get_role_risks_info()) {
-            $this->print_field('', get_string('rolerisks', 'role'), $risks);
-        }
-        echo "</div>";
-
-        $this->print_show_hide_advanced_button();
-
-        // Now the permissions table.
-        parent::display();
-    }
-
-    protected function add_permission_cells($capability) {
-    /// One cell for each possible permission.
-        foreach ($this->displaypermissions as $perm => $permname) {
-            $strperm = $this->strperms[$permname];
-            $extraclass = '';
-            if ($perm == $this->parentpermissions[$capability->name]) {
-                $extraclass = ' capdefault';
-            }
-            $checked = '';
-            if ($this->permissions[$capability->name] == $perm) {
-                $checked = 'checked="checked" ';
-            }
-            echo '<td class="' . $permname . $extraclass . '">';
-            echo '<label><input type="radio" name="' . $capability->name .
-                    '" value="' . $perm . '" ' . $checked . '/> ';
-            echo '<span class="note">' . $strperm . '</span>';
-            echo '</label></td>';
-        }
-    }
-}
-
-class define_role_table_basic extends define_role_table_advanced {
-    protected $stradvmessage;
-    protected $strallow;
-
-    public function __construct($context, $roleid) {
-        parent::__construct($context, $roleid);
-        $this->displaypermissions = array(CAP_ALLOW => $this->allpermissions[CAP_ALLOW]);
-        $this->stradvmessage = get_string('useshowadvancedtochange', 'role');
-        $this->strallow = $this->strperms[$this->allpermissions[CAP_ALLOW]];
-    }
-
-    protected function print_show_hide_advanced_button() {
-        echo '<div class="advancedbutton">';
-        echo '<input type="submit" name="toggleadvanced" value="' . get_string('showadvanced', 'form') . '" />';
-        echo '</div>';
-    }
-
-    protected function add_permission_cells($capability) {
-        $perm = $this->permissions[$capability->name];
-        $permname = $this->allpermissions[$perm];
-        $defaultperm = $this->allpermissions[$this->parentpermissions[$capability->name]];
-        echo '<td class="' . $permname . '">';
-        if ($perm == CAP_ALLOW || $perm == CAP_INHERIT) {
-            $checked = '';
-            if ($perm == CAP_ALLOW) {
-                $checked = 'checked="checked" ';
-            }
-            echo '<input type="hidden" name="' . $capability->name . '" value="' . CAP_INHERIT . '" />';
-            echo '<label><input type="checkbox" name="' . $capability->name .
-                    '" value="' . CAP_ALLOW . '" ' . $checked . '/> ' . $this->strallow . '</label>';
-        } else {
-            echo '<input type="hidden" name="' . $capability->name . '" value="' . $perm . '" />';
-            echo $this->strperms[$permname] . '<span class="note">' . $this->stradvmessage . '</span>';
-        }
-        echo '</td>';
-    }
-}
-class view_role_definition_table extends define_role_table_advanced {
-    public function __construct($context, $roleid) {
-        parent::__construct($context, $roleid);
-        $this->displaypermissions = array(CAP_ALLOW => $this->allpermissions[CAP_ALLOW]);
-        $this->disabled = 'disabled="disabled" ';
-    }
-
-    public function save_changes() {
-        throw new moodle_exception('invalidaccess');
-    }
-
-    protected function get_name_field($id) {
-        return role_get_name($this->role);
-    }
-
-    protected function get_shortname_field($id) {
-        return $this->role->shortname;
-    }
-
-    protected function get_description_field($id) {
-        return role_get_description($this->role);
-    }
-
-    protected function get_archetype_field($id) {
-        if (empty($this->role->archetype)) {
-            return get_string('none');
-        } else {
-            return get_string('archetype'.$this->role->archetype, 'role');
-        }
-    }
-
-    protected function print_show_hide_advanced_button() {
-        // Do nothing.
-    }
-
-    /**
-     * Returns HTML risk icons.
-     *
-     * @return string
-     */
-    protected function get_role_risks_info() {
-        global $OUTPUT;
-
-        if (empty($this->roleid)) {
-            return '';
-        }
-
-        $risks = array();
-        $allrisks = get_all_risks();
-        foreach ($this->capabilities as $capability) {
-            $perm = $this->permissions[$capability->name];
-            if ($perm != CAP_ALLOW) {
-                continue;
-            }
-            foreach ($allrisks as $type=>$risk) {
-                if ($risk & (int)$capability->riskbitmask) {
-                    $risks[$type] = $risk;
-                }
-            }
-        }
-
-        $risksurl = new moodle_url(get_docs_url(s(get_string('risks', 'role'))));
-        foreach ($risks as $type=>$risk) {
-            $pixicon = new pix_icon('/i/' . str_replace('risk', 'risk_', $type), get_string($type . 'short', 'admin'));
-            $risks[$type] = $OUTPUT->action_icon($risksurl, $pixicon, new popup_action('click', $risksurl));
-        }
-
-        return implode(' ', $risks);
-    }
-
-    /**
-     * Returns true if the row should be skipped.
-     *
-     * @param string $capability
-     * @return bool
-     */
-    protected function skip_row($capability) {
-        $perm = $this->permissions[$capability->name];
-        if ($perm == CAP_INHERIT) {
-            // Do not print empty rows in role overview, admins need to know quickly what is allowed and prohibited,
-            // if they want to see the list of all capabilities they can go to edit role page.
-            return true;
-        }
-        parent::skip_row($capability);
-    }
-
-    protected function add_permission_cells($capability) {
-        $perm = $this->permissions[$capability->name];
-        $permname = $this->allpermissions[$perm];
-        $defaultperm = $this->allpermissions[$this->parentpermissions[$capability->name]];
-        if ($permname != $defaultperm) {
-            $default = get_string('defaultx', 'role', $this->strperms[$defaultperm]);
-        } else {
-            $default = "&#xa0;";
-        }
-        echo '<td class="' . $permname . '">' . $this->strperms[$permname] . '<span class="note">' .