How to (not) override get_content_for_output in moodleblocks.class.php

How to (not) override get_content_for_output in moodleblocks.class.php

Joseph Rézeau -
回帖数:3
Core developers的头像 Particularly helpful Moodlers的头像 Plugin developers的头像 Testers的头像 Translators的头像

Moodle 2.0.

Further to my report MDL-26074 I have found a way to achieve the feature I wanted in my block_glossary_export_to_quiz. Here is a description of the needed feature:

When the block is displayed, if there are no glossaries available in the current course, and Edit mode is ON, I do not want the Configuration icon to be displayed at the top of my block. I only want the other 3 icons there: Roles, Hide, Delete and Move.

To implement this feature, I copy function get_content_for_output from moodleblocks.class.php and override it by adding a condition thus:

if ($this->page->user_is_editing()) {
$numglossaries = $DB->count_records('glossary', array('course' => $this->course->id));
$bc->controls = $this->page->blocks->edit_controls($this);
if (!$numglossaries) {
unset ($bc->controls[2]);
}
}

This gives me exactly the functionality I want. However, the comments for function get_content_for_output in moodleblocks.class.php say:

You probably should not override this method, but instead override {@link html_attributes()}, {@link formatted_contents()} or {@link get_content()}, {@link hide_header()}, {@link (get_edit_controls)}, etc.

I would like to just do that, but a function get_edit_controls() is nowhere to be found in moodleblocks.class.php. Where is that function? How can I over-ride it in my block's block_glossary_export_to_quiz.php file?

What does {@link} mean in moodle comments?

When the comments say you probably should not override this method,, what are the risks in doing it?

I do not understand the second $this in $bc->controls = $this->page->blocks->edit_controls($this); It looks strange to me.

TIA for any help and please excuse an amateur programmer's naive questions.小丑

Joseph

回复Joseph Rézeau

Re: How to (not) override get_content_for_output in moodleblocks.class.php

Tim Hunt -
Core developers的头像 Documentation writers的头像 Particularly helpful Moodlers的头像 Peer reviewers的头像 Plugin developers的头像

1. Well, $this->page->blocks is an instance of the block_manager class defined in blocklib.php. You can find the method definition there.

2. If you really insist on overriding get_content_for_output, then do not copy-and-paste the existing code.

Instead, your method should look like

public function get_content_for_output($output) {
global $DB;
$bc = parent::get_content_for_output($output);
if (!$DB->record_exists('glossary', array('course' => $this->course->id)) {
unset ($bc->controls[2]);
}
return $bc;

The main point is to call the parent method to do most of the work, rather than duplicating it.

A second point is that it is more efficient to use record_exists, which can stop the moment it finds one record, instead of count_records, which has to count exactly how many records match the condition.

3. When I say "You probably should not override this method", what I mean is that this method is absolutely critical to the functioning of the blocks system, so if you override it an screw up you will probably break something. Conversely, the other methods mentioned are are designed to be extension points to let you safely change all the things you might reasonably want to change.

4. And, indeed you have broken something important. The block edit icon takes you to a form that does two things:

a. it lets you edit any block-specific settings, and

b. it lets you control the standard settings for where the block appears.

It is reasonable for you to want to hide a. if there are not glossaries on the course, but it is bad for you to hide b.

Therefore, what you should do is put your

if ($DB->record_exists('glossary', array('course' => $this->course->id)) {

check in the editing form definition, and only add your extra controls to the form if there are some glossaries on the course.

回复Tim Hunt

Re: How to (not) override get_content_for_output in moodleblocks.class.php

Joseph Rézeau -
Core developers的头像 Particularly helpful Moodlers的头像 Plugin developers的头像 Testers的头像 Translators的头像

Hi Tim,

Thanks for your detailed explanations, which have been most useful.

2. That's exactly what I thought I should do, but did not know how.  I did not know you could use parent:: that way.

Thanks for the tip to use record_exists.

3. "Conversely, the other methods mentioned are designed to be extension points to let you safely change all the things you might reasonably want to change." Yes, but my point was that I do not know where to find, e.g. get_edit_controls() function.糊涂

You did not answer my question : What does {@link} mean in moodle comments?思考

4.- Point taken as regards (b). By the way, is it at all possible to not display the (b) settings, which, in the case of my block are useless?

Finally, I agree that the most reasonable thing for me to do is to leave the Edit icon in place and put my test for the existence of glossaries in my block's edit_form.php. That way I won't "break" anything.

Joseph

回复Joseph Rézeau

Re: How to (not) override get_content_for_output in moodleblocks.class.php

Tim Hunt -
Core developers的头像 Documentation writers的头像 Particularly helpful Moodlers的头像 Peer reviewers的头像 Plugin developers的头像

In theory, PHPdoc comments can get compiled into HTML documentation pages. {@link ...} gets converted into a link to the other thing - whether it is a function, class or method. Sadly, in practice, the compilation has been broken since August. However, these docs are older than that. See, for example

http://phpdocs.moodle.org/HEAD/core/block/block_manager.html#edit_controls

Which comes from

https://github.com/moodle/moodle/blob/master/lib/blocklib.php#L960

Oh, look, I have a typo. The comment tries to link to get_content_for_output, but actually I typed get_contents_for_output which does not exist, so that @link does not work.