diff --git a/admin/site.php b/admin/site.php index ab18e5e9e82..b4d35cfbc5d 100644 --- a/admin/site.php +++ b/admin/site.php @@ -35,19 +35,17 @@ error("Serious Error! Could not update the site record! (id = $form->id)"); } } else { - // [pj] We are about to create the site, so let's add some blocks... - // calendar_month is included as a Moodle feature advertisement ;-) + // We are about to create the site "course" require_once($CFG->dirroot.'/lib/blocklib.php'); - if ($newid = insert_record("course", $form)) { + if ($newid = insert_record('course', $form)) { + // Site created, add blocks for it - $page = new stdClass; - $page->type = MOODLE_PAGE_COURSE; - $page->id = $newid; + $page = MoodlePage::create_object(MOODLE_PAGE_COURSE, $newid); blocks_repopulate_page($page); // Return value not checked because you can always edit later - $cat->name = get_string("miscellaneous"); - if (insert_record("course_categories", $cat)) { + $cat->name = get_string('miscellaneous'); + if (insert_record('course_categories', $cat)) { redirect("$CFG->wwwroot/$CFG->admin/index.php", get_string("changessaved"), 1); } else { error("Serious Error! Could not set up a default course category!"); diff --git a/backup/backuplib.php b/backup/backuplib.php index fa2b98cc4ff..7a15b65f540 100644 --- a/backup/backuplib.php +++ b/backup/backuplib.php @@ -616,9 +616,7 @@ // Read all of the block table $blocks = blocks_get_record(); - $page = new stdClass; - $page->id = $preferences->backup_course; - $page->type = MOODLE_PAGE_COURSE; + $page = MoodlePage::create_object(MOODLE_PAGE_COURSE, $preferences->backup_course); if ($instances = blocks_get_by_page($page)) { //Blocks open tag diff --git a/backup/restore_execute.html b/backup/restore_execute.html index 7983b231916..cb5e8fc7f0c 100644 --- a/backup/restore_execute.html +++ b/backup/restore_execute.html @@ -117,9 +117,7 @@ if (empty($info->backup_block_format)) { // This is a backup from Moodle < 1.5 if (empty($course_header->blockinfo)) { // Looks like it's from Moodle < 1.3. Let's give the course default blocks... - $newpage = new stdClass; - $newpage->type = MOODLE_PAGE_COURSE; - $newpage->id = $course_header->course_id; + $newpage = MoodlePage::create_object(MOODLE_PAGE_COURSE, $course_header->course_id); blocks_repopulate_page($newpage); } else { @@ -137,11 +135,7 @@ continue; } $blockinstance = new stdClass; - $blockinstance->blockid = $blockrecords[$blockname]->id; - $blockinstance->pageid = $course_header->course_id; - $blockinstance->pagetype = MOODLE_PAGE_COURSE; - $blockinstance->position = $blockposition; - $blockinstance->weight = $blockweight; + // Remove any - prefix before doing the name-to-id mapping if(substr($blockname, 0, 1) == '-') { $blockname = substr($blockname, 1); $blockinstance->visible = 0; @@ -149,6 +143,11 @@ else { $blockinstance->visible = 1; } + $blockinstance->blockid = $blockrecords[$blockname]->id; + $blockinstance->pageid = $course_header->course_id; + $blockinstance->pagetype = MOODLE_PAGE_COURSE; + $blockinstance->position = $blockposition; + $blockinstance->weight = $blockweight; if(!$status = insert_record('block_instance', $blockinstance)) { notify('Error while creating the course blocks'); } @@ -163,7 +162,7 @@ } } } - //Otherwise we are bringing into a course which already has blocks + //Otherwise we are adding the backup into an existing course; do nothing else { } } diff --git a/blocks/moodleblock.class.php b/blocks/moodleblock.class.php index 0167c5309af..50cc7588086 100644 --- a/blocks/moodleblock.class.php +++ b/blocks/moodleblock.class.php @@ -296,8 +296,6 @@ class MoodleBlock { $pixpath = $path .'/../theme/'. $CFG->theme .'/pix'; } - $sesskeystr = '&sesskey='. $USER->sesskey; - $movebuttons = '
';
}
- $movebuttons .= '' .
+ $movebuttons .= '' .
'
';
if ($options & BLOCK_MOVE_LEFT) {
- $movebuttons .= '' .
+ $movebuttons .= '' .
'
';
}
if ($options & BLOCK_MOVE_UP) {
- $movebuttons .= '' .
+ $movebuttons .= '' .
'
';
}
if ($options & BLOCK_MOVE_DOWN) {
- $movebuttons .= '' .
+ $movebuttons .= '' .
'
';
}
if ($options & BLOCK_MOVE_RIGHT) {
- $movebuttons .= '' .
+ $movebuttons .= '' .
'
';
}
@@ -404,7 +400,6 @@ class MoodleBlock {
* You don't need to override this if you're satisfied with the above
*
* @uses $CFG
- * @uses $USER
* @uses $THEME
* @return boolean
*/
@@ -414,7 +409,7 @@ class MoodleBlock {
if (!$this->has_config()) {
return false;
}
- global $CFG, $USER, $THEME;
+ global $CFG, $THEME;
print_simple_box_start('center', '', $THEME->cellheading);
include($CFG->dirroot.'/blocks/'. $this->name() .'/config_global.html');
print_simple_box_end();
@@ -505,7 +500,21 @@ class MoodleBlock {
}
/**
- *Are you going to allow multiple instances of each block?
+ * Is each block of this type going to have instance-specific configuration?
+ * Normally, this setting is controlled by {@link instance_allow_multiple}: if multiple
+ * instances are allowed, then each will surely need its own configuration. However, in some
+ * cases it may be necessary to provide instance configuration to blocks that do not want to
+ * allow multiple instances. In that case, make this function return true.
+ * I stress again that this makes a difference ONLY if {@link instance_allow_multiple} returns false.
+ * @return boolean
+ * @todo finish documenting this function by explaining per-instance configuration further
+ */
+ function instance_allow_config() {
+ return false;
+ }
+
+ /**
+ * Are you going to allow multiple instances of each block?
* If yes, then it is assumed that the block WILL USE per-instance configuration
* @return boolean
* @todo finish documenting this function by explaining per-instance configuration further
@@ -522,14 +531,13 @@ class MoodleBlock {
*
* @uses $CFG
* @uses $THEME
- * @uses $USER
* @return boolean
* @todo finish documenting this function
*/
function instance_config_print() {
// Default behavior: print the config_instance.html file
// You don't need to override this if you're satisfied with the above
- if (!$this->instance_allow_multiple()) {
+ if (!$this->instance_allow_multiple() && !$this->instance_allow_config()) {
return false;
}
global $CFG, $USER, $THEME;
diff --git a/course/edit.php b/course/edit.php
index 345a94d41be..2ba4f4b7766 100644
--- a/course/edit.php
+++ b/course/edit.php
@@ -32,8 +32,6 @@
}
-
-
/// If data submitted, then process and store.
if ($form = data_submitted() and confirm_sesskey()) {
@@ -54,29 +52,24 @@
if (!empty($course)) {
// Test for and remove blocks which aren't appropriate anymore
- $page = new stdClass;
- $page->id = $course->id;
- $page->type = MOODLE_PAGE_COURSE;
-
+ $page = MoodlePage::create_object(MOODLE_PAGE_COURSE, $course->id);
blocks_remove_inappropriate($page);
// Update with the new data
- if (update_record("course", $form)) {
+ if (update_record('course', $form)) {
add_to_log($course->id, "course", "update", "edit.php?id=$id", "");
fix_course_sortorder();
- redirect("view.php?id=$course->id", get_string("changessaved"));
+ redirect($page->url_get_full(), get_string('changessaved'));
} else {
error("Serious Error! Could not update the course record! (id = $form->id)");
}
} else {
$form->timecreated = time();
- if ($newcourseid = insert_record("course", $form)) { // Set up new course
+ if ($newcourseid = insert_record('course', $form)) { // Set up new course
// Setup the blocks
- $page = new stdClass;
- $page->type = MOODLE_PAGE_COURSE;
- $page->id = $newcourseid;
+ $page = MoodlePage::create_object(MOODLE_PAGE_COURSE, $newcourseid);
blocks_repopulate_page($page); // Return value not checked because you can always edit later
$section = NULL;
diff --git a/course/format/social/format.php b/course/format/social/format.php
index c10a254eb8c..ca658c76197 100644
--- a/course/format/social/format.php
+++ b/course/format/social/format.php
@@ -27,7 +27,7 @@
if(blocks_have_content($pageblocks[BLOCK_POS_LEFT]) || $editing) {
echo '".user_login_string($course, $USER)."
"; - - print_header("$strcourse: $course->fullname", "$course->fullname", "$course->shortname", - "", "", true, update_course_icon($course->id), $loggedinas); + $PAGE->print_header(get_string('course').': %fullname%'); get_all_mods($course->id, $mods, $modnames, $modnamesplural, $modnamesused); diff --git a/index.php b/index.php index d3bb6d1fecc..a2d7d774af7 100644 --- a/index.php +++ b/index.php @@ -55,34 +55,32 @@ $langmenu = popup_form ($CFG->wwwroot .'/index.php?lang=', $langs, 'chooselang', $currlang, '', '', '', true); } + $PAGE = MoodlePage::create_object(MOODLE_PAGE_COURSE, SITEID); + print_header(strip_tags($site->fullname), $site->fullname, 'home', '', '', true, '', $loginstring . $langmenu); $editing = isediting($site->id); - $page = new stdClass; - $page->id = SITEID; - $page->type = MOODLE_PAGE_COURSE; - - $pageblocks = blocks_get_by_page($page); + $pageblocks = blocks_get_by_page($PAGE); if($editing) { if (!empty($blockaction) && confirm_sesskey()) { if (!empty($blockid)) { - blocks_execute_action($page, $pageblocks, strtolower($blockaction), intval($blockid)); + blocks_execute_action($PAGE, $pageblocks, strtolower($blockaction), intval($blockid)); } else if (!empty($instanceid)) { $instance = blocks_find_instance($instanceid, $pageblocks); - blocks_execute_action($page, $pageblocks, strtolower($blockaction), $instance); + blocks_execute_action($PAGE, $pageblocks, strtolower($blockaction), $instance); } // This re-query could be eliminated by judicious programming in blocks_execute_action(), // but I'm not sure if it's worth the complexity increase... - $pageblocks = blocks_get_by_page($page); + $pageblocks = blocks_get_by_page($PAGE); } - $missingblocks = blocks_get_missing($page, $pageblocks); + $missingblocks = blocks_get_missing($PAGE, $pageblocks); } optional_variable($preferred_width_left, blocks_preferred_width($pageblocks[BLOCK_POS_LEFT])); @@ -101,7 +99,7 @@ if(blocks_have_content($pageblocks[BLOCK_POS_LEFT]) || $editing) { echo ''. user_login_string($course, $USER) .'
'; - print_header(get_string('blockconfigin', 'moodle', $course->fullname), $course->fullname, $course->shortname, - '', '', true, update_course_icon($course->id), $loggedinas); + // We need to show the config screen, so we highjack the display logic and then die + $page->print_header(get_string('pageheaderconfigablock', 'moodle')); print_heading(get_string('blockconfiga', 'moodle', $block->name)); - echo ''; print_footer(); - die(); // Do not go on with the other course-related stuff + die(); // Do not go on with the other page-related stuff } break; case 'toggle': @@ -389,79 +354,81 @@ function blocks_execute_action($page, &$pageblocks, $blockaction, $instanceorid) if(empty($instance)) { error('Invalid block instance for '. $blockaction); } - // This configuration will make sure that even if somehow the weights - // become not continuous, block move operations will eventually bring - // the situation back to normal without printing any warnings. - if(!empty($pageblocks[$instance->position][$instance->weight - 1])) { - $other = $pageblocks[$instance->position][$instance->weight - 1]; + + if($instance->weight == 0) { + // The block is the first one, so a move "up" probably means it changes position + // Where is the instance going to be moved? + $newpos = $page->blocks_move_position($instance, BLOCK_MOVE_UP); + $newweight = max(array_keys($pageblocks[$newpos])) + 1; + + blocks_execute_repositioning($instance, $newpos, $newweight); } - if(!empty($other)) { - ++$other->weight; - update_record('block_instance', $other); + else { + // The block is just moving upwards in the same position. + // This configuration will make sure that even if somehow the weights + // become not continuous, block move operations will eventually bring + // the situation back to normal without printing any warnings. + if(!empty($pageblocks[$instance->position][$instance->weight - 1])) { + $other = $pageblocks[$instance->position][$instance->weight - 1]; + } + if(!empty($other)) { + ++$other->weight; + update_record('block_instance', $other); + } + --$instance->weight; + update_record('block_instance', $instance); } - --$instance->weight; - update_record('block_instance', $instance); break; case 'movedown': if(empty($instance)) { error('Invalid block instance for '. $blockaction); } - // This configuration will make sure that even if somehow the weights - // become not continuous, block move operations will eventually bring - // the situation back to normal without printing any warnings. - if(!empty($pageblocks[$instance->position][$instance->weight + 1])) { - $other = $pageblocks[$instance->position][$instance->weight + 1]; + + if($instance->weight == max(array_keys($pageblocks[$instance->position]))) { + // The block is the last one, so a move "down" probably means it changes position + // Where is the instance going to be moved? + $newpos = $page->blocks_move_position($instance, BLOCK_MOVE_DOWN); + $newweight = max(array_keys($pageblocks[$newpos])) + 1; + + blocks_execute_repositioning($instance, $newpos, $newweight); } - if(!empty($other)) { - --$other->weight; - update_record('block_instance', $other); + else { + // The block is just moving downwards in the same position. + // This configuration will make sure that even if somehow the weights + // become not continuous, block move operations will eventually bring + // the situation back to normal without printing any warnings. + if(!empty($pageblocks[$instance->position][$instance->weight + 1])) { + $other = $pageblocks[$instance->position][$instance->weight + 1]; + } + if(!empty($other)) { + --$other->weight; + update_record('block_instance', $other); + } + ++$instance->weight; + update_record('block_instance', $instance); } - ++$instance->weight; - update_record('block_instance', $instance); break; case 'moveleft': if(empty($instance)) { error('Invalid block instance for '. $blockaction); } - $sql = ''; - switch($instance->position) { - case BLOCK_POS_RIGHT: - // To preserve the continuity of block weights - $sql = 'UPDATE '. $CFG->prefix .'block_instance SET weight = weight - 1 WHERE pagetype = \''. $instance->pagetype. - '\' AND pageid = '. $instance->pageid .' AND position = \'' .$instance->position. - '\' AND weight > '. $instance->weight; - $instance->position = BLOCK_POS_LEFT; - $maxweight = max(array_keys($pageblocks[$instance->position])); - $instance->weight = $maxweight + 1; - break; - } - if($sql) { - update_record('block_instance', $instance); - execute_sql($sql, false); - } + // Where is the instance going to be moved? + $newpos = $page->blocks_move_position($instance, BLOCK_MOVE_LEFT); + $newweight = max(array_keys($pageblocks[$newpos])) + 1; + + blocks_execute_repositioning($instance, $newpos, $newweight); break; case 'moveright': if(empty($instance)) { error('Invalid block instance for '. $blockaction); } - $sql = ''; - switch($instance->position) { - case BLOCK_POS_LEFT: - // To preserve the continuity of block weights - $sql = 'UPDATE '. $CFG->prefix .'block_instance SET weight = weight - 1 WHERE pagetype = \''. $instance->pagetype. - '\' AND pageid = '. $instance->pageid .' AND position = \''. $instance->position. - '\' AND weight > '. $instance->weight; - $instance->position = BLOCK_POS_RIGHT; - $maxweight = max(array_keys($pageblocks[$instance->position])); - $instance->weight = $maxweight + 1; - break; - } - if($sql) { - update_record('block_instance', $instance); - execute_sql($sql, false); - } + // Where is the instance going to be moved? + $newpos = $page->blocks_move_position($instance, BLOCK_MOVE_RIGHT); + $newweight = max(array_keys($pageblocks[$newpos])) + 1; + + blocks_execute_repositioning($instance, $newpos, $newweight); break; case 'add': // Add a new instance of this block, if allowed @@ -477,25 +444,56 @@ function blocks_execute_action($page, &$pageblocks, $blockaction, $instanceorid) return false; } - $weight = get_record_sql('SELECT 1, max(weight) + 1 AS nextfree FROM '. $CFG->prefix .'block_instance WHERE pageid = '. $page->id .' AND pagetype = \''. $page->type .'\' AND position = \''. BLOCK_POS_RIGHT .'\''); + $newpos = $page->blocks_default_position(); + $weight = get_record_sql('SELECT 1, max(weight) + 1 AS nextfree FROM '. $CFG->prefix .'block_instance WHERE pageid = '. $page->get_id() .' AND pagetype = \''. $page->get_type() .'\' AND position = \''. $newpos .'\''); $newinstance = new stdClass; $newinstance->blockid = $blockid; - $newinstance->pageid = $page->id; - $newinstance->pagetype = $page->type; - $newinstance->position = BLOCK_POS_RIGHT; + $newinstance->pageid = $page->get_id(); + $newinstance->pagetype = $page->get_type(); + $newinstance->position = $newpos; $newinstance->weight = $weight->nextfree; $newinstance->visible = 1; $newinstance->configdata = ''; insert_record('block_instance', $newinstance); break; } + + // In order to prevent accidental duplicate actions, redirect to a page with a clean url + redirect($page->url_get_full()); +} + +// This shouldn't be used externally at all, it's here for use by blocks_execute_action() +// in order to reduce code repetition. +function blocks_execute_repositioning(&$instance, $newpos, $newweight) { + global $CFG; + + // If it's staying where it is, don't do anything + if($newpos == $instance->position) { + return; + } + + // Close the weight gap we 'll leave behind + execute_sql('UPDATE '. $CFG->prefix .'block_instance SET weight = weight - 1 WHERE pagetype = \''. $instance->pagetype. + '\' AND pageid = '. $instance->pageid .' AND position = \'' .$instance->position. + '\' AND weight > '. $instance->weight, + false); + + $instance->position = $newpos; + $instance->weight = $newweight; + + update_record('block_instance', $instance); } function blocks_get_by_page($page) { - $blocks = get_records_select('block_instance', 'pageid = '. $page->id .' AND pagetype = \''. $page->type .'\'', 'position, weight'); + $blocks = get_records_select('block_instance', 'pageid = '. $page->get_id() .' AND pagetype = \''. $page->get_type() .'\'', 'position, weight'); + + $positions = $page->blocks_get_positions(); + $arr = array(); + foreach($positions as $key => $position) { + $arr[$position] = array(); + } - $arr = array(BLOCK_POS_LEFT => array(), BLOCK_POS_RIGHT => array()); if(empty($blocks)) { return $arr; } @@ -516,14 +514,6 @@ function blocks_print_adminblock($page, $missingblocks) { if (!empty($missingblocks)) { foreach ($missingblocks as $blockid) { $block = blocks_get_record($blockid); - - switch($page->type) { - case MOODLE_PAGE_COURSE: - $course = get_record('course', 'id', $page->id); - break; - default: die('unknown pagetype: '. $page->type); - } - $blockobject = block_instance($block->name); if ($blockobject === false) { continue; @@ -531,15 +521,9 @@ function blocks_print_adminblock($page, $missingblocks) { $menu[$block->id] = $blockobject->get_title(); } - if($page->id == SITEID) { - $target = 'index.php'; - } - else { - $target = 'view.php'; - } - $content = popup_form($target .'?id='. $course->id .'&sesskey='. $USER->sesskey .'&blockaction=add&blockid=', - $menu, 'add_block', '', $stradd .'...', '', '', true); - $content = ''. user_login_string($this->courserecord, $USER) .'
'; + print_header($title, $this->courserecord->fullname, $this->courserecord->shortname, + '', '', true, update_course_icon($this->courserecord->id), $loggedinas); + } + + // This is hardwired here so the factory method create_object() can be sure there was no mistake. + // Also, it doubles as a way to let others inquire about our type. + function get_type() { + return MOODLE_PAGE_COURSE; + } + + // This is like the "category" of a page of this "type". For example, if the type is MOODLE_PAGE_COURSE + // the format_name is the actual name of the course format. If the type were MOODLE_PAGE_ACTIVITY, then + // the format_name might be that activity's name etc. + function get_format_name() { + $this->init_full(); + return $this->courserecord->format; + } + + // This should return a fully qualified path to the URL which is responsible for displaying us. + function url_get_path() { + global $CFG; + if($this->id == SITEID) { + return $CFG->wwwroot.'/index.php'; + } + else { + return $CFG->wwwroot.'/course/view.php'; + } + } + + // This should return an associative array of any GET/POST parameters that are needed by the URL + // which displays us to make it work. If none are needed, return an empty array. + function url_get_parameters() { + if($this->id == SITEID) { + return array(); + } + else { + return array('id' => $this->id); + } + } + + // Blocks-related section + + // Which are the positions in this page which support blocks? Return an array containing their identifiers. + // BE CAREFUL, ORDER DOES MATTER! In textual representations, lists of blocks in a page use the ':' character + // to delimit different positions in the page. The part before the first ':' in such a representation will map + // directly to the first item of the array you return here, the second to the next one and so on. This way, + // you can add more positions in the future without interfering with legacy textual representations. + function blocks_get_positions() { + return array(BLOCK_POS_LEFT, BLOCK_POS_RIGHT); + } + + // When a new block is created in this page, which position should it go to? + function blocks_default_position() { + return BLOCK_POS_RIGHT; + } + + // When we are creating a new page, use the data at your disposal to provide a textual representation of the + // blocks that are going to get added to this new page. Delimit block names with commas (,) and use double + // colons (:) to delimit between block positions in the page. See blocks_get_positions() for additional info. + function blocks_get_default() { + global $CFG; + + $this->init_full(); + + if($this->id == SITEID) { + // Is it the site? + if (!empty($CFG->defaultblocks_site)) { + $blocknames = $CFG->defaultblocks_site; + } + /// Failsafe - in case nothing was defined. + else { + $blocknames = 'site_main_menu,admin,course_list:course_summary,calendar_month'; + } + } + // It's a normal course, so do it according to the course format + else { + $pageformat = $this->courserecord->format; + if (!empty($CFG->{'defaultblocks_'. $pageformat})) { + $blocknames = $CFG->{'defaultblocks_'. $pageformat}; + } + else { + $format_config = $CFG->dirroot.'/course/format/'.$pageformat.'/config.php'; + if (@is_file($format_config) && is_readable($format_config)) { + require($format_config); + } + if (!empty($format['defaultblocks'])) { + $blocknames = $format['defaultblocks']; + } + else if (!empty($CFG->defaultblocks)){ + $blocknames = $CFG->defaultblocks; + } + /// Failsafe - in case nothing was defined. + else { + $blocknames = 'participants,activity_modules,search_forums,admin,course_list:news_items,calendar_upcoming,recent_activity'; + } + } + } + + return $blocknames; + } + + // Given an instance of a block in this page and the direction in which we want to move it, where is + // it going to go? Return the identifier of the instance's new position. This allows us to tell blocklib + // how we want the blocks to move around in this page in an arbitrarily complex way. If the move as given + // does not make sense, make sure to return the instance's original position. + // + // Since this is going to get called a LOT, pass the instance by reference purely for speed. Do **NOT** + // modify its data in any way, this will actually confuse blocklib!!! + function blocks_move_position(&$instance, $move) { + if($instance->position == BLOCK_POS_LEFT && $move == BLOCK_MOVE_RIGHT) { + return BLOCK_POS_RIGHT; + } + else if ($instance->position == BLOCK_POS_RIGHT && $move == BLOCK_MOVE_LEFT) { + return BLOCK_POS_LEFT; + } + return $instance->position; + } +} + +?> diff --git a/lib/weblib.php b/lib/weblib.php index 6e57b4ba8fa..59cd3c9208d 100644 --- a/lib/weblib.php +++ b/lib/weblib.php @@ -3476,15 +3476,5 @@ function print_speller_button () { echo ''."\n"; } -function page_source_script($page) { - global $CFG; - - switch($page->type) { - case MOODLE_PAGE_COURSE: - return $CFG->wwwroot.'/course/view.php?id='.$page->id; - break; - } -} - // vim:autoindent:expandtab:shiftwidth=4:tabstop=4:tw=140: ?>