Skip to content

Commit

Permalink
MDL-74271 core: Replace upgrade steps for blocks to be more performant
Browse files Browse the repository at this point in the history
The previous upgrade step was both duplicating a lot of code, and also
very non-performant as each record was fetched from the DB into PHP and
updated there.

Most of the operations can be performed straight into the database
without requiring any fetch to PHP at all.

This change includes unit tests for the new upgrade steps to ensure that
only the relevant data is created, updated, or deleted.
  • Loading branch information
andrewnicols committed Apr 6, 2022
1 parent b5f5188 commit 14dca23
Show file tree
Hide file tree
Showing 6 changed files with 694 additions and 181 deletions.
36 changes: 6 additions & 30 deletions blocks/calendar_month/db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

defined('MOODLE_INTERNAL') || die();

require_once("{$CFG->libdir}/db/upgradelib.php");

/**
* Upgrade the calendar_month block
* @param int $oldversion
Expand All @@ -58,36 +62,8 @@ function xmldb_block_calendar_month_upgrade($oldversion, $block) {
// Put any upgrade step following this.

if ($oldversion < 2022030200) {
$context = context_system::instance();

// Begin looking for any and all customised /my pages.
$pageselect = 'name = :name and private = :private';
$pageparams['name'] = '__default';
$pageparams['private'] = 1;
$pages = $DB->get_recordset_select('my_pages', $pageselect, $pageparams);
foreach ($pages as $subpage) {
$blockinstance = $DB->get_record('block_instances', ['blockname' => 'calendar_month',
'pagetypepattern' => 'my-index', 'subpagepattern' => $subpage->id]);

if (!$blockinstance) {
// Insert the calendar month into the default index page.
$blockinstance = new stdClass;
$blockinstance->blockname = 'calendar_month';
$blockinstance->parentcontextid = $context->id;
$blockinstance->showinsubcontexts = false;
$blockinstance->pagetypepattern = 'my-index';
$blockinstance->subpagepattern = $subpage->id;
$blockinstance->defaultregion = 'content';
$blockinstance->defaultweight = 0;
$blockinstance->timecreated = time();
$blockinstance->timemodified = time();
$DB->insert_record('block_instances', $blockinstance);
} else if ($blockinstance->defaultregion !== 'content') {
$blockinstance->defaultregion = 'content';
$DB->update_record('block_instances', $blockinstance);
}
}
$pages->close();
// Update all calendar_month blocks in the my-index to be in the main content region.
upgrade_block_set_defaultregion('calendar_month', '__default', 'my-index', 'content');
upgrade_block_savepoint(true, 2022030200, 'calendar_month', false);
}

Expand Down
110 changes: 19 additions & 91 deletions blocks/myoverview/db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@

defined('MOODLE_INTERNAL') || die();

require_once($CFG->dirroot . '/my/lib.php');
require_once("{$CFG->dirroot}/my/lib.php");
require_once("{$CFG->libdir}/db/upgradelib.php");

/**
* Upgrade code for the MyOverview block.
Expand Down Expand Up @@ -84,104 +85,31 @@ function xmldb_block_myoverview_upgrade($oldversion) {
// Put any upgrade step following this.

if ($oldversion < 2021052504) {
/**
* Small helper function for this version upgrade to delete instances of this block.
*
* @param stdClass $instance DB record of a block that we need to delete within Moodle.
*/
function delete_block_instance(stdClass $instance) {
global $DB;
if ($instance) {
list($sql, $params) = $DB->get_in_or_equal($instance->id, SQL_PARAMS_NAMED);
$params['contextlevel'] = CONTEXT_BLOCK;
$DB->delete_records_select('context', "contextlevel=:contextlevel AND instanceid " . $sql, $params);
$DB->delete_records('block_positions', ['blockinstanceid' => $instance->id]);
$DB->delete_records('block_instances', ['id' => $instance->id]);
$DB->delete_records_list('user_preferences', 'name',
['block' . $instance->id . 'hidden', 'docked_block_instance_' . $instance->id]);
}
}
upgrade_block_delete_instances('myoverview', '__default', 'my-index');

