MDL-70444 my: Improved robustness of bulk dashboard reset

This commit is contained in:
Peter Burnett 2021-01-07 11:15:05 +10:00
parent fd840ab59c
commit 4e72d5916c
4 changed files with 77 additions and 27 deletions

View File

@ -267,6 +267,7 @@ $string['commentsnotenabled'] = 'Comments feature is not enabled';
$string['commentsrequirelogin'] = 'You need to log in to view the comments.';
$string['comparelanguage'] = 'Compare and edit current language';
$string['complete'] = 'Complete';
$string['completed'] = 'Completed';
$string['completereport'] = 'Complete report';
$string['configuration'] = 'Configuration';
$string['confirm'] = 'Confirm';
@ -1115,6 +1116,7 @@ $string['indicator:readactions_help'] = 'This indicator represents the number of
$string['indicator:userforumstracking'] = 'User is tracking forums';
$string['indicator:userforumstracking_help'] = 'This indicator represents whether or not the student has tracking turned on in the forums.';
$string['info'] = 'Information';
$string['inprogress'] = 'In progress';
$string['institution'] = 'Institution';
$string['instudentview'] = 'in student view';
$string['interests'] = 'Interests';

View File

@ -31,6 +31,7 @@ $string['defaultpage'] = 'Default My Moodle page';
$string['defaultprofilepage'] = 'Default profile page';
$string['addpage'] = 'Add page';
$string['alldashboardswerereset'] = 'All Dashboard pages have been reset to default.';
$string['resettingdashboards'] = 'Resetting user dashboards to default...';
$string['allprofileswerereset'] = 'All profile pages have been reset to default.';
$string['delpage'] = 'Delete page';
$string['managepages'] = 'Manage pages';

View File

