Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Very flexible block system proposal: Difference between revisions

From MoodleDocs
Line 104: Line 104:
  $PAGE->add_required_block($fakeblock);
  $PAGE->add_required_block($fakeblock);


The new quiz navigation in Moodle 2.0 appears on the screen looking exactly like a block, but is not stored in the database as a block instance, because we already know we must have exactly one copy of this 'block' on each attempt page.  
The new quiz navigation in Moodle 2.0 ([[quiz_navigation#Screenshots|see this screenshot]]) appears on the screen looking exactly like a block, but is not stored in the database as a block instance, because we already know we must have exactly one copy of this 'block' on each attempt page.  


The admin menu on admin screens should probably be handled in a similar way. At the moment, admins can remove this block, but if they do, all that happens is that they get stuck unable to configure their site.
The admin menu on admin screens should probably be handled in a similar way. At the moment, admins can remove this block, but if they do, all that happens is that they get stuck unable to configure their site.

Revision as of 04:43, 9 February 2009

Note: This page is a work-in-progress. Feedback and suggested improvements are welcome. Please join the discussion on moodle.org or use the page comments.

Moodle 2.0


This is my attempt the devise the most flexible possible blocks system I could, which still had reasonable performance. (Whether that was a sensible thing to do remains to be seen ;-))

Goals

  • Existing blocks should continue to work in the new scheme. (If absolutely necessary, we may require small changes.)
  • Consistent implementation of (essentially) every page in Moodle.
  • Let themes, and possibly the page itself, determine where on the page the blocks should appear. (I.e, not just 'right' and 'left'.)
  • Much more flexible sticky blocks. (Show this on very course in category X, Add this block to every wiki in my system, ...)
  • Easy way to set up default blocks for certain sorts of page.

Interesting use cases

Some more miscellaneous things to consider:

Switching to sticky blocks

Admin notices that almost all courses in the site use the participants block. They decide that, instead of having all these individual instances, and to promote consistency, they want to add this as a sticky-block. However, when they do, they will then need to remove all the old individual instances. We need to provide a nice UI to facilitate this.

Perhaps we can provide better drill-down into the list of block instances (the link in the 'Instances column' of Administration > Modules > Blocks > Manage blocks); in the report, give ways to edit the block instances; and then link into that from the sticky blocks UI.

Setting the scene

This relies on some ideas from Navigation/Pagelib/Blocks_2.0_design.

What happens when a page is requested

The page, for example, mod/quiz/view.php, has to do this.

require_once('../../config.php');

As part of the standard set-up, the $PAGE global object is created (we are getting rid of the different page subclasses). $PAGE has pagetype set to 'mod-quiz-view'.

// Early on in mod/quiz/view.php.
$PAGE->set_context(get_context_instance(CONTEXT_MODULE, $cm->id));
$PAGE->set_title(format_string($quiz->name));
$PAGE->add_navigation(format_string($quiz->name));
$PAGE->this_page_params('id', 'q');
$PAGE->complete_setup();

// ...

// Later in mod/quiz/view.php, before  other  output.
$HTML->print_header();

// ...

// At the end of mod/quiz/view.php.
$HTML->print_footer();

$PAGE needs to know the context associated with this page. The other calls replace parameters to print_header. That is, $HTML->print_header() gets all the information it needs form $PAGE. The call to set_context automatically builds most of the required links in the navigation bar, we just need to add any extra links. (Actually, we might be able to make set_title automatically add a link at the end of the nav bar, which would be all that is required in this case).

$PAGE->this_page_params tells the page which URL params you need to preserve to reload this page exactly. Useful for doing redirects after editing actions.

What happens in $PAGE->complete_setup()

Here, the list of blocks currently on this page is fetched from the database.

Now that we know exactly where we are in Moodle, the current theme and language can be worked out. Actually, no. That bit happens earlier, during require_login, where $COURSE is set up, as at present.

The theme is asked for the following pieces of information:

  • what places on the page should blocks be allowed to appear
  • which of those places is the default place for adding new blocks.

If any blocks are configured to appear with a 'place' that the theme does not recognise (suppose the theme was just changed), they are instead put in the default place for new blocks.

Also, any block actions in the URL are processed, in which case there is a redirect back to the same page again. (This is why we need this_page_params).

What happens in $HTML->print_header() and print_footer()

These not only output the parts of the page they do at the moment. They are also responsible for outputting the large-scale page layout, and printing all the blocks (probably using some library functions to help).

Thus mod/quiz/view.php page does not have to worry about blocks at all. It just has to output the main contents of the page.

Some optional things the page can do

The quiz view page is a fairly normal sort of page, so it does not have to do much more. Other pages may need to do one or more of the following:


$PAGE->set_page_class(PAGECLASS_POPUP); // or PAGECLASS_WIDEREPORT

This is a hint (to the theme) that it might be better not to have blocks on this page. We will have a few pre-defined classes of page. Possibly just these three. Or maybe we don't bother. If teachers really want to add blocks both sides of the grader report, perhaps we should let them. (But, I think when it comes to sticky blocks, this might be necessary.)


$PAGE->set_sub_page($somename);

This is needed by, for example, the Lesson, where all pages have the same pagetype and contextid, but the teacher may want different blocks on different pages (I am assuming that each lesson page would be given a shortname to support this). Or on the quiz attempt page, sub_page would be the page number within the quiz.


$PAGE->set_page_type('mod-quiz-attempt');

The quiz review page could do this if it wants to force the review page to have the same blocks as the quiz attempt page.


$PAGE->extra_blocks_area('mymoodle-centrecolumn');

If the My Moodle page (say) wants to let the user put blocks in the centre of the page, irrespective of what the theme wants to allow in general.


$fakeblock->name = 'quiznavigation';
$fakeblock->header = get_string('quiznavigation', 'quiz');
$fakeblock->contents = '...';
$PAGE->add_required_block($fakeblock);

The new quiz navigation in Moodle 2.0 (see this screenshot) appears on the screen looking exactly like a block, but is not stored in the database as a block instance, because we already know we must have exactly one copy of this 'block' on each attempt page.

The admin menu on admin screens should probably be handled in a similar way. At the moment, admins can remove this block, but if they do, all that happens is that they get stuck unable to configure their site.

How blocks are configured

Adding blocks to a page, and the icons in the block to configure it, will remain pretty much the same.

The major change will be to moving blocks. Instead of arrows that move the block one place at a time, it will be more like rearranging activities on the course page. You will click the move icon, and lots of drop boxes will appear everywhere the block could go, and you click one to complete the move. (This copes much better when the theme and the page can have arbitrarily many places where blocks can be added. It is also much easier to convert to Ajax.)

Sticky blocks are more complicated, and are explained below.

Inner workings of this proposal

Database tables

Proposed BlocksDB.png

Column Type Comment

Need to create a page_postitions table, to list the available positions on each type of page.

What happens when a page is requested

SELECT * FROM
    mdl_block_instances bi
    LEFT JOIN mdl_block_positions bp ON bp.blockinstanceid = bi.id
                                        AND bp.contextid = $contextid
                                        AND bp.pagetype = $pagetype
                                        AND bp.subtype = $subtype

WHERE 
    bi.contextid IN ($thiscontextandparents)
AND $pagetype LIKE bi.pagetypepattern
    $subtype LIKE bi.subtypepattern

ORDER BY
    bp.position,
    bp.weight

User interface

Configuring blocks

Rearranging blocks

Configuring sticky blocks

See also