Merge branch 'MDL-41722-master' of git://github.com/sammarshallou/moodle
authorDan Poltawski <dan@moodle.com>
Tue, 8 Oct 2013 07:19:09 +0000 (15:19 +0800)
committerDan Poltawski <dan@moodle.com>
Tue, 8 Oct 2013 07:19:09 +0000 (15:19 +0800)
335 files changed:
admin/auth.php
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/filters.php
admin/index.php
admin/localplugins.php
admin/message.php
admin/modules.php
admin/plagiarism.php
admin/plugins.php
admin/portfolio.php
admin/qbehaviours.php
admin/qtypes.php
admin/renderer.php
admin/reports.php
admin/repository.php
admin/repositoryinstance.php
admin/roles/assign.php
admin/roles/permissions.php
admin/settings/courses.php
admin/settings/plugins.php
admin/settings/security.php
admin/tool/behat/cli/util.php
admin/tool/behat/tests/behat/basic_actions.feature
admin/tool/behat/tests/behat/data_generators.feature
admin/tool/behat/tests/behat/manipulate_forms.feature
admin/tool/dbtransfer/locallib.php
admin/tool/installaddon/classes/installer.php
admin/tool/phpunit/cli/util.php
admin/tool/qeupgradehelper/locallib.php
admin/tools.php
auth/cas/version.php
backup/cc/cc_lib/gral_lib/cssparser.php
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_stepslib.php
badges/ajax.php
badges/assertion.php
badges/backpackconnect.php
blocks/community/communitycourse.php
blocks/community/forms.php
blocks/feedback/version.php
blocks/glossary_random/version.php
blocks/quiz_results/version.php
blocks/search_forums/version.php
calendar/yui/build/moodle-calendar-eventmanager/assets/skins/sam/eventmanager.css [deleted file]
course/ajax/management.php [new file with mode: 0644]
course/category.php
course/classes/deletecategory_form.php [new file with mode: 0644]
course/classes/editcategory_form.php [new file with mode: 0644]
course/classes/management/helper.php [new file with mode: 0644]
course/classes/management_renderer.php [new file with mode: 0644]
course/delete.php
course/delete_category_form.php
course/edit.php
course/editcategory.php
course/editcategory_form.php
course/format/lib.php
course/format/singleactivity/lib.php
course/format/singleactivity/settingslib.php
course/format/singleactivity/styles.css
course/lib.php
course/manage.php
course/management.php [new file with mode: 0644]
course/moodleform_mod.php
course/renderer.php
course/request.php
course/search.php
course/tests/behat/behat_course.php
course/tests/behat/category_change_visibility.feature [new file with mode: 0644]
course/tests/behat/category_management.feature [new file with mode: 0644]
course/tests/behat/category_resort.feature [new file with mode: 0644]
course/tests/behat/course_category_management_listing.feature [new file with mode: 0644]
course/tests/behat/course_change_visibility.feature [new file with mode: 0644]
course/tests/behat/course_resort.feature [new file with mode: 0644]
course/tests/courselib_test.php
course/tests/fixtures/course_capability_assignment.php [new file with mode: 0644]
course/tests/management_helper_test.php [new file with mode: 0644]
course/yui/build/moodle-course-management/moodle-course-management-debug.js [new file with mode: 0644]
course/yui/build/moodle-course-management/moodle-course-management-min.js [new file with mode: 0644]
course/yui/build/moodle-course-management/moodle-course-management.js [new file with mode: 0644]
course/yui/src/management/build.json [new file with mode: 0644]
course/yui/src/management/js/category.js [new file with mode: 0644]
course/yui/src/management/js/console.js [new file with mode: 0644]
course/yui/src/management/js/course.js [new file with mode: 0644]
course/yui/src/management/js/dd.js [new file with mode: 0644]
course/yui/src/management/js/item.js [new file with mode: 0644]
course/yui/src/management/meta/management.json [new file with mode: 0644]
enrol/imsenterprise/lib.php
enrol/imsenterprise/tests/imsenterprise_test.php
enrol/instances.php
enrol/manual/edit_form.php
enrol/paypal/edit_form.php
enrol/self/edit_form.php
filter/manage.php
lang/en/admin.php
lang/en/enrol.php
lang/en/error.php
lang/en/moodle.php
lang/en/question.php
lib/adminlib.php
lib/classes/component.php
lib/classes/plugin_manager.php [new file with mode: 0644]
lib/classes/plugininfo/auth.php [new file with mode: 0644]
lib/classes/plugininfo/base.php [new file with mode: 0644]
lib/classes/plugininfo/block.php [new file with mode: 0644]
lib/classes/plugininfo/cachelock.php [new file with mode: 0644]
lib/classes/plugininfo/cachestore.php [new file with mode: 0644]
lib/classes/plugininfo/calendartype.php [new file with mode: 0644]
lib/classes/plugininfo/coursereport.php [new file with mode: 0644]
lib/classes/plugininfo/editor.php [new file with mode: 0644]
lib/classes/plugininfo/enrol.php [new file with mode: 0644]
lib/classes/plugininfo/filter.php [new file with mode: 0644]
lib/classes/plugininfo/format.php [new file with mode: 0644]
lib/classes/plugininfo/general.php [new file with mode: 0644]
lib/classes/plugininfo/gradeexport.php [new file with mode: 0644]
lib/classes/plugininfo/gradeimport.php [new file with mode: 0644]
lib/classes/plugininfo/gradereport.php [new file with mode: 0644]
lib/classes/plugininfo/gradingform.php [new file with mode: 0644]
lib/classes/plugininfo/local.php [new file with mode: 0644]
lib/classes/plugininfo/message.php [new file with mode: 0644]
lib/classes/plugininfo/mnetservice.php [new file with mode: 0644]
lib/classes/plugininfo/mod.php [new file with mode: 0644]
lib/classes/plugininfo/plagiarism.php [new file with mode: 0644]
lib/classes/plugininfo/portfolio.php [new file with mode: 0644]
lib/classes/plugininfo/profilefield.php [new file with mode: 0644]
lib/classes/plugininfo/qbehaviour.php [new file with mode: 0644]
lib/classes/plugininfo/qformat.php [new file with mode: 0644]
lib/classes/plugininfo/qtype.php [new file with mode: 0644]
lib/classes/plugininfo/report.php [new file with mode: 0644]
lib/classes/plugininfo/repository.php [new file with mode: 0644]
lib/classes/plugininfo/theme.php [new file with mode: 0644]
lib/classes/plugininfo/tool.php [new file with mode: 0644]
lib/classes/plugininfo/webservice.php [new file with mode: 0644]
lib/classes/session/database.php
lib/classes/shutdown_manager.php [new file with mode: 0644]
lib/classes/text.php
lib/classes/update/checker.php [new file with mode: 0644]
lib/classes/update/checker_exception.php [new file with mode: 0644]
lib/classes/update/deployer.php [new file with mode: 0644]
lib/classes/update/info.php [new file with mode: 0644]
lib/coursecatlib.php
lib/cronlib.php
lib/db/caches.php
lib/db/install.xml
lib/db/services.php
lib/db/upgrade.php
lib/dml/moodle_database.php
lib/editor/atto/classes/plugininfo/atto.php [new file with mode: 0644]
lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js
lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js
lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js
lib/editor/atto/yui/src/editor/js/editor.js
lib/editor/tinymce/adminlib.php
lib/editor/tinymce/classes/plugininfo/tinymce.php [new file with mode: 0644]
lib/editor/tinymce/settings.php
lib/editor/tinymce/subplugins.php
lib/enrollib.php
lib/filelib.php
lib/filestorage/file_storage.php
lib/moodlelib.php
lib/navigationlib.php
lib/outputrenderers.php
lib/phpunit/classes/util.php
lib/pluginlib.php
lib/setup.php
lib/tests/behat/behat_general.php
lib/tests/component_test.php
lib/tests/coursecatlib_test.php
lib/tests/plugin_manager_test.php
lib/tests/text_test.php
lib/tests/update_checker_test.php [moved from lib/tests/available_update_checker_test.php with 97% similarity]
lib/tests/update_deployer_test.php [moved from lib/tests/available_update_deployer_test.php with 91% similarity]
lib/upgrade.txt
lib/upgradelib.php
lib/weblib.php
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-debug.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-min.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue.js
lib/yui/src/notification/js/dialogue.js
login/forgot_password.php
login/forgot_password_form.php
login/index.php
login/lib.php [new file with mode: 0644]
login/set_password_form.php [new file with mode: 0644]
message/lib.php
message/renderer.php
mod/assign/adminlib.php
mod/assign/classes/plugininfo/assignfeedback.php [new file with mode: 0644]
mod/assign/classes/plugininfo/assignsubmission.php [new file with mode: 0644]
mod/assign/feedback/editpdf/ajax.php
mod/assign/feedback/editpdf/classes/page_editor.php
mod/assign/feedback/editpdf/testgs.php
mod/assign/lang/en/assign.php
mod/assign/lib.php
mod/assign/locallib.php
mod/assign/settings.php
mod/assign/tests/lib_test.php
mod/assignment/classes/plugininfo/assignment.php [new file with mode: 0644]
mod/book/classes/event/chapter_created.php [new file with mode: 0644]
mod/book/classes/event/chapter_deleted.php [new file with mode: 0644]
mod/book/classes/event/chapter_updated.php [new file with mode: 0644]
mod/book/classes/event/chapter_viewed.php [new file with mode: 0644]
mod/book/classes/event/course_module_viewed.php [new file with mode: 0644]
mod/book/classes/event/instances_list_viewed.php [new file with mode: 0644]
mod/book/classes/plugininfo/booktool.php [new file with mode: 0644]
mod/book/delete.php
mod/book/edit.php
mod/book/index.php
mod/book/lang/en/book.php
mod/book/move.php
mod/book/show.php
mod/book/tests/events_test.php [new file with mode: 0644]
mod/book/tests/generator/lib.php [new file with mode: 0644]
mod/book/tests/generator_test.php [new file with mode: 0644]
mod/book/tool/exportimscp/classes/event/book_exported.php [new file with mode: 0644]
mod/book/tool/exportimscp/index.php
mod/book/tool/exportimscp/lang/en/booktool_exportimscp.php
mod/book/tool/exportimscp/tests/events_test.php [new file with mode: 0644]
mod/book/tool/importhtml/locallib.php
mod/book/tool/importhtml/tests/fixtures/chapters.zip [new file with mode: 0644]
mod/book/tool/importhtml/tests/locallib_test.php [new file with mode: 0644]
mod/book/tool/print/classes/event/book_printed.php [new file with mode: 0644]
mod/book/tool/print/classes/event/chapter_printed.php [new file with mode: 0644]
mod/book/tool/print/index.php
mod/book/tool/print/lang/en/booktool_print.php
mod/book/tool/print/tests/events_test.php [new file with mode: 0644]
mod/book/view.php
mod/data/classes/plugininfo/datafield.php [new file with mode: 0644]
mod/data/classes/plugininfo/datapreset.php [new file with mode: 0644]
mod/folder/mod_form.php
mod/forum/post.php
mod/forum/tests/behat/edit_post_student.feature
mod/lti/view.php
mod/page/classes/event/course_module_viewed.php [new file with mode: 0644]
mod/page/classes/event/instances_list_viewed.php [new file with mode: 0644]
mod/page/index.php
mod/page/lang/en/page.php
mod/page/view.php
mod/quiz/attemptlib.php
mod/quiz/classes/plugininfo/quiz.php [moved from mod/quiz/adminlib.php with 85% similarity]
mod/quiz/classes/plugininfo/quizaccess.php [new file with mode: 0644]
mod/quiz/comment.php
mod/quiz/lang/en/quiz.php
mod/quiz/renderer.php
mod/quiz/report/grading/report.php
mod/quiz/review.php
mod/quiz/view.php
mod/scorm/classes/plugininfo/scormreport.php [new file with mode: 0644]
mod/workshop/classes/plugininfo/workshopallocation.php [new file with mode: 0644]
mod/workshop/classes/plugininfo/workshopeval.php [new file with mode: 0644]
mod/workshop/classes/plugininfo/workshopform.php [new file with mode: 0644]
question/behaviour/adaptive/behaviourtype.php [new file with mode: 0644]
question/behaviour/adaptivenopenalty/behaviour.php
question/behaviour/adaptivenopenalty/behaviourtype.php [new file with mode: 0644]
question/behaviour/behaviourbase.php
question/behaviour/behaviourtypebase.php [new file with mode: 0644]
question/behaviour/deferredcbm/behaviour.php
question/behaviour/deferredcbm/behaviourtype.php [new file with mode: 0644]
question/behaviour/deferredcbm/lang/en/qbehaviour_deferredcbm.php
question/behaviour/deferredcbm/renderer.php
question/behaviour/deferredcbm/styles.css [new file with mode: 0644]
question/behaviour/deferredcbm/tests/behaviourtype_test.php [new file with mode: 0644]
question/behaviour/deferredcbm/tests/question_cbm_test.php [new file with mode: 0644]
question/behaviour/deferredcbm/tests/walkthrough_test.php
question/behaviour/deferredfeedback/behaviour.php
question/behaviour/deferredfeedback/behaviourtype.php [new file with mode: 0644]
question/behaviour/immediatecbm/behaviour.php
question/behaviour/immediatecbm/behaviourtype.php [new file with mode: 0644]
question/behaviour/immediatecbm/tests/walkthrough_test.php
question/behaviour/immediatefeedback/behaviourtype.php [new file with mode: 0644]
question/behaviour/informationitem/behaviour.php
question/behaviour/informationitem/behaviourtype.php [new file with mode: 0644]
question/behaviour/interactive/behaviour.php
question/behaviour/interactive/behaviourtype.php [new file with mode: 0644]
question/behaviour/interactivecountback/behaviour.php
question/behaviour/interactivecountback/behaviourtype.php [new file with mode: 0644]
question/behaviour/manualgraded/behaviour.php
question/behaviour/manualgraded/behaviourtype.php [new file with mode: 0644]
question/behaviour/missing/behaviour.php
question/behaviour/missing/behaviourtype.php [new file with mode: 0644]
question/behaviour/missing/tests/missingbehaviour_test.php
question/behaviour/rendererbase.php
question/behaviour/upgrade.txt
question/engine/datalib.php
question/engine/lib.php
question/engine/questionattempt.php
question/engine/questionattemptstep.php
question/engine/questionusage.php
question/engine/renderer.php
question/engine/tests/helpers.php
question/engine/tests/questionattempt_db_test.php
question/engine/tests/questionattempt_with_steps_test.php
question/engine/tests/questioncbm_test.php [deleted file]
question/engine/tests/questionusagebyactivity_test.php
question/engine/tests/unitofwork_test.php
question/engine/upgrade.txt [new file with mode: 0644]
question/engine/upgrade/behaviourconverters.php
question/preview.php
question/type/calculated/tests/upgradelibnewqe_test.php
question/type/calculatedmulti/tests/upgradelibnewqe_test.php
question/type/calculatedsimple/tests/upgradelibnewqe_test.php
question/type/description/tests/upgradelibnewqe_test.php
question/type/essay/question.php
question/type/essay/tests/upgradelibnewqe_test.php
question/type/match/tests/upgradelibnewqe_test.php
question/type/multianswer/question.php
question/type/multianswer/tests/upgradelibnewqe_test.php
question/type/multichoice/tests/upgradelibnewqe_test.php
question/type/numerical/tests/upgradelibnewqe_test.php
question/type/questionbase.php
question/type/random/tests/upgradelibnewqe_test.php
question/type/shortanswer/tests/upgradelibnewqe_test.php
question/type/truefalse/tests/upgradelibnewqe_test.php
repository/tests/behat/delete_files.feature
theme/base/style/core.css
theme/base/style/course.css
theme/base/style/filemanager.css
theme/bootstrapbase/less/moodle/bootstrapoverride.less
theme/bootstrapbase/less/moodle/core.less
theme/bootstrapbase/less/moodle/course.less
theme/bootstrapbase/less/moodle/filemanager.less
theme/bootstrapbase/less/moodle/responsive.less
theme/bootstrapbase/style/moodle.css
theme/bootstrapbase/yui/build/moodle-theme_bootstrap-bootstrap/moodle-theme_bootstrap-bootstrap-debug.js [deleted file]
theme/bootstrapbase/yui/build/moodle-theme_bootstrap-bootstrap/moodle-theme_bootstrap-bootstrap-min.js [deleted file]
theme/bootstrapbase/yui/build/moodle-theme_bootstrap-bootstrap/moodle-theme_bootstrap-bootstrap.js [deleted file]
user/externallib.php
user/portfolio.php
user/tests/externallib_test.php
version.php

index 4310901..c83e848 100644 (file)
@@ -10,7 +10,6 @@
 require_once('../config.php');
 require_once($CFG->libdir.'/adminlib.php');
 require_once($CFG->libdir.'/tablelib.php');
-require_once($CFG->libdir.'/pluginlib.php');
 
 require_login();
 require_capability('moodle/site:config', context_system::instance());
@@ -53,7 +52,7 @@ switch ($action) {
             set_config('registerauth', '');
         }
         \core\session\manager::gc(); // Remove stale sessions.
-        plugin_manager::reset_caches();
+        core_plugin_manager::reset_caches();
         break;
 
     case 'enable':
@@ -64,7 +63,7 @@ switch ($action) {
             set_config('auth', implode(',', $authsenabled));
         }
         \core\session\manager::gc(); // Remove stale sessions.
-        plugin_manager::reset_caches();
+        core_plugin_manager::reset_caches();
         break;
 
     case 'down':
index 1e37dd2..a37af21 100644 (file)
@@ -5,7 +5,6 @@
     require_once('../config.php');
     require_once($CFG->libdir.'/adminlib.php');
     require_once($CFG->libdir.'/tablelib.php');
-    require_once($CFG->libdir.'/pluginlib.php');
 
     admin_externalpage_setup('manageblocks');
 
@@ -37,7 +36,7 @@
             print_error('blockdoesnotexist', 'error');
         }
         $DB->set_field('block', 'visible', '0', array('id'=>$block->id));      // Hide block
-        plugin_manager::reset_caches();
+        core_plugin_manager::reset_caches();
         admin_get_root(true, false);  // settings not required - only pages
     }
 
@@ -46,7 +45,7 @@
             print_error('blockdoesnotexist', 'error');
         }
         $DB->set_field('block', 'visible', '1', array('id'=>$block->id));      // Show block
-        plugin_manager::reset_caches();
+        core_plugin_manager::reset_caches();
         admin_get_root(true, false);  // settings not required - only pages
     }
 
@@ -97,8 +96,8 @@
 
     $table = new flexible_table('admin-blocks-compatible');
 
-    $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_columns(array('name', 'instances', 'version', 'hideshow', 'undeletable', 'settings', 'uninstall'));
+    $table->define_headers(array($strname, $strcourses, $strversion, $strhide.'/'.$strshow, $strprotecthdr, $strsettings, $struninstall));
     $table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/blocks.php');
     $table->set_attribute('class', 'admintable blockstable generaltable');
     $table->set_attribute('id', 'compatibleblockstable');
             }
         }
 
-        if ($uninstallurl = plugin_manager::instance()->get_uninstall_url('block_'.$blockname)) {
+        if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('block_'.$blockname, 'manage')) {
             $uninstall = html_writer::link($uninstallurl, $struninstall);
         } else {
             $uninstall = '';
         } else {
             $visible = '<a href="blocks.php?show='.$blockid.'&amp;sesskey='.sesskey().'" title="'.$strshow.'">'.
                        '<img src="'.$OUTPUT->pix_url('t/show') . '" class="iconsmall" alt="'.$strshow.'" /></a>';
-            $class = ' class="dimmed_text"'; // Leading space required!
+            $class = 'dimmed_text';
         }
 
         if ($dbversion == $plugin->version) {
         }
 
         $row = array(
-            '<span'.$class.'>'.$strblockname.'</span>',
+            $strblockname,
             $blocklist,
-            '<span'.$class.'>'.$version.'</span>',
+            $version,
             $visible,
             $undeletable,
+            $settings,
             $uninstall,
-            $settings
         );
-        $table->add_data($row);
+        $table->add_data($row, $class);
     }
 
     $table->print_html();
         $table->setup();
 
         foreach ($incompatible as $block) {
-            if ($uninstallurl = plugin_manager::instance()->get_uninstall_url('block_'.$block->name)) {
+            if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('block_'.$block->name, 'manage')) {
                 $uninstall = html_writer::link($uninstallurl, $struninstall);
             } else {
                 $uninstall = '';
index 0a5ce9b..a6c3873 100644 (file)
@@ -753,9 +753,8 @@ if (!$envstatus) {
 }
 
 // Test plugin dependencies.
-require_once($CFG->libdir . '/pluginlib.php');
 $failed = array();
-if (!plugin_manager::instance()->all_plugins_ok($version, $failed)) {
+if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
     cli_problem(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed)))));
     cli_error(get_string('pluginschecktodo', 'admin'));
 }
index 7a4f288..3ab6279 100644 (file)
@@ -167,9 +167,8 @@ if (!$envstatus) {
 }
 
 // Test plugin dependencies.
-require_once($CFG->libdir . '/pluginlib.php');
 $failed = array();
-if (!plugin_manager::instance()->all_plugins_ok($version, $failed)) {
+if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
     cli_problem(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed)))));
     cli_error(get_string('pluginschecktodo', 'admin'));
 }
index 28d7c8d..be2ba8b 100644 (file)
@@ -43,7 +43,6 @@ require_once($CFG->libdir.'/adminlib.php');       // various admin-only function
 require_once($CFG->libdir.'/upgradelib.php');     // general upgrade/install related functions
 require_once($CFG->libdir.'/clilib.php');         // cli only functions
 require_once($CFG->libdir.'/environmentlib.php');
-require_once($CFG->libdir.'/pluginlib.php');
 
 // now get cli options
 list($options, $unrecognized) = cli_get_params(
@@ -117,7 +116,7 @@ if (!$envstatus) {
 
 // Test plugin dependencies.
 $failed = array();
-if (!plugin_manager::instance()->all_plugins_ok($version, $failed)) {
+if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
     cli_problem(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed)))));
     cli_error(get_string('pluginschecktodo', 'admin'));
 }
index f86c4be..80f7680 100644 (file)
@@ -24,7 +24,6 @@
 
 require_once('../config.php');
 require_once($CFG->libdir.'/adminlib.php');
-require_once($CFG->libdir.'/pluginlib.php');
 
 $action  = required_param('action', PARAM_ALPHANUMEXT);
 $formatname   = required_param('format', PARAM_PLUGIN);
@@ -39,7 +38,7 @@ require_sesskey();
 
 $return = new moodle_url('/admin/settings.php', array('section' => 'manageformats'));
 
-$formatplugins = plugin_manager::instance()->get_plugins_of_type('format');
+$formatplugins = core_plugin_manager::instance()->get_plugins_of_type('format');
 $sortorder = array_flip(array_keys($formatplugins));
 
 if (!isset($formatplugins[$formatname])) {
@@ -53,13 +52,13 @@ switch ($action) {
                 print_error('cannotdisableformat', 'error', $return);
             }
             set_config('disabled', 1, 'format_'. $formatname);
-            plugin_manager::reset_caches();
+            core_plugin_manager::reset_caches();
         }
         break;
     case 'enable':
         if (!$formatplugins[$formatname]->is_enabled()) {
             unset_config('disabled', 'format_'. $formatname);
-            plugin_manager::reset_caches();
+            core_plugin_manager::reset_caches();
         }
         break;
     case 'up':
index 50ee7a5..e1be31f 100644 (file)
@@ -7,7 +7,6 @@
 require_once('../config.php');
 require_once($CFG->libdir.'/adminlib.php');
 require_once($CFG->libdir.'/tablelib.php');
-require_once($CFG->libdir.'/pluginlib.php');
 
 $action  = required_param('action', PARAM_ALPHANUMEXT);
 $editor  = required_param('editor', PARAM_PLUGIN);
@@ -94,7 +93,7 @@ if (empty($active_editors)) {
 }
 
 set_config('texteditors', implode(',', $active_editors));
