mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 16:32:18 +02:00
blocklib: MDL-19010 start of block_manager - get and set regions
This commit is contained in:
parent
c33db6e690
commit
86b5ea0f85
@ -167,6 +167,13 @@ $CFG->admin = 'admin';
|
||||
// These blocks are used when no other default setting is found.
|
||||
// $CFG->defaultblocks = 'participants,activity_modules,search_forums,admin,course_list:news_items,calendar_upcoming,recent_activity';
|
||||
//
|
||||
// You can specify a different class to be created for the $PAGE global, and to
|
||||
// compute which blocks appear on each page. However, I cannot think of any good
|
||||
// reason why you would need to change that. It just felt wrong to hard-code the
|
||||
// the class name. You are stronly advised not to use these to settings unless
|
||||
// you are absolutely sure you know what you are doing.
|
||||
// $CFG->moodlepageclass = 'moodle_page';
|
||||
// $CFG->blockmanagerclass = 'block_manager';
|
||||
//
|
||||
// Seconds for files to remain in caches. Decrease this if you are worried
|
||||
// about students being served outdated versions of uploaded files.
|
||||
|
113
lib/blocklib.php
113
lib/blocklib.php
@ -45,6 +45,109 @@ define('BLOCKS_PINNED_BOTH',2);
|
||||
|
||||
require_once($CFG->libdir.'/pagelib.php');
|
||||
|
||||
/**
|
||||
* This class keeps track of the block that should appear on a moodle_page.
|
||||
* The page to work with as passed to the constructor.
|
||||
* The only fields of moodle_page that is uses are ->context, ->pagetype and
|
||||
* ->subpage, so instead of passing a full moodle_page object, you may also
|
||||
* pass a stdClass object with those three fields. These field values are read
|
||||
* only at the point that the load_blocks() method is called. It is the caller's
|
||||
* responsibility to ensure that those fields do not subsequently change.
|
||||
*/
|
||||
class block_manager {
|
||||
/**#@+ Tracks the where we are in the generation of the page. */
|
||||
const STATE_BLOCKS_NOT_LOADED = 0;
|
||||
const STATE_BLOCKS_LOADED = 1;
|
||||
/**#@-*/
|
||||
|
||||
/// Field declarations =========================================================
|
||||
|
||||
protected $loaded = self::STATE_BLOCKS_NOT_LOADED;
|
||||
|
||||
protected $page;
|
||||
|
||||
protected $regions = array();
|
||||
|
||||
protected $defaultregion;
|
||||
|
||||
/// Constructor ================================================================
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param object $page the moodle_page object object we are managing the blocks for,
|
||||
* or a reasonable faxilimily. (See the comment at the top of this classe
|
||||
* and http://en.wikipedia.org/wiki/Duck_typing)
|
||||
*/
|
||||
public function __construct($page) {
|
||||
$this->page = $page;
|
||||
}
|
||||
|
||||
/// Getter methods =============================================================
|
||||
|
||||
/**
|
||||
* @return array the internal names of the regions on this page where block may appear.
|
||||
*/
|
||||
public function get_regions() {
|
||||
return array_keys($this->regions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the internal names of the region where new blocks are added
|
||||
* by default, and where any blocks from an unrecognised region are shown.
|
||||
* (Imagine that blocks were added with one theme selected, then you switched
|
||||
* to a theme with different block positions.)
|
||||
*/
|
||||
public function get_default_region() {
|
||||
return $this->defaultregion;
|
||||
}
|
||||
|
||||
/// Setter methods =============================================================
|
||||
|
||||
/**
|
||||
* @param string $region add a named region where blocks may appear on the
|
||||
* current page. This is an internal name, like 'side-pre', not a string to
|
||||
* display in the UI.
|
||||
*/
|
||||
public function add_region($region) {
|
||||
$this->check_not_yet_loaded();
|
||||
$this->regions[$region] = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $regions this utility method calls add_region for each array element.
|
||||
*/
|
||||
public function add_regions($regions) {
|
||||
foreach ($regions as $region) {
|
||||
$this->add_region($region);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $defaultregion the internal names of the region where new
|
||||
* blocks should be added by default, and where any blocks from an
|
||||
* unrecognised region are shown.
|
||||
*/
|
||||
public function set_default_region($defaultregion) {
|
||||
$this->check_not_yet_loaded();
|
||||
if (!array_key_exists($defaultregion, $this->regions)) {
|
||||
throw new coding_exception('Trying to set an unknown block region as the default.');
|
||||
}
|
||||
$this->defaultregion = $defaultregion;
|
||||
}
|
||||
|
||||
/// Inner workings =============================================================
|
||||
|
||||
protected function check_not_yet_loaded() {
|
||||
if ($this->loaded) {
|
||||
throw new coding_exception('block_manager has already loaded the blocks, to it is too late to change things that might affect which blocks are visible.');
|
||||
}
|
||||
}
|
||||
|
||||
protected function mark_loaded() {
|
||||
$this->loaded = self::STATE_BLOCKS_LOADED;
|
||||
}
|
||||
}
|
||||
|
||||
//This function retrieves a method-defined property of a class WITHOUT instantiating an object
|
||||
function block_method_result($blockname, $method, $param = NULL) {
|
||||
if(!block_load_class($blockname)) {
|
||||
@ -329,7 +432,7 @@ function blocks_print_group(&$page, &$pageblocks, $position) {
|
||||
$managecourseblocks = has_capability('moodle/site:manageblocks', $coursecontext);
|
||||
$editmymoodle = $page->pagetype == PAGE_MY_MOODLE && has_capability('moodle/my:manageblocks', $coursecontext);
|
||||
|
||||
if ($page->blocks->get_default_position() == $position &&
|
||||
if ($page->blocks->get_default_region() == $position &&
|
||||
$page->user_is_editing() &&
|
||||
($managecourseblocks || $editmymoodle || $myownblogpage || defined('ADMIN_STICKYBLOCKS'))) {
|
||||
|
||||
@ -639,7 +742,7 @@ function blocks_execute_action($page, &$pageblocks, $blockaction, $instanceorid,
|
||||
break;
|
||||
}
|
||||
|
||||
$newpos = $page->blocks->get_default_position();
|
||||
$newpos = $page->blocks->get_default_region();
|
||||
if (!empty($pinned)) {
|
||||
$sql = "SELECT 1, MAX(weight) + 1 AS nextfree
|
||||
FROM {block_pinned_old}
|
||||
@ -835,7 +938,7 @@ function blocks_get_pinned($page) {
|
||||
|
||||
$blocks = $DB->get_records_select('block_pinned_old', $select, $params, 'position, weight');
|
||||
|
||||
$positions = $page->blocks->get_positions();
|
||||
$positions = $page->blocks->get_regions();
|
||||
$arr = array();
|
||||
|
||||
foreach($positions as $key => $position) {
|
||||
@ -897,7 +1000,7 @@ function blocks_get_by_page($page) {
|
||||
$blocks = $DB->get_records_select('block_instance_old', "pageid = ? AND ? LIKE (" . $DB->sql_concat('pagetype', "'%'") . ")",
|
||||
array($page->get_id(), $page->pagetype), 'position, weight');
|
||||
|
||||
$positions = $page->blocks->get_positions();
|
||||
$positions = $page->blocks->get_regions();
|
||||
$arr = array();
|
||||
foreach($positions as $key => $position) {
|
||||
$arr[$position] = array();
|
||||
@ -986,7 +1089,7 @@ function blocks_repopulate_page($page) {
|
||||
$blocknames = $page->blocks_get_default();
|
||||
}
|
||||
|
||||
$positions = $page->blocks->get_positions();
|
||||
$positions = $page->blocks->get_regions();
|
||||
$posblocks = explode(':', $blocknames);
|
||||
|
||||
// Now one array holds the names of the positions, and the other one holds the blocks
|
||||
|
@ -268,8 +268,14 @@ class moodle_page {
|
||||
* @return blocks_manager the blocks manager object for this page.
|
||||
*/
|
||||
public function get_blocks() {
|
||||
global $CFG;
|
||||
if (is_null($this->_blocks)) {
|
||||
$this->_blocks = new blocks_manager();
|
||||
if (!empty($CFG->blockmanagerclass)) {
|
||||
$classname = $CFG->blockmanagerclass;
|
||||
} else {
|
||||
$classname = 'block_manager';
|
||||
}
|
||||
$this->_blocks = new $classname($this);
|
||||
}
|
||||
return $this->_blocks;
|
||||
}
|
||||
@ -745,21 +751,21 @@ class moodle_page {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Moodle 2.0 - use $PAGE->blocks->get_positions() instead
|
||||
* @deprecated since Moodle 2.0 - use $PAGE->blocks->get_regions() instead
|
||||
* @return string the places on this page where blocks can go.
|
||||
*/
|
||||
function blocks_get_positions() {
|
||||
debugging('Call to deprecated method moodle_page::blocks_get_positions. Use $PAGE->blocks->get_positions() instead.');
|
||||
return $this->blocks->get_positions();
|
||||
debugging('Call to deprecated method moodle_page::blocks_get_positions. Use $PAGE->blocks->get_regions() instead.');
|
||||
return $this->blocks->get_regions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Moodle 2.0 - use $PAGE->blocks->get_default_position() instead
|
||||
* @deprecated since Moodle 2.0 - use $PAGE->blocks->get_default_region() instead
|
||||
* @return string the default place for blocks on this page.
|
||||
*/
|
||||
function blocks_default_position() {
|
||||
debugging('Call to deprecated method moodle_page::blocks_default_position. Use $PAGE->blocks->get_default_position() instead.');
|
||||
return $this->blocks->get_default_position();
|
||||
debugging('Call to deprecated method moodle_page::blocks_default_position. Use $PAGE->blocks->get_default_region() instead.');
|
||||
return $this->blocks->get_default_region();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -856,17 +862,6 @@ class moodle_page {
|
||||
}
|
||||
}
|
||||
|
||||
/** Stub implementation of the blocks_manager, to stop things from breaking too badly. */
|
||||
class blocks_manager {
|
||||
public function get_positions() {
|
||||
return array(BLOCK_POS_LEFT, BLOCK_POS_RIGHT);
|
||||
}
|
||||
|
||||
public function get_default_position() {
|
||||
return BLOCK_POS_RIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Moodle 2.0
|
||||
* Not needed any more.
|
||||
|
@ -275,7 +275,12 @@ global $SCRIPT;
|
||||
}
|
||||
|
||||
/// Create the $PAGE global.
|
||||
$PAGE = new moodle_page();
|
||||
if (!empty($CFG->moodlepageclass)) {
|
||||
$classname = $CFG->moodlepageclass;
|
||||
} else {
|
||||
$classname = 'moodle_page';
|
||||
}
|
||||
$PAGE = new $classname();
|
||||
|
||||
/// Set error reporting back to normal
|
||||
if ($originaldatabasedebug == -1) {
|
||||
|
130
lib/simpletest/testblocklib_blockmanager.php
Normal file
130
lib/simpletest/testblocklib_blockmanager.php
Normal file
@ -0,0 +1,130 @@
|
||||
<?php // $Id$
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// NOTICE OF COPYRIGHT //
|
||||
// //
|
||||
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
|
||||
// http://moodle.org //
|
||||
// //
|
||||
// Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com //
|
||||
// //
|
||||
// This program 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 2 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program 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: //
|
||||
// //
|
||||
// http://www.gnu.org/copyleft/gpl.html //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Tests for the block_manager class in ../blocklib.php.
|
||||
*
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
* @package moodlecore
|
||||
*/
|
||||
|
||||
if (!defined('MOODLE_INTERNAL')) {
|
||||
die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
|
||||
}
|
||||
|
||||
require_once($CFG->libdir . '/pagelib.php');
|
||||
require_once($CFG->libdir . '/blocklib.php');
|
||||
|
||||
/** Test-specific subclass to make some protected things public. */
|
||||
class testable_block_manager extends block_manager {
|
||||
public function mark_loaded() {
|
||||
parent::mark_loaded();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test functions that don't need to touch the database.
|
||||
*/
|
||||
class moodle_page_test extends UnitTestCase {
|
||||
protected $testpage;
|
||||
protected $blockmanager;
|
||||
|
||||
public function setUp() {
|
||||
$this->testpage = new moodle_page();
|
||||
$this->blockmanager = new testable_block_manager($this->testpage);
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
$this->testpage = NULL;
|
||||
$this->blockmanager = NULL;
|
||||
}
|
||||
|
||||
public function test_no_regions_initially() {
|
||||
// Exercise SUT & Validate
|
||||
$this->assertEqual(array(), $this->blockmanager->get_regions());
|
||||
}
|
||||
|
||||
public function test_add_region() {
|
||||
// Exercise SUT.
|
||||
$this->blockmanager->add_region('a-region-name');
|
||||
// Validate
|
||||
$this->assertEqual(array('a-region-name'), $this->blockmanager->get_regions());
|
||||
}
|
||||
|
||||
public function test_add_regions() {
|
||||
// Set up fixture.
|
||||
$regions = array('a-region', 'another-region');
|
||||
// Exercise SUT.
|
||||
$this->blockmanager->add_regions($regions);
|
||||
// Validate
|
||||
$this->assert(new ArraysHaveSameValuesExpectation($regions), $this->blockmanager->get_regions());
|
||||
}
|
||||
|
||||
public function test_add_region_twice() {
|
||||
// Exercise SUT.
|
||||
$this->blockmanager->add_region('a-region-name');
|
||||
$this->blockmanager->add_region('another-region');
|
||||
// Validate
|
||||
$this->assert(new ArraysHaveSameValuesExpectation(array('a-region-name', 'another-region')),
|
||||
$this->blockmanager->get_regions());
|
||||
}
|
||||
|
||||
public function test_cannot_add_region_after_loaded() {
|
||||
// Set up fixture.
|
||||
$this->blockmanager->mark_loaded();
|
||||
// Set expectation
|
||||
$this->expectException();
|
||||
// Exercise SUT.
|
||||
$this->blockmanager->add_region('too-late');
|
||||
}
|
||||
|
||||
public function test_set_default_region() {
|
||||
// Set up fixture.
|
||||
$this->blockmanager->add_region('a-region-name');
|
||||
// Exercise SUT.
|
||||
$this->blockmanager->set_default_region('a-region-name');
|
||||
// Validate
|
||||
$this->assertEqual('a-region-name', $this->blockmanager->get_default_region());
|
||||
}
|
||||
|
||||
public function test_cannot_set_unknown_region_as_default() {
|
||||
// Set expectation
|
||||
$this->expectException();
|
||||
// Exercise SUT.
|
||||
$this->blockmanager->set_default_region('a-region-name');
|
||||
}
|
||||
|
||||
public function test_cannot_change_default_region_after_loaded() {
|
||||
// Set up fixture.
|
||||
$this->blockmanager->mark_loaded();
|
||||
// Set expectation
|
||||
$this->expectException();
|
||||
// Exercise SUT.
|
||||
$this->blockmanager->set_default_region('too-late');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
Loading…
x
Reference in New Issue
Block a user