// Delete the default indexsys version of the block.
$mysubpagepattern = $DB->get_record(
'my_pages',
['userid' => null, 'name' => MY_PAGE_DEFAULT, 'private' => MY_PAGE_PRIVATE],
'id',
IGNORE_MULTIPLE
)->id;

$instanceselect = 'blockname = :blockname and pagetypepattern = :pagetypepattern and subpagepattern = :subpagepattern';
$instanceparams['blockname'] = 'myoverview';
$instanceparams['pagetypepattern'] = 'my-index';
$instanceparams['subpagepattern'] = $mysubpagepattern;

$total = $DB->count_records_select('block_instances', $instanceselect, $instanceparams);
// Check if where have blocks to delete.
if ($total > 0) {
$instances = $DB->get_recordset_select('block_instances', $instanceselect, $instanceparams);
// Show a progress bar.
$pbar = new progress_bar('deleteblockinstances', 500, true);
$i = 0;
$pbar->update($i, $total, "Deleting block instance - $i/$total.");
foreach ($instances as $instance) {
delete_block_instance($instance);
// Update progress.
$pbar->update($i, $total, "Deleting block instance - $i/$total.");
$i++;
}
$instances->close();
// Update progress.
$pbar->update($total, $total, "Deleting block instance - $total/$total.");
}
// Add new instance to the /my/courses.php page.
$subpagepattern = $DB->get_record('my_pages', [
'userid' => null,
'name' => MY_PAGE_COURSES,
'private' => MY_PAGE_PUBLIC,
], 'id', IGNORE_MULTIPLE)->id;

// Begin looking for any and all instances of course overview in customised /my pages.
$pageselect = 'name = :name and private = :private and userid IS NOT NULL';
$pageparams['name'] = MY_PAGE_DEFAULT;
$pageparams['private'] = MY_PAGE_PRIVATE;

$total = $DB->count_records_select('my_pages', $pageselect, $pageparams);
// Check if where have pages to check for blocks.
if ($total > 0) {
$pages = $DB->get_recordset_select('my_pages', $pageselect, $pageparams);
// Show a progress bar.
$pagepbar = new progress_bar('deletepageblockinstances', 500, true);
$i = 0;
$pagepbar->update($i, $total, "Deleting user page block instance - $i/$total.");
foreach ($pages as $page) {
$blocksql = 'blockname = :blockname and pagetypepattern = :pagetypepattern and subpagepattern = :subpagepattern';
$blockparams['blockname'] = 'myoverview';
$blockparams['pagetypepattern'] = 'my-index';
$blockparams['subpagepattern'] = $page->id;
$instances = $DB->get_records_select('block_instances', $blocksql, $blockparams);
foreach ($instances as $instance) {
delete_block_instance($instance);
}
// Update progress.
$pagepbar->update($i, $total, "Deleting user page block instance - $i/$total.");
$i++;
}
$pages->close();
// Update progress.
$pagepbar->update($total, $total, "Deleting user page block instance - $total/$total.");
}
$blockname = 'myoverview';
$pagetypepattern = 'my-index';

// Add new instance to the /my/courses.php page.
$subpagepattern = $DB->get_record(
'my_pages',
['userid' => null, 'name' => MY_PAGE_COURSES, 'private' => MY_PAGE_PUBLIC],
'id',
IGNORE_MULTIPLE
)->id;
$blockparams = [
'blockname' => $blockname,
'pagetypepattern' => $pagetypepattern,
'subpagepattern' => $subpagepattern,
];