-plugin_manager::reset_caches();
+core_plugin_manager::reset_caches();
 
 if ($return) {
     redirect ($returnurl);
index 14a7649..642d93b 100644 (file)
@@ -27,7 +27,6 @@ define('NO_OUTPUT_BUFFERING', true);
 
 require_once('../config.php');
 require_once($CFG->libdir.'/adminlib.php');
-require_once($CFG->libdir.'/pluginlib.php');
 
 $action  = required_param('action', PARAM_ALPHANUMEXT);
 $enrol   = required_param('enrol', PARAM_PLUGIN);
@@ -51,7 +50,7 @@ switch ($action) {
     case 'disable':
         unset($enabled[$enrol]);
         set_config('enrol_plugins_enabled', implode(',', array_keys($enabled)));
-        plugin_manager::reset_caches();
+        core_plugin_manager::reset_caches();
         $syscontext->mark_dirty(); // resets all enrol caches
         break;
 
@@ -62,7 +61,7 @@ switch ($action) {
         $enabled = array_keys($enabled);
         $enabled[] = $enrol;
         set_config('enrol_plugins_enabled', implode(',', $enabled));
-        plugin_manager::reset_caches();
+        core_plugin_manager::reset_caches();
         $syscontext->mark_dirty(); // resets all enrol caches
         break;
 
@@ -122,7 +121,7 @@ switch ($action) {
 
         echo $OUTPUT->notification(get_string('success'), 'notifysuccess');
 
-        if (!$return = plugin_manager::instance()->get_uninstall_url('enrol_'.$enrol)) {
+        if (!$return = core_plugin_manager::instance()->get_uninstall_url('enrol_'.$enrol, 'manage')) {
             $return = new moodle_url('/admin/plugins.php');
         }
         echo $OUTPUT->continue_button($return);
index 05c463a..ae64944 100644 (file)
@@ -33,7 +33,6 @@
 
     require_once(dirname(__FILE__) . '/../config.php');
     require_once($CFG->libdir . '/adminlib.php');
-    require_once($CFG->libdir . '/pluginlib.php');
 
     $action = optional_param('action', '', PARAM_ALPHANUMEXT);
     $filterpath = optional_param('filterpath', '', PARAM_SAFEDIR);
 
     // Reset caches and return
     if ($action) {
-        plugin_manager::reset_caches();
+        core_plugin_manager::reset_caches();
         reset_text_filters_cache();
         redirect($returnurl);
     }
 
     $table = new html_table();
     $table->head  = array(get_string('filter'), get_string('isactive', 'filters'),
-            get_string('order'), get_string('applyto', 'filters'), get_string('settings'), get_string('delete'));
+            get_string('order'), get_string('applyto', 'filters'), get_string('settings'), get_string('uninstallplugin', 'core_admin'));
     $table->colclasses = array ('leftalign', 'leftalign', 'centeralign', 'leftalign', 'leftalign', 'leftalign');
     $table->attributes['class'] = 'admintable generaltable';
     $table->id = 'filterssetting';
 
 function filters_action_url($filterpath, $action) {
     if ($action === 'delete') {
-        return new moodle_url('/admin/plugins.php', array('sesskey'=>sesskey(), 'uninstall'=>'filter_'.$filterpath));
+        return core_plugin_manager::instance()->get_uninstall_url('filter_'.$filterpath, 'manage');
     }
     return new moodle_url('/admin/filters.php', array('sesskey'=>sesskey(), 'filterpath'=>$filterpath, 'action'=>$action));
 }
@@ -233,7 +232,7 @@ function get_table_row($filterinfo, $isfirstrow, $islastactive, $applytostrings)
     }
 
     // Delete
-    $row[] = '<a href="' . filters_action_url($filter, 'delete') . '">' . get_string('delete') . '</a>';
+    $row[] = '<a href="' . filters_action_url($filter, 'delete') . '">' . get_string('uninstallplugin', 'core_admin') . '</a>';
 
     return $row;
 }
index cf2e78a..ea9f37d 100644 (file)
@@ -78,7 +78,6 @@ core_component::get_core_subsystems();
 
 require_once($CFG->libdir.'/adminlib.php');    // various admin-only functions
 require_once($CFG->libdir.'/upgradelib.php');  // general upgrade/install related functions
-require_once($CFG->libdir.'/pluginlib.php');   // available updates notifications
 
 $id             = optional_param('id', '', PARAM_TEXT);
 $confirmupgrade = optional_param('confirmupgrade', 0, PARAM_BOOL);
@@ -196,7 +195,7 @@ if (!core_tables_exist()) {
 
     // check plugin dependencies
     $failed = array();
-    if (!plugin_manager::instance()->all_plugins_ok($version, $failed)) {
+    if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
         $PAGE->navbar->add(get_string('pluginscheck', 'admin'));
         $PAGE->set_title($strinstallation);
         $PAGE->set_heading($strinstallation . ' - Moodle ' . $CFG->target_release);
@@ -323,7 +322,7 @@ if (!$cache and $version > $CFG->version) {  // upgrade
 
         // check plugin dependencies first
         $failed = array();
-        if (!plugin_manager::instance()->all_plugins_ok($version, $failed)) {
+        if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
             echo $output->unsatisfied_dependencies_page($version, $failed, $reloadurl);
             die();
         }
@@ -332,12 +331,12 @@ if (!$cache and $version > $CFG->version) {  // upgrade
         if ($fetchupdates) {
             // no sesskey support guaranteed here
             if (empty($CFG->disableupdatenotifications)) {
-                available_update_checker::instance()->fetch();
+                \core\update\checker::instance()->fetch();
             }
             redirect($reloadurl);
         }
 
-        $deployer = available_update_deployer::instance();
+        $deployer = \core\update\deployer::instance();
         if ($deployer->enabled()) {
             $deployer->initialize($reloadurl, $reloadurl);
 
@@ -348,7 +347,7 @@ if (!$cache and $version > $CFG->version) {  // upgrade
             }
         }
 
-        echo $output->upgrade_plugin_check_page(plugin_manager::instance(), available_update_checker::instance(),
+        echo $output->upgrade_plugin_check_page(core_plugin_manager::instance(), \core\update\checker::instance(),
                 $version, $showallplugins, $reloadurl,
                 new moodle_url('/admin/index.php', array('confirmupgrade'=>1, 'confirmrelease'=>1, 'confirmplugincheck'=>1)));
         die();
@@ -386,13 +385,13 @@ if (!$cache and moodle_needs_upgrading()) {
 
             if ($fetchupdates) {
                 // no sesskey support guaranteed here
-                available_update_checker::instance()->fetch();
+                \core\update\checker::instance()->fetch();
                 redirect($PAGE->url);
             }
 
             $output = $PAGE->get_renderer('core', 'admin');
 
-            $deployer = available_update_deployer::instance();
+            $deployer = \core\update\deployer::instance();
             if ($deployer->enabled()) {
                 $deployer->initialize($PAGE->url, $PAGE->url);
 
@@ -405,14 +404,14 @@ if (!$cache and moodle_needs_upgrading()) {
 
             // check plugin dependencies first
             $failed = array();
-            if (!plugin_manager::instance()->all_plugins_ok($version, $failed)) {
+            if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
                 echo $output->unsatisfied_dependencies_page($version, $failed, $PAGE->url);
                 die();
             }
             unset($failed);
 
             // dependencies check passed, let's rock!
-            echo $output->upgrade_plugin_check_page(plugin_manager::instance(), available_update_checker::instance(),
+            echo $output->upgrade_plugin_check_page(core_plugin_manager::instance(), \core\update\checker::instance(),
                     $version, $showallplugins,
                     new moodle_url($PAGE->url),
                     new moodle_url('/admin/index.php', array('confirmplugincheck'=>1)));
@@ -514,6 +513,15 @@ if (any_new_admin_settings($adminroot)){
     redirect('upgradesettings.php');
 }
 
+// Return to original page that started the plugin uninstallation if necessary.
+if (isset($SESSION->pluginuninstallreturn)) {
+    $return = $SESSION->pluginuninstallreturn;
+    unset($SESSION->pluginuninstallreturn);
+    if ($return) {
+        redirect($return);
+    }
+}
+
 // Everything should now be set up, and the user is an admin
 
 // Print default admin page with notifications.
@@ -525,13 +533,13 @@ $dbproblems = $DB->diagnose();
 $maintenancemode = !empty($CFG->maintenance_enabled);
 
 // Available updates for Moodle core
-$updateschecker = available_update_checker::instance();
+$updateschecker = \core\update\checker::instance();
 $availableupdates = array();
 $availableupdates['core'] = $updateschecker->get_update_info('core',
     array('minmaturity' => $CFG->updateminmaturity, 'notifybuilds' => $CFG->updatenotifybuilds));
 
 // Available updates for contributed plugins
-$pluginman = plugin_manager::instance();
+$pluginman = core_plugin_manager::instance();
 foreach ($pluginman->get_plugins() as $plugintype => $plugintypeinstances) {
     foreach ($plugintypeinstances as $pluginname => $plugininfo) {
         if (!empty($plugininfo->availableupdates)) {
index 8286e96..fb5c4cf 100644 (file)
@@ -30,7 +30,6 @@
 require_once(dirname(dirname(__FILE__)) . '/config.php');
 require_once($CFG->libdir.'/adminlib.php');
 require_once($CFG->libdir.'/tablelib.php');
-require_once($CFG->libdir.'/pluginlib.php');
 
 admin_externalpage_setup('managelocalplugins');
 
@@ -60,7 +59,7 @@ core_collator::asort($plugins);
 
 foreach ($plugins as $plugin => $name) {
     $uninstall = '';
-    if ($uninstallurl = plugin_manager::instance()->get_uninstall_url('local_'.$plugin)) {
+    if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('local_'.$plugin, 'manage')) {
         $uninstall = html_writer::link($uninstallurl, get_string('uninstallplugin', 'core_admin'));
     }
 
index f9fee27..270a230 100644 (file)
@@ -24,7 +24,6 @@
 require_once(dirname(__FILE__) . '/../config.php');
 require_once($CFG->dirroot . '/message/lib.php');
 require_once($CFG->libdir.'/adminlib.php');
-require_once($CFG->libdir.'/pluginlib.php');
 
 // This is an admin page
 admin_externalpage_setup('managemessageoutputs');
@@ -43,7 +42,7 @@ if (!empty($disable) && confirm_sesskey()) {
         print_error('outputdoesnotexist', 'message');
     }
     $DB->set_field('message_processors', 'enabled', '0', array('id'=>$processor->id));      // Disable output
-    plugin_manager::reset_caches();
+    core_plugin_manager::reset_caches();
 }
 
 if (!empty($enable) && confirm_sesskey()) {
@@ -51,7 +50,7 @@ if (!empty($enable) && confirm_sesskey()) {
         print_error('outputdoesnotexist', 'message');
     }
     $DB->set_field('message_processors', 'enabled', '1', array('id'=>$processor->id));      // Enable output
-    plugin_manager::reset_caches();
+    core_plugin_manager::reset_caches();
 }
 
 if ($disable || $enable) {
index a964c73..4cca569 100644 (file)
@@ -5,7 +5,6 @@
     require_once('../course/lib.php');
     require_once($CFG->libdir.'/adminlib.php');
     require_once($CFG->libdir.'/tablelib.php');
-    require_once($CFG->libdir.'/pluginlib.php');
 
     // defines
     define('MODULE_TABLE','module_administration_table');
@@ -48,7 +47,7 @@
                                 FROM {course_modules}
                                WHERE visibleold=1 AND module=?)",
                 array($module->id));
-        plugin_manager::reset_caches();
+        core_plugin_manager::reset_caches();
         admin_get_root(true, false);  // settings not required - only pages
     }
 
@@ -65,7 +64,7 @@
                                 FROM {course_modules}
                                WHERE visible=1 AND module=?)",
                 array($module->id));
-        plugin_manager::reset_caches();
+        core_plugin_manager::reset_caches();
         admin_get_root(true, false);  // settings not required - only pages
     }
 
     // construct the flexible table ready to display
     $table = new flexible_table(MODULE_TABLE);
     $table->define_columns(array('name', 'instances', 'version', 'hideshow', 'uninstall', 'settings'));
-    $table->define_headers(array($stractivitymodule, $stractivities, $strversion, "$strhide/$strshow", $struninstall, $strsettings));
+    $table->define_headers(array($stractivitymodule, $stractivities, $strversion, "$strhide/$strshow", $strsettings, $struninstall));
     $table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/modules.php');
     $table->set_attribute('id', 'modules');
-    $table->set_attribute('class', 'generaltable');
+    $table->set_attribute('class', 'admintable generaltable');
     $table->setup();
 
     foreach ($modules as $module) {
         }
 
         $uninstall = '';
-        if ($uninstallurl = plugin_manager::instance()->get_uninstall_url('mod_'.$module->name)) {
+        if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('mod_'.$module->name, 'manage')) {
             $uninstall = html_writer::link($uninstallurl, $struninstall);
         }
 
         } else {
             $visible = "<a href=\"modules.php?show=$module->name&amp;sesskey=".sesskey()."\" title=\"$strshow\">".
                        "<img src=\"" . $OUTPUT->pix_url('t/show') . "\" class=\"iconsmall\" alt=\"$strshow\" /></a>";
-            $class =   ' class="dimmed_text"';
+            $class =   'dimmed_text';
         }
         if ($module->name == "forum") {
             $uninstall = "";
         $version = get_config('mod_'.$module->name, 'version');
 
         $table->add_data(array(
-            '<span'.$class.'>'.$strmodulename.'</span>',
+            $strmodulename,
             $countlink,
-            '<span'.$class.'>'.$version.'</span>',
+            $version,
             $visible,
+            $settings,
             $uninstall,
-            $settings
-        ));
+        ), $class);
     }
 
     $table->print_html();
index d5fc85a..d004869 100644 (file)
@@ -29,7 +29,6 @@
 require_once(dirname(dirname(__FILE__)) . '/config.php');
 require_once($CFG->libdir.'/adminlib.php');
 require_once($CFG->libdir.'/tablelib.php');
-require_once($CFG->libdir.'/pluginlib.php');
 
 
 admin_externalpage_setup('manageplagiarismplugins');
@@ -74,7 +73,7 @@ foreach ($plagiarismplugins as $plugin => $dir) {
         }
         // uninstall link.
         $uninstall = '';
-        if ($uninstallurl = plugin_manager::instance()->get_uninstall_url('plagiarism_'.$plugin)) {
+        if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('plagiarism_'.$plugin, 'manage')) {
             $uninstall = html_writer::link($uninstallurl, $txt->uninstall);
         }
         $table->data[] = array($displayname, $version, $uninstall, $settings);
index a092e00..c156f9d 100644 (file)
 
 require_once(dirname(dirname(__FILE__)) . '/config.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->libdir . '/pluginlib.php');
 require_once($CFG->libdir . '/filelib.php');
 
 $fetchremote = optional_param('fetchremote', false, PARAM_BOOL);
 $updatesonly = optional_param('updatesonly', false, PARAM_BOOL);
 $contribonly = optional_param('contribonly', false, PARAM_BOOL);
-$uninstall = optional_param('uninstall', '', PARAM_COMPONENT);
-$delete = optional_param('delete', '', PARAM_COMPONENT);
-$confirmed = optional_param('confirm', false, PARAM_BOOL);
+$uninstall   = optional_param('uninstall', '', PARAM_COMPONENT);
+$delete      = optional_param('delete', '', PARAM_COMPONENT);
+$confirmed   = optional_param('confirm', false, PARAM_BOOL);
+$return      = optional_param('return', 'overview', PARAM_ALPHA);
 
 // NOTE: do not use admin_externalpage_setup() here because it loads
 //       full admin tree which is not possible during uninstallation.
@@ -52,7 +52,7 @@ require_login();
 $syscontext = context_system::instance();
 require_capability('moodle/site:config', $syscontext);
 
-$pluginman = plugin_manager::instance();
+$pluginman = core_plugin_manager::instance();
 
 if ($uninstall) {
     require_sesskey();
@@ -74,7 +74,7 @@ if ($uninstall) {
     // Make sure we know the plugin.
     if (is_null($pluginfo)) {
         throw new moodle_exception('err_uninstalling_unknown_plugin', 'core_plugin', '', array('plugin' => $uninstall),
-            'plugin_manager::get_plugin_info() returned null for the plugin to be uninstalled');
+            'core_plugin_manager::get_plugin_info() returned null for the plugin to be uninstalled');
     }
 
     $pluginname = $pluginman->plugin_name($pluginfo->component);
@@ -84,15 +84,17 @@ if ($uninstall) {
     if (!$pluginman->can_uninstall_plugin($pluginfo->component)) {
         throw new moodle_exception('err_cannot_uninstall_plugin', 'core_plugin', '',
             array('plugin' => $pluginfo->component),
-            'plugin_manager::can_uninstall_plugin() returned false');
+            'core_plugin_manager::can_uninstall_plugin() returned false');
     }
 
     if (!$confirmed) {
-        $continueurl = new moodle_url($PAGE->url, array('uninstall' => $pluginfo->component, 'sesskey' => sesskey(), 'confirm' => 1));
-        echo $output->plugin_uninstall_confirm_page($pluginman, $pluginfo, $continueurl);
+        $continueurl = new moodle_url($PAGE->url, array('uninstall' => $pluginfo->component, 'sesskey' => sesskey(), 'confirm' => 1, 'return'=>$return));
+        $cancelurl = $pluginfo->get_return_url_after_uninstall($return);
+        echo $output->plugin_uninstall_confirm_page($pluginman, $pluginfo, $continueurl, $cancelurl);
         exit();
 
     } else {
+        $SESSION->pluginuninstallreturn = $pluginfo->get_return_url_after_uninstall($return);
         $progress = new progress_trace_buffer(new text_progress_trace(), false);
         $pluginman->uninstall_plugin($pluginfo->component, $progress);
         $progress->finished();
@@ -133,7 +135,7 @@ if ($delete and $confirmed) {
     // Make sure we know the plugin.
     if (is_null($pluginfo)) {
         throw new moodle_exception('err_removing_unknown_plugin', 'core_plugin', '', array('plugin' => $delete),
-            'plugin_manager::get_plugin_info() returned null for the plugin to be deleted');
+            'core_plugin_manager::get_plugin_info() returned null for the plugin to be deleted');
     }
 
     $pluginname = $pluginman->plugin_name($pluginfo->component);
@@ -144,7 +146,7 @@ if ($delete and $confirmed) {
     if (!is_null($pluginfo->versiondb)) {
         throw new moodle_exception('err_removing_installed_plugin', 'core_plugin', '',
             array('plugin' => $pluginfo->component, 'versiondb' => $pluginfo->versiondb),
-            'plugin_manager::get_plugin_info() returned not-null versiondb for the plugin to be deleted');
+            'core_plugin_manager::get_plugin_info() returned not-null versiondb for the plugin to be deleted');
     }
 
     // Make sure the folder is removable.
@@ -176,7 +178,7 @@ admin_externalpage_setup('pluginsoverview');
 /** @var core_admin_renderer $output */
 $output = $PAGE->get_renderer('core', 'admin');
 
-$checker = available_update_checker::instance();
+$checker = \core\update\checker::instance();
 
 // Filtering options.
 $options = array(
@@ -190,7 +192,7 @@ if ($fetchremote) {
     redirect(new moodle_url($PAGE->url, $options));
 }
 
-$deployer = available_update_deployer::instance();
+$deployer = \core\update\deployer::instance();
 if ($deployer->enabled()) {
     $myurl = new moodle_url($PAGE->url, array('updatesonly' => $updatesonly, 'contribonly' => $contribonly));
     $deployer->initialize($myurl, new moodle_url('/admin'));
index 3b460fd..48237bb 100644 (file)
@@ -4,7 +4,6 @@ require_once(dirname(dirname(__FILE__)) . '/config.php');
 require_once($CFG->libdir . '/portfoliolib.php');
 require_once($CFG->libdir . '/portfolio/forms.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->libdir . '/pluginlib.php');
 
 $portfolio     = optional_param('pf', '', PARAM_ALPHANUMEXT);
 $action        = optional_param('action', '', PARAM_ALPHA);
@@ -89,7 +88,7 @@ if (($action == 'edit') || ($action == 'new')) {
         } else {
             portfolio_static_function($plugin, 'create_instance', $plugin, $fromform->name, $fromform);
         }
-        plugin_manager::reset_caches();
+        core_plugin_manager::reset_caches();
         $savedstr = get_string('instancesaved', 'portfolio');
         redirect($baseurl, $savedstr, 1);
         exit;
@@ -118,7 +117,7 @@ if (($action == 'edit') || ($action == 'new')) {
 
     $instance->set('visible', $visible);
     $instance->save();
-    plugin_manager::reset_caches();
+    core_plugin_manager::reset_caches();
     $return = true;
 } else if ($action == 'delete') {
     $instance = portfolio_instance($portfolio);
index 8e98af4..7cd027e 100644 (file)
@@ -28,7 +28,6 @@
 require_once(dirname(__FILE__) . '/../config.php');
 require_once($CFG->libdir . '/questionlib.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->libdir . '/pluginlib.php');
 require_once($CFG->libdir . '/tablelib.php');
 
 // Check permissions.
@@ -40,7 +39,7 @@ admin_externalpage_setup('manageqbehaviours');
 $thispageurl = new moodle_url('/admin/qbehaviours.php');
 
 $behaviours = core_component::get_plugin_list('qbehaviour');
-$pluginmanager = plugin_manager::instance();
+$pluginmanager = core_plugin_manager::instance();
 
 // Get some data we will need - question counts and which types are needed.
 $counts = $DB->get_records_sql_menu("
@@ -92,7 +91,7 @@ if (($disable = optional_param('disable', '', PARAM_PLUGIN)) && confirm_sesskey(
         $disabledbehaviours[] = $disable;
         set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
     }
-    plugin_manager::reset_caches();
+    core_plugin_manager::reset_caches();
     redirect($thispageurl);
 }
 
@@ -110,7 +109,7 @@ if (($enable = optional_param('enable', '', PARAM_PLUGIN)) && confirm_sesskey())
         unset($disabledbehaviours[$key]);
         set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
     }
-    plugin_manager::reset_caches();
+    core_plugin_manager::reset_caches();
     redirect($thispageurl);
 }
 
@@ -138,65 +137,6 @@ if (($down = optional_param('down', '', PARAM_PLUGIN)) && confirm_sesskey()) {
     redirect($thispageurl);
 }
 
-// Delete.
-if (($delete = optional_param('delete', '', PARAM_PLUGIN)) && confirm_sesskey()) {
-    // Check it is OK to delete this question type.
-    if ($delete == 'missing') {
-        print_error('cannotdeletemissingbehaviour', 'question', $thispageurl);
-    }
-
-    if (!isset($behaviours[$delete]) && !get_config('qbehaviour_' . $delete, 'version')) {
-        print_error('unknownbehaviour', 'question', $thispageurl, $delete);
-    }
-
-    $behaviourname = $sortedbehaviours[$delete];
-    if ($counts[$delete] > 0) {
-        print_error('cannotdeletebehaviourinuse', 'question', $thispageurl, $behaviourname);
-    }
-    if ($needed[$delete] > 0) {
-        print_error('cannotdeleteneededbehaviour', 'question', $thispageurl, $behaviourname);
-    }
-
-    // If not yet confirmed, display a confirmation message.
-    if (!optional_param('confirm', '', PARAM_BOOL)) {
-        echo $OUTPUT->header();
-        echo $OUTPUT->heading(get_string('deletebehaviourareyousure', 'question', $behaviourname));
-        echo $OUTPUT->confirm(
-                get_string('deletebehaviourareyousuremessage', 'question', $behaviourname),
-                new moodle_url($thispageurl, array('delete' => $delete, 'confirm' => 1)),
-                $thispageurl);
-        echo $OUTPUT->footer();
-        exit;
-    }
-
-    // Do the deletion.
-    echo $OUTPUT->header();
-    echo $OUTPUT->heading(get_string('deletingbehaviour', 'question', $behaviourname));
-
-    // Remove this behaviour from configurations where it might appear.
-    if (($key = array_search($delete, $disabledbehaviours)) !== false) {
-        unset($disabledbehaviours[$key]);
-        set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
-    }
-    $behaviourorder = array_keys($sortedbehaviours);
-    if (($key = array_search($delete, $behaviourorder)) !== false) {
-        unset($behaviourorder[$key]);
-        set_config('behavioursortorder', implode(',', $behaviourorder), 'question');
-    }
-
-    // Then uninstall the plugin.
-    uninstall_plugin('qbehaviour', $delete);
-
-    // Display a message.
-    $a = new stdClass();
-    $a->behaviour = $behaviourname;
-    $a->directory = core_component::get_plugin_directory('qbehaviour', $delete);
-    echo $OUTPUT->box(get_string('qbehaviourdeletefiles', 'question', $a), 'generalbox', 'notice');
-    echo $OUTPUT->continue_button($thispageurl);
-    echo $OUTPUT->footer();
-    exit;
-}
-
 // End of process actions ==================================================
 
 // Print the page heading.
@@ -207,12 +147,12 @@ echo $OUTPUT->heading(get_string('manageqbehaviours', 'admin'));
 $table = new flexible_table('qbehaviouradmintable');
 $table->define_baseurl($thispageurl);
 $table->define_columns(array('behaviour', 'numqas', 'version', 'requires',
-        'available', 'delete'));
+        'available', 'uninstall'));
 $table->define_headers(array(get_string('behaviour', 'question'), get_string('numqas', 'question'),
         get_string('version'), get_string('requires', 'admin'),
-        get_string('availableq', 'question'), get_string('delete')));
+        get_string('availableq', 'question'), get_string('uninstallplugin', 'core_admin')));
 $table->set_attribute('id', 'qbehaviours');
-$table->set_attribute('class', 'generaltable generalbox boxaligncenter boxwidthwide');
+$table->set_attribute('class', 'generaltable admintable');
 $table->setup();
 
 // Add a row for each question type.
@@ -267,9 +207,11 @@ foreach ($sortedbehaviours as $behaviour => $behaviourname) {
     if ($needed[$behaviour]) {
         $row[] = '';
     } else {
-        $row[] = html_writer::link(new moodle_url($thispageurl,
-                array('delete' => $behaviour, 'sesskey' => sesskey())), get_string('delete'),
+        $uninstallurl = core_plugin_manager::instance()->get_uninstall_url('qbehaviour_'.$behaviour, 'manage');
+        if ($uninstallurl) {
+            $row[] = html_writer::link($uninstallurl, get_string('uninstallplugin', 'core_admin'),
                 array('title' => get_string('uninstallbehaviour', 'question')));
+        }
     }
 
     $table->add_data($row, $rowclass);
index 3e865d1..80c6c6d 100644 (file)
@@ -28,7 +28,6 @@
 require_once(dirname(__FILE__) . '/../config.php');
 require_once($CFG->libdir . '/questionlib.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->libdir . '/pluginlib.php');
 require_once($CFG->libdir . '/tablelib.php');
 
 // Check permissions.
@@ -41,7 +40,7 @@ admin_externalpage_setup('manageqtypes');
 $thispageurl = new moodle_url('/admin/qtypes.php');
 
 $qtypes = question_bank::get_all_qtypes();
-$pluginmanager = plugin_manager::instance();
+$pluginmanager = core_plugin_manager::instance();
 
 // Get some data we will need - question counts and which types are needed.
 $counts = $DB->get_records_sql("
@@ -122,58 +121,6 @@ if (($down = optional_param('down', '', PARAM_PLUGIN)) && confirm_sesskey()) {
     redirect($thispageurl);
 }
 
-// Delete.
-if (($delete = optional_param('delete', '', PARAM_PLUGIN)) && confirm_sesskey()) {
-    // Check it is OK to delete this question type.
-    if ($delete == 'missingtype') {
-        print_error('cannotdeletemissingqtype', 'question', $thispageurl);
-    }
-
-    if (!isset($qtypes[$delete]) && !get_config('qtype_' . $delete, 'version')) {
-        print_error('unknownquestiontype', 'question', $thispageurl, $delete);
-    }
-
-    $qtypename = $qtypes[$delete]->local_name();
-    if ($counts[$delete]->numquestions + $counts[$delete]->numhidden > 0) {
-        print_error('cannotdeleteqtypeinuse', 'question', $thispageurl, $qtypename);
-    }
-
-    if ($needed[$delete] > 0) {
-        print_error('cannotdeleteqtypeneeded', 'question', $thispageurl, $qtypename);
-    }
-
-    // If not yet confirmed, display a confirmation message.
-    if (!optional_param('confirm', '', PARAM_BOOL)) {
-        $qtypename = $qtypes[$delete]->local_name();
-        echo $OUTPUT->header();
-        echo $OUTPUT->heading(get_string('deleteqtypeareyousure', 'question', $qtypename));
-        echo $OUTPUT->confirm(get_string('deleteqtypeareyousuremessage', 'question', $qtypename),
-                new moodle_url($thispageurl, array('delete' => $delete, 'confirm' => 1)),
-                $thispageurl);
-        echo $OUTPUT->footer();
-        exit;
-    }
-
-    // Do the deletion.
-    echo $OUTPUT->header();
-    echo $OUTPUT->heading(get_string('deletingqtype', 'question', $qtypename));
-
-    // Delete any questoin configuration records mentioning this plugin.
-    unset_config($delete . '_disabled', 'question');
-    unset_config($delete . '_sortorder', 'question');
-
-    // Then uninstall the plugin.
-    uninstall_plugin('qtype', $delete);
-
-    $a = new stdClass();
-    $a->qtype = $qtypename;
-    $a->directory = $qtypes[$delete]->plugin_dir();
-    echo $OUTPUT->box(get_string('qtypedeletefiles', 'question', $a), 'generalbox', 'notice');
-    echo $OUTPUT->continue_button($thispageurl);
-    echo $OUTPUT->footer();
-    exit;
-}
-
 // End of process actions ==================================================
 
 // Print the page heading.
@@ -184,10 +131,10 @@ echo $OUTPUT->heading(get_string('manageqtypes', 'admin'));
 $table = new flexible_table('qtypeadmintable');
 $table->define_baseurl($thispageurl);
 $table->define_columns(array('questiontype', 'numquestions', 'version', 'requires',
-        'availableto', 'delete', 'settings'));
+        'availableto', 'uninstall', 'settings'));
 $table->define_headers(array(get_string('questiontype', 'question'), get_string('numquestions', 'question'),
         get_string('version'), get_string('requires', 'admin'), get_string('availableq', 'question'),
-        get_string('delete'), get_string('settings')));
+        get_string('settings'), get_string('uninstallplugin', 'core_admin')));
 $table->set_attribute('id', 'qtypes');
 $table->set_attribute('class', 'admintable generaltable');
 $table->setup();
@@ -259,15 +206,6 @@ foreach ($sortedqtypes as $qtypename => $localname) {
     $icons .= question_type_icon_html('down', $qtypename, 't/down', get_string('down'), '');
     $row[] = $icons;
 
-    // Delete link, if available.
-    if ($needed[$qtypename]) {
-        $row[] = '';
-    } else {
-        $row[] = html_writer::link(new moodle_url($thispageurl,
-                array('delete' => $qtypename, 'sesskey' => sesskey())), get_string('delete'),
-                array('title' => get_string('uninstallqtype', 'question')));
-    }
-
     // Settings link, if available.
     $settings = admin_get_root()->locate('qtypesetting' . $qtypename);
     if ($settings instanceof admin_externalpage) {
@@ -279,6 +217,17 @@ foreach ($sortedqtypes as $qtypename => $localname) {
         $row[] = '';
     }
 
+    // Uninstall link, if available.
+    if ($needed[$qtypename]) {
+        $row[] = '';
+    } else {
+        $uninstallurl = core_plugin_manager::instance()->get_uninstall_url('qtype_'.$qtypename, 'manage');
+        if ($uninstallurl) {
+            $row[] = html_writer::link($uninstallurl, get_string('uninstallplugin', 'core_admin'),
+                array('title' => get_string('uninstallqtype', 'question')));
+        }
+    }
+
     $table->add_data($row, $rowclass);
 }
 
index ca1a28c..0f84e00 100644 (file)
@@ -25,7 +25,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-require_once($CFG->libdir . '/pluginlib.php');
 
 /**
  * Standard HTML output renderer for core_admin subsystem
@@ -121,7 +120,7 @@ class core_admin_renderer extends plugin_renderer_base {
         $output .= $this->header();
         $output .= $this->heading(get_string('pluginscheck', 'admin'));
         $output .= $this->warning(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed)))));
-        $output .= $this->plugins_check_table(plugin_manager::instance(), $version, array('xdep' => true));
+        $output .= $this->plugins_check_table(core_plugin_manager::instance(), $version, array('xdep' => true));
         $output .= $this->warning(get_string('pluginschecktodo', 'admin'));
         $output .= $this->continue_button($reloadurl);
 
@@ -190,15 +189,15 @@ class core_admin_renderer extends plugin_renderer_base {
 
     /**
      * Display the upgrade page that lists all the plugins that require attention.
-     * @param plugin_manager $pluginman provides information about the plugins.
-     * @param available_update_checker $checker provides information about available updates.
+     * @param core_plugin_manager $pluginman provides information about the plugins.
+     * @param \core\update\checker $checker provides information about available updates.
      * @param int $version the version of the Moodle code from version.php.
      * @param bool $showallplugins
      * @param moodle_url $reloadurl
      * @param moodle_url $continueurl
      * @return string HTML to output.
      */
-    public function upgrade_plugin_check_page(plugin_manager $pluginman, available_update_checker $checker,
+    public function upgrade_plugin_check_page(core_plugin_manager $pluginman, \core\update\checker $checker,
             $version, $showallplugins, $reloadurl, $continueurl) {
         global $CFG;
 
@@ -240,11 +239,11 @@ class core_admin_renderer extends plugin_renderer_base {
     /**
      * Prints a page with a summary of plugin deployment to be confirmed.
      *
-     * @param available_update_deployer $deployer
-     * @param array $data deployer's data package as returned by {@link available_update_deployer::submitted_data()}
+     * @param \core\update\deployer $deployer
+     * @param array $data deployer's data package as returned by {@link \core\update\deployer::submitted_data()}
      * @return string
      */
-    public function upgrade_plugin_confirm_deploy_page(available_update_deployer $deployer, array $data) {
+    public function upgrade_plugin_confirm_deploy_page(\core\update\deployer $deployer, array $data) {
 
         if (!$deployer->initialized()) {
             throw new coding_exception('Unable to render a page for non-initialized deployer.');
@@ -302,7 +301,7 @@ class core_admin_renderer extends plugin_renderer_base {
      * @param bool $dbproblems warn db has problems
      * @param bool $maintenancemode warn in maintenance mode
      * @param bool $buggyiconvnomb warn iconv problems
-     * @param array|null $availableupdates array of available_update_info objects or null
+     * @param array|null $availableupdates array of \core\update\info objects or null
      * @param int|null $availableupdatesfetch timestamp of the most recent updates fetch or null (unknown)
      *
      * @return string HTML to output.
@@ -341,12 +340,12 @@ class core_admin_renderer extends plugin_renderer_base {
      *  bool contribonly - show only contributed extensions
      *  bool updatesonly - show only plugins with an available update
      *
-     * @param plugin_manager $pluginman
-     * @param available_update_checker $checker
+     * @param core_plugin_manager $pluginman
+     * @param \core\update\checker $checker
      * @param array $options filtering options
      * @return string HTML to output.
      */
-    public function plugin_management_page(plugin_manager $pluginman, available_update_checker $checker, array $options = array()) {
+    public function plugin_management_page(core_plugin_manager $pluginman, \core\update\checker $checker, array $options = array()) {
         global $CFG;
 
         $output = '';
@@ -377,12 +376,13 @@ class core_admin_renderer extends plugin_renderer_base {
     /**
      * Display a page to confirm the plugin uninstallation.
      *
-     * @param plugin_manager $pluginman
-     * @param plugininfo_base $pluginfo
+     * @param core_plugin_manager $pluginman
+     * @param \core\plugininfo\base $pluginfo
      * @param moodle_url $continueurl URL to continue after confirmation
+     * @param moodle_url $cancelurl URL to to go if cancelled
      * @return string
      */
-    public function plugin_uninstall_confirm_page(plugin_manager $pluginman, plugininfo_base $pluginfo, moodle_url $continueurl) {
+    public function plugin_uninstall_confirm_page(core_plugin_manager $pluginman, \core\plugininfo\base $pluginfo, moodle_url $continueurl, moodle_url $cancelurl) {
         $output = '';
 
         $pluginname = $pluginman->plugin_name($pluginfo->component);
@@ -394,7 +394,7 @@ class core_admin_renderer extends plugin_renderer_base {
 
         $output .= $this->output->header();
         $output .= $this->output->heading(get_string('uninstalling', 'core_plugin', array('name' => $pluginname)));
-        $output .= $this->output->confirm($confirm, $continueurl, $this->page->url);
+        $output .= $this->output->confirm($confirm, $continueurl, $cancelurl);
         $output .= $this->output->footer();
 
         return $output;
@@ -403,13 +403,13 @@ 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 plugininfo_base $pluginfo
+     * @param core_plugin_manager $pluginman
+     * @param \core\plugininfo\base $pluginfo
      * @param progress_trace_buffer $progress
      * @param moodle_url $continueurl URL to continue to remove the plugin folder
      * @return string
      */
-    public function plugin_uninstall_results_removable_page(plugin_manager $pluginman, plugininfo_base $pluginfo,
+    public function plugin_uninstall_results_removable_page(core_plugin_manager $pluginman, \core\plugininfo\base $pluginfo,
                                                             progress_trace_buffer $progress, moodle_url $continueurl) {
         $output = '';
 
@@ -442,12 +442,12 @@ 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 plugininfo_base $pluginfo
+     * @param core_plugin_manager $pluginman
+     * @param \core\plugininfo\base $pluginfo
      * @param progress_trace_buffer $progress
      * @return string
      */
-    public function plugin_uninstall_results_page(plugin_manager $pluginman, plugininfo_base $pluginfo, progress_trace_buffer $progress) {
+    public function plugin_uninstall_results_page(core_plugin_manager $pluginman, \core\plugininfo\base $pluginfo, progress_trace_buffer $progress) {
         $output = '';
 
         $pluginname = $pluginfo->component;
@@ -676,7 +676,7 @@ class core_admin_renderer extends plugin_renderer_base {
      * The structure of the $updates param has changed since 2.4. It contains not only updates
      * for the core itself, but also for all other installed plugins.
      *
-     * @param array|null $updates array of (string)component => array of available_update_info objects or null
+     * @param array|null $updates array of (string)component => array of \core\update\info objects or null
      * @param int|null $fetch timestamp of the most recent updates fetch or null (unknown)
      * @return string
      */
@@ -748,9 +748,9 @@ class core_admin_renderer extends plugin_renderer_base {
     /**
      * Helper method to render the information about the available Moodle update
      *
-     * @param available_update_info $updateinfo information about the available Moodle core update
+     * @param \core\update\info $updateinfo information about the available Moodle core update
      */
-    protected function moodle_available_update_info(available_update_info $updateinfo) {
+    protected function moodle_available_update_info(\core\update\info $updateinfo) {
 
         $boxclasses = 'moodleupdateinfo';
         $info = array();
@@ -817,12 +817,12 @@ class core_admin_renderer extends plugin_renderer_base {
      *     (bool)full = false: whether to display up-to-date plugins, too
      *     (bool)xdep = false: display the plugins with unsatisified dependecies only
      *
-     * @param plugin_manager $pluginman provides information about the plugins.
+     * @param core_plugin_manager $pluginman provides information about the plugins.
      * @param int $version the version of the Moodle code from version.php.
      * @param array $options rendering options
      * @return string HTML code
      */
-    public function plugins_check_table(plugin_manager $pluginman, $version, array $options = array()) {
+    public function plugins_check_table(core_plugin_manager $pluginman, $version, array $options = array()) {
         global $CFG;
 
         $plugininfo = $pluginman->get_plugins();
@@ -915,7 +915,7 @@ class core_admin_renderer extends plugin_renderer_base {
                 $requires = new html_table_cell($this->required_column($plugin, $pluginman, $version));
 
                 $statusisboring = in_array($statuscode, array(
-                        plugin_manager::PLUGIN_STATUS_NODB, plugin_manager::PLUGIN_STATUS_UPTODATE));
+                        core_plugin_manager::PLUGIN_STATUS_NODB, core_plugin_manager::PLUGIN_STATUS_UPTODATE));
 
                 $coredependency = $plugin->is_core_dependency_satisfied($version);
                 $otherpluginsdependencies = $pluginman->are_dependencies_satisfied($plugin->get_other_required_plugins());
@@ -991,12 +991,12 @@ class core_admin_renderer extends plugin_renderer_base {
 
     /**
      * Formats the information that needs to go in the 'Requires' column.
-     * @param plugininfo_base $plugin the plugin we are rendering the row for.
-     * @param plugin_manager $pluginman provides data on all the plugins.
+     * @param \core\plugininfo\base $plugin the plugin we are rendering the row for.
+     * @param core_plugin_manager $pluginman provides data on all the plugins.
      * @param string $version
      * @return string HTML code
      */
-    protected function required_column(plugininfo_base $plugin, plugin_manager $pluginman, $version) {
+    protected function required_column(\core\plugininfo\base $plugin, core_plugin_manager $pluginman, $version) {
         $requires = array();
 
         if (!empty($plugin->versionrequires)) {
@@ -1048,11 +1048,11 @@ class core_admin_renderer extends plugin_renderer_base {
     /**
      * Prints an overview about the plugins - number of installed, number of extensions etc.
      *
-     * @param plugin_manager $pluginman provides information about the plugins
+     * @param core_plugin_manager $pluginman provides information about the plugins
      * @param array $options filtering options
      * @return string as usually
      */
-    public function plugins_overview_panel(plugin_manager $pluginman, array $options = array()) {
+    public function plugins_overview_panel(core_plugin_manager $pluginman, array $options = array()) {
         global $CFG;
 
         $plugininfo = $pluginman->get_plugins();
@@ -1061,7 +1061,7 @@ class core_admin_renderer extends plugin_renderer_base {
 
         foreach ($plugininfo as $type => $plugins) {
             foreach ($plugins as $name => $plugin) {
-                if ($plugin->get_status() === plugin_manager::PLUGIN_STATUS_MISSING) {
+                if ($plugin->get_status() === core_plugin_manager::PLUGIN_STATUS_MISSING) {
                     continue;
                 }
                 $numtotal++;
@@ -1128,11 +1128,11 @@ class core_admin_renderer extends plugin_renderer_base {
      *
      * This default implementation renders all plugins into one big table.
      *
-     * @param plugin_manager $pluginman provides information about the plugins.
+     * @param core_plugin_manager $pluginman provides information about the plugins.
      * @param array $options filtering options
      * @return string HTML code
      */
-    public function plugins_control_panel(plugin_manager $pluginman, array $options = array()) {
+    public function plugins_control_panel(core_plugin_manager $pluginman, array $options = array()) {
         global $CFG;
 
         $plugininfo = $pluginman->get_plugins();
@@ -1186,8 +1186,12 @@ class core_admin_renderer extends plugin_renderer_base {
         );
 
         foreach ($plugininfo as $type => $plugins) {
-
-            $header = new html_table_cell($pluginman->plugintype_name_plural($type));
+            $heading = $pluginman->plugintype_name_plural($type);
+            $pluginclass = core_plugin_manager::resolve_plugininfo_class($type);
+            if ($manageurl = $pluginclass::get_manage_url()) {
+                $heading = html_writer::link($manageurl, $heading);
+            }
+            $header = new html_table_cell(html_writer::tag('span', $heading, array('id'=>'plugin_type_cell_'.$type)));
             $header->header = true;
             $header->colspan = array_sum($table->headspan);
             $header = new html_table_row(array($header));
@@ -1214,9 +1218,9 @@ class core_admin_renderer extends plugin_renderer_base {
                 }
                 $status = $plugin->get_status();
                 $row->attributes['class'] .= ' status-'.$status;
-                if ($status === plugin_manager::PLUGIN_STATUS_MISSING) {
+                if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
                     $msg = html_writer::tag('span', get_string('status_missing', 'core_plugin'), array('class' => 'statusmsg'));
-                } else if ($status === plugin_manager::PLUGIN_STATUS_NEW) {
+                } else if ($status === core_plugin_manager::PLUGIN_STATUS_NEW) {
                     $msg = html_writer::tag('span', get_string('status_new', 'core_plugin'), array('class' => 'statusmsg'));
                 } else {
                     $msg = '';
@@ -1254,8 +1258,7 @@ class core_admin_renderer extends plugin_renderer_base {
                 }
                 $settings = new html_table_cell($settings);
 
-                if ($pluginman->can_uninstall_plugin($plugin->component)) {
-                    $uninstallurl = $plugin->get_uninstall_url();
+                if ($uninstallurl = $pluginman->get_uninstall_url($plugin->component, 'overview')) {
                     $uninstall = html_writer::link($uninstallurl, get_string('uninstall', 'core_plugin'));
                 } else {
                     $uninstall = '';
@@ -1295,9 +1298,9 @@ class core_admin_renderer extends plugin_renderer_base {
      * The passed objects always provides at least the 'version' property containing
      * the (higher) version of the plugin available.
      *
-     * @param available_update_info $updateinfo information about the available update for the plugin
+     * @param \core\update\info $updateinfo information about the available update for the plugin
      */
-    protected function plugin_available_update_info(available_update_info $updateinfo) {
+    protected function plugin_available_update_info(\core\update\info $updateinfo) {
 
         $boxclasses = 'pluginupdateinfo';
         $info = array();
@@ -1326,7 +1329,7 @@ class core_admin_renderer extends plugin_renderer_base {
         $box .= html_writer::tag('div', get_string('updateavailable', 'core_plugin', $updateinfo->version), array('class' => 'version'));
         $box .= $this->output->box(implode(html_writer::tag('span', ' ', array('class' => 'separator')), $info), '');
 
-        $deployer = available_update_deployer::instance();
+        $deployer = \core\update\deployer::instance();
         if ($deployer->initialized()) {
             $impediments = $deployer->deployment_impediments($updateinfo);
             if (empty($impediments)) {
index 879497c..46c244f 100644 (file)
@@ -30,7 +30,6 @@
 require_once(dirname(__FILE__) . '/../config.php');
 require_once($CFG->libdir.'/adminlib.php');
 require_once($CFG->libdir.'/tablelib.php');
-require_once($CFG->libdir.'/pluginlib.php');
 
 admin_externalpage_setup('managereports');
 
@@ -46,7 +45,7 @@ $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');
+$table->set_attribute('class', 'admintable generaltable');
 $table->setup();
 
 $plugins = array();
@@ -74,7 +73,7 @@ foreach ($installed as $config) {
 
 foreach ($plugins as $plugin => $name) {
     $uninstall = '';
-    if ($uninstallurl = plugin_manager::instance()->get_uninstall_url('report_'.$plugin)) {
+    if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('report_'.$plugin, 'manage')) {
         $uninstall = html_writer::link($uninstallurl, $struninstall);
     }
 
index 05fc755..1e991e4 100644 (file)
@@ -17,7 +17,6 @@
 require_once(dirname(dirname(__FILE__)) . '/config.php');
 require_once($CFG->dirroot . '/repository/lib.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->libdir . '/pluginlib.php');
 
 $repository       = optional_param('repos', '', PARAM_ALPHANUMEXT);
 $action           = optional_param('action', '', PARAM_ALPHANUMEXT);
@@ -149,7 +148,7 @@ if (($action == 'edit') || ($action == 'new')) {
         }
         if ($success) {
             // configs saved
-            plugin_manager::reset_caches();
+            core_plugin_manager::reset_caches();
             redirect($baseurl);
         } else {
             print_error('instancenotsaved', 'repository', $baseurl);
@@ -190,7 +189,7 @@ if (($action == 'edit') || ($action == 'new')) {
         print_error('invalidplugin', 'repository', '', $repository);
     }
     $repositorytype->update_visibility(true);
-    plugin_manager::reset_caches();
+    core_plugin_manager::reset_caches();
     $return = true;
 } else if ($action == 'hide') {
     if (!confirm_sesskey()) {
@@ -201,7 +200,7 @@ if (($action == 'edit') || ($action == 'new')) {
         print_error('invalidplugin', 'repository', '', $repository);
     }
     $repositorytype->update_visibility(false);
-    plugin_manager::reset_caches();
+    core_plugin_manager::reset_caches();
     $return = true;
 } else if ($action == 'delete') {
     $repositorytype = repository::get_type_by_typename($repository);
@@ -212,7 +211,7 @@ if (($action == 'edit') || ($action == 'new')) {
         }
 
         if ($repositorytype->delete($downloadcontents)) {
-            plugin_manager::reset_caches();
+            core_plugin_manager::reset_caches();
             redirect($baseurl);
         } else {
             print_error('instancenotdeleted', 'repository', $baseurl);
index 3def4f3..0373857 100644 (file)
@@ -17,7 +17,6 @@
 require_once(dirname(dirname(__FILE__)) . '/config.php');
 require_once($CFG->dirroot . '/repository/lib.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->libdir . '/pluginlib.php');
 
 require_sesskey();
 
@@ -103,7 +102,7 @@ if (!empty($edit) || !empty($new)) {
             $data = data_submitted();
         }
         if ($success) {
-            plugin_manager::reset_caches();
+            core_plugin_manager::reset_caches();
             redirect($parenturl);
         } else {
             print_error('instancenotsaved', 'repository', $parenturl);
@@ -120,7 +119,7 @@ if (!empty($edit) || !empty($new)) {
 } else if (!empty($hide)) {
     $instance = repository::get_type_by_typename($hide);
     $instance->hide();
-    plugin_manager::reset_caches();
+    core_plugin_manager::reset_caches();
     $return = true;
 } else if (!empty($delete)) {
     $instance = repository::get_instance($delete);
@@ -133,7 +132,7 @@ if (!empty($edit) || !empty($new)) {
     if ($sure) {
         if ($instance->delete($downloadcontents)) {
             $deletedstr = get_string('instancedeleted', 'repository');
-            plugin_manager::reset_caches();
+            core_plugin_manager::reset_caches();
             redirect($parenturl, $deletedstr, 3);
         } else {
             print_error('instancenotdeleted', 'repository', $parenturl);
index cce2334..6fa632e 100644 (file)
@@ -29,6 +29,7 @@ define("MAX_USERS_TO_LIST_PER_ROLE", 10);
 
 $contextid = required_param('contextid', PARAM_INT);
 $roleid    = optional_param('roleid', 0, PARAM_INT);
+$returnto  = optional_param('return', null, PARAM_ALPHANUMEXT);
 
 list($context, $course, $cm) = get_context_info_array($contextid);
 
@@ -181,6 +182,9 @@ if ($roleid) {
 
     // Print the form.
     $assignurl = new moodle_url($PAGE->url, array('roleid'=>$roleid));
+    if ($returnto !== null) {
+        $assignurl->param('return', $returnto);
+    }
 ?>
 <form id="assignform" method="post" action="<?php echo $assignurl ?>"><div>
   <input type="hidden" name="sesskey" value="<?php echo sesskey() ?>" />
@@ -225,10 +229,17 @@ if ($roleid) {
     // Print a form to swap roles, and a link back to the all roles list.
     echo '<div class="backlink">';
 
-    $select = new single_select($PAGE->url, 'roleid', $nameswithcounts, $roleid, null);
+    $newroleurl = new moodle_url($PAGE->url);
+    if ($returnto !== null) {
+        $newroleurl->param('return', $returnto);
+    }
+    $select = new single_select($newroleurl, 'roleid', $nameswithcounts, $roleid, null);
     $select->label = get_string('assignanotherrole', 'core_role');
     echo $OUTPUT->render($select);
     $backurl = new moodle_url('/admin/roles/assign.php', array('contextid' => $contextid));
+    if ($returnto !== null) {
+        $backurl->param('return', $returnto);
+    }
     echo '<p><a href="' . $backurl->out() . '">' . get_string('backtoallroles', 'core_role') . '</a></p>';
     echo '</div>';
 
@@ -266,6 +277,9 @@ if ($roleid) {
             }
         } else if ($assigncounts[$roleid] > MAX_USERS_TO_LIST_PER_ROLE) {
             $assignurl = new moodle_url($PAGE->url, array('roleid'=>$roleid));
+            if ($returnto !== null) {
+                $assignurl->param('return', $returnto);
+            }
             $roleholdernames[$roleid] = '<a href="'.$assignurl.'">'.$strmorethanmax.'</a>';
         } else {
             $roleholdernames[$roleid] = '';
@@ -286,6 +300,9 @@ if ($roleid) {
     foreach ($assignableroles as $roleid => $rolename) {
         $description = format_string($DB->get_field('role', 'description', array('id'=>$roleid)));
         $assignurl = new moodle_url($PAGE->url, array('roleid'=>$roleid));
+        if ($returnto !== null) {
+            $assignurl->param('return', $returnto);
+        }
         $row = array('<a href="'.$assignurl.'">'.$rolename.'</a>',
                 $description, $assigncounts[$roleid]);
         if ($showroleholders) {
@@ -297,8 +314,15 @@ if ($roleid) {
     echo html_writer::table($table);
 
     if ($context->contextlevel > CONTEXT_USER) {
+
+        if ($context->contextlevel === CONTEXT_COURSECAT && $returnto === 'management') {
+            $url = new moodle_url('/course/management.php', array('categoryid' => $context->instanceid));
+        } else {
+            $url = $context->get_url();
+        }
+
         echo html_writer::start_tag('div', array('class'=>'backlink'));
-        echo html_writer::tag('a', get_string('backto', '', $contextname), array('href'=>$context->get_url()));
+        echo html_writer::tag('a', get_string('backto', '', $contextname), array('href' => $url));
         echo html_writer::end_tag('div');
     }
 }
index cfff956..8af137a 100644 (file)
@@ -33,6 +33,7 @@ $prevent    = optional_param('prevent', 0, PARAM_BOOL);
 $allow      = optional_param('allow', 0, PARAM_BOOL);
 $unprohibit = optional_param('unprohibit', 0, PARAM_BOOL);
 $prohibit   = optional_param('prohibit', 0, PARAM_BOOL);
+$return     = optional_param('return', null, PARAM_ALPHANUMEXT);
 
 list($context, $course, $cm) = get_context_info_array($contextid);
 
@@ -201,8 +202,15 @@ echo $OUTPUT->box_end();
 
 
 if ($context->contextlevel > CONTEXT_USER) {
+
+    if ($context->contextlevel === CONTEXT_COURSECAT && $return === 'management') {
+        $url = new moodle_url('/course/management.php', array('categoryid' => $context->instanceid));
+    } else {
+        $url = $context->get_url();
+    }
+
     echo html_writer::start_tag('div', array('class'=>'backlink'));
-    echo html_writer::tag('a', get_string('backto', '', $contextname), array('href'=>$context->get_url()));
+    echo html_writer::tag('a', get_string('backto', '', $contextname), array('href' => $url));
     echo html_writer::end_tag('div');
 }
 
index 4005c7c..d69b8e2 100644 (file)
@@ -1,20 +1,51 @@
 <?php
-
-// This file defines settingpages and externalpages under the "courses" category
-
-if ($hassiteconfig
- or has_capability('moodle/backup:backupcourse', $systemcontext)
- or has_capability('moodle/category:manage', $systemcontext)
- or has_capability('moodle/course:create', $systemcontext)
- or has_capability('moodle/site:approvecourse', $systemcontext)) { // speedup for non-admins, add all caps used on this page
-
-    $ADMIN->add('courses', new admin_externalpage('coursemgmt', new lang_string('coursemgmt', 'admin'), $CFG->wwwroot . '/course/manage.php',
-            array('moodle/category:manage', 'moodle/course:create')));
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file defines settingpages and externalpages under the "courses" category
+ *
+ * @package core
+ * @copyright 2002 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$capabilities = array(
+    'moodle/backup:backupcourse',
+    'moodle/category:manage',
+    'moodle/course:create',
+    'moodle/site:approvecourse'
+);
+if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
+    // Speedup for non-admins, add all caps used on this page.
+    $ADMIN->add('courses',
+        new admin_externalpage('coursemgmt', new lang_string('coursemgmt', 'admin'),
+            $CFG->wwwroot . '/course/management.php',
+            array('moodle/category:manage', 'moodle/course:create')
+        )
+    );
+    $ADMIN->add('courses',
+        new admin_externalpage('addcategory', new lang_string('addcategory', 'admin'),
+            new moodle_url('/course/editcategory.php', array('parent' => 0)),
+            array('moodle/category:manage')
+        )
+    );
 
     // Course Default Settings Page.
     // NOTE: these settings must be applied after all other settings because they depend on them.
 
-
     // Main course settings.
     $temp = new admin_settingpage('coursesettings', new lang_string('coursesettings'));
     require_once($CFG->dirroot.'/course/lib.php');
@@ -25,7 +56,6 @@ if ($hassiteconfig
     $temp->add(new admin_setting_configselect('moodlecourse/visible', new lang_string('visible'), new lang_string('visible_help'),
         1, $choices));
 
-
     // Course format.
     $temp->add(new admin_setting_heading('courseformathdr', new lang_string('type_format', 'plugin'), ''));
 
@@ -55,7 +85,6 @@ if ($hassiteconfig
     $temp->add(new admin_setting_configselect('moodlecourse/coursedisplay', new lang_string('coursedisplay'),
         new lang_string('coursedisplay_help'), COURSE_DISPLAY_SINGLEPAGE, $choices));
 
-
     // Appearance.
     $temp->add(new admin_setting_heading('appearancehdr', new lang_string('appearance'), ''));
 
@@ -73,7 +102,6 @@ if ($hassiteconfig
     $temp->add(new admin_setting_configselect('moodlecourse/showreports', new lang_string('showreports'), '', 0,
         array(0 => new lang_string('no'), 1 => new lang_string('yes'))));
 
-
     // Files and uploads.
     $temp->add(new admin_setting_heading('filesanduploadshdr', new lang_string('filesanduploads'), ''));
 
@@ -92,13 +120,11 @@ if ($hassiteconfig
     $temp->add(new admin_setting_configselect('moodlecourse/maxbytes', new lang_string('maximumupload'),
         new lang_string('coursehelpmaximumupload'), key($choices), $choices));
 
-
     // Completion tracking.
     $temp->add(new admin_setting_heading('progress', new lang_string('completion','completion'), ''));
     $temp->add(new admin_setting_configselect('moodlecourse/enablecompletion', new lang_string('completion', 'completion'),
         new lang_string('enablecompletion_help', 'completion'), 0, array(0 => new lang_string('no'), 1 => new lang_string('yes'))));
 
-
     // Groups.
     $temp->add(new admin_setting_heading('groups', new lang_string('groups', 'group'), ''));
     $choices = array();
@@ -119,13 +145,13 @@ if ($hassiteconfig
     $temp->add(new admin_setting_users_with_capability('courserequestnotify', new lang_string('courserequestnotify', 'admin'), new lang_string('configcourserequestnotify2', 'admin'), array(), 'moodle/site:approvecourse'));
     $ADMIN->add('courses', $temp);
 
-/// Pending course requests.
+    // Pending course requests.
     if (!empty($CFG->enablecourserequests)) {
         $ADMIN->add('courses', new admin_externalpage('coursespending', new lang_string('pendingrequests'),
                 $CFG->wwwroot . '/course/pending.php', array('moodle/site:approvecourse')));
     }
 
-    // Add a category for backups
+    // Add a category for backups.
     $ADMIN->add('courses', new admin_category('backups', new lang_string('backups','admin')));
 
     // Create a page for general backups configuration and defaults.
@@ -239,10 +265,8 @@ if ($hassiteconfig
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_histories', new lang_string('generalhistories','backup'), new lang_string('configgeneralhistories','backup'), 0));
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_questionbank', new lang_string('generalquestionbank','backup'), new lang_string('configgeneralquestionbank','backup'), 1));
 
-
     //$temp->add(new admin_setting_configcheckbox('backup/backup_auto_messages', new lang_string('messages', 'message'), new lang_string('backupmessageshelp','message'), 0));
     //$temp->add(new admin_setting_configcheckbox('backup/backup_auto_blogs', new lang_string('blogs', 'blog'), new lang_string('backupblogshelp','blog'), 0));
 
     $ADMIN->add('backups', $temp);
-
-} // end of speedup
+}
index 19bace3..0865b75 100644 (file)
@@ -1,23 +1,38 @@
 <?php
-
-/*
- * Please note that is file is always loaded last - it means that you can inject entries into other categories too.
- */
+// 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/>.
+
+/**
+ * Load all plugins into the admin tree.
+ *
+* Please note that is file is always loaded last - it means that you can inject entries into other categories too.
+*
+* @package    core
+* @copyright  2007 Petr Skoda {@link http://skodak.org}
+* @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+*/
 
 if ($hassiteconfig) {
-    require_once("$CFG->libdir/pluginlib.php");
-    $allplugins = plugin_manager::instance()->get_plugins();
-
     $ADMIN->add('modules', new admin_page_pluginsoverview());
 
     // activity modules
     $ADMIN->add('modules', new admin_category('modsettings', new lang_string('activitymodules')));
     $ADMIN->add('modsettings', new admin_page_managemods());
-    foreach ($allplugins['mod'] as $module) {
-        if (!$module->is_updated()) {
-            continue;
-        }
-        $module->load_settings($ADMIN, 'modsettings', $hassiteconfig);
+    foreach (core_plugin_manager::instance()->get_plugins_of_type('mod') as $plugin) {
+        /** @var \core\plugininfo\mod $plugin */
+        $plugin->load_settings($ADMIN, 'modsettings', $hassiteconfig);
     }
 
     // course formats
@@ -25,32 +40,26 @@ if ($hassiteconfig) {
     $temp = new admin_settingpage('manageformats', new lang_string('manageformats', 'core_admin'));
     $temp->add(new admin_setting_manageformats());
     $ADMIN->add('formatsettings', $temp);
-    foreach ($allplugins['format'] as $format) {
-        if (!$format->is_updated()) {
-            continue;
-        }
-        $format->load_settings($ADMIN, 'formatsettings', $hassiteconfig);
+    foreach (core_plugin_manager::instance()->get_plugins_of_type('format') as $plugin) {
+        /** @var \core\plugininfo\format $plugin */
+        $plugin->load_settings($ADMIN, 'formatsettings', $hassiteconfig);
     }
 
     // blocks
     $ADMIN->add('modules', new admin_category('blocksettings', new lang_string('blocks')));
     $ADMIN->add('blocksettings', new admin_page_manageblocks());
-    foreach ($allplugins['block'] as $block) {
-        if (!$block->is_updated()) {
-            continue;
-        }
-        $block->load_settings($ADMIN, 'blocksettings', $hassiteconfig);
+    foreach (core_plugin_manager::instance()->get_plugins_of_type('block') as $plugin) {
+        /** @var \core\plugininfo\block $plugin */
+        $plugin->load_settings($ADMIN, 'blocksettings', $hassiteconfig);
     }
 
     // message outputs
     $ADMIN->add('modules', new admin_category('messageoutputs', new lang_string('messageoutputs', 'message')));
     $ADMIN->add('messageoutputs', new admin_page_managemessageoutputs());
     $ADMIN->add('messageoutputs', new admin_page_defaultmessageoutputs());
-    foreach ($allplugins['message'] as $processor) {
-        if (!$processor->is_updated()) {
-            continue;
-        }
-        $processor->load_settings($ADMIN, 'messageoutputs', $hassiteconfig);
+    foreach (core_plugin_manager::instance()->get_plugins_of_type('message') as $plugin) {
+        /** @var \core\plugininfo\message $plugin */
+        $plugin->load_settings($ADMIN, 'messageoutputs', $hassiteconfig);
     }
 
     // authentication plugins
@@ -78,11 +87,9 @@ if ($hassiteconfig) {
     $temp->add(new admin_setting_configtext('recaptchaprivatekey', new lang_string('recaptchaprivatekey', 'admin'), new lang_string('configrecaptchaprivatekey', 'admin'), '', PARAM_NOTAGS));
     $ADMIN->add('authsettings', $temp);
 
-    foreach ($allplugins['auth'] as $auth) {
-        if (!$auth->is_updated()) {
-            continue;
-        }
-        $auth->load_settings($ADMIN, 'authsettings', $hassiteconfig);
+    foreach (core_plugin_manager::instance()->get_plugins_of_type('auth') as $plugin) {
+        /** @var \core\plugininfo\auth $plugin */
+        $plugin->load_settings($ADMIN, 'authsettings', $hassiteconfig);
     }
 
     // Enrolment plugins
@@ -90,11 +97,9 @@ if ($hassiteconfig) {
     $temp = new admin_settingpage('manageenrols', new lang_string('manageenrols', 'enrol'));
     $temp->add(new admin_setting_manageenrols());
     $ADMIN->add('enrolments', $temp);
-    foreach($allplugins['enrol'] as $enrol) {
-        if (!$enrol->is_updated()) {
-            continue;
-        }
-        $enrol->load_settings($ADMIN, 'enrolments', $hassiteconfig);
+    foreach(core_plugin_manager::instance()->get_plugins_of_type('enrol') as $plugin) {
+        /** @var \core\plugininfo\enrol $plugin */
+        $plugin->load_settings($ADMIN, 'enrolments', $hassiteconfig);
     }
 
 
@@ -103,11 +108,9 @@ if ($hassiteconfig) {
     $temp = new admin_settingpage('manageeditors', new lang_string('editorsettings', 'editor'));
     $temp->add(new admin_setting_manageeditors());
     $ADMIN->add('editorsettings', $temp);
-    foreach ($allplugins['editor'] as $editor) {
-        if (!$editor->is_updated()) {
-            continue;
-        }
-        $editor->load_settings($ADMIN, 'editorsettings', $hassiteconfig);
+    foreach (core_plugin_manager::instance()->get_plugins_of_type('editor') as $plugin) {
+        /** @var \core\plugininfo\editor $plugin */
+        $plugin->load_settings($ADMIN, 'editorsettings', $hassiteconfig);
     }
 
 /// License types
@@ -168,11 +171,9 @@ if ($hassiteconfig) {
     }
     $ADMIN->add('filtersettings', $temp);
 
-    foreach ($allplugins['filter'] as $filter) {
-        if (!$filter->is_updated()) {
-            continue;
-        }
-        $filter->load_settings($ADMIN, 'filtersettings', $hassiteconfig);
+    foreach (core_plugin_manager::instance()->get_plugins_of_type('filter') as $plugin) {
+        /** @var \core\plugininfo\filter $plugin */
+        $plugin->load_settings($ADMIN, 'filtersettings', $hassiteconfig);
     }
 
 
@@ -262,11 +263,9 @@ if ($hassiteconfig) {
         new lang_string('createrepository', 'repository'), $url, 'moodle/site:config', true));
     $ADMIN->add('repositorysettings', new admin_externalpage('repositoryinstanceedit',
         new lang_string('editrepositoryinstance', 'repository'), $url, 'moodle/site:config', true));
-    foreach ($allplugins['repository'] as $repositorytype) {
-        if (!$repositorytype->is_updated()) {
-            continue;
-        }
-        $repositorytype->load_settings($ADMIN, 'repositorysettings', $hassiteconfig);
+    foreach (core_plugin_manager::instance()->get_plugins_of_type('repository') as $plugin) {
+        /** @var \core\plugininfo\repository $plugin */
+        $plugin->load_settings($ADMIN, 'repositorysettings', $hassiteconfig);
     }
 
 /// Web services
@@ -314,11 +313,9 @@ if ($hassiteconfig) {
                         'admin'), new lang_string('configenablewsdocumentation', 'admin', $wsdoclink), false));
     $ADMIN->add('webservicesettings', $temp);
     /// links to protocol pages
-    foreach ($allplugins['webservice'] as $webservice) {
-        if (!$webservice->is_updated()) {
-            continue;
-        }
-        $webservice->load_settings($ADMIN, 'webservicesettings', $hassiteconfig);
+    foreach (core_plugin_manager::instance()->get_plugins_of_type('webservice') as $plugin) {
+        /** @var \core\plugininfo\webservice $plugin */
+        $plugin->load_settings($ADMIN, 'webservicesettings', $hassiteconfig);
     }
     /// manage token page link
     $ADMIN->add('webservicesettings', new admin_externalpage('addwebservicetoken', new lang_string('managetokens', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/tokens.php", 'moodle/site:config', true));
@@ -332,10 +329,6 @@ if ($hassiteconfig) {
 
 // Question type settings
 if ($hassiteconfig || has_capability('moodle/question:config', $systemcontext)) {
-    if (!$hassiteconfig) {
-        require_once("$CFG->libdir/pluginlib.php");
-        $allplugins = plugin_manager::instance()->get_plugins();
-    }
 
     // Question behaviour settings.
     $ADMIN->add('modules', new admin_category('qbehavioursettings', new lang_string('questionbehaviours', 'admin')));
@@ -392,11 +385,9 @@ if ($hassiteconfig || has_capability('moodle/question:config', $systemcontext))
             get_string('responsehistory', 'question'), '', 0, $hiddenofvisible));
 
     // Settings for particular question types.
-    foreach ($allplugins['qtype'] as $qtype) {
-        if (!$qtype->is_updated()) {
-            continue;
-        }
-        $qtype->load_settings($ADMIN, 'qtypesettings', $hassiteconfig);
+    foreach (core_plugin_manager::instance()->get_plugins_of_type('qtype') as $plugin) {
+        /** @var \core\plugininfo\qtype $plugin */
+        $plugin->load_settings($ADMIN, 'qtypesettings', $hassiteconfig);
     }
 }
 
@@ -406,10 +397,8 @@ if ($hassiteconfig && !empty($CFG->enableplagiarism)) {
     $ADMIN->add('plagiarism', new admin_externalpage('manageplagiarismplugins', new lang_string('manageplagiarism', 'plagiarism'),
         $CFG->wwwroot . '/' . $CFG->admin . '/plagiarism.php'));
 
-    foreach ($allplugins['plagiarism'] as $plugin) {
-        if (!$plugin->is_updated()) {
-            continue;
-        }
+    foreach (core_plugin_manager::instance()->get_plugins_of_type('plagiarism') as $plugin) {
+        /** @var \core\plugininfo\plagiarism $plugin */
         $plugin->load_settings($ADMIN, 'plagiarism', $hassiteconfig);
     }
 }
@@ -466,12 +455,10 @@ if ($hassiteconfig) {
                                                      $CFG->wwwroot . '/' . $CFG->admin . '/tools.php'));
 }
 
-// Now add various admin tools
-foreach (core_component::get_plugin_list('tool') as $plugin => $plugindir) {
-    $settings_path = "$plugindir/settings.php";
-    if (file_exists($settings_path)) {
-        include($settings_path);
-    }
+// Now add various admin tools.
+foreach (core_plugin_manager::instance()->get_plugins_of_type('tool') as $plugin) {
+    /** @var \core\plugininfo\tool $plugin */
+    $plugin->load_settings($ADMIN, null, $hassiteconfig);
 }
 
 // Now add the Cache plugins
@@ -497,12 +484,9 @@ if ($hassiteconfig) {
                                                         $CFG->wwwroot . '/' . $CFG->admin . '/localplugins.php'));
 }
 
-// extend settings for each local plugin. Note that their settings may be in any part of the
-// settings tree and may be visible not only for administrators. We can not use $allplugins here
-foreach (core_component::get_plugin_list('local') as $plugin => $plugindir) {
-    $settings_path = "$plugindir/settings.php";
-    if (file_exists($settings_path)) {
-        include($settings_path);
-        continue;
-    }
+// Extend settings for each local plugin. Note that their settings may be in any part of the
+// settings tree and may be visible not only for administrators.
+foreach (core_plugin_manager::instance()->get_plugins_of_type('local') as $plugin) {
+    /** @var \core\plugininfo\local $plugin */
+    $plugin->load_settings($ADMIN, null, $hassiteconfig);
 }
index 3d63ce6..62712e3 100644 (file)
@@ -70,6 +70,22 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
     $temp->add(new admin_setting_configtext('minpasswordupper', new lang_string('minpasswordupper', 'admin'), new lang_string('configminpasswordupper', 'admin'), 1, PARAM_INT));
     $temp->add(new admin_setting_configtext('minpasswordnonalphanum', new lang_string('minpasswordnonalphanum', 'admin'), new lang_string('configminpasswordnonalphanum', 'admin'), 1, PARAM_INT));
     $temp->add(new admin_setting_configtext('maxconsecutiveidentchars', new lang_string('maxconsecutiveidentchars', 'admin'), new lang_string('configmaxconsecutiveidentchars', 'admin'), 0, PARAM_INT));
+    $pwresetoptions = array(
+        300 => new lang_string('numminutes', '', 5),
+        900 => new lang_string('numminutes', '', 15),
+        1800 => new lang_string('numminutes', '', 30),
+        2700 => new lang_string('numminutes', '', 45),
+        3600 => new lang_string('numminutes', '', 60),
+        7200 => new lang_string('numminutes', '', 120),
+        14400 => new lang_string('numminutes', '', 240)
+    );
+    $adminsetting = new admin_setting_configselect(
+            'pwresettime',
+            new lang_string('passwordresettime','admin'),
+            new lang_string('configpasswordresettime','admin'),
+            1800,
+            $pwresetoptions);
+    $temp->add($adminsetting);
     $temp->add(new admin_setting_configcheckbox('groupenrolmentkeypolicy', new lang_string('groupenrolmentkeypolicy', 'admin'), new lang_string('groupenrolmentkeypolicy_desc', 'admin'), 1));
     $temp->add(new admin_setting_configcheckbox('disableuserimages', new lang_string('disableuserimages', 'admin'), new lang_string('configdisableuserimages', 'admin'), 0));
     $temp->add(new admin_setting_configcheckbox('emailchangeconfirmation', new lang_string('emailchangeconfirmation', 'admin'), new lang_string('configemailchangeconfirmation', 'admin'), 1));
index ab41e3d..287a535 100644 (file)
@@ -164,7 +164,6 @@ require("$CFG->dirroot/lib/setup.php");
 require_once($CFG->libdir.'/adminlib.php');
 require_once($CFG->libdir.'/upgradelib.php');
 require_once($CFG->libdir.'/clilib.php');
-require_once($CFG->libdir.'/pluginlib.php');
 require_once($CFG->libdir.'/installlib.php');
 require_once($CFG->libdir.'/testing/classes/test_lock.php');
 
index 4ec803d..364b54e 100644 (file)
@@ -36,7 +36,7 @@ Feature: Page contents assertions
     And I log in as "admin"
     And I follow "Course 1"
     When I click on "Move this to the dock" "button" in the "Administration" "block"
-    Then I should not see "Question bank"
+    Then I should not see "Question bank" in the "region-pre" "region"
     And I click on "//div[@id='dock']/descendant::h2[normalize-space(.)='Administration']" "xpath_element"
 
   @javascript
@@ -46,4 +46,4 @@ Feature: Page contents assertions
       | Course 1 | C1 | 0 |
     And I log in as "admin"
     When I click on "Move this to the dock" "button" in the "Administration" "block"
-    Then I should not see "Turn editing on"
+    Then I should not see "Turn editing on" in the "region-pre" "region"
index c0d3665..45d1ed6 100644 (file)
@@ -37,9 +37,9 @@ Feature: Set up contextual data for tests
     And I follow "Cat 3"
     And I should see "Course 1"
     And I should see "Course 2"
-    And I select "Cat 1 / Cat 2" from "Course categories:"
+    And I follow "Cat 2"
     And I should see "No courses in this category"
-    And I select "Miscellaneous" from "Course categories:"
+    And I follow "Miscellaneous"
     And I should see "Course 3"
 
   @javascript
index 4bf47d0..2b9ed46 100644 (file)
@@ -32,5 +32,5 @@ Feature: Forms manipulation
     Then I should see "Close the quiz"
     And I should see "Group mode"
     And I should see "Grouping"
-    And I should not see "Show more..."
+    And I should not see "Show more..." in the "region-main-box" "region"
     And I should see "Show less..."
index 3357365..c7e622f 100644 (file)
@@ -165,7 +165,7 @@ function tool_dbtransfer_get_drivers() {
 function tool_dbtransfer_create_maintenance_file() {
     global $CFG;
 
-    register_shutdown_function('tool_dbtransfer_maintenance_callback');
+    core_shutdown_manager::register_function('tool_dbtransfer_maintenance_callback');
 
     $options = new stdClass();
     $options->trusted = false;
index 37c3600..1a1866c 100644 (file)
@@ -158,9 +158,8 @@ class tool_installaddon_installer {
      */
     public function get_plugin_types_menu() {
         global $CFG;
-        require_once($CFG->libdir.'/pluginlib.php');
 
-        $pluginman = plugin_manager::instance();
+        $pluginman = core_plugin_manager::instance();
 
         $menu = array('' => get_string('choosedots'));
         foreach (array_keys($pluginman->get_plugin_types()) as $plugintype) {
index be593a2..13dcacc 100644 (file)
@@ -90,7 +90,6 @@ require(__DIR__ . '/../../../../lib/phpunit/bootstrap.php');
 require_once($CFG->libdir.'/adminlib.php');
 require_once($CFG->libdir.'/upgradelib.php');
 require_once($CFG->libdir.'/clilib.php');
-require_once($CFG->libdir.'/pluginlib.php');
 require_once($CFG->libdir.'/installlib.php');
 
 if ($unrecognized) {
index eda56a8..f471b23 100644 (file)
@@ -572,6 +572,7 @@ function tool_qeupgradehelper_generate_unit_test($questionsessionid, $namesuffix
             'variant' => 1,
             'maxmark' => {$question->maxmark},
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => '',
             'rightanswer' => '',
index 5f6a468..d4223b6 100644 (file)
@@ -45,7 +45,7 @@ $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', 'toolplugins');
-$table->set_attribute('class', 'generaltable generalbox boxaligncenter boxwidthwide');
+$table->set_attribute('class', 'admintable generaltable');
 $table->setup();
 
 $plugins = array();
@@ -73,7 +73,7 @@ foreach ($installed as $config) {
 
 foreach ($plugins as $plugin => $name) {
     $uninstall = '';
-    if ($uninstallurl = plugin_manager::instance()->get_uninstall_url('tool_'.$plugin)) {
+    if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('tool_'.$plugin, 'manage')) {
         $uninstall = html_writer::link($uninstallurl, $struninstall);
     }
 
index b18fa1a..3155958 100644 (file)
@@ -29,3 +29,5 @@ defined('MOODLE_INTERNAL') || die();
 $plugin->version   = 2013052100;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2013050100;        // Requires this Moodle version
 $plugin->component = 'auth_cas';        // Full name of the plugin (used for diagnostics)
+
+$plugin->dependencies = array('auth_ldap' => 2013052100);
index 1dcbee8..3d5653f 100644 (file)
@@ -20,7 +20,7 @@ class cssparser {
 
   function cssparser($html = true) {
     // Register "destructor"
-    register_shutdown_function(array(&$this, "finalize"));
+    core_shutdown_manager::register_function(array(&$this, "finalize"));
     $this->html = ($html != false);
     $this->Clear();
   }
index fa22a79..7aaefe6 100644 (file)
@@ -209,7 +209,7 @@ abstract class backup_questions_activity_structure_step extends backup_activity_
 
         $qas = new backup_nested_element($nameprefix . 'question_attempts');
         $qa = new backup_nested_element($nameprefix . 'question_attempt', array('id'), array(
-                'slot', 'behaviour', 'questionid', 'maxmark', 'minfraction',
+                'slot', 'behaviour', 'questionid', 'maxmark', 'minfraction', 'maxfraction',
                 'flagged', 'questionsummary', 'rightanswer', 'responsesummary',
                 'timemodified'));
 
index 1afa523..dea8ab0 100644 (file)
@@ -4047,6 +4047,10 @@ abstract class restore_questions_activity_structure_step extends restore_activit
         $data->questionid      = $question->newitemid;
         $data->timemodified    = $this->apply_date_offset($data->timemodified);
 
+        if (!property_exists($data, 'maxfraction')) {
+            $data->maxfraction = 1;
+        }
+
         $newitemid = $DB->insert_record('question_attempts', $data);
 
         $this->set_mapping($nameprefix . 'question_attempt', $oldid, $newitemid);
index 29c1f1d..1615dac 100644 (file)
@@ -41,6 +41,8 @@ $result = badges_check_backpack_accessibility();
 $outcome = new stdClass();
 $outcome->code = $result;
 $outcome->response = get_string('error:backpacknotavailable', 'badges') . $OUTPUT->help_icon('backpackavailability', 'badges');
+
+echo $OUTPUT->header();
 echo json_encode($outcome);
 
 die();
index 0bd944e..2e8d3ac 100644 (file)
@@ -24,6 +24,8 @@
  * @author     Yuliya Bozhko <yuliya.bozhko@totaralms.com>
  */
 
+define('AJAX_SCRIPT', true);
+
 require_once(dirname(dirname(__FILE__)) . '/config.php');
 
 if (empty($CFG->enablebadges)) {
@@ -43,6 +45,6 @@ if (!is_null($action)) {
     $json = $assertion->get_badge_assertion();
 }
 
-header('Content-type: application/json; charset=utf-8');
 
+echo $OUTPUT->header();
 echo json_encode($json);
index 55bc2ec..bbcc78f 100644 (file)
@@ -34,6 +34,7 @@ require_sesskey();
 require_login();
 $PAGE->set_url('/badges/backpackconnect.php');
 $PAGE->set_context(context_system::instance());
+echo $OUTPUT->header();
 
 // Use PHP input filtering as there is no PARAM type for
 // the type of cleaning that is required (ASCII chars 32-127 only).
index fe21d76..a7224e5 100644 (file)
@@ -142,7 +142,7 @@ $fromformdata['subject'] = optional_param('subject', 'all', PARAM_ALPHANUMEXT);
 $fromformdata['audience'] = optional_param('audience', 'all', PARAM_ALPHANUMEXT);
 $fromformdata['language'] = optional_param('language', current_language(), PARAM_ALPHANUMEXT);
 $fromformdata['educationallevel'] = optional_param('educationallevel', 'all', PARAM_ALPHANUMEXT);
-$fromformdata['downloadable'] = optional_param('downloadable', 1, PARAM_ALPHANUM);
+$fromformdata['downloadable'] = optional_param('downloadable', $usercandownload, PARAM_ALPHANUM);
 $fromformdata['orderby'] = optional_param('orderby', 'newest', PARAM_ALPHA);
 $fromformdata['huburl'] = optional_param('huburl', HUB_MOODLEORGHUBURL, PARAM_URL);
 $fromformdata['search'] = $search;
index 3a01716..b92dd5c 100644 (file)
@@ -213,6 +213,7 @@ class community_hub_search_form extends moodleform {
             } else {
                 $mform->addElement('hidden', 'downloadable', 0);
             }
+            $mform->setType('downloadable', PARAM_INT);
 
             $options = array();
             $options['all'] = get_string('any');
index 9636ae7..8af781e 100644 (file)
@@ -28,3 +28,5 @@ defined('MOODLE_INTERNAL') || die();
 $plugin->version   = 2013050100;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2013050100;        // Requires this Moodle version
 $plugin->component = 'block_feedback';  // Full name of the plugin (used for diagnostics)
+
+$plugin->dependencies = array('mod_feedback' => 2013050100);
index 1348e96..dd5d0e2 100644 (file)
@@ -28,3 +28,5 @@ defined('MOODLE_INTERNAL') || die();
 $plugin->version   = 2013050100;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2013050100;        // Requires this Moodle version
 $plugin->component = 'block_glossary_random'; // Full name of the plugin (used for diagnostics)
+
+$plugin->dependencies = array('mod_glossary' => 2013050100);
index 0ed1df9..c16b985 100644 (file)
@@ -28,3 +28,5 @@ defined('MOODLE_INTERNAL') || die();
 $plugin->version   = 2013050100;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2013050100;        // Requires this Moodle version
 $plugin->component = 'block_quiz_results'; // Full name of the plugin (used for diagnostics)
+
+$plugin->dependencies = array('mod_quiz' => 2013100200);
index 5159923..32317ce 100644 (file)
@@ -28,3 +28,5 @@ defined('MOODLE_INTERNAL') || die();
 $plugin->version   = 2013050100;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2013050100;        // Requires this Moodle version
 $plugin->component = 'block_search_forums'; // Full name of the plugin (used for diagnostics)
+
+$plugin->dependencies = array('mod_forum' => 2013092600);
diff --git a/calendar/yui/build/moodle-calendar-eventmanager/assets/skins/sam/eventmanager.css b/calendar/yui/build/moodle-calendar-eventmanager/assets/skins/sam/eventmanager.css
deleted file mode 100644 (file)
index bad89d8..0000000
Binary files a/calendar/yui/build/moodle-calendar-eventmanager/assets/skins/sam/eventmanager.css and /dev/null differ
diff --git a/course/ajax/management.php b/course/ajax/management.php
new file mode 100644 (file)
index 0000000..92315a8
--- /dev/null
@@ -0,0 +1,111 @@
+<?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/>.
+
+/**
+ * Performs course category management ajax actions.
+ *
+ * Please note functions may throw exceptions, please ensure your JS handles them as well as the outcome objects.
+ *
+ * @package    core_course
+ * @copyright  2013 Sam Hemelryk
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define('AJAX_SCRIPT', true);
+
+require_once('../../config.php');
+require_once($CFG->dirroot.'/lib/coursecatlib.php');
+require_once($CFG->dirroot.'/course/lib.php');
+
+$action = required_param('action', PARAM_ALPHA);
+require_sesskey(); // Gotta have the sesskey.
+require_login(); // Gotta be logged in (of course).
+
+// Prepare an outcome object. We always use this.
+$outcome = new stdClass;
+$outcome->error = false;
+$outcome->outcome = false;
+
+echo $OUTPUT->header();
+
+switch ($action) {
+    case 'movecourseup' :
+        $courseid = required_param('courseid', PARAM_INT);
+        $outcome->outcome = \core_course\management\helper::action_course_change_sortorder_up_one_by_record($courseid);
+        break;
+    case 'movecoursedown' :
+        $courseid = required_param('courseid', PARAM_INT);
+        $outcome->outcome = \core_course\management\helper::action_course_change_sortorder_down_one_by_record($courseid);
+        break;
+    case 'movecourseintocategory':
+        $courseid = required_param('courseid', PARAM_INT);
+        $categoryid = required_param('categoryid', PARAM_INT);
+        $outcome->outcome = \core_course\management\helper::move_courses_into_category($categoryid, $courseid);
+        break;
+    case 'movecourseafter' :
+        $courseid = required_param('courseid', PARAM_INT);
+        $moveaftercourseid = required_param('moveafter', PARAM_INT);
+        $outcome->outcome = \core_course\management\helper::action_course_change_sortorder_after_course(
+            $courseid, $moveaftercourseid);
+        break;
+    case 'hidecourse' :
+        $courseid = required_param('courseid', PARAM_INT);
+        $outcome->outcome = \core_course\management\helper::action_course_hide_by_record($courseid);
+        break;
+    case 'showcourse' :
+        $courseid = required_param('courseid', PARAM_INT);
+        $outcome->outcome = \core_course\management\helper::action_course_show_by_record($courseid);
+        break;
+    case 'movecategoryup' :
+        $categoryid = required_param('categoryid', PARAM_INT);
+        $outcome->outcome = \core_course\management\helper::action_category_change_sortorder_up_one_by_id($categoryid);
+        break;
+    case 'movecategorydown' :
+        $categoryid = required_param('categoryid', PARAM_INT);
+        $outcome->outcome = \core_course\management\helper::action_category_change_sortorder_down_one_by_id($categoryid);
+        break;
+    case 'hidecategory' :
+        $categoryid = required_param('categoryid', PARAM_INT);
+        $outcome->outcome = \core_course\management\helper::action_category_hide_by_id($categoryid);
+        $outcome->categoryvisibility = \core_course\management\helper::get_category_children_visibility($categoryid);
+        $outcome->coursevisibility = \core_course\management\helper::get_category_courses_visibility($categoryid);
+        break;
+    case 'showcategory' :
+        $categoryid = required_param('categoryid', PARAM_INT);
+        $outcome->outcome = \core_course\management\helper::action_category_show_by_id($categoryid);
+        $outcome->categoryvisibility = \core_course\management\helper::get_category_children_visibility($categoryid);
+        $outcome->coursevisibility = \core_course\management\helper::get_category_courses_visibility($categoryid);
+        break;
+    case 'getsubcategorieshtml' :
+        $categoryid = required_param('categoryid', PARAM_INT);
+        /* @var core_course_management_renderer $renderer */
+        $renderer = $PAGE->get_renderer('core_course', 'management');
+        $outcome->html = html_writer::start_tag('ul', array('class' => 'ml'));
+        $coursecat = coursecat::get($categoryid);
+        foreach ($coursecat->get_children() as $subcat) {
+            $outcome->html .= $renderer->category_listitem($subcat, array(), $subcat->get_children_count());
+        }
+        $outcome->html .= html_writer::end_tag('ul');
+        $outcome->outcome = true;
+        break;
+}
+
+echo json_encode($outcome);
+echo $OUTPUT->footer();
+// Thats all folks.
+// Don't ever even consider putting anything after this. It just wouldn't make sense.
+// But you already knew that, you smart developer you.
+exit;
\ No newline at end of file
index df2a352..89a119d 100644 (file)
 /**
  * Displays the top level category or all courses
  *
- * @package    core
- * @subpackage course
+ * @package    core_coure
  * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 require_once("../config.php");
 
-$categoryid = required_param('id', PARAM_INT); // Category id
+$categoryid = required_param('id', PARAM_INT); // Category id.
 
 debugging('Please use URL /course/index.php?categoryid=XXX instead of /course/category.php?id=XXX', DEBUG_DEVELOPER);
 
diff --git a/course/classes/deletecategory_form.php b/course/classes/deletecategory_form.php
new file mode 100644 (file)
index 0000000..0d171c4
--- /dev/null
@@ -0,0 +1,143 @@
+<?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/>.
+
+/**
+ * Delete category form.
+ *
+ * @package core_course
+ * @copyright 2002 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->libdir . '/formslib.php');
+require_once($CFG->libdir . '/questionlib.php');
+require_once($CFG->libdir . '/coursecatlib.php');
+
+/**
+ * Delete category moodleform.
+ * @package core_course
+ * @copyright 2002 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class core_course_deletecategory_form extends moodleform {
+
+    /**
+     * The coursecat object for that category being deleted.
+     * @var coursecat
+     */
+    protected $coursecat;
+
+    /**
+     * Defines the form.
+     */
+    public function definition() {
+        $mform = $this->_form;
+        $this->coursecat = $this->_customdata;
+
+        $categorycontext = context_coursecat::instance($this->coursecat->id);
+        $categoryname = $this->coursecat->get_formatted_name();
+
+        // Check permissions, to see if it OK to give the option to delete
+        // the contents, rather than move elsewhere.
+        $candeletecontent = $this->coursecat->can_delete_full();
+
+        // Get the list of categories we might be able to move to.
+        $displaylist = $this->coursecat->move_content_targets_list();
+
+        // Now build the options.
+        $options = array();
+        if ($displaylist) {
+            $options[0] = get_string('movecontentstoanothercategory');
+        }
+        if ($candeletecontent) {
+            $options[1] = get_string('deleteallcannotundo');
+        }
+        if (empty($options)) {
+            print_error('youcannotdeletecategory', 'error', 'index.php', $categoryname);
+        }
+
+        // Now build the form.
+        $mform->addElement('header', 'general', get_string('categorycurrentcontents', '', $categoryname));
+
+        // Describe the contents of this category.
+        $contents = '';
+        if ($this->coursecat->has_children()) {
+            $contents .= '<li>' . get_string('subcategories') . '</li>';
+        }
+        if ($this->coursecat->has_courses()) {
+            $contents .= '<li>' . get_string('courses') . '</li>';
+        }
+        if (question_context_has_any_questions($categorycontext)) {
+            $contents .= '<li>' . get_string('questionsinthequestionbank') . '</li>';
+        }
+        if (!empty($contents)) {
+            $mform->addElement('static', 'emptymessage', get_string('thiscategorycontains'), html_writer::tag('ul', $contents));
+        } else {
+            $mform->addElement('static', 'emptymessage', '', get_string('deletecategoryempty'));
+        }
+
+        // Give the options for what to do.
+        $mform->addElement('select', 'fulldelete', get_string('whattodo'), $options);
+        if (count($options) == 1) {
+            $optionkeys = array_keys($options);
+            $option = reset($optionkeys);
+            $mform->hardFreeze('fulldelete');
+            $mform->setConstant('fulldelete', $option);
+        }
+
+        if ($displaylist) {
+            $mform->addElement('select', 'newparent', get_string('movecategorycontentto'), $displaylist);
+            if (in_array($this->coursecat->parent, $displaylist)) {
+                $mform->setDefault('newparent', $this->coursecat->parent);
+            }
+            $mform->disabledIf('newparent', 'fulldelete', 'eq', '1');
+        }
+
+        $mform->addElement('hidden', 'categoryid', $this->coursecat->id);
+        $mform->setType('categoryid', PARAM_ALPHANUM);
+        $mform->addElement('hidden', 'action', 'deletecategory');
+        $mform->setType('action', PARAM_ALPHANUM);
+        $mform->addElement('hidden', 'sure');
+        // This gets set by default to ensure that if the user changes it manually we can detect it.
+        $mform->setDefault('sure', md5(serialize($this->coursecat)));
+        $mform->setType('sure', PARAM_ALPHANUM);
+
+        $this->add_action_buttons(true, get_string('delete'));
+    }
+
+    /**
+     * Perform some extra moodle validation.
+     *
+     * @param array $data
+     * @param array $files
+     * @return array An array of errors.
+     */
+    public function validation($data, $files) {
+        $errors = parent::validation($data, $files);
+        if (empty($data['fulldelete']) && empty($data['newparent'])) {
+            // When they have chosen the move option, they must specify a destination.
+            $errors['newparent'] = get_string('required');
+        }
+
+        if ($data['sure'] !== md5(serialize($this->coursecat))) {
+            $errors['categorylabel'] = get_string('categorymodifiedcancel');
+        }
+
+        return $errors;
+    }
+}
\ No newline at end of file
diff --git a/course/classes/editcategory_form.php b/course/classes/editcategory_form.php
new file mode 100644 (file)
index 0000000..a28ea9b
--- /dev/null
@@ -0,0 +1,134 @@
+<?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/>.
+
+/**
+ * Edit category form.
+ *
+ * @package core_course
+ * @copyright 2002 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->libdir.'/formslib.php');
+require_once($CFG->libdir.'/coursecatlib.php');
+
+/**
+ * Edit category form.
+ *
+ * @package core_course
+ * @copyright 2002 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class core_course_editcategory_form extends moodleform {
+
+    /**
+     * The form definition.
+     */
+    public function definition() {
+        global $CFG, $DB;
+        $mform = $this->_form;
+        $categoryid = $this->_customdata['categoryid'];
+        $parent = $this->_customdata['parent'];
+
+        // Get list of categories to use as parents, with site as the first one.
+        $options = array();
+        if (has_capability('moodle/category:manage', context_system::instance()) || $parent == 0) {
+            $options[0] = get_string('top');
+        }
+        if ($categoryid) {
+            // Editing an existing category.
+            $options += coursecat::make_categories_list('moodle/category:manage', $categoryid);
+            if (empty($options[$parent])) {
+                // Ensure the the category parent has been included in the options.
+                $options[$parent] = $DB->get_field('course_categories', 'name', array('id'=>$parent));
+            }
+            $strsubmit = get_string('savechanges');
+        } else {
+            // Making a new category.
+            $options += coursecat::make_categories_list('moodle/category:manage');
+            $strsubmit = get_string('createcategory');
+        }
+
+        $mform->addElement('select', 'parent', get_string('parentcategory'), $options);
+
+        $mform->addElement('text', 'name', get_string('categoryname'), array('size' => '30'));
+        $mform->addRule('name', get_string('required'), 'required', null);
+        $mform->setType('name', PARAM_TEXT);
+
+        $mform->addElement('text', 'idnumber', get_string('idnumbercoursecategory'), 'maxlength="100" size="10"');
+        $mform->addHelpButton('idnumber', 'idnumbercoursecategory');
+        $mform->setType('idnumber', PARAM_RAW);
+
+        $mform->addElement('editor', 'description_editor', get_string('description'), null,
+            $this->get_description_editor_options());
+
+        if (!empty($CFG->allowcategorythemes)) {
+            $themes = array(''=>get_string('forceno'));
+            $allthemes = get_list_of_themes();
+            foreach ($allthemes as $key => $theme) {
+                if (empty($theme->hidefromselector)) {
+                    $themes[$key] = get_string('pluginname', 'theme_'.$theme->name);
+                }
+            }
+            $mform->addElement('select', 'theme', get_string('forcetheme'), $themes);
+        }
+
+        $mform->addElement('hidden', 'id', 0);
+        $mform->setType('id', PARAM_INT);
+        $mform->setDefault('id', $categoryid);
+
+        $this->add_action_buttons(true, $strsubmit);
+    }
+
+    /**
+     * Returns the description editor options.
+     * @return array
+     */
+    public function get_description_editor_options() {
+        global $CFG;
+        $context = $this->_customdata['context'];
+        $itemid = $this->_customdata['itemid'];
+        return array(
+            'maxfiles'  => EDITOR_UNLIMITED_FILES,
+            'maxbytes'  => $CFG->maxbytes,
+            'trusttext' => true,
+            'context'   => $context,
+            'subdirs'   => file_area_contains_subdirs($context, 'coursecat', 'description', $itemid),
+        );
+    }
+
+    /**
+     * Validates the data submit for this form.
+     *
+     * @param array $data An array of key,value data pairs.
+     * @param array $files Any files that may have been submit as well.
+     * @return array An array of errors.
+     */
+    public function validation($data, $files) {
+        global $DB;
+        $errors = parent::validation($data, $files);
+        if (!empty($data['idnumber'])) {
+            if ($existing = $DB->get_record('course_categories', array('idnumber' => $data['idnumber']))) {
+                if (!$data['id'] || $existing->id != $data['id']) {
+                    $errors['idnumber']= get_string('categoryidnumbertaken');
+                }
+            }
+        }
+        return $errors;
+    }
+}
\ No newline at end of file
diff --git a/course/classes/management/helper.php b/course/classes/management/helper.php
new file mode 100644 (file)
index 0000000..aa9e0ac
--- /dev/null
@@ -0,0 +1,806 @@
+<?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/>.
+
+/**
+ * Course and category management helper class.
+ *
+ * @package    core_course
+ * @copyright  2013 Sam Hemelryk
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core_course\management;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Course and category management interface helper class.
+ *
+ * This class provides methods useful to the course and category management interfaces.
+ * Many of the methods on this class are static and serve one of two purposes.
+ *  1.  encapsulate functionality in an effort to ensure minimal changes between the different
+ *      methods of interaction. Specifically browser, AJAX and webservice.
+ *  2.  abstract logic for acquiring actions away from output so that renderers may use them without
+ *      having to include any logic or capability checks.
+ *
+ * @package    core_course
+ * @copyright  2013 Sam Hemelryk
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class helper {
+    /**
+     * Returns course details in an array ready to be printed.
+     *
+     * @global \moodle_database $DB
+     * @param \course_in_list $course
+     * @return array
+     */
+    public static function get_course_detail_array(\course_in_list $course) {
+        global $DB;
+
+        $canaccess = $course->can_access();
+
+        $format = \course_get_format($course->id);
+        $modinfo = \get_fast_modinfo($course->id);
+        $modules = $modinfo->get_used_module_names();
+        $sections = array();
+        if ($format->uses_sections()) {
+            foreach ($modinfo->get_section_info_all() as $section) {
+                if ($section->uservisible) {
+                    $sections[] = $format->get_section_name($section);
+                }
+            }
+        }
+
+        $category = \coursecat::get($course->category);
+        $categoryurl = new \moodle_url('/course/management.php', array('categoryid' => $course->category));
+        $categoryname = $category->get_formatted_name();
+
+        $details = array(
+            'fullname' => array(
+                'key' => \get_string('fullname'),
+                'value' => $course->get_formatted_fullname()
+            ),
+            'shortname' => array(
+                'key' => \get_string('shortname'),
+                'value' => $course->get_formatted_shortname()
+            ),
+            'idnumber' => array(
+                'key' => \get_string('idnumber'),
+                'value' => s($course->idnumber)
+            ),
+            'category' => array(
+                'key' => \get_string('category'),
+                'value' => \html_writer::link($categoryurl, $categoryname)
+            )
+        );
+        if (has_capability('moodle/site:accessallgroups', $course->get_context())) {
+            $groups = \groups_get_course_data($course->id);
+            $details += array(
+                'groupings' => array(
+                    'key' => \get_string('groupings', 'group'),
+                    'value' => count($groups->groupings)
+                ),
+                'groups' => array(
+                    'key' => \get_string('groups'),
+                    'value' => count($groups->groups)
+                )
+            );
+        }
+        if ($canaccess) {
+            $names = \role_get_names($course->get_context());
+            $sql = 'SELECT ra.roleid, COUNT(ra.id) AS rolecount
+                      FROM {role_assignments} ra
+                     WHERE ra.contextid = :contextid
+                  GROUP BY ra.roleid';
+            $rolecounts = $DB->get_records_sql($sql, array('contextid' => $course->get_context()->id));
+            $roledetails = array();
+            foreach ($rolecounts as $result) {
+                $a = new \stdClass;
+                $a->role = $names[$result->roleid]->localname;
+                $a->count = $result->rolecount;
+                $roledetails[] = \get_string('assignedrolecount', 'moodle', $a);
+            }
+
+            $details['roleassignments'] = array(
+                'key' => \get_string('roleassignments'),
+                'value' => join('<br />', $roledetails)
+            );
+        }
+        if ($course->can_review_enrolments()) {
+            $enrolmentlines = array();
+            $instances = \enrol_get_instances($course->id, true);
+            $plugins = \enrol_get_plugins(true);
+            foreach ($instances as $instance) {
+                if (!isset($plugins[$instance->enrol])) {
+                    // Weird.
+                    continue;
+                }
+                $plugin = $plugins[$instance->enrol];
+                $enrolmentlines[] = $plugin->get_instance_name($instance);
+            }
+            $details['enrolmentmethods'] = array(
+                'key' => \get_string('enrolmentmethods'),
+                'value' => join('<br />', $enrolmentlines)
+            );
+        }
+        if ($canaccess) {
+            $details['format'] = array(
+                'key' => \get_string('format'),
+                'value' => \course_get_format($course)->get_format_name()
+            );
+            $details['sections'] = array(
+                'key' => \get_string('sections'),
+                'value' => join('<br />', $sections)
+            );
+            $details['modulesused'] = array(
+                'key' => \get_string('modulesused'),
+                'value' =>  join('<br />', $modules)
+            );
+        }
+        return $details;
+    }
+
+    /**
+     * Returns an array of actions that can be performed upon a category being shown in a list.
+     *
+     * @param \coursecat $category
+     * @return array
+     */
+    public static function get_category_listitem_actions(\coursecat $category) {
+        $baseurl = new \moodle_url('/course/management.php', array('categoryid' => $category->id, 'sesskey' => \sesskey()));
+        $actions = array();
+        // Edit.
+        if ($category->can_edit()) {
+            $actions['edit'] = array(
+                'url' => new \moodle_url('/course/editcategory.php', array('id' => $category->id)),
+                'icon' => new \pix_icon('t/edit', new \lang_string('edit')),
+                'string' => new \lang_string('edit')
+            );
+        }
+
+        // Show/Hide.
+        if ($category->can_change_visibility()) {
+            // We always show both icons and then just toggle the display of the invalid option with CSS.
+            $actions['hide'] = array(
+                'url' => new \moodle_url($baseurl, array('action' => 'hidecategory')),
+                'icon' => new \pix_icon('t/hide', new \lang_string('hide')),
+                'string' => new \lang_string('hide')
+            );
+            $actions['show'] = array(
+                'url' => new \moodle_url($baseurl, array('action' => 'showcategory')),
+                'icon' => new \pix_icon('t/show', new \lang_string('show')),
+                'string' => new \lang_string('show')
+            );
+        }
+
+        // Move up/down.
+        if ($category->can_change_sortorder()) {
+            $actions['moveup'] = array(
+                'url' => new \moodle_url($baseurl, array('action' => 'movecategoryup')),
+                'icon' => new \pix_icon('t/up', new \lang_string('up')),
+                'string' => new \lang_string('up')
+            );
+            $actions['movedown'] = array(
+                'url' => new \moodle_url($baseurl, array('action' => 'movecategorydown')),
+                'icon' => new \pix_icon('t/down', new \lang_string('down')),
+                'string' => new \lang_string('down')
+            );
+        }
+
+        // Delete.
+        if ($category->can_delete_full()) {
+            $actions['delete'] = array(
+                'url' => new \moodle_url($baseurl, array('action' => 'deletecategory')),
+                'icon' => new \pix_icon('t/delete', new \lang_string('delete')),
+                'string' => new \lang_string('delete')
+            );
+        }
+
+        // Roles.
+        if ($category->can_review_roles()) {
+            $actions['assignroles'] = array(
+                'url' => new \moodle_url('/admin/roles/assign.php', array('contextid' => $category->get_context()->id,
+                    'return' => 'management')),
+                'icon' => new \pix_icon('i/assignroles', new \lang_string('assignroles', 'role')),
+                'string' => new \lang_string('assignroles', 'role')
+            );
+        }
+
+        // Permissions.
+        if ($category->can_review_permissions()) {
+            $actions['permissions'] = array(
+                'url' => new \moodle_url('/admin/roles/permissions.php', array('contextid' => $category->get_context()->id,
+                    'return' => 'management')),
+                'icon' => new \pix_icon('i/permissions', new \lang_string('permissions', 'role')),
+                'string' => new \lang_string('permissions', 'role')
+            );
+        }
+
+        // Cohorts.
+        if ($category->can_review_cohorts()) {
+            $actions['cohorts'] = array(
+                'url' => new \moodle_url('/cohort/index.php', array('contextid' => $category->get_context()->id)),
+                'icon' => new \pix_icon('i/cohort', new \lang_string('cohorts', 'cohort')),
+                'string' => new \lang_string('cohorts', 'cohort')
+            );
+        }
+
+        // Filters.
+        if ($category->can_review_filters()) {
+            $actions['filters'] = array(
+                'url' => new \moodle_url('/filter/manage.php', array('contextid' => $category->get_context()->id,
+                    'return' => 'management')),
+                'icon' => new \pix_icon('i/filter', new \lang_string('filters', 'admin')),
+                'string' => new \lang_string('filters', 'admin')
+            );
+        }
+
+        return $actions;
+    }
+
+    /**
+     * Returns an array of actions for a course listitem.
+     *
+     * @param \coursecat $category
+     * @param \course_in_list $course
+     * @return string
+     */
+    public static function get_course_listitem_actions(\coursecat $category, \course_in_list $course) {
+        $baseurl = new \moodle_url(
+            '/course/management.php',
+            array('courseid' => $course->id, 'categoryid' => $course->category, 'sesskey' => \sesskey())
+        );
+        $actions = array();
+        // Edit.
+        if ($course->can_edit()) {
+            $actions[] = array(
+                'url' => new \moodle_url('/course/edit.php', array('id' => $course->id)),
+                'icon' => new \pix_icon('t/edit', \get_string('edit')),
+                'attributes' => array('class' => 'action-edit')
+            );
+        }
+        // Show/Hide.
+        if ($course->can_change_visibility()) {
+            $actions[] = array(
+                'url' => new \moodle_url($baseurl, array('action' => 'hidecourse')),
+                'icon' => new \pix_icon('t/hide', \get_string('hide')),
+                'attributes' => array('data-action' => 'hide', 'class' => 'action-hide')
+            );
+            $actions[] = array(
+                'url' => new \moodle_url($baseurl, array('action' => 'showcourse')),
+                'icon' => new \pix_icon('t/show', \get_string('show')),
+                'attributes' => array('data-action' => 'show', 'class' => 'action-show')
+            );
+        }
+        // Move up/down.
+        if ($category->can_resort_courses()) {
+            $actions[] = array(
+                'url' => new \moodle_url($baseurl, array('action' => 'movecourseup')),
+                'icon' => new \pix_icon('t/up', \get_string('up')),
+                'attributes' => array('data-action' => 'moveup', 'class' => 'action-moveup')
+            );
+            $actions[] = array(
+                'url' => new \moodle_url($baseurl, array('action' => 'movecoursedown')),
+                'icon' => new \pix_icon('t/down', \get_string('down')),
+                'attributes' => array('data-action' => 'movedown', 'class' => 'action-movedown')
+            );
+        }
+        return $actions;
+    }
+
+    /**
+     * Returns an array of actions that can be performed on the course being displayed.
+     *
+     * @param \course_in_list $course
+     * @return array
+     */
+    public static function get_course_detail_actions(\course_in_list $course) {
+        $params = array('courseid' => $course->id, 'categoryid' => $course->category, 'sesskey' => \sesskey());
+        $baseurl = new \moodle_url('/course/management.php', $params);
+        $actions = array();
+        // View.
+        if ($course->is_uservisible()) {
+            $actions['view'] = array(
+                'url' => new \moodle_url('/course/view.php', array('id' => $course->id)),
+                'string' => \get_string('view')
+            );
+        }
+        // Edit.
+        if ($course->can_edit()) {
+            $actions['edit'] = array(
+                'url' => new \moodle_url('/course/edit.php', array('id' => $course->id)),
+                'string' => \get_string('edit')
+            );
+        }
+        // Permissions.
+        if ($course->can_review_enrolments()) {
+            $actions['enrolledusers'] = array(
+                'url' => new \moodle_url('/enrol/users.php', array('id' => $course->id)),
+                'string' => \get_string('enrolledusers', 'enrol')
+            );
+        }
+        // Delete.
+        if ($course->can_delete()) {
+            $actions['delete'] = array(
+                'url' => new \moodle_url('/course/delete.php', array('id' => $course->id)),
+                'string' => \get_string('delete')
+            );
+        }
+        // Show/Hide.
+        if ($course->can_change_visibility()) {
+            if ($course->visible) {
+                $actions['hide'] = array(
+                    'url' => new \moodle_url($baseurl, array('action' => 'hidecourse')),
+                    'string' => \get_string('hide')
+                );
+            } else {
+                $actions['show'] = array(
+                    'url' => new \moodle_url($baseurl, array('action' => 'showcourse')),
+                    'string' => \get_string('show')
+                );
+            }
+        }
+        // Backup.
+        if ($course->can_backup()) {
+            $actions['backup'] = array(
+                'url' => new \moodle_url('/backup/backup.php', array('id' => $course->id)),
+                'string' => \get_string('backup')
+            );
+        }
+        // Restore.
+        if ($course->can_restore()) {
+            $actions['restore'] = array(
+                'url' => new \moodle_url('/backup/restorefile.php', array('contextid' => $course->get_context()->id)),
+                'string' => \get_string('restore')
+            );
+        }
+        return $actions;
+    }
+
+    /**
+     * Resorts the courses within a category moving the given course up by one.
+     *
+     * @param \course_in_list $course
+     * @param \coursecat $category
+     * @return bool
+     * @throws \moodle_exception
+     */
+    public static function action_course_change_sortorder_up_one(\course_in_list $course, \coursecat $category) {
+        if (!$category->can_resort_courses()) {
+            throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_resort');
+        }
+        return \course_change_sortorder_by_one($course, true);
+    }
+
+    /**
+     * Resorts the courses within a category moving the given course down by one.
+     *
+     * @param \course_in_list $course
+     * @param \coursecat $category
+     * @return bool
+     * @throws \moodle_exception
+     */
+    public static function action_course_change_sortorder_down_one(\course_in_list $course, \coursecat $category) {
+        if (!$category->can_resort_courses()) {
+            throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_resort');
+        }
+        return \course_change_sortorder_by_one($course, false);
+    }
+
+    /**
+     * Resorts the courses within a category moving the given course up by one.
+     *
+     * @global \moodle_database $DB
+     * @param int|\stdClass $courserecordorid
+     * @return bool
+     */
+    public static function action_course_change_sortorder_up_one_by_record($courserecordorid) {
+        if (is_int($courserecordorid)) {
+            $courserecordorid = get_course($courserecordorid);
+        }
+        $course = new \course_in_list($courserecordorid);
+        $category = \coursecat::get($course->category);
+        return self::action_course_change_sortorder_up_one($course, $category);
+    }
+
+    /**
+     * Resorts the courses within a category moving the given course down by one.
+     *
+     * @global \moodle_database $DB
+     * @param int|\stdClass $courserecordorid
+     * @return bool
+     */
+    public static function action_course_change_sortorder_down_one_by_record($courserecordorid) {
+        if (is_int($courserecordorid)) {
+            $courserecordorid = get_course($courserecordorid);
+        }
+        $course = new \course_in_list($courserecordorid);
+        $category = \coursecat::get($course->category);
+        return self::action_course_change_sortorder_down_one($course, $category);
+    }
+
+    /**
+     * Changes the sort order so that the first course appears after the second course.
+     *
+     * @param int|\stdClass $courserecordorid
+     * @param int $moveaftercourseid
+     * @return bool
+     * @throws \moodle_exception
+     */
+    public static function action_course_change_sortorder_after_course($courserecordorid, $moveaftercourseid) {
+        $course = \get_course($courserecordorid);
+        $category = \coursecat::get($course->category);
+        if (!$category->can_resort_courses()) {
+            $url = '/course/management.php?categoryid='.$course->category;
+            throw new \moodle_exception('nopermissions', 'error', $url, \get_string('resortcourses', 'moodle'));
+        }
+        return \course_change_sortorder_after_course($course, $moveaftercourseid);
+    }
+
+    /**
+     * Makes a course visible given a \course_in_list object.
+     *
+     * @param \course_in_list $course
+     * @return bool
+     * @throws \moodle_exception
+     */
+    public static function action_course_show(\course_in_list $course) {
+        if (!$course->can_change_visibility()) {
+            throw new \moodle_exception('permissiondenied', 'error', '', null, 'course_in_list::can_change_visbility');
+        }
+        return course_change_visibility($course->id, true);
+    }
+
+    /**
+     * Makes a course hidden given a \course_in_list object.
+     *
+     * @param \course_in_list $course
+     * @return bool
+     * @throws \moodle_exception
+     */
+    public static function action_course_hide(\course_in_list $course) {
+        if (!$course->can_change_visibility()) {
+            throw new \moodle_exception('permissiondenied', 'error', '', null, 'course_in_list::can_change_visbility');
+        }
+        return course_change_visibility($course->id, false);
+    }
+
+    /**
+     * Makes a course visible given a course id or a database record.
+     *
+     * @global \moodle_database $DB
+     * @param int|\stdClass $courserecordorid
+     * @return bool
+     */
+    public static function action_course_show_by_record($courserecordorid) {
+        if (is_int($courserecordorid)) {
+            $courserecordorid = get_course($courserecordorid);
+        }
+        $course = new \course_in_list($courserecordorid);
+        return self::action_course_show($course);
+    }
+
+    /**
+     * Makes a course hidden given a course id or a database record.
+     *
+     * @global \moodle_database $DB
+     * @param int|\stdClass $courserecordorid
+     * @return bool
+     */
+    public static function action_course_hide_by_record($courserecordorid) {
+        if (is_int($courserecordorid)) {
+            $courserecordorid = get_course($courserecordorid);
+        }
+        $course = new \course_in_list($courserecordorid);
+        return self::action_course_hide($course);
+    }
+
+    /**
+     * Resort a categories subcategories shifting the given category up one.
+     *
+     * @param \coursecat $category
+     * @return bool
+     * @throws \moodle_exception
+     */
+    public static function action_category_change_sortorder_up_one(\coursecat $category) {
+        if (!$category->can_change_sortorder()) {
+            throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_change_sortorder');
+        }
+        return $category->change_sortorder_by_one(true);
+    }
+
+    /**
+     * Resort a categories subcategories shifting the given category down one.
+     *
+     * @param \coursecat $category
+     * @return bool
+     * @throws \moodle_exception
+     */
+    public static function action_category_change_sortorder_down_one(\coursecat $category) {
+        if (!$category->can_change_sortorder()) {
+            throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_change_sortorder');
+        }
+        return $category->change_sortorder_by_one(false);
+    }
+
+    /**
+     * Resort a categories subcategories shifting the given category up one.
+     *
+     * @param int $categoryid
+     * @return bool
+     */
+    public static function action_category_change_sortorder_up_one_by_id($categoryid) {
+        $category = \coursecat::get($categoryid);
+        return self::action_category_change_sortorder_up_one($category);
+    }
+
+    /**
+     * Resort a categories subcategories shifting the given category down one.
+     *
+     * @param int $categoryid
+     * @return bool
+     */
+    public static function action_category_change_sortorder_down_one_by_id($categoryid) {
+        $category = \coursecat::get($categoryid);
+        return self::action_category_change_sortorder_down_one($category);
+    }
+
+    /**
+     * Makes a category hidden given a \coursecat record.
+     *
+     * @param \coursecat $category
+     * @return bool
+     * @throws \moodle_exception
+     */
+    public static function action_category_hide(\coursecat $category) {
+        if (!$category->can_change_visibility()) {
+            throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_change_visbility');
+        }
+        $category->hide();
+        return true;
+    }
+
+    /**
+     * Makes a category visible given a \coursecat record.
+     *
+     * @param \coursecat $category
+     * @return bool
+     * @throws \moodle_exception
+     */
+    public static function action_category_show(\coursecat $category) {
+        if (!$category->can_change_visibility()) {
+            throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_change_visbility');
+        }
+        if ((int)$category->get_parent_coursecat()->visible === 0) {
+            // You cannot mark a category visible if its parent is hidden.
+            return false;
+        }
+        $category->show();
+        return true;
+    }
+
+    /**
+     * Makes a category visible given a \coursecat id or database record.
+     *
+     * @param int|\stdClass $categoryid
+     * @return bool
+     */
+    public static function action_category_show_by_id($categoryid) {
+        return self::action_category_show(\coursecat::get($categoryid));
+    }
+
+    /**
+     * Makes a category hidden given a \coursecat id or database record.
+     *
+     * @param int|\stdClass $categoryid
+     * @return bool
+     */
+    public static function action_category_hide_by_id($categoryid) {
+        return self::action_category_hide(\coursecat::get($categoryid));
+    }
+
+    /**
+     * Resorts the sub categories of the given category.
+     *
+     * @param \coursecat $category
+     * @param string $sort One of idnumber or name.
+     * @param bool $cleanup If true cleanup will be done, if false you will need to do it manually later.
+     * @return bool
+     * @throws \moodle_exception
+     */
+    public static function action_category_resort_subcategories(\coursecat $category, $sort, $cleanup = true) {
+        if (!$category->can_resort_subcategories()) {
+            throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_resort');
+        }
+        return $category->resort_subcategories($sort, $cleanup);
+    }
+
+    /**
+     * Resorts the courses within the given category.
+     *
+     * @param \coursecat $category
+     * @param string $sort One of fullname, shortname or idnumber
+     * @return bool
+     * @throws \moodle_exception
+     */
+    public static function action_category_resort_courses(\coursecat $category, $sort) {
+        if (!$category->can_resort_courses()) {
+            throw new \moodle_exception('permissiondenied', 'error', '', null, 'coursecat::can_resort');
+        }
+        return $category->resort_courses($sort);
+    }
+
+    /**
+     * Moves courses out of one category and into a new category.
+     *
+     * @param \coursecat $oldcategory The category we are moving courses out of.
+     * @param \coursecat $newcategory The category we are moving courses into.
+     * @param array $courseids The ID's of the courses we want to move.
+     * @return bool True on success.
+     * @throws \moodle_exception
+     */
+    public static function action_category_move_courses_into(\coursecat $oldcategory, \coursecat $newcategory, array $courseids) {
+        global $DB;
+
+        list($where, $params) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
+        $params['categoryid'] = $oldcategory->id;
+        $sql = "SELECT c.id FROM {course} c WHERE c.id {$where} AND c.category <> :categoryid";
+        if ($DB->record_exists_sql($sql, $params)) {
+            // Likely being tinkered with.
+            throw new \moodle_exception('coursedoesnotbelongtocategory');
+        }
+
+        // All courses are currently within the old category.
+        return self::move_courses_into_category($newcategory, $courseids);
+    }
+
+    /**
+     * Returns the view modes for the management interface.
+     * @return array
+     */
+    public static function get_management_viewmodes() {
+        return array(
+            'combined' => new \lang_string('categoriesandcoures'),
+            'categories' => new \lang_string('categories'),
+            'courses' => new \lang_string('courses')
+        );
+    }
+
+    /**
+     * Search for courses with matching params.
+     *
+     * Please note that only one of search, blocklist, or modulelist can be specified at a time.
+     * Specifying more than one will result in only the first being used.
+     *
+     * @param string $search Words to search for. We search fullname, shortname, idnumber and summary.
+     * @param int $blocklist The ID of a block, courses will only be returned if they use this block.
+     * @param string $modulelist The name of a module (relates to database table name). Only courses containing this module
+     *      will be returned.
+     * @param int $page The page number to display, starting at 0.
+     * @param int $perpage The number of courses to display per page.
+     * @return array
+     */
+    public static function search_courses($search, $blocklist, $modulelist, $page = 0, $perpage = null) {
+        global $CFG;
+
+        if ($perpage === null) {
+            $perpage = $CFG->coursesperpage;
+        }
+
+        $searchcriteria = array();
+        if (!empty($search)) {
+            $searchcriteria = array('search' => $search);
+        } else if (!empty($blocklist)) {
+            $searchcriteria = array('blocklist' => $blocklist);
+        } else if (!empty($modulelist)) {
+            $searchcriteria = array('modulelist' => $modulelist);
+        }
+
+        $courses = \coursecat::get(0)->search_courses($searchcriteria, array(
+            'recursive' => true,
+            'offset' => $page * $perpage,
+            'limit' => $perpage,
+            'sort' => array('fullname' => 1)
+        ));
+        $totalcount = \coursecat::get(0)->search_courses_count($searchcriteria, array('recursive' => true));
+
+        return array($courses, \count($courses), $totalcount);
+    }
+
+    /**
+     * Moves one or more courses out of the category they are currently in and into a new category.
+     *
+     * This function works much the same way as action_category_move_courses_into however it allows courses from multiple
+     * categories to be moved into a single category.
+     *
+     * @param int|\coursecat $categoryorid The category to move them into.
+     * @param array|int $courseids An array of course id's or optionally just a single course id.
+     * @return bool True on success or false on failure.
+     * @throws \moodle_exception
+     */
+    public static function move_courses_into_category($categoryorid, $courseids = array()) {
+        global $DB;
+        if (!is_array($courseids)) {
+            // Just a single course ID.
+            $courseids = array($courseids);
+        }
+        // Bulk move courses from one category to another.
+        if (count($courseids) === 0) {
+            return false;
+        }
+        if ($categoryorid instanceof \coursecat) {
+            $moveto = $categoryorid;
+        } else {
+            $moveto = \coursecat::get($categoryorid);
+        }
+        if (!$moveto->can_move_courses_out_of() || !$moveto->can_move_courses_into()) {
+            throw new \moodle_exception('cannotmovecourses');
+        }
+
+        list($where, $params) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
+        $params['categoryid'] = $moveto->id;
+        $sql = "SELECT c.id, c.category FROM {course} c WHERE c.id {$where} AND c.category <> :categoryid";
+        $courses = $DB->get_records_sql($sql, $params);
+        $checks = array();
+        foreach ($courseids as $id) {
+            if (!isset($courses[$id])) {
+                throw new \moodle_exception('invalidcourseid');
+            }
+            $catid = $courses[$id]->category;
+            if (!isset($checks[$catid])) {
+                $coursecat = \coursecat::get($catid);
+                $checks[$catid] = $coursecat->can_move_courses_out_of() && $coursecat->can_move_courses_into();
+            }
+            if (!$checks[$catid]) {
+                throw new \moodle_exception('cannotmovecourses');
+            }
+        }
+        return \move_courses($courseids, $moveto->id);
+    }
+
+    /**
+     * Returns an array of courseids and visiblity for all courses within the given category.
+     * @param int $categoryid
+     * @return array
+     */
+    public static function get_category_courses_visibility($categoryid) {
+        global $DB;
+        $sql = "SELECT c.id, c.visible as show
+                  FROM {course} c
+                 WHERE c.category = :category";
+        $params = array('category' => (int)$categoryid);
+        return $DB->get_records_sql($sql, $params);
+    }
+
+    /**
+     * Returns an array of all categoryids that have the given category as a parent and their visible value.
+     * @param int $categoryid
+     * @return array
+     */
+    public static function get_category_children_visibility($categoryid) {
+        global $DB;
+        $category = \coursecat::get($categoryid);
+        $select = $DB->sql_like('path', ':path');
+        $path = $category->path . '/%';
+
+        $sql = "SELECT c.id, c.visible as show
+                  FROM {course_categories} c
+                 WHERE ".$select;
+        $params = array('path' => $path);
+        return $DB->get_records_sql($sql, $params);
+    }
+}
diff --git a/course/classes/management_renderer.php b/course/classes/management_renderer.php
new file mode 100644 (file)
index 0000000..27e5aa4
--- /dev/null
@@ -0,0 +1,1125 @@
+<?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/>.
+
+/**
+ * Contains renderers for the course management pages.
+ *
+ * @package core_course
+ * @copyright 2013 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die;
+
+require_once($CFG->dirroot.'/course/renderer.php');
+
+/**
+ * Main renderer for the course management pages.
+ *
+ * @package core_course
+ * @copyright 2013 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class core_course_management_renderer extends plugin_renderer_base {
+
+    /**
+     * Initialises the JS required to enhance the management interface.
+     *
+     * Thunderbirds are go, this function kicks into gear the JS that makes the
+     * course management pages that much cooler.
+     */
+    public function enhance_management_interface() {
+        $this->page->requires->yui_module('moodle-course-management', 'M.course.management.init');
+        $this->page->requires->strings_for_js(
+            array('show', 'hide', 'expand', 'collapse', 'confirmcoursemove', 'yes', 'no', 'confirm'),
+            'moodle'
+        );
+    }
+
+    /**
+     * Displays a heading for the management pages.
+     *
+     * @param string $heading The heading to display
+     * @param string|null $viewmode The current view mode if there are options.
+     * @param int|null $categoryid The currently selected category if there is one.
+     * @return string
+     */
+    public function management_heading($heading, $viewmode = null, $categoryid = null) {
+        $html = html_writer::start_div('coursecat-management-header clearfix');
+        if (!empty($heading)) {
+            $html .= $this->heading($heading);
+        }
+        if ($viewmode !== null) {
+            if ($viewmode === 'courses') {
+                $categories = coursecat::make_categories_list(array('moodle/category:manage', 'moodle/course:create'));
+                $nothing = false;
+                if ($categoryid === null) {
+                    $nothing = array('' => get_string('selectacategory'));
+                    $categoryid = '';
+                }
+                $select = new single_select($this->page->url, 'categoryid', $categories, $categoryid, $nothing);
+                $html .= $this->render($select);
+            }
+            $html .= $this->view_mode_selector(\core_course\management\helper::get_management_viewmodes(), $viewmode);
+        }
+        $html .= html_writer::end_div();
+        return $html;
+    }
+
+    /**
+     * Prepares the form element for the course category listing bulk actions.
+     *
+     * @return string
+     */
+    public function management_form_start() {
+        $form = array('action' => $this->page->url->out(), 'method' => 'POST', 'id' => 'coursecat-management');
+
+        $html = html_writer::start_tag('form', $form);
+        $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
+        $html .=  html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'action', 'value' => 'bulkaction'));
+        return $html;
+    }
+
+    /**
+     * Closes the course category bulk management form.
+     *
+     * @return string
+     */
+    public function management_form_end() {
+        return html_writer::end_tag('form');
+    }
+
+    /**
+     * Presents a course category listing.
+     *
+     * @param coursecat $category The currently selected category. Also the category to highlight in the listing.
+     * @return string
+     */
+    public function category_listing(coursecat $category = null) {
+
+        if ($category === null) {
+            $selectedparents = array();
+            $selectedcategory = null;
+        } else {
+            $selectedparents = $category->get_parents();
+            $selectedparents[] = $category->id;
+            $selectedcategory = $category->id;
+        }
+        $catatlevel = array_shift($selectedparents);
+
+        $listing = coursecat::get(0)->get_children();
+
+        $attributes = array(
+            'class' => 'ml',
+            'role' => 'tree',
+            'aria-labelledby' => 'category-listing-title'
+        );
+
+        $html  = html_writer::start_div('category-listing');
+        $html .= html_writer::tag('h3', get_string('categories'), array('id' => 'category-listing-title'));
+        $html .= $this->category_listing_actions($category);
+        $html .= html_writer::start_tag('ul', $attributes);
+        foreach ($listing as $listitem) {
+            // Render each category in the listing.
+            $subcategories = array();
+            if ($listitem->id == $catatlevel) {
+                $subcategories = $listitem->get_children();
+            }
+            $html .= $this->category_listitem(
+                $listitem,
+                $subcategories,
+                $listitem->get_children_count(),
+                $selectedcategory,
+                $selectedparents
+            );
+        }
+        $html .= html_writer::end_tag('ul');
+        $html .= $this->category_bulk_actions();
+        $html .= html_writer::end_div();
+        return $html;
+    }
+
+    /**
+     * Renders a category list item.
+     *
+     * This function gets called recursively to render sub categories.
+     *
+     * @param coursecat $category The category to render as listitem.
+     * @param coursecat[] $subcategories The subcategories belonging to the category being rented.
+     * @param int $totalsubcategories The total number of sub categories.
+     * @param int $selectedcategory The currently selected category
+     * @param int[] $selectedcategories The path to the selected category and its ID.
+     * @return string
+     */
+    public function category_listitem(coursecat $category, array $subcategories, $totalsubcategories,
+                                      $selectedcategory = null, $selectedcategories = array()) {
+        $isexpandable = ($totalsubcategories > 0);
+        $isexpanded = (!empty($subcategories));
+        $activecategory = ($selectedcategory === $category->id);
+        $attributes = array(
+            'class' => 'listitem listitem-category',
+            'data-id' => $category->id,
+            'data-expandable' => $isexpandable ? '1' : '0',
+            'data-expanded' => $isexpanded ? '1' : '0',
+            'data-selected' => $activecategory ? '1' : '0',
+            'data-visible' => $category->visible ? '1' : '0',
+            'role' => 'treeitem',
+            'aria-expanded' => $isexpanded ? 'true' : 'false'
+        );
+        $text = $category->get_formatted_name();
+        $courseicon = $this->output->pix_icon('i/course', get_string('courses'));
+        $bcatinput = array('type' => 'checkbox', 'name' => 'bcat[]', 'value' => $category->id, 'class' => 'bulk-action-checkbox');
+
+        if (!$category->can_resort_subcategories() && !$category->has_manage_capability()) {
+            // Very very hardcoded here.
+            $bcatinput['style'] = 'visibility:hidden';
+        }
+
+        $viewcaturl = new moodle_url('/course/management.php', array('categoryid' => $category->id));
+        if ($isexpanded) {
+            $icon = $this->output->pix_icon('t/switch_minus', get_string('collapse'), 'moodle', array('class' => 'tree-icon'));
+            $icon = html_writer::link($viewcaturl, $icon, array('class' => 'float-left', 'data-action' => 'collapse'));
+        } else if ($isexpandable) {
+            $icon = $this->output->pix_icon('t/switch_plus', get_string('expand'), 'moodle', array('class' => 'tree-icon'));
+            $icon = html_writer::link($viewcaturl, $icon, array('class' => 'float-left', 'data-action' => 'expand'));
+        } else {
+            $icon = $this->output->pix_icon('i/navigationitem', '', 'moodle', array('class' => 'tree-icon'));
+            $icon = html_writer::link($viewcaturl, $icon, array('class' => 'float-left'));
+        }
+        $actions = \core_course\management\helper::get_category_listitem_actions($category);
+        $hasactions = !empty($actions) || $category->can_create_course();
+
+        $html = html_writer::start_tag('li', $attributes);
+        $html .= html_writer::start_div('clearfix');
+        $html .= html_writer::start_div('float-left');
+        $html .= html_writer::empty_tag('input', $bcatinput).'&nbsp;';
+        $html .= html_writer::end_div();
+        $html .= $icon;
+        if ($hasactions) {
+            $html .= html_writer::link($viewcaturl, $text, array('class' => 'float-left categoryname'));
+        } else {
+            $html .= html_writer::link($viewcaturl, $text, array('class' => 'float-left categoryname without-actions'));
+        }
+        $html .= html_writer::start_div('float-right');
+        if ($hasactions) {
+            $html .= $this->category_listitem_actions($category, $actions);
+        }
+        $countid = 'course-count-'.$category->id;
+        $html .= html_writer::span(get_string('courses'), 'accesshide', array('id' => $countid));
+        $html .= html_writer::span($category->coursecount.$courseicon, 'course-count dimmed', array('aria-labelledby' => $countid));
+        $html .= html_writer::end_div();
+        $html .= html_writer::end_div();
+        if ($isexpanded) {
+            $html .= html_writer::start_tag('ul', array('class' => 'ml', 'role' => 'group'));
+            $catatlevel = array_shift($selectedcategories);
+            foreach ($subcategories as $listitem) {
+                $childcategories = ($listitem->id == $catatlevel) ? $listitem->get_children() : array();
+                $html .= $this->category_listitem(
+                    $listitem,
+                    $childcategories,
+                    $listitem->get_children_count(),
+                    $selectedcategory,
+                    $selectedcategories
+                );
+            }
+            $html .= html_writer::end_tag('ul');
+        }
+        $html .= html_writer::end_tag('li');
+        return $html;
+    }
+
+    /**
+     * Renderers the actions that are possible for the course category listing.
+     *
+     * These are not the actions associated with an individual category listing.
+     * That happens through category_listitem_actions.
+     *
+     * @param coursecat $category
+     * @return string
+     */
+    public function category_listing_actions(coursecat $category = null) {
+        $actions = array();
+        $createtoplevel = coursecat::can_create_top_level_category();
+        $createsubcategory = $category && $category->can_create_subcategory();
+        if ($category === null) {
+            $category = coursecat::get(0);
+        }
+
+        $hasitems = false;
+        if ($createtoplevel || $createsubcategory) {
+            $hasitems = true;
+            $menu = new action_menu;
+            if ($createtoplevel) {
+                $url = new moodle_url('/course/editcategory.php', array('parent' => 0));
+                $menu->add(new action_menu_link_secondary(
+                    $url,
+                    null,
+                    get_string('toplevelcategory')
+                ));
+            }
+            if ($createsubcategory) {
+                $url = new moodle_url('/course/editcategory.php', array('parent' => $category->id));
+                $attributes = array(
+                    'title' => get_string('createsubcategoryof', 'moodle', $category->get_formatted_name())
+                );
+                $menu->add(new action_menu_link_secondary(
+                    $url,
+                    null,
+                    get_string('subcategory'),
+                    $attributes
+                ));
+            }
+            $menu->actiontext = get_string('createnew');
+            $menu->actionicon = new pix_icon('t/add', ' ', 'moodle', array('class' => 'iconsmall', 'title' => ''));
+            $actions[] = $this->render($menu);
+        }
+        if (coursecat::can_approve_course_requests()) {
+            $actions[] = html_writer::link(new moodle_url('/course/pending.php'), get_string('coursespending'));
+        }
+        if ($category->can_resort_subcategories()) {
+            $hasitems = true;
+            $params = $this->page->url->params();
+            $params['action'] = 'resortcategories';
+            $params['sesskey'] = sesskey();
+            $baseurl = new moodle_url('/course/management.php', $params);
+            $menu = new action_menu(array(
+                new action_menu_link_secondary(
+                    new moodle_url($baseurl, array('resort' => 'name')),
+                    null,
+                    get_string('resortbyname')
+                ),
+                new action_menu_link_secondary(
+                    new moodle_url($baseurl, array('resort' => 'idnumber')),
+                    null,
+                    get_string('resortbyidnumber')
+                )
+            ));
+            if ($category->id === 0) {
+                $menu->actiontext = get_string('resortcategories');
+            } else {
+                $menu->actiontext = get_string('resortsubcategories');
+            }
+            $menu->actionicon = new pix_icon('t/sort', ' ', 'moodle', array('class' => 'iconsmall', 'title' => ''));
+            $actions[] = $this->render($menu);
+        }
+        if (!$hasitems) {
+            return '';
+        }
+        return html_writer::div(join(' | ', $actions), 'listing-actions category-listing-actions');
+    }
+
+    /**
+     * Renderers the actions for individual category list items.
+     *
+     * @param coursecat $category
+     * @return string
+     */
+    public function category_listitem_actions(coursecat $category, array $actions = null) {
+        if ($actions === null) {
+            $actions = \core_course\management\helper::get_category_listitem_actions($category);
+        }
+        $menu = new action_menu();
+        $menu->attributes['class'] .= ' category-item-actions item-actions';
+        $hasitems = false;
+        foreach ($actions as $key => $action) {
+            $hasitems = true;
+            $menu->add(new action_menu_link(
+                $action['url'],
+                $action['icon'],
+                $action['string'],
+                in_array($key, array('show', 'hide', 'moveup', 'movedown')),
+                array('data-action' => $key, 'class' => 'action-'.$key)
+            ));
+        }
+        if (!$hasitems) {
+            return '';
+        }
+        return $this->render($menu);
+    }
+
+    /**
+     * Renders bulk actions for categories.
+     *
+     * @return string
+     */
+    public function category_bulk_actions() {
+        // Resort courses.
+        // Change parent.
+        $strgo = new lang_string('go');
+
+        $html  = html_writer::start_div('category-bulk-actions bulk-actions');
+        if (coursecat::can_resort_any()) {
+            $options = array(
+                'name' => get_string('resortbyname'),
+                'idnumber' => get_string('resortbyidnumber'),
+            );
+            $select = html_writer::select(
+                $options,
+                'resortcategoriesby',
+                '',
+                array('' => 'choosedots'),
+                array('aria-labelledby' => 'resortselectedcategoriesby')
+            );
+            $submit = array('type' => 'submit', 'name' => 'bulkresortcategories', 'value' => $strgo);
+            $html .= $this->detail_pair(
+                html_writer::span(get_string('resortselectedcategoriesby'), '', array('id' => 'resortselectedcategoriesby')),
+                $select . html_writer::empty_tag('input', $submit)
+            );
+        }
+        if (coursecat::can_change_parent_any()) {
+            $options = coursecat::make_categories_list('moodle/category:manage');
+            $select = html_writer::select(
+                $options,
+                'movecategoriesto',
+                '',
+                array('' => 'choosedots'),
+                array('aria-labelledby' => 'moveselectedcategoriesto')
+            );
+            $submit = array('type' => 'submit', 'name' => 'bulkmovecategories', 'value' => $strgo);
+            $html .= $this->detail_pair(
+                html_writer::span(get_string('moveselectedcategoriesto'), '', array('id' => 'moveselectedcategoriesto')),
+                $select . html_writer::empty_tag('input', $submit)
+            );
+        }
+        $html .= html_writer::end_div();
+        return $html;
+    }
+
+    /**
+     * Renders a course listing.
+     *
+     * @param coursecat $category The currently selected category. This is what the listing is focused on.
+     * @param course_in_list $course The currently selected course.
+     * @param int $page The page being displayed.
+     * @param int $perpage The number of courses to display per page.
+     * @return string
+     */
+    public function course_listing(coursecat $category = null, course_in_list $course = null, $page = 0, $perpage = 20) {
+
+        if ($category === null) {
+            $html = html_writer::start_div('select-a-category');
+            $html .= html_writer::tag('h3', get_string('courses'));
+            $html .= $this->output->notification(get_string('selectacategory'), 'notifymessage');
+            $html .= html_writer::end_div();
+            return $html;
+        }
+
+        $page = max($page, 0);
+        $perpage = max($perpage, 2);
+        $totalcourses = $category->coursecount;
+        $totalpages = ceil($totalcourses / $perpage);
+        if ($page > $totalpages - 1) {
+            $page = $totalpages - 1;
+        }
+        $options = array(
+            'offset' => $page * $perpage,
+            'limit' => $perpage
+        );
+        $courseid = isset($course) ? $course->id : null;
+        $class = '';
+        if ($page === 0) {
+            $class .= ' firstpage';
+        }
+        if ($page + 1 === (int)$totalpages) {
+            $class .= ' lastpage';
+        }
+
+        $html  = html_writer::start_div('course-listing'.$class, array(
+            'data-category' => $category->id,
+            'data-page' => $page,
+            'data-totalpages' => $totalpages,
+            'data-totalcourses' => $totalcourses,
+            'data-canmoveoutof' => $category->can_move_courses_out_of() && $category->can_move_courses_into()
+        ));
+        $html .= html_writer::tag('h3', $category->get_formatted_name());
+        $html .= $this->course_listing_actions($category, $course, $perpage);
+        $html .= $this->listing_pagination($category, $page, $perpage);
+        $html .= html_writer::start_tag('ul', array('class' => 'ml'));
+        foreach ($category->get_courses($options) as $listitem) {
+            $html .= $this->course_listitem($category, $listitem, $courseid);
+        }
+        $html .= html_writer::end_tag('ul');
+        $html .= $this->listing_pagination($category, $page, $perpage, true);
+        $html .= $this->course_bulk_actions($category);
+        $html .= html_writer::end_div();
+        return $html;
+    }
+
+    /**
+     * Renders pagination for a course listing.
+     *
+     * @param coursecat $category The category to produce pagination for.
+     * @param int $page The current page.
+     * @param int $perpage The number of courses to display per page.
+     * @param bool $showtotals Set to true to show the total number of courses and what is being displayed.
+     * @return string
+     */
+    protected function listing_pagination(coursecat $category, $page, $perpage, $showtotals = false) {
+        $html = '';
+        $totalcourses = $category->coursecount;
+        $totalpages = ceil($totalcourses / $perpage);
+        if ($showtotals) {
+            if ($totalpages == 0) {
+                $str = get_string('nocoursesyet');
+            } else if ($totalpages == 1) {
+                $str = get_string('showingacourses', 'moodle', $totalcourses);
+            } else {
+                $a = new stdClass;
+                $a->start = ($page * $perpage) + 1;
+                $a->end = min((($page + 1) * $perpage), $totalcourses);
+                $a->total = $totalcourses;
+                $str = get_string('showingxofycourses', 'moodle', $a);
+            }
+            $html .= html_writer::div($str, 'listing-pagination-totals dimmed');
+        }
+
+        if ($totalcourses < $perpage) {
+            return $html;
+        }
+        $aside = 2;
+        $span = $aside * 2 + 1;
+        $start = max($page - $aside, 0);
+        $end = min($page + $aside, $totalpages - 1);
+        if (($end - $start) < $span) {
+            if ($start == 0) {
+                $end = min($totalpages - 1, $span - 1);
+            } else if ($end == ($totalpages - 1)) {
+                $start = max(0, $end - $span + 1);
+            }
+        }
+        $items = array();
+        $baseurl = new moodle_url('/course/management.php', array('categoryid' => $category->id));
+        if ($page > 0) {
+            $items[] = $this->action_button(new moodle_url($baseurl, array('page' => 0)), get_string('first'));
+            $items[] = $this->action_button(new moodle_url($baseurl, array('page' => $page - 1)), get_string('prev'));
+            $items[] = '...';
+        }
+        for ($i = $start; $i <= $end; $i++) {
+            $class = '';
+            if ($page == $i) {
+                $class = 'active-page';
+            }
+            $pageurl = new moodle_url($baseurl, array('page' => $i));
+            $items[] = $this->action_button($pageurl, $i + 1, null, $class, get_string('pagea', 'moodle', $i+1));
+        }
+        if ($page < ($totalpages - 1)) {
+            $items[] = '...';
+            $items[] = $this->action_button(new moodle_url($baseurl, array('page' => $page + 1)), get_string('next'));
+            $items[] = $this->action_button(new moodle_url($baseurl, array('page' => $totalpages - 1)), get_string('last'));
+        }
+
+        $html .= html_writer::div(join('', $items), 'listing-pagination');
+        return $html;
+    }
+
+    /**
+     * Renderers a course list item.
+     *
+     * This function will be called for every course being displayed by course_listing.
+     *
+     * @param coursecat $category The currently selected category and the category the course belongs to.
+     * @param course_in_list $course The course to produce HTML for.
+     * @param int $selectedcourse The id of the currently selected course.
+     * @return string
+     */
+    public function course_listitem(coursecat $category, course_in_list $course, $selectedcourse) {
+
+        $text = $course->get_formatted_name();
+        $attributes = array(
+            'class' => 'listitem listitem-course',
+            'data-id' => $course->id,
+            'data-selected' => ($selectedcourse == $course->id) ? '1' : '0',
+            'data-visible' => $course->visible ? '1' : '0'
+        );
+
+        $bulkcourseinput = array('type' => 'checkbox', 'name' => 'bc[]', 'value' => $course->id, 'class' => 'bulk-action-checkbox');
+        if (!$category->has_manage_capability()) {
+            // Very very hardcoded here.
+            $bulkcourseinput['style'] = 'visibility:hidden';
+        }
+
+        $viewcourseurl = new moodle_url($this->page->url, array('courseid' => $course->id));
+
+        $html  = html_writer::start_tag('li', $attributes);
+        $html .= html_writer::start_div('clearfix');
+
+        if ($category->can_resort_courses()) {
+            // In order for dnd to be available the user must be able to resort the category children..
+            $html .= html_writer::div($this->output->pix_icon('i/dragdrop', get_string('dndcourse')), 'float-left drag-handle');
+        }
+
+        $html .= html_writer::start_div('float-left');
+        $html .= html_writer::empty_tag('input', $bulkcourseinput).'&nbsp;';
+        $html .= html_writer::end_div();
+        $html .= html_writer::link($viewcourseurl, $text, array('class' => 'float-left coursename'));
+        $html .= html_writer::start_div('float-right');
+        $html .= html_writer::tag('span', s($course->idnumber), array('class' => 'dimmed idnumber'));
+        $html .= $this->course_listitem_actions($category, $course);
+        $html .= html_writer::end_div();
+        $html .= html_writer::end_div();
+        $html .= html_writer::end_tag('li');
+        return $html;
+    }
+
+    /**
+     * Renderers actions for the course listing.
+     *
+     * Not to be confused with course_listitem_actions which renderers the actions for individual courses.
+     *
+     * @param coursecat $category
+     * @param course_in_list $course The currently selected course.
+     * @param int $perpage
+     * @return string
+     */
+    public function course_listing_actions(coursecat $category, course_in_list $course = null, $perpage = 20) {
+        $actions = array();
+        if ($category->can_create_course()) {
+            $url = new moodle_url('/course/edit.php', array('category' => $category->id, 'returnto' => 'catmanage'));
+            $actions[] = html_writer::link($url, get_string('newcourse'));
+        }
+        if ($category->can_request_course()) {
+            // Request a new course.
+            $url = new moodle_url('/course/request.php', array('return' => 'management'));
+            $actions[] = html_writer::link($url, get_string('requestcourse'));
+        }
+        if ($category->can_resort_courses()) {
+            $params = $this->page->url->params();
+            $params['action'] = 'resortcourses';
+            $params['sesskey'] = sesskey();
+            $baseurl = new moodle_url('/course/management.php', $params);
+            $fullnameurl = new moodle_url($baseurl, array('resort' => 'fullname'));
+            $shortnameurl = new moodle_url($baseurl, array('resort' => 'shortname'));
+            $idnumberurl = new moodle_url($baseurl, array('resort' => 'idnumber'));
+            $menu = new action_menu(array(
+                new action_menu_link_secondary($fullnameurl, null, get_string('resortbyfullname')),
+                new action_menu_link_secondary($shortnameurl, null, get_string('resortbyshortname')),
+                new action_menu_link_secondary($idnumberurl, null, get_string('resortbyidnumber'))
+            ));
+            $menu->actiontext = get_string('resortcourses');
+            $menu->actionicon = new pix_icon('t/sort', ' ', 'moodle', array('class' => 'iconsmall', 'title' => ''));
+            $actions[] = $this->render($menu);
+        }
+        $strall = get_string('all');
+        $menu = new action_menu(array(
+            new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 5)), null, 5),
+            new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 10)), null, 10),
+            new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 20)), null, 20),
+            new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 50)), null, 50),
+            new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 100)), null, 100),
+            new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 999)), null, $strall),
+        ));
+        if ((int)$perpage === 999) {
+            $perpage = $strall;
+        }
+        $menu->attributes['class'] .= ' courses-per-page';
+        $menu->actiontext = get_string('perpagea', 'moodle', $perpage);
+        $actions[] = $this->render($menu);
+        return html_writer::div(join(' | ', $actions), 'listing-actions course-listing-actions');
+    }
+
+    /**
+     * Renderers actions for individual course actions.
+     *
+     * @param coursecat $category The currently selected category.
+     * @param course_in_list $course The course to renderer actions for.
+     * @return string
+     */
+    public function course_listitem_actions(coursecat $category, course_in_list $course) {
+        $actions = \core_course\management\helper::get_course_listitem_actions($category, $course);
+        if (empty($actions)) {
+            return '';
+        }
+        $actionshtml = array();
+        foreach ($actions as $action) {
+            $action['attributes']['role'] = 'button';
+            $actionshtml[] = $this->output->action_icon($action['url'], $action['icon'], null, $action['attributes']);
+        }
+        return html_writer::span(join('', $actionshtml), 'course-item-actions item-actions');
+    }
+
+    /**
+     * Renderers bulk actions that can be performed on courses.
+     *
+     * @param coursecat $category The currently selected category and the category in which courses that
+     *      are selectable belong.
+     * @return string
+     */
+    public function course_bulk_actions(coursecat $category) {
+        $html  = html_writer::start_div('course-bulk-actions bulk-actions');
+        if ($category->can_move_courses_out_of()) {
+            $options = coursecat::make_categories_list('moodle/category:manage');
+            $select = html_writer::select(
+                $options,
+                'movecoursesto',
+                '',
+                array('' => 'choosedots'),
+                array('aria-labelledby' => 'moveselectedcoursesto')
+            );
+            $submit = array('type' => 'submit', 'name' => 'bulkmovecourses', 'value' => get_string('go'));
+            $html .= $this->detail_pair(
+                html_writer::span(get_string('moveselectedcoursesto'), '', array('id' => 'moveselectedcoursesto')),
+                $select . html_writer::empty_tag('input', $submit)
+            );
+        }
+        $html .= html_writer::end_div();
+        return $html;
+    }
+
+    /**
+     * Renderers detailed course information.
+     *
+     * @param course_in_list $course The course to display details for.
+     * @return string
+     */
+    public function course_detail(course_in_list $course) {
+        $details = \core_course\management\helper::get_course_detail_array($course);
+        $fullname = $details['fullname']['value'];
+
+        $html  = html_writer::start_div('course-detail');
+        $html .= html_writer::tag('h3', $fullname);
+        $html .= $this->course_detail_actions($course);
+        foreach ($details as $class => $data) {
+            $html .= $this->detail_pair($data['key'], $data['value'], $class);
+        }
+        $html .= html_writer::end_div();
+        return $html;
+    }
+
+    /**
+     * Renderers a key value pair of information for display.
+     *
+     * @param string $key
+     * @param string $value
+     * @param string $class
+     * @return string
+     */
+    protected function detail_pair($key, $value, $class ='') {
+        $html = html_writer::start_div('detail-pair row yui3-g '.preg_replace('#[^a-zA-Z0-9_\-]#', '-', $class));
+        $html .= html_writer::div(html_writer::span($key), 'pair-key span3 yui3-u-1-4');
+        $html .= html_writer::div(html_writer::span($value), 'pair-value span9 yui3-u-3-4');
+        $html .= html_writer::end_div();
+        return $html;
+    }
+
+    /**
+     * A collection of actions for a course.
+     *
+     * @param course_in_list $course The course to display actions for.
+     * @return string
+     */
+    public function course_detail_actions(course_in_list $course) {
+        $actions = \core_course\management\helper::get_course_detail_actions($course);
+        if (empty($actions)) {
+            return '';
+        }
+        $options = array();
+        foreach ($actions as $action) {
+            $options[] = $this->action_link($action['url'], $action['string']);
+        }
+        return html_writer::div(join(' | ', $options), 'listing-actions course-detail-listing-actions');
+    }
+
+    /**
+     * Creates an action button (styled link)
+     *
+     * @param moodle_url $url The URL to go to when clicked.
+     * @param string $text The text for the button.
+     * @param string $id An id to give the button.
+     * @param string $class A class to give the button.
+     * @return string
+     */
+    protected function action_button(moodle_url $url, $text, $id = null, $class = null, $title = null) {
+        $attributes = array(
+            'class' => 'yui3-button',
+        );
+        if (!is_null($id)) {
+            $attributes['id'] = $id;
+        }
+        if (!is_null($class)) {
+            $attributes['class'] .= ' '.$class;
+        }
+        if (is_null($title)) {
+            $title = $text;
+        }
+        $attributes['title'] = $title;
+        return html_writer::link($url, $text, $attributes);
+    }
+
+    /**
+     * Opens a grid.
+     *
+     * Call {@link core_course_management_renderer::grid_column_start()} to create columns.
+     *
+     * @param string $id An id to give this grid.
+     * @param string $class A class to give this grid.
+     * @return string
+     */
+    public function grid_start($id = null, $class = null) {
+        $gridclass = 'grid-row-r row-fluid';
+        if (is_null($class)) {
+            $class = $gridclass;
+        } else {
+            $class .= ' ' . $gridclass;
+        }
+        $attributes = array();
+        if (!is_null($id)) {
+            $attributes['id'] = $id;
+        }
+        return html_writer::start_div($class, $attributes);
+    }
+
+    /**
+     * Closes the grid.
+     *
+     * @return string
+     */
+    public function grid_end() {
+        return html_writer::end_div();
+    }
+
+    /**
+     * Opens a grid column
+     *
+     * @param int $size The number of segments this column should span.
+     * @param string $id An id to give the column.
+     * @param string $class A class to give the column.
+     * @return string
+     */
+    public function grid_column_start($size, $id = null, $class = null) {
+
+        // Calculate Bootstrap grid sizing.
+        $bootstrapclass = 'span'.$size;
+
+        // Calculate YUI grid sizing.
+        if ($size === 12) {
+            $maxsize = 1;
+            $size = 1;
+        } else {
+            $maxsize = 12;
+            $divisors = array(8, 6, 5, 4, 3, 2);
+            foreach ($divisors as $divisor) {
+                if (($maxsize % $divisor === 0) && ($size % $divisor === 0)) {
+                    $maxsize = $maxsize / $divisor;
+                    $size = $size / $divisor;
+                    break;
+                }
+            }
+        }
+        if ($maxsize > 1) {
+            $yuigridclass =  "grid-col-{$size}-{$maxsize} grid-col";
+        } else {
+            $yuigridclass =  "grid-col-1 grid-col";
+        }
+
+        if (is_null($class)) {
+            $class = $yuigridclass . ' ' . $bootstrapclass;
+        } else {
+            $class .= ' ' . $yuigridclass . ' ' . $bootstrapclass;
+        }
+        $attributes = array();
+        if (!is_null($id)) {
+            $attributes['id'] = $id;
+        }
+        return html_writer::start_div($class, $attributes);
+    }
+
+    /**
+     * Closes a grid column.
+     *
+     * @return string
+     */
+    public function grid_column_end() {
+        return html_writer::end_div();
+    }
+
+    /**
+     * Renders an action_icon.
+     *
+     * This function uses the {@link core_renderer::action_link()} method for the
+     * most part. What it does different is prepare the icon as HTML and use it
+     * as the link text.
+     *
+     * @param string|moodle_url $url A string URL or moodel_url
+     * @param pix_icon $pixicon
+     * @param component_action $action
+     * @param array $attributes associative array of html link attributes + disabled
+     * @param bool $linktext show title next to image in link
+     * @return string HTML fragment
+     */
+    public function action_icon($url, pix_icon $pixicon, component_action $action = null,
+                                array $attributes = null, $linktext = false) {
+        if (!($url instanceof moodle_url)) {
+            $url = new moodle_url($url);
+        }
+        $attributes = (array)$attributes;
+
+        if (empty($attributes['class'])) {
+            // Let devs override the class via $attributes.
+            $attributes['class'] = 'action-icon';
+        }
+
+        $icon = $this->render($pixicon);
+
+        if ($linktext) {
+            $text = $pixicon->attributes['alt'];
+        } else {
+            $text = '';
+        }
+
+        return $this->action_link($url, $icon.$text, $action, $attributes);
+    }
+
+    /**
+     * Displays a view mode selector.
+     *
+     * @param array $modes An array of view modes.
+     * @param string $currentmode The current view mode.
+     * @param moodle_url $url The URL to use when changing actions. Defaults to the page URL.
+     * @param string $param The param name.
+     * @return string
+     */
+    public function view_mode_selector(array $modes, $currentmode, moodle_url $url = null, $param = 'view') {
+        if ($url === null) {
+            $url = $this->page->url;
+        }
+
+        $menu = new action_menu;
+        $menu->attributes['class'] .= ' view-mode-selector vms';
+
+        $selected = null;
+        foreach ($modes as $mode => $modestr) {
+            $attributes = array(
+                'class' => 'vms-mode',
+                'data-mode' => $mode
+            );
+            if ($currentmode === $mode) {
+                $attributes['class'] .= ' currentmode';
+                $selected = $modestr;
+            }
+            if ($selected === null) {
+                $selected = $modestr;
+            }
+            $modeurl = new moodle_url($url, array($param => $mode));
+            if ($mode === 'default') {
+                $modeurl->remove_params($param);
+            }
+            $menu->add(new action_menu_link_secondary($modeurl, null, $modestr, $attributes));
+        }
+
+        $menu->actiontext = get_string('viewing', 'moodle', $selected);
+
+        $html = html_writer::start_div('view-mode-selector vms');
+        $html .= $this->render($menu);
+        $html .= html_writer::end_div();
+
+        return $html;
+    }
+
+    /**
+     * Displays a search result listing.
+     *
+     * @param array $courses The courses to display.
+     * @param int $totalcourses The total number of courses to display.
+     * @param course_in_list $course The currently selected course if there is one.
+     * @param int $page The current page, starting at 0.
+     * @param int $perpage The number of courses to display per page.
+     * @return string
+     */
+    public function search_listing(array $courses, $totalcourses, course_in_list $course = null, $page = 0, $perpage = 20) {
+        $page = max($page, 0);
+        $perpage = max($perpage, 2);
+        $totalpages = ceil($totalcourses / $perpage);
+        if ($page > $totalpages - 1) {
+            $page = $totalpages - 1;
+        }
+        $courseid = isset($course) ? $course->id : null;
+        $first = true;
+        $last = false;
+        $i = $page * $perpage;
+
+        $html  = html_writer::start_div('course-listing', array(
+            'data-category' => 'search',
+            'data-page' => $page,
+            'data-totalpages' => $totalpages,
+            'data-totalcourses' => $totalcourses
+        ));
+        $html .= html_writer::tag('h3', get_string('courses'));
+        $html .= $this->search_pagination($totalcourses, $page, $perpage);
+        $html .= html_writer::start_tag('ul', array('class' => 'ml'));
+        foreach ($courses as $listitem) {
+            $i++;
+            if ($i == $totalcourses) {
+                $last = true;
+            }
+            $html .= $this->search_listitem($listitem, $courseid, $first, $last);
+            $first = false;
+        }
+        $html .= html_writer::end_tag('ul');
+        $html .= $this->search_pagination($totalcourses, $page, $perpage, true);
+        $html .= html_writer::end_div();
+        return $html;
+    }
+
+    /**
+     * Displays pagination for search results.
+     *
+     * @param int $totalcourses The total number of courses to be displayed.
+     * @param int $page The current page.
+     * @param int $perpage The number of courses being displayed.
+     * @param bool $showtotals Whether or not to print total information.
+     * @return string
+     */
+    protected function search_pagination($totalcourses, $page, $perpage, $showtotals = false) {
+        $html = '';
+        $totalpages = ceil($totalcourses / $perpage);
+        if ($showtotals) {
+            if ($totalpages == 1) {
+                $str = get_string('showingacourses', 'moodle', $totalcourses);
+            } else {
+                $a = new stdClass;
+                $a->start = ($page * $perpage) + 1;
+                $a->end = min((($page + 1) * $perpage), $totalcourses);
+                $a->total = $totalcourses;
+                $str = get_string('showingxofycourses', 'moodle', $a);
+            }
+            $html .= html_writer::div($str, 'listing-pagination-totals dimmed');
+        }
+
+        if ($totalcourses < $perpage) {
+            return $html;
+        }
+        $aside = 2;
+        $span = $aside * 2 + 1;
+        $start = max($page - $aside, 0);
+        $end = min($page + $aside, $totalpages - 1);
+        if (($end - $start) < $span) {
+            if ($start == 0) {
+                $end = min($totalpages - 1, $span - 1);
+            } else if ($end == ($totalpages - 1)) {
+                $start = max(0, $end - $span + 1);
+            }
+        }
+        $items = array();
+        $baseurl = $this->page->url;
+        if ($page > 0) {
+            $items[] = $this->action_button(new moodle_url($baseurl, array('page' => 0)), get_string('first'));
+            $items[] = $this->action_button(new moodle_url($baseurl, array('page' => $page - 1)), get_string('prev'));
+            $items[] = '...';
+        }
+        for ($i = $start; $i <= $end; $i++) {
+            $class = '';
+            if ($page == $i) {
+                $class = 'active-page';
+            }
+            $items[] = $this->action_button(new moodle_url($baseurl, array('page' => $i)), $i + 1, null, $class);
+        }
+        if ($page < ($totalpages - 1)) {
+            $items[] = '...';
+            $items[] = $this->action_button(new moodle_url($baseurl, array('page' => $page + 1)), get_string('next'));
+            $items[] = $this->action_button(new moodle_url($baseurl, array('page' => $totalpages - 1)), get_string('last'));
+        }
+
+        $html .= html_writer::div(join('', $items), 'listing-pagination');
+        return $html;
+    }
+
+    /**
+     * Renderers a search result course list item.
+     *
+     * This function will be called for every course being displayed by course_listing.
+     *
+     * @param course_in_list $course The course to produce HTML for.
+     * @param int $selectedcourse The id of the currently selected course.
+     * @return string
+     */
+    public function search_listitem(course_in_list $course, $selectedcourse) {
+
+        $text = $course->get_formatted_name();
+        $attributes = array(
+            'class' => 'listitem listitem-course',
+            'data-id' => $course->id,
+            'data-selected' => ($selectedcourse == $course->id) ? '1' : '0',
+            'data-visible' => $course->visible ? '1' : '0'
+        );
+
+        $bulkcourseinput = array('type' => 'checkbox', 'name' => 'bc[]', 'value' => $course->id, 'class' => 'bulk-action-checkbox');
+        $viewcourseurl = new moodle_url($this->page->url, array('courseid' => $course->id));
+        $categoryname = coursecat::get($course->category)->get_formatted_name();
+
+        $html  = html_writer::start_tag('li', $attributes);
+        $html .= html_writer::start_div('clearfix');
+        $html .= html_writer::start_div('float-left');
+        $html .= html_writer::empty_tag('input', $bulkcourseinput).'&nbsp;';
+        $html .= html_writer::end_div();
+        $html .= html_writer::link($viewcourseurl, $text, array('class' => 'float-left coursename'));
+        $html .= html_writer::tag('span', $categoryname, array('class' => 'float-left categoryname'));
+        $html .= html_writer::start_div('float-right');
+        $html .= $this->search_listitem_actions($course);
+        $html .= html_writer::tag('span', s($course->idnumber), array('class' => 'dimmed idnumber'));
+        $html .= html_writer::end_div();
+        $html .= html_writer::end_div();
+        $html .= html_writer::end_tag('li');
+        return $html;
+    }
+
+    /**
+     * Renderers actions for individual course actions.
+     *
+     * @param course_in_list $course The course to renderer actions for.
+     * @return string
+     */
+    public function search_listitem_actions(course_in_list $course) {
+        $baseurl = new moodle_url(
+            '/course/managementsearch.php',
+            array('courseid' => $course->id, 'categoryid' => $course->category, 'sesskey' => sesskey())
+        );
+        $actions = array();
+        // Edit.
+        if ($course->can_access()) {
+            if ($course->can_edit()) {
+                $actions[] = $this->output->action_icon(
+                    new moodle_url('/course/edit.php', array('id' => $course->id)),
+                    new pix_icon('t/edit', get_string('edit')),
+                    null,
+                    array('class' => 'action-edit')
+                );
+            }
+            // Show/Hide.
+            if ($course->can_change_visibility()) {
+                if ($course->visible) {
+                    $actions[] = $this->output->action_icon(
+                        new moodle_url($baseurl, array('action' => 'hidecourse')),
+                        new pix_icon('t/show', get_string('hide')),
+                        null,
+                        array('data-action' => 'hide', 'class' => 'action-hide')
+                    );
+                } else {
+                    $actions[] = $this->output->action_icon(
+                        new moodle_url($baseurl, array('action' => 'showcourse')),
+                        new pix_icon('t/hide', get_string('show')),
+                        null,
+                        array('data-action' => 'show', 'class' => 'action-show')
+                    );
+                }
+            }
+        }
+        if (empty($actions)) {
+            return '';
+        }
+        return html_writer::span(join('', $actions), 'course-item-actions item-actions');
+    }
+
+}
\ No newline at end of file
index 26c3de2..185a05e 100644 (file)
@@ -1,83 +1,82 @@
 <?php
-      // Admin-only code to delete a course utterly
-
-    require_once(dirname(__FILE__) . '/../config.php');
-    require_once($CFG->dirroot . '/course/lib.php');
-
-    $id     = required_param('id', PARAM_INT);              // course id
-    $delete = optional_param('delete', '', PARAM_ALPHANUM); // delete confirmation hash
-
-    $PAGE->set_url('/course/delete.php', array('id' => $id));
-    $PAGE->set_context(context_system::instance());
-    require_login();
-
-    $site = get_site();
-
-    $strdeletecourse = get_string("deletecourse");
-    $stradministration = get_string("administration");
-    $strcategories = get_string("categories");
-
-    if (! $course = $DB->get_record("course", array("id"=>$id))) {
-        print_error("invalidcourseid");
-    }
-    if ($site->id == $course->id) {
-        // can not delete frontpage!
-        print_error("invalidcourseid");
-    }
-
-    $coursecontext = context_course::instance($course->id);
-
-    if (!can_delete_course($id)) {
-        print_error('cannotdeletecourse');
-    }
-
-    $category = $DB->get_record("course_categories", array("id"=>$course->category));
-    $courseshortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id)));
-    $categoryname = format_string($category->name, true, array('context' => context_coursecat::instance($category->id)));
-
-    $PAGE->navbar->add($stradministration, new moodle_url('/admin/index.php/'));
-    $PAGE->navbar->add($strcategories, new moodle_url('/course/index.php'));
-    $PAGE->navbar->add($categoryname, new moodle_url('/course/index.php', array('categoryid' => $course->category)));
-    if (! $delete) {
-        $strdeletecheck = get_string("deletecheck", "", $courseshortname);
-        $strdeletecoursecheck = get_string("deletecoursecheck");
-
-        $PAGE->navbar->add($strdeletecheck);
-        $PAGE->set_title("$site->shortname: $strdeletecheck");
-        $PAGE->set_heading($site->fullname);
-        echo $OUTPUT->header();
-
-        $message = "$strdeletecoursecheck<br /><br />" . format_string($course->fullname, true, array('context' => $coursecontext)) .  " (" . $courseshortname . ")";
-
-        echo $OUTPUT->confirm($message, "delete.php?id=$course->id&delete=".md5($course->timemodified), "manage.php?categoryid=$course->category");
-
-        echo $OUTPUT->footer();
-        exit;
-    }
-
-    if ($delete != md5($course->timemodified)) {
-        print_error("invalidmd5");
-    }
-
-    if (!confirm_sesskey()) {
-        print_error('confirmsesskeybad', 'error');
-    }
+// 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/>.
+
+/**
+ * Admin-only code to delete a course utterly.
+ *
+ * @package core_course
+ * @copyright 2002 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 . '/course/lib.php');
+
+$id = required_param('id', PARAM_INT); // Course ID.
+$delete = optional_param('delete', '', PARAM_ALPHANUM); // Confirmation hash.
+
+$PAGE->set_url('/course/delete.php', array('id' => $id));
+$PAGE->set_context(context_system::instance());
+require_login();
+
+$course = $DB->get_record('course', array('id' => $id), '*', MUST_EXIST);
+$coursecontext = context_course::instance($course->id);
+
+if ((int)$SITE->id === (int)$course->id || !can_delete_course($id)) {
+    // Can not delete frontpage or don't have permission to delete the course.
+    print_error('cannotdeletecourse');
+}
+
+$courseshortname = format_string($course->shortname, true, array('context' => $coursecontext));
+$coursefullname = format_string($course->fullname, true, array('context' => $coursecontext));
+$categoryurl = new moodle_url('/course/management.php', array('categoryid' => $course->category));
+
+navigation_node::override_active_url(new moodle_url('/course/management.php'));
+
+// Check if we've got confirmation.
+if ($delete === md5($course->timemodified)) {
+    // We do - time to delete the course.
+    require_sesskey();
+    delete_course($course);
+    // Update course count in categories.
+    fix_course_sortorder();
 
     $strdeletingcourse = get_string("deletingcourse", "", $courseshortname);
 
     $PAGE->navbar->add($strdeletingcourse);
-    $PAGE->set_title("$site->shortname: $strdeletingcourse");
-    $PAGE->set_heading($site->fullname);
+    $PAGE->set_title("$SITE->shortname: $strdeletingcourse");
+    $PAGE->set_heading($SITE->fullname);
+
     echo $OUTPUT->header();
     echo $OUTPUT->heading($strdeletingcourse);
-
-    delete_course($course);
-    fix_course_sortorder(); //update course count in catagories
-
     echo $OUTPUT->heading( get_string("deletedcourse", "", $courseshortname) );
-
-    echo $OUTPUT->continue_button("manage.php?categoryid=$course->category");
-
+    echo $OUTPUT->continue_button($categoryurl);
     echo $OUTPUT->footer();
+}
+
+$strdeletecheck = get_string("deletecheck", "", $courseshortname);
+$strdeletecoursecheck = get_string("deletecoursecheck");
+$message = "{$strdeletecoursecheck}<br /><br />{$coursefullname} ({$courseshortname})";
 
+$continueurl = new moodle_url('/course/delete.php', array('id' => $course->id, 'delete' => md5($course->timemodified)));
 
+$PAGE->navbar->add($strdeletecheck);
+$PAGE->set_title("$SITE->shortname: $strdeletecheck");
+$PAGE->set_heading($SITE->fullname);
+echo $OUTPUT->header();
+echo $OUTPUT->confirm($message, $continueurl, $categoryurl);
+echo $OUTPUT->footer();
+exit;
\ No newline at end of file
index f76655e..fa694f4 100644 (file)
 <?php
-
-if (!defined('MOODLE_INTERNAL')) {
-    die('Direct access to this script is forbidden.');    ///  It must be included from a Moodle page
-}
-
-require_once($CFG->libdir.'/formslib.php');
-require_once($CFG->libdir.'/questionlib.php');
-require_once($CFG->libdir. '/coursecatlib.php');
-
-class delete_category_form extends moodleform {
-
-    var $_category;
-
-    function definition() {
-        $mform = & $this->_form;
-        $this->_category = $this->_customdata;
-        $categorycontext = context_coursecat::instance($this->_category->id);
-
-        // Check permissions, to see if it OK to give the option to delete
-        // the contents, rather than move elsewhere.
-        $candeletecontent = $this->_category->can_delete_full();
-
-        // Get the list of categories we might be able to move to.
-        $displaylist = $this->_category->move_content_targets_list();
-
-        // Now build the options.
-        $options = array();
-        if ($displaylist) {
-            $options[0] = get_string('movecontentstoanothercategory');
-        }
-        if ($candeletecontent) {
-            $options[1] = get_string('deleteallcannotundo');
-        }
-        if (empty($options)) {
-            print_error('youcannotdeletecategory', 'error', 'index.php', $this->_category->get_formatted_name());
-        }
-
-        // Now build the form.
-        $mform->addElement('header','general', get_string('categorycurrentcontents', '', $this->_category->get_formatted_name()));
-
-        // Describe the contents of this category.
-        $contents = '';
-        if ($this->_category->has_children()) {
-            $contents .= '<li>' . get_string('subcategories') . '</li>';
-        }
-        if ($this->_category->has_courses()) {
-            $contents .= '<li>' . get_string('courses') . '</li>';
-        }
-        if (question_context_has_any_questions($categorycontext)) {
-            $contents .= '<li>' . get_string('questionsinthequestionbank') . '</li>';
-        }
-        if (!empty($contents)) {
-            $mform->addElement('static', 'emptymessage', get_string('thiscategorycontains'), html_writer::tag('ul', $contents));
-        } else {
-            $mform->addElement('static', 'emptymessage', '', get_string('deletecategoryempty'));
-        }
-
-        // Give the options for what to do.
-        $mform->addElement('select', 'fulldelete', get_string('whattodo'), $options);
-        if (count($options) == 1) {
-            $optionkeys = array_keys($options);
-            $option = reset($optionkeys);
-            $mform->hardFreeze('fulldelete');
-            $mform->setConstant('fulldelete', $option);
-        }
-
-        if ($displaylist) {
-            $mform->addElement('select', 'newparent', get_string('movecategorycontentto'), $displaylist);
-            if (in_array($this->_category->parent, $displaylist)) {
-                $mform->setDefault('newparent', $this->_category->parent);
-            }
-            $mform->disabledIf('newparent', 'fulldelete', 'eq', '1');
-        }
-
-        $mform->addElement('hidden', 'deletecat');
-        $mform->setType('deletecat', PARAM_ALPHANUM);
-        $mform->addElement('hidden', 'sure');
-        $mform->setType('sure', PARAM_ALPHANUM);
-        $mform->setDefault('sure', md5(serialize($this->_category)));
-
-//--------------------------------------------------------------------------------
-        $this->add_action_buttons(true, get_string('delete'));
-
-        $this->set_data(array('deletecat' => $this->_category->id));
-    }
-
-/// perform some extra moodle validation
-    function validation($data, $files) {
-        $errors = parent::validation($data, $files);
-
-        if (empty($data['fulldelete']) && empty($data['newparent'])) {
-        /// When they have chosen the move option, they must specify a destination.
-            $errors['newparent'] = get_string('required');
-        }
-
-        if ($data['sure'] != md5(serialize($this->_category))) {
-            $errors['categorylabel'] = get_string('categorymodifiedcancel');
-        }
-
-        return $errors;
-    }
+// 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/>.
+
+
+/**
+ * Delete category form.
+ *
+ * This file has been deprecated since 2.6.
+ * The class delete_category_form has been renamed to core_course_deletecategory_form and is now autloaded.
+ * Please update your code to use that new class.
+ *
+ * @deprecated since 2.6
+ * @package core_course
+ * @copyright 2002 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Class delete_category_form
+ *
+ * The class delete_category_form has been renamed to core_course_deletecategory_form and is now autloaded.
+ * Please update your code to use that new class.
+ *
+ * @deprecated since 2.6
+ * @todo remove in 2.7 MDL-41502
+ * @package core_course
+ * @copyright 2002 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class delete_category_form extends core_course_deletecategory_form {
+    // Nothing to do here.
 }
 
index 1021c23..f257f91 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
@@ -18,7 +17,7 @@
 /**
  * Edit course settings
  *
- * @package    moodlecore
+ * @package    core_course
  * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
@@ -27,9 +26,9 @@ require_once('../config.php');
 require_once('lib.php');
 require_once('edit_form.php');
 
-$id         = optional_param('id', 0, PARAM_INT);       // course id
-$categoryid = optional_param('category', 0, PARAM_INT); // course category - can be changed in edit form
-$returnto = optional_param('returnto', 0, PARAM_ALPHANUM); // generic navigation return page switch
+$id = optional_param('id', 0, PARAM_INT); // Course id.
+$categoryid = optional_param('category', 0, PARAM_INT); // Course category - can be changed in edit form.
+$returnto = optional_param('returnto', 0, PARAM_ALPHANUM); // Generic navigation return page switch.
 
 $PAGE->set_pagelayout('admin');
 $pageparams = array('id'=>$id);
@@ -38,10 +37,11 @@ if (empty($id)) {
 }
 $PAGE->set_url('/course/edit.php', $pageparams);
 
-// basic access control checks
-if ($id) { // editing course
+// Basic access control checks.
+if ($id) {
+    // Editing course.
     if ($id == SITEID){
-        // don't allow editing of  'site course' using this from
+        // Don't allow editing of  'site course' using this from.
         print_error('cannoteditsiteform');
     }
 
@@ -51,7 +51,8 @@ if ($id) { // editing course
     $coursecontext = context_course::instance($course->id);
     require_capability('moodle/course:update', $coursecontext);
 
-} else if ($categoryid) { // creating new course in this category
+} else if ($categoryid) {
+    // Creating new course in this category.
     $course = null;
     require_login();
     $category = $DB->get_record('course_categories', array('id'=>$categoryid), '*', MUST_EXIST);
@@ -64,11 +65,11 @@ if ($id) { // editing course
     print_error('needcoursecategroyid');
 }
 
-// Prepare course and the editor
+// Prepare course and the editor.
 $editoroptions = array('maxfiles' => EDITOR_UNLIMITED_FILES, 'maxbytes'=>$CFG->maxbytes, 'trusttext'=>false, 'noclean'=>true);
 $overviewfilesoptions = course_overviewfiles_options($course);
 if (!empty($course)) {
-    //add context for editor
+    // Add context for editor.
     $editoroptions['context'] = $coursecontext;
     $editoroptions['subdirs'] = file_area_contains_subdirs($coursecontext, 'course', 'summary', 0);
     $course = file_prepare_standard_editor($course, 'summary', $editoroptions, $coursecontext, 'course', 'summary', 0);
@@ -76,14 +77,14 @@ if (!empty($course)) {
         file_prepare_standard_filemanager($course, 'overviewfiles', $overviewfilesoptions, $coursecontext, 'course', 'overviewfiles', 0);
     }
 
-    // Inject current aliases
+    // Inject current aliases.
     $aliases = $DB->get_records('role_names', array('contextid'=>$coursecontext->id));
     foreach($aliases as $alias) {
         $course->{'role_'.$alias->roleid} = $alias->name;
     }
 
 } else {
-    //editor should respect category context if course context is not set.
+    // Editor should respect category context if course context is not set.
     $editoroptions['context'] = $catcontext;
     $editoroptions['subdirs'] = 0;
     $course = file_prepare_standard_editor($course, 'summary', $editoroptions, null, 'course', 'summary', null);
@@ -92,7 +93,7 @@ if (!empty($course)) {
     }
 }
 
-// first create the form
+// First create the form.
 $editform = new course_edit_form(NULL, array('course'=>$course, 'category'=>$category, 'editoroptions'=>$editoroptions, 'returnto'=>$returnto));
 if ($editform->is_cancelled()) {
         switch ($returnto) {
@@ -100,10 +101,10 @@ if ($editform->is_cancelled()) {
                 $url = new moodle_url($CFG->wwwroot.'/course/index.php', array('categoryid' => $categoryid));
                 break;
             case 'catmanage':
-                $url = new moodle_url($CFG->wwwroot.'/course/manage.php', array('categoryid' => $categoryid));
+                $url = new moodle_url($CFG->wwwroot.'/course/management.php', array('categoryid' => $categoryid));
                 break;
             case 'topcatmanage':
-                $url = new moodle_url($CFG->wwwroot.'/course/manage.php');
+                $url = new moodle_url($CFG->wwwroot.'/course/management.php');
                 break;
             case 'topcat':
                 $url = new moodle_url($CFG->wwwroot.'/course/');
@@ -119,34 +120,32 @@ if ($editform->is_cancelled()) {
         redirect($url);
 
 } else if ($data = $editform->get_data()) {
-    // process data if submitted
-
+    // Process data if submitted.
     if (empty($course->id)) {
-        // In creating the course
+        // In creating the course.
         $course = create_course($data, $editoroptions);
 
-        // Get the context of the newly created course
+        // Get the context of the newly created course.
         $context = context_course::instance($course->id, MUST_EXIST);
 
         if (!empty($CFG->creatornewroleid) and !is_viewing($context, NULL, 'moodle/role:assign') and !is_enrolled($context, NULL, 'moodle/role:assign')) {
-            // deal with course creators - enrol them internally with default role
+            // Deal with course creators - enrol them internally with default role.
             enrol_try_internal_enrol($course->id, $USER->id, $CFG->creatornewroleid);
-
         }
         if (!is_enrolled($context)) {
-            // Redirect to manual enrolment page if possible
+            // Redirect to manual enrolment page if possible.
             $instances = enrol_get_instances($course->id, true);
             foreach($instances as $instance) {
                 if ($plugin = enrol_get_plugin($instance->enrol)) {
                     if ($plugin->get_manual_enrol_link($instance)) {
-                        // we know that the ajax enrol UI will have an option to enrol
+                        // We know that the ajax enrol UI will have an option to enrol.
                         redirect(new moodle_url('/enrol/users.php', array('id'=>$course->id)));
                     }
                 }
             }
         }
     } else {
-        // Save any changes to the files used in the editor
+        // Save any changes to the files used in the editor.
         update_course($data, $editoroptions);
     }
 
@@ -154,8 +153,7 @@ if ($editform->is_cancelled()) {
     redirect(new moodle_url('/course/view.php', array('id' => $course->id)));
 }
 
-
-// Print the form
+// Print the form.
 
 $site = get_site();
 
@@ -185,4 +183,3 @@ echo $OUTPUT->heading($streditcoursesettings);
 $editform->display();
 
 echo $OUTPUT->footer();
-
index 05a5777..f2793a2 100644 (file)
 
 /**
  * Page for creating or editing course category name/parent/description.
+ *
  * When called with an id parameter, edits the category with that id.
  * Otherwise it creates a new category with default parent from the parent
  * parameter, which may be 0.
  *
- * @package    core
- * @subpackage course
+ * @package    core_course
  * @copyright  2007 Nicolas Connault
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 require_once('../config.php');
 require_once($CFG->dirroot.'/course/lib.php');
-require_once($CFG->dirroot.'/course/editcategory_form.php');
 require_once($CFG->libdir.'/coursecatlib.php');
 
 require_login();
 
 $id = optional_param('id', 0, PARAM_INT);
-$itemid = 0; //initalise itemid, as all files in category description has item id 0
 
+$url = new moodle_url('/course/editcategory.php');
 if ($id) {
-    if (!$category = $DB->get_record('course_categories', array('id' => $id))) {
-        print_error('unknowcategory');
-    }
-    $PAGE->set_url('/course/editcategory.php', array('id' => $id));
-    $categorycontext = context_coursecat::instance($id);
-    $PAGE->set_context($categorycontext);
-    require_capability('moodle/category:manage', $categorycontext);
-    $strtitle = get_string('editcategorysettings');
-    $editorcontext = $categorycontext;
+    $coursecat = coursecat::get($id, MUST_EXIST, true);
+    $category = $coursecat->get_db_record();
+    $context = context_coursecat::instance($id);
+
+    $url->param('id', $id);
+    $strtitle = new lang_string('editcategorysettings');
+    $itemid = 0; // Initialise itemid, as all files in category description has item id 0.
     $title = $strtitle;
-    $fullname = $category->name;
+    $fullname = $coursecat->get_formatted_name();
 } else {
     $parent = required_param('parent', PARAM_INT);
-    $PAGE->set_url('/course/editcategory.php', array('parent' => $parent));
+    $url->param('parent', $parent);
     if ($parent) {
-        if (!$DB->record_exists('course_categories', array('id' => $parent))) {
-            print_error('unknowcategory');
-        }
+        $DB->record_exists('course_categories', array('id' => $parent), '*', MUST_EXIST);
         $context = context_coursecat::instance($parent);
     } else {
         $context = context_system::instance();
     }
-    $PAGE->set_context($context);
+
     $category = new stdClass();
     $category->id = 0;
     $category->parent = $parent;
-    require_capability('moodle/category:manage', $context);
-    $strtitle = get_string("addnewcategory");
-    $editorcontext = $context;
-    $itemid = null; //set this explicitly, so files for parent category should not get loaded in draft area.
+    $strtitle = new lang_string("addnewcategory");
+    $itemid = null; // Set this explicitly, so files for parent category should not get loaded in draft area.
     $title = "$SITE->shortname: ".get_string('addnewcategory');
     $fullname = $SITE->fullname;
 }
 
-$PAGE->set_pagelayout('admin');
+require_capability('moodle/category:manage', $context);
 
-$editoroptions = array(
-    'maxfiles'  => EDITOR_UNLIMITED_FILES,
-    'maxbytes'  => $CFG->maxbytes,
-    'trusttext' => true,
-    'context'   => $editorcontext,
-    'subdirs'   => file_area_contains_subdirs($editorcontext, 'coursecat', 'description', $itemid),
-);
-$category = file_prepare_standard_editor($category, 'description', $editoroptions, $editorcontext, 'coursecat', 'description', $itemid);
+// Page "Add new category" (with "Top" as a parent) does not exist in navigation.
+// We pretend we are on course management page.
+if ($id !== 0) {
+    navigation_node::override_active_url(new moodle_url('/course/management.php'));
+}
 
-$mform = new editcategory_form('editcategory.php', compact('category', 'editoroptions'));
-$mform->set_data($category);
+$PAGE->set_context($context);
+$PAGE->set_url($url);
+$PAGE->set_pagelayout('admin');
+$PAGE->set_title($title);
+$PAGE->set_heading($fullname);
 
+$mform = new core_course_editcategory_form(null, array(
+    'categoryid' => $id,
+    'parent' => $category->parent,
+    'context' => $context,
+    'itemid' => $itemid
+));
+$mform->set_data(file_prepare_standard_editor(
+    $category,
+    'description',
+    $mform->get_description_editor_options(),
+    $context,
+    'coursecat',
+    'description',
+    $itemid
+));
+
+$manageurl = new moodle_url('/course/management.php');
 if ($mform->is_cancelled()) {
     if ($id) {
-        redirect($CFG->wwwroot . '/course/manage.php?categoryid=' . $id);
+        $manageurl->param('categoryid', $id);
     } else if ($parent) {
-        redirect($CFG->wwwroot .'/course/manage.php?categoryid=' . $parent);
-    } else {
-        redirect($CFG->wwwroot .'/course/manage.php');
+        $manageurl->param('categoryid', $parent);
     }
+    redirect($manageurl);
 } else if ($data = $mform->get_data()) {
-    if ($id) {
-        $newcategory = coursecat::get($id);
-        if ($data->parent != $category->parent && !$newcategory->can_change_parent($data->parent)) {
+    if (isset($coursecat)) {
+        if ((int)$data->parent !== (int)$coursecat->parent && !$coursecat->can_change_parent($data->parent)) {
             print_error('cannotmovecategory');
         }
-        $newcategory->update($data, $editoroptions);
+        $coursecat->update($data, $mform->get_description_editor_options());
     } else {
-        $newcategory = coursecat::create($data, $editoroptions);
+        $category = coursecat::create($data, $mform->get_description_editor_options());
     }
-
-    redirect('manage.php?categoryid='.$newcategory->id);
+    $manageurl->param('categoryid', $category->id);
+    redirect($manageurl);
 }
 
-// Page "Add new category" (with "Top" as a parent) does not exist in navigation.
-// We pretend we are on course management page.
-if (empty($id) && empty($parent)) {
-    navigation_node::override_active_url(new moodle_url('/course/manage.php'));
-}
-
-$PAGE->set_title($title);
-$PAGE->set_heading($fullname);
 echo $OUTPUT->header();
 echo $OUTPUT->heading($strtitle);
 $mform->display();
 echo $OUTPUT->footer();
-
index 4e0db04..ebff691 100644 (file)
@@ -1,76 +1,66 @@
 <?php
-if (!defined('MOODLE_INTERNAL')) {
-    die('Direct access to this script is forbidden.');    ///  It must be included from a Moodle page
-}
+// 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/>.
 
-require_once ($CFG->dirroot.'/course/moodleform_mod.php');
-require_once ($CFG->libdir.'/coursecatlib.php');
-class editcategory_form extends moodleform {
+/**
+ * Edit category form.
+ *
+ * This file and class have been deprecated, the form has been renamed to core_course_editcategory_form and is not autoloaded when
+ * first used. Please update your code to use this new form.
+ *
+ * @deprecated since 2.6
+ * @todo remove in 2.7 MDL-41502
+ *
+ * @package core_course
+ * @copyright 2002 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
 
-    // form definition
-    function definition() {
-        global $CFG, $DB;
-        $mform =& $this->_form;
-        $category = $this->_customdata['category'];
-        $editoroptions = $this->_customdata['editoroptions'];
+defined('MOODLE_INTERNAL') || die;
 
-        // get list of categories to use as parents, with site as the first one
-        $options = array();
-        if (has_capability('moodle/category:manage', context_system::instance()) || $category->parent == 0) {
-            $options[0] = get_string('top');
-        }
-        if ($category->id) {
-            // Editing an existing category.
-            $options += coursecat::make_categories_list('moodle/category:manage', $category->id);
-            if (empty($options[$category->parent])) {
-                $options[$category->parent] = $DB->get_field('course_categories', 'name', array('id'=>$category->parent));
-            }
-            $strsubmit = get_string('savechanges');
-        } else {
-            // Making a new category
-            $options += coursecat::make_categories_list('moodle/category:manage');
-            $strsubmit = get_string('createcategory');
-        }
+debugging('Please update your code to use core_course_editcategory_form (autloaded). This file will be removed in 2.7');
 
-        $mform->addElement('select', 'parent', get_string('parentcategory'), $options);
-        $mform->addElement('text', 'name', get_string('categoryname'), array('size'=>'30'));
-        $mform->addRule('name', get_string('required'), 'required', null);
-        $mform->setType('name', PARAM_TEXT);
-        $mform->addElement('text', 'idnumber', get_string('idnumbercoursecategory'),'maxlength="100"  size="10"');
-        $mform->addHelpButton('idnumber', 'idnumbercoursecategory');
-        $mform->setType('idnumber', PARAM_RAW);
-        $mform->addElement('editor', 'description_editor', get_string('description'), null, $editoroptions);
-        $mform->setType('description_editor', PARAM_RAW);
-        if (!empty($CFG->allowcategorythemes)) {
-            $themes = array(''=>get_string('forceno'));
-            $allthemes = get_list_of_themes();
-            foreach ($allthemes as $key=>$theme) {
-                if (empty($theme->hidefromselector)) {
-                    $themes[$key] = get_string('pluginname', 'theme_'.$theme->name);
-                }
-            }
-            $mform->addElement('select', 'theme', get_string('forcetheme'), $themes);
-        }
+/**
+ * Class editcategory_form.
+ *
+ * This file and class have been deprecated, the form has been renamed to core_course_editcategory_form and is not autoloaded when
+ * first used. Please update your code to use this new form.
+ *
+ * @deprecated since 2.6
+ * @todo remove in 2.7 MDL-41502
+ * @package core_course
+ * @copyright 2002 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class editcategory_form extends core_course_editcategory_form {
 
-        $mform->addElement('hidden', 'id', 0);
-        $mform->setType('id', PARAM_INT);
-        $mform->setDefault('id', $category->id);
-