@ -35,20 +35,32 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('NO_OUTPUT_BUFFERING', true);
require_once(__DIR__ . '/../config.php');
require_once($CFG->dirroot . '/my/lib.php');
require_once($CFG->libdir.'/adminlib.php');
$resetall = optional_param('resetall', null, PARAM_BOOL);
$resetall = optional_param('resetall', false, PARAM_BOOL);
$header = "$SITE->shortname: ".get_string('myhome')." (".get_string('mypage', 'admin').")";
$PAGE->set_blocks_editing_capability('moodle/my:configsyspages');
admin_externalpage_setup('mypage', '', null, '', array('pagelayout' => 'mydashboard'));
// If we are resetting all, just output a progress bar.
if ($resetall && confirm_sesskey()) {
my_reset_page_for_all_users(MY_PAGE_PRIVATE, 'my-index');
redirect($PAGE->url, get_string('alldashboardswerereset', 'my'));
echo $OUTPUT->header($header);
echo $OUTPUT->heading(get_string('resettingdashboards', 'my'), 3);
$progressbar = new progress_bar();
$progressbar->create();
\core\session\manager::write_close();
my_reset_page_for_all_users(MY_PAGE_PRIVATE, 'my-index', $progressbar);
core\notification::success(get_string('alldashboardswerereset', 'my'));
echo $OUTPUT->continue_button($PAGE->url);
echo $OUTPUT->footer();
die();
}
// Override pagetype to show blocks properly.
@ -65,7 +77,8 @@ if (!$currentpage = my_get_page(null, MY_PAGE_PRIVATE)) {
$PAGE->set_subpage($currentpage->id);
// Display a button to reset everyone's dashboard.
$url = new moodle_url($PAGE->url, array('resetall' => 1));
$url = $PAGE->url;
$url->params(['resetall' => true, 'sesskey' => sesskey()]);
$button = $OUTPUT->single_button($url, get_string('reseteveryonesdashboard', 'my'));
$PAGE->set_button($button . $PAGE->button);

View File

@ -166,40 +166,70 @@ function my_reset_page($userid, $private=MY_PAGE_PRIVATE, $pagetype='my-index')
*
* @param int $private Either MY_PAGE_PRIVATE or MY_PAGE_PUBLIC.
* @param string $pagetype Either my-index or user-profile.
* @param progress_bar $progressbar A progress bar to update.
* @return void
*/
function my_reset_page_for_all_users($private = MY_PAGE_PRIVATE, $pagetype = 'my-index') {
function my_reset_page_for_all_users($private = MY_PAGE_PRIVATE, $pagetype = 'my-index', $progressbar = null) {
global $DB;
// This may take a while. Raise the execution time limit.
core_php_time_limit::raise();
// Find all the user pages and all block instances in them.
$sql = "SELECT bi.id
FROM {my_pages} p
JOIN {context} ctx ON ctx.instanceid = p.userid AND ctx.contextlevel = :usercontextlevel
JOIN {block_instances} bi ON bi.parentcontextid = ctx.id AND
bi.pagetypepattern = :pagetypepattern AND
(bi.subpagepattern IS NULL OR bi.subpagepattern = " . $DB->sql_concat("''", 'p.id') . ")
WHERE p.private = :private";
$params = array('private' => $private,
'usercontextlevel' => CONTEXT_USER,
'pagetypepattern' => $pagetype);
$blockids = $DB->get_fieldset_sql($sql, $params);
$users = $DB->get_fieldset_select(
'my_pages',
'DISTINCT(userid)',
'userid IS NOT NULL AND private = :private',
['private' => $private]
);
$chunks = array_chunk($users, 20);
// Wrap the SQL queries in a transaction.
$transaction = $DB->start_delegated_transaction();
// Delete the block instances.
if (!empty($blockids)) {
blocks_delete_instances($blockids);
if (!empty($progressbar) && count($chunks) > 0) {
$count = count($chunks);
$message = get_string('inprogress');
$progressbar->update(0, $count, $message);
}
// Finally delete the pages.
$DB->delete_records_select('my_pages', 'userid IS NOT NULL AND private = :private', ['private' => $private]);
foreach ($chunks as $key => $userchunk) {
list($infragment, $inparams) = $DB->get_in_or_equal($userchunk, SQL_PARAMS_NAMED);
// Find all the user pages and all block instances in them.
$sql = "SELECT bi.id
FROM {my_pages} p
JOIN {context} ctx ON ctx.instanceid = p.userid AND ctx.contextlevel = :usercontextlevel
JOIN {block_instances} bi ON bi.parentcontextid = ctx.id
AND bi.pagetypepattern = :pagetypepattern
AND (bi.subpagepattern IS NULL OR bi.subpagepattern = " . $DB->sql_concat("''", 'p.id') . ")
WHERE p.private = :private
AND p.userid $infragment";
// We should be good to go now.
$transaction->allow_commit();
$params = array_merge([
'private' => $private,
'usercontextlevel' => CONTEXT_USER,
'pagetypepattern' => $pagetype
], $inparams);
$blockids = $DB->get_fieldset_sql($sql, $params);
// Wrap the SQL queries in a transaction.
$transaction = $DB->start_delegated_transaction();
// Delete the block instances.
if (!empty($blockids)) {
blocks_delete_instances($blockids);
}
// Finally delete the pages.
$DB->delete_records_select(
'my_pages',
"userid $infragment AND private = :private",
array_merge(['private' => $private], $inparams)
);
// We should be good to go now.
$transaction->allow_commit();
if (!empty($progressbar)) {
$progressbar->update(((int) $key + 1), $count, $message);
}
}
// Trigger dashboard has been reset event.
$eventparams = array(
@ -211,6 +241,10 @@ function my_reset_page_for_all_users($private = MY_PAGE_PRIVATE, $pagetype = 'my
);
$event = \core\event\dashboards_reset::create($eventparams);
$event->trigger();
if (!empty($progressbar)) {
$progressbar->update(1, 1, get_string('completed'));
}
}
class my_syspage_block_manager extends block_manager {