Merge branch 'MDL-56902-master' of git://github.com/damyon/moodle

This commit is contained in:
David Monllao 2016-11-23 08:29:41 +08:00
commit 44c3d0775c
5 changed files with 151 additions and 4 deletions

View File

@ -234,12 +234,18 @@ class block_manager {
return false;
}
$undeletableblocks = self::get_undeletable_block_types();
foreach ($this->blockinstances as $region) {
foreach ($region as $instance) {
if (empty($instance->instance->blockname)) {
continue;
}
if ($instance->instance->blockname == $blockname) {
if ($instance->instance->requiredbytheme) {
if (!in_array($block->name, $undeletableblocks)) {
continue;
}
}
return true;
}
}
@ -579,6 +585,20 @@ class block_manager {
return;
}
// Exclude auto created blocks if they are not undeletable in this theme.
$undeletable = $this->get_undeletable_block_types();
$undeletablecheck = '';
$undeletableparams = array();
$undeletablenotparams = array();
if (!empty($undeletable)) {
list($testsql, $undeletableparams) = $DB->get_in_or_equal($undeletable, SQL_PARAMS_NAMED, 'undeletable');
list($testnotsql, $undeletablenotparams) = $DB->get_in_or_equal($undeletable, SQL_PARAMS_NAMED, 'deletable', false);
$undeletablecheck = 'AND ((bi.blockname ' . $testsql . ' AND bi.requiredbytheme = 1) OR ' .
' (bi.blockname ' . $testnotsql . ' AND bi.requiredbytheme = 0))';
} else {
$undeletablecheck = 'AND (bi.requiredbytheme = 0)';
}
if (is_null($includeinvisible)) {
$includeinvisible = $this->page->user_is_editing();
}
@ -626,6 +646,7 @@ class block_manager {
bi.parentcontextid,
bi.showinsubcontexts,
bi.pagetypepattern,
bi.requiredbytheme,
bi.subpagepattern,
bi.defaultregion,
bi.defaultweight,
@ -649,12 +670,15 @@ class block_manager {
AND (bi.subpagepattern IS NULL OR bi.subpagepattern = :subpage2)
$visiblecheck
AND b.visible = 1
$undeletablecheck
ORDER BY
COALESCE(bp.region, bi.defaultregion),
COALESCE(bp.weight, bi.defaultweight),
bi.id";
$blockinstances = $DB->get_recordset_sql($sql, $params + $parentcontextparams + $pagetypepatternparams);
$allparams = $params + $parentcontextparams + $pagetypepatternparams + $undeletableparams + $undeletablenotparams;
$blockinstances = $DB->get_recordset_sql($sql, $allparams);
$this->birecordsbyregion = $this->prepare_per_region_arrays();
$unknown = array();
@ -957,6 +981,10 @@ class block_manager {
* load_blocks. This is used, for example, to ensure that all blocks get a
* chance to initialise themselves via the {@link block_base::specialize()}
* method, before any output is done.
*
* It is also used to create any blocks that are "undeletable" by the current theme.
* These blocks that are auto-created have requiredbytheme set on the block instance
* so they are only visible on themes that require them.
*/
public function create_all_block_instances() {
global $PAGE;
@ -977,7 +1005,7 @@ class block_manager {
}
}
if (!$found) {
$this->add_block_at_end_of_default_region($forced);
$this->add_block_required_by_theme($forced);
$missing = true;
}
}
@ -993,6 +1021,45 @@ class block_manager {
}
/**
* Add a block that is required by the current theme but has not been
* created yet. This is a special type of block that only shows in themes that
* require it (by listing it in undeletable_block_types).
*
* @param string $blockname the name of the block type.
*/
protected function add_block_required_by_theme($blockname) {
global $DB;
if (empty($this->birecordsbyregion)) {
// No blocks or block regions exist yet.
return;
}
$systemcontext = context_system::instance();
$defaultregion = $this->get_default_region();
// Add a special system wide block instance only for themes that require it.
$blockinstance = new stdClass;
$blockinstance->blockname = $blockname;
$blockinstance->parentcontextid = $systemcontext->id;
$blockinstance->showinsubcontexts = true;
$blockinstance->requiredbytheme = true;
$blockinstance->pagetypepattern = '*';
$blockinstance->subpagepattern = null;
$blockinstance->defaultregion = $defaultregion;
$blockinstance->defaultweight = 0;
$blockinstance->configdata = '';
$blockinstance->id = $DB->insert_record('block_instances', $blockinstance);
// Ensure the block context is created.
context_block::instance($blockinstance->id);
// If the new instance was created, allow it to do additional setup.
if ($block = block_instance($blockname, $blockinstance)) {
$block->instance_create();
}
}
/**
* Return an array of content objects from a set of block instances
*

3
lib/db/install.xml Normal file → Executable file
View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="lib/db" VERSION="20160804" COMMENT="XMLDB file for core Moodle tables"
<XMLDB PATH="lib/db" VERSION="20161119" COMMENT="XMLDB file for core Moodle tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
>
@ -2459,6 +2459,7 @@
<FIELD NAME="blockname" TYPE="char" LENGTH="40" NOTNULL="true" SEQUENCE="false" COMMENT="The type of block this is. Foreign key, references block.name."/>
<FIELD NAME="parentcontextid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The context within which this block appears. Foreign key, references context.id."/>
<FIELD NAME="showinsubcontexts" TYPE="int" LENGTH="4" NOTNULL="true" SEQUENCE="false" COMMENT="If 1, this block appears on all matching pages in subcontexts of parentcontextid, as well in pages belonging to parentcontextid."/>
<FIELD NAME="requiredbytheme" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If 1, this block was created because it was required by the theme and did not exist."/>
<FIELD NAME="pagetypepattern" TYPE="char" LENGTH="64" NOTNULL="true" SEQUENCE="false" COMMENT="The types of page this block appears on. Either an exact page type like mod-quiz-view, or a pattern like mod-quiz-* or course-view-*. Note that course-view-* will match course-view."/>
<FIELD NAME="subpagepattern" TYPE="char" LENGTH="16" NOTNULL="false" SEQUENCE="false" COMMENT="Further restrictions on where this block appears. In some places, e.g. during a quiz or lesson attempt, different pages have different subpage ids. If this field is not null, the block only appears on that particular subpage."/>
<FIELD NAME="defaultregion" TYPE="char" LENGTH="16" NOTNULL="true" SEQUENCE="false" COMMENT="Which block region this block should appear in on each page, in the absence of a specific position in the block_positions table."/>

View File

@ -2406,5 +2406,32 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2016110600.00);
}
if ($oldversion < 2016112200.01) {
// Define field requiredbytheme to be added to block_instances.
$table = new xmldb_table('block_instances');
$field = new xmldb_field('requiredbytheme', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0', 'showinsubcontexts');
// Conditionally launch add field requiredbytheme.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Main savepoint reached.
upgrade_main_savepoint(true, 2016112200.01);
}
if ($oldversion < 2016112200.02) {
// Change the existing site level admin and settings blocks to be requiredbytheme which means they won't show in boost.
$context = context_system::instance();
$params = array('blockname' => 'settings', 'parentcontextid' => $context->id);
$DB->set_field('block_instances', 'requiredbytheme', 1, $params);
$params = array('blockname' => 'navigation', 'parentcontextid' => $context->id);
$DB->set_field('block_instances', 'requiredbytheme', 1, $params);
// Main savepoint reached.
upgrade_main_savepoint(true, 2016112200.02);
}
return true;
}

View File

@ -542,6 +542,58 @@ class core_blocklib_testcase extends advanced_testcase {
context_block::instance($tokeep); // Would throw an exception if it was deleted.
}
public function test_create_all_block_instances() {
global $CFG, $PAGE, $DB;
$this->resetAfterTest();
$regionname = 'side-pre';
$context = context_system::instance();
$PAGE->reset_theme_and_output();
$CFG->theme = 'boost';
list($page, $blockmanager) = $this->get_a_page_and_block_manager(array($regionname),
$context, 'page-type');
$blockmanager->load_blocks();
$blockmanager->create_all_block_instances();
$blocks = $blockmanager->get_blocks_for_region($regionname);
$this->assertEmpty($blocks);
// There should be no blocks in the DB.
$PAGE->reset_theme_and_output();
// Change to a theme with undeletable blocks.
$CFG->theme = 'clean';
list($page, $blockmanager) = $this->get_a_page_and_block_manager(array($regionname),
$context, 'page-type');
$blockmanager->load_blocks();
$blockmanager->create_all_block_instances();
$blocks = $blockmanager->get_blocks_for_region($regionname);
$this->assertCount(2, $blocks);
$undeletable = block_manager::get_undeletable_block_types();
foreach ($undeletable as $blockname) {
$instance = $DB->get_record('block_instances', array('blockname' => $blockname));
$this->assertEquals(1, $instance->requiredbytheme);
}
// Switch back and those auto blocks should not be returned.
$PAGE->reset_theme_and_output();
$CFG->theme = 'boost';
list($page, $blockmanager) = $this->get_a_page_and_block_manager(array($regionname),
$context, 'page-type');
$blockmanager->load_blocks();
$blockmanager->create_all_block_instances();
$blocks = $blockmanager->get_blocks_for_region($regionname);
$this->assertEmpty($blocks);
// But they should exist in the DB.
foreach ($undeletable as $blockname) {
$count = $DB->count_records('block_instances', array('blockname' => $blockname));
$this->assertEquals(1, $count);
}
}
}
/**

View File

@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2016112200.00; // YYYYMMDD = weekly release date of this DEV branch.
$version = 2016112200.02; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.