// See if this block already somehow exists, it should not but who knows.
if (!$DB->record_exists('block_instances', ['blockname' => 'myoverview',
'pagetypepattern' => 'my-index', 'subpagepattern' => $subpagepattern])) {
if (!$DB->record_exists('block_instances', $blockparams)) {
$page = new moodle_page();
$systemcontext = context_system::instance();
$page->set_context($systemcontext);
$page->set_context(context_system::instance());
// Add the block to the default /my/courses.
$page->blocks->add_region('content');
$page->blocks->add_block('myoverview', 'content', 0, false, 'my-index', $subpagepattern);
$page->blocks->add_block($blockname, 'content', 0, false, $pagetypepattern, $subpagepattern);
}

upgrade_block_savepoint(true, 2021052504, 'myoverview', false);
Expand Down
34 changes: 4 additions & 30 deletions blocks/recentlyaccesseditems/db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@

defined('MOODLE_INTERNAL') || die();

require_once("{$CFG->libdir}/db/upgradelib.php");

/**
* Upgrade the recentlyaccesseditems db table.
*
Expand Down Expand Up @@ -76,36 +78,8 @@ function xmldb_block_recentlyaccesseditems_upgrade($oldversion, $block) {
// Put any upgrade step following this.

if ($oldversion < 2022030200) {
$context = context_system::instance();

// Begin looking for any and all customised /my pages.
$pageselect = 'name = :name and private = :private';
$pageparams['name'] = '__default';
$pageparams['private'] = 1;
$pages = $DB->get_recordset_select('my_pages', $pageselect, $pageparams);
foreach ($pages as $subpage) {
$blockinstance = $DB->get_record('block_instances', ['blockname' => 'recentlyaccesseditems',
'pagetypepattern' => 'my-index', 'subpagepattern' => $subpage->id]);

if (!$blockinstance) {
// Insert the recentlyaccesseditems into the default index page.
$blockinstance = new stdClass;
$blockinstance->blockname = 'recentlyaccesseditems';
$blockinstance->parentcontextid = $context->id;
$blockinstance->showinsubcontexts = false;
$blockinstance->pagetypepattern = 'my-index';
$blockinstance->subpagepattern = $subpage->id;
$blockinstance->defaultregion = 'side-post';
$blockinstance->defaultweight = -10;
$blockinstance->timecreated = time();
$blockinstance->timemodified = time();
$DB->insert_record('block_instances', $blockinstance);
} else if ($blockinstance->defaultregion !== 'side-post') {
$blockinstance->defaultregion = 'side-post';
$DB->update_record('block_instances', $blockinstance);
}
}
$pages->close();
// Update all recentlyaccesseditems blocks in the my-index to be in the main side-post region.
upgrade_block_set_defaultregion('recentlyaccesseditems', '__default', 'my-index', 'side-post');
upgrade_block_savepoint(true, 2022030200, 'recentlyaccesseditems', false);
}

Expand Down
36 changes: 6 additions & 30 deletions blocks/timeline/db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

defined('MOODLE_INTERNAL') || die();

require_once("{$CFG->libdir}/db/upgradelib.php");

/**
* Upgrade the timeline block
* @param int $oldversion
Expand All @@ -57,36 +61,8 @@ function xmldb_block_timeline_upgrade($oldversion, $block) {
// Put any upgrade step following this.

if ($oldversion < 2022030200) {
$context = context_system::instance();

// Begin looking for any and all customised /my pages.
$pageselect = 'name = :name and private = :private';
$pageparams['name'] = '__default';
$pageparams['private'] = 1;
$pages = $DB->get_recordset_select('my_pages', $pageselect, $pageparams);
foreach ($pages as $subpage) {
$blockinstance = $DB->get_record('block_instances', ['blockname' => 'timeline',
'pagetypepattern' => 'my-index', 'subpagepattern' => $subpage->id]);

if (!$blockinstance) {
// Insert the timeline into the default index page.
$blockinstance = new stdClass;
$blockinstance->blockname = 'timeline';
$blockinstance->parentcontextid = $context->id;
$blockinstance->showinsubcontexts = false;
$blockinstance->pagetypepattern = 'my-index';
$blockinstance->subpagepattern = $subpage->id;
$blockinstance->defaultregion = 'content';
$blockinstance->defaultweight = -10;
$blockinstance->timecreated = time();
$blockinstance->timemodified = time();
$DB->insert_record('block_instances', $blockinstance);
} else if ($blockinstance->defaultregion !== 'content') {
$blockinstance->defaultregion = 'content';
$DB->update_record('block_instances', $blockinstance);
}
}
$pages->close();
// Update all timeline blocks in the my-index to be in the main content region.
upgrade_block_set_defaultregion('timeline', '__default', 'my-index', 'content');
upgrade_block_savepoint(true, 2022030200, 'timeline', false);
}

Expand Down
Loading

0 comments on commit 14dca23

Please sign in to comment.