"MDL-13766, use OUTPUT to print box"
[moodle.git] / blocks / moodleblock.class.php
CommitLineData
56e29ea0 1<?php // $Id$
0f3fe4b6 2
c7e3bc51 3/**
ccd3dd0c 4 * This file contains the parent class for moodle blocks, block_base.
c7e3bc51 5 *
c7e3bc51 6 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
7 * @package blocks
8 */
9
10/// Constants
11
12/**
13 * Block type of list. Contents of block should be set as an associative array in the content object as items ($this->content->items). Optionally include footer text in $this->content->footer.
14 */
0f3fe4b6 15define('BLOCK_TYPE_LIST', 1);
c7e3bc51 16
17/**
18 * Block type of text. Contents of block should be set to standard html text in the content object as items ($this->content->text). Optionally include footer text in $this->content->footer.
19 */
0f3fe4b6 20define('BLOCK_TYPE_TEXT', 2);
c7e3bc51 21
c7e3bc51 22/**
e0134f84 23 * Class for describing a moodle block, all Moodle blocks derive from this class
c7e3bc51 24 *
25 * @author Jon Papaioannou
26 * @package blocks
27 */
e89d741a 28class block_base {
c7e3bc51 29
30 /**
31 * Internal var for storing/caching translated strings
32 * @var string $str
33 */
0f3fe4b6 34 var $str;
c7e3bc51 35
36 /**
f8582e3e 37 * The title of the block to be displayed in the block title area.
c7e3bc51 38 * @var string $title
39 */
9b4b78fd 40 var $title = NULL;
c7e3bc51 41
c7e3bc51 42 /**
ccd3dd0c 43 * The type of content that this block creates. Currently support options - BLOCK_TYPE_LIST, BLOCK_TYPE_TEXT
c7e3bc51 44 * @var int $content_type
45 */
3ef642d9 46 var $content_type = BLOCK_TYPE_TEXT;
c7e3bc51 47
48 /**
49 * An object to contain the information to be displayed in the block.
50 * @var stdObject $content
51 */
9b4b78fd 52 var $content = NULL;
c7e3bc51 53
54 /**
1345403a 55 * A string generated by {@link _add_edit_controls()} to display block manipulation links when the user is in editing mode.
c7e3bc51 56 * @var string $edit_controls
57 */
0f3fe4b6 58 var $edit_controls = NULL;
c7e3bc51 59
60 /**
61 * The current version that the block type defines.
62 * @var string $version
63 */
9b4b78fd 64 var $version = NULL;
c7e3bc51 65
66 /**
67 * The initialized instance of this block object.
68 * @var block $instance
69 */
9b4b78fd 70 var $instance = NULL;
c7e3bc51 71
3179b000 72 /**
73 * The page that this block is appearing on.
74 * @var moodle_page
75 */
76 public $page = NULL;
77
c7e3bc51 78 /**
79 * An object containing the instance configuration information for the current instance of this block.
80 * @var stdObject $config
81 */
9b4b78fd 82 var $config = NULL;
83
f9648e77 84 /**
85 * How often the cronjob should run, 0 if not at all.
86 * @var int $cron
87 */
88
89 var $cron = NULL;
90
5c10879f 91 /**
92 * Indicates blocked is pinned - can not be moved, always present, does not have own context
93 */
94 var $pinned = false;
c7e3bc51 95
e0134f84 96/// Class Functions
c7e3bc51 97
98 /**
99 * The class constructor
100 *
101 */
e89d741a 102 function block_base() {
9b4b78fd 103 $this->init();
104 }
0f3fe4b6 105
73554752 106 /**
107 * Fake constructor to keep PHP5 happy
108 *
109 */
110 function __construct() {
e89d741a 111 $this->block_base();
73554752 112 }
44c55d46 113
44c55d46 114 /**
115 * Function that can be overridden to do extra cleanup before
116 * the database tables are deleted. (Called once per block, not per instance!)
117 */
118 function before_delete() {
119 }
a82e9bc3 120
121 /**
122 * Function that can be overridden to do extra setup after a block instance has been
123 * restored from backup. For example, it may need to alter any dates that the block
124 * stores, if the $restore->course_startdateoffset is set.
125 */
126 function after_restore($restore) {
127 }
73554752 128
b486ef1a 129 /**
5cfefc9b 130 * Enable custom instance data section in backup and restore.
b486ef1a 131 *
132 * If return true, then {@link instance_backup()} and
133 * {@link instance_restore()} will be called during
134 * backup/restore routines.
135 *
136 * @return boolean
137 **/
5cfefc9b 138 function backuprestore_instancedata_used() {
b486ef1a 139 return false;
140 }
141
142 /**
143 * Allows the block class to have a backup routine. Handy
144 * when the block has its own tables that have foreign keys to
145 * other tables (example: user table).
146 *
147 * Note: at the time of writing this comment, the indent level
148 * for the {@link full_tag()} should start at 5.
149 *
150 * @param resource $bf Backup File
151 * @param object $preferences Backup preferences
152 * @return boolean
153 **/
154 function instance_backup($bf, $preferences) {
155 return true;
156 }
157
158 /**
159 * Allows the block class to restore its backup routine.
160 *
161 * Should not return false if data is empty
162 * because old backups would not contain block instance backup data.
163 *
164 * @param object $restore Standard restore object
165 * @param object $data Object from backup_getid for this block instance
166 * @return boolean
167 **/
168 function instance_restore($restore, $data) {
169 return true;
170 }
171
43457dc8 172 /**
173 * Will be called before an instance of this block is backed up, so that any links in
5cfefc9b 174 * in config can be encoded. For example config->text, for the HTML block
175 * @return string
43457dc8 176 */
5cfefc9b 177 function get_backup_encoded_config() {
178 return base64_encode(serialize($this->config));
43457dc8 179 }
180
181 /**
5cfefc9b 182 * Return the content encoded to support interactivities linking. This function is
183 * called automatically from the backup procedure by {@link backup_encode_absolute_links()}.
43457dc8 184 *
5cfefc9b 185 * NOTE: There is no block instance when this method is called.
186 *
187 * @param string $content Content to be encoded
188 * @param object $restore Restore preferences object
189 * @return string The encoded content
190 **/
191 function encode_content_links($content, $restore) {
192 return $content;
193 }
194
195 /**
196 * This function makes all the necessary calls to {@link restore_decode_content_links_worker()}
197 * function in order to decode contents of this block from the backup
198 * format to destination site/course in order to mantain inter-activities
199 * working in the backup/restore process.
200 *
201 * This is called from {@link restore_decode_content_links()} function in the restore process.
202 *
203 * NOTE: There is no block instance when this method is called.
204 *
205 * @param object $restore Standard restore object
206 * @return boolean
207 **/
208 function decode_content_links_caller($restore) {
209 return true;
210 }
211
212 /**
213 * Return content decoded to support interactivities linking.
214 * This is called automatically from
215 * {@link restore_decode_content_links_worker()} function
216 * in the restore process.
217 *
218 * NOTE: There is no block instance when this method is called.
219 *
220 * @param string $content Content to be dencoded
221 * @param object $restore Restore preferences object
222 * @return string The dencoded content
223 **/
224 function decode_content_links($content, $restore) {
225 return $content;
43457dc8 226 }
227
c7e3bc51 228 /**
229 * Returns the block name, as present in the class name,
230 * the database, the block directory, etc etc.
231 *
232 * @return string
233 */
0f3fe4b6 234 function name() {
235 // Returns the block name, as present in the class name,
236 // the database, the block directory, etc etc.
237 static $myname;
c7e3bc51 238 if ($myname === NULL) {
0f3fe4b6 239 $myname = strtolower(get_class($this));
240 $myname = substr($myname, strpos($myname, '_') + 1);
241 }
242 return $myname;
243 }
244
c7e3bc51 245 /**
246 * Parent class version of this function simply returns NULL
247 * This should be implemented by the derived class to return
248 * the content object.
249 *
250 * @return stdObject
251 */
0f3fe4b6 252 function get_content() {
253 // This should be implemented by the derived class.
254 return NULL;
255 }
c7e3bc51 256
257 /**
258 * Returns the class $title var value.
259 *
260 * Intentionally doesn't check if a title is set.
261 * This is already done in {@link _self_test()}
262 *
263 * @return string $this->title
264 */
0f3fe4b6 265 function get_title() {
6195e04a 266 // Intentionally doesn't check if a title is set. This is already done in _self_test()
0f3fe4b6 267 return $this->title;
268 }
c7e3bc51 269
270 /**
271 * Returns the class $content_type var value.
272 *
273 * Intentionally doesn't check if content_type is set.
274 * This is already done in {@link _self_test()}
275 *
276 * @return string $this->content_type
277 */
0f3fe4b6 278 function get_content_type() {
6195e04a 279 // Intentionally doesn't check if a content_type is set. This is already done in _self_test()
0f3fe4b6 280 return $this->content_type;
281 }
c7e3bc51 282
283 /**
284 * Returns the class $version var value.
285 *
286 * Intentionally doesn't check if a version is set.
287 * This is already done in {@link _self_test()}
288 *
289 * @return string $this->version
290 */
0f3fe4b6 291 function get_version() {
6195e04a 292 // Intentionally doesn't check if a version is set. This is already done in _self_test()
0f3fe4b6 293 return $this->version;
294 }
c7e3bc51 295
3ef642d9 296 /**
297 * Returns true or false, depending on whether this block has any content to display
7e874772 298 * and whether the user has permission to view the block
3ef642d9 299 *
300 * @return boolean
301 */
302 function is_empty() {
7e874772 303
f474a4e5 304 // TODO - temporary hack to get the block context only if it already exists.
305 global $DB;
306 if ($DB->record_exists('context', array('contextlevel' => CONTEXT_BLOCK, 'instanceid' => $this->instance->id))) {
5c10879f 307 $context = get_context_instance(CONTEXT_BLOCK, $this->instance->id);
308 } else {
309 $context = get_context_instance(CONTEXT_SYSTEM); // pinned blocks do not have own context
310 }
3179b000 311
7e874772 312 if ( !has_capability('moodle/block:view', $context) ) {
313 return true;
314 }
315
3ef642d9 316 $this->get_content();
317 return(empty($this->content->text) && empty($this->content->footer));
318 }
319
c7e3bc51 320 /**
321 * First sets the current value of $this->content to NULL
322 * then calls the block's {@link get_content()} function
323 * to set its value back.
324 *
325 * @return stdObject
326 */
0f3fe4b6 327 function refresh_content() {
328 // Nothing special here, depends on content()
329 $this->content = NULL;
330 return $this->get_content();
331 }
c7e3bc51 332
333 /**
334 * Display the block!
335 */
1345403a 336 function _print_block() {
61240489 337 global $COURSE;
0a0bb380 338
3ef642d9 339 // is_empty() includes a call to get_content()
28e7967a 340 if ($this->is_empty() && empty($COURSE->javascriptportal)) {
3ef642d9 341 if (empty($this->edit_controls)) {
342 // No content, no edit controls, so just shut up
76a8339a 343 return;
3ef642d9 344 } else {
345 // No content but editing, so show something at least
346 $this->_print_shadow();
347 }
348 } else {
349 if ($this->hide_header() && empty($this->edit_controls)) {
350 // Header wants to hide, no edit controls to show, so no header it is
351 print_side_block(NULL, $this->content->text, NULL, NULL, $this->content->footer, $this->html_attributes());
352 } else {
78279204 353 // The full treatment, please. Include the title text.
354 print_side_block($this->_title_html(), $this->content->text, NULL, NULL, $this->content->footer, $this->html_attributes(), $this->title);
3ef642d9 355 }
0f3fe4b6 356 }
357 }
c7e3bc51 358
359 /**
360 * Block contents are missing. Simply display an empty block so that
361 * edit controls are accessbile to the user and they are aware that this
362 * block is in place, even if empty.
363 */
1345403a 364 function _print_shadow() {
78279204 365 print_side_block($this->_title_html(), '&nbsp;', NULL, NULL, '', array('class' => 'hidden'), $this->title);
c4d951e1 366 }
367
368
369 function _title_html() {
6b608f8f 370 global $OUTPUT;
c4d951e1 371
02db7f7a 372 //Accessibility: validation, can't have <div> inside <h2>, use <span>.
68ac3b35 373 $title = '<div class="title">';
a044c05d 374
c4d951e1 375 if (!empty($CFG->allowuserblockhiding)) {
c076f4be 376 //Accessibility: added 'alt' text for the +- icon.
377 //Theme the buttons using, Admin - Miscellaneous - smartpix.
1f967c82 378 $strshow = addslashes_js(get_string('showblocka', 'access', strip_tags($this->title)));
379 $strhide = addslashes_js(get_string('hideblocka', 'access', strip_tags($this->title)));
6b608f8f 380 $title .= '<input type="image" src="'.$OUTPUT->old_icon_url('t/switch_minus') . '" '.
c076f4be 381 'id="togglehide_inst'.$this->instance->id.'" '.
382 'onclick="elementToggleHide(this, true, function(el) {'.
383 'return findParentNode(el, \'DIV\', \'sideblock\'); },'.
384 ' \''.$strshow.'\', \''.$strhide.'\'); return false;" '.
385 'alt="'.$strhide.'" title="'.$strhide.'" class="hide-show-image" />';
c4d951e1 386 }
387
68ac3b35 388 //Accesssibility: added H2 (was in, weblib.php: print_side_block)
ccc161f8 389 $title .= '<h2>'.format_string($this->title).'</h2>';
c4d951e1 390
c7e3bc51 391 if ($this->edit_controls !== NULL) {
0f3fe4b6 392 $title .= $this->edit_controls;
393 }
c4d951e1 394
68ac3b35 395 $title .= '</div>';
c4d951e1 396 return $title;
0f3fe4b6 397 }
89adb174 398
c7e3bc51 399 /**
400 * Sets class $edit_controls var with correct block manipulation links.
401 *
402 * @uses $CFG
c7e3bc51 403 * @uses $USER
404 * @param stdObject $options ?
405 * @todo complete documenting this function. Define $options.
406 */
1345403a 407 function _add_edit_controls($options) {
6b608f8f 408 global $CFG, $USER, $OUTPUT;
3179b000 409
f474a4e5 410 // TODO - temporary hack to get the block context only if it already exists.
411 global $DB;
412 if ($DB->record_exists('context', array('contextlevel' => CONTEXT_BLOCK, 'instanceid' => $this->instance->id))) {
5c10879f 413 $context = get_context_instance(CONTEXT_BLOCK, $this->instance->id);
414 } else {
415 $context = get_context_instance(CONTEXT_SYSTEM); // pinned blocks do not have own context
416 }
3179b000 417
61240489 418 // context for site or course, i.e. participant list etc
419 // check to see if user can edit site or course blocks.
420 // blocks can appear on other pages such as mod and blog pages...
217a8ee9 421
3179b000 422 if (!$this->page->user_can_edit_blocks()) {
423 return null;
61240489 424 }
3179b000 425
0f3fe4b6 426 if (!isset($this->str)) {
427 $this->str->delete = get_string('delete');
428 $this->str->moveup = get_string('moveup');
429 $this->str->movedown = get_string('movedown');
430 $this->str->moveright = get_string('moveright');
431 $this->str->moveleft = get_string('moveleft');
432 $this->str->hide = get_string('hide');
433 $this->str->show = get_string('show');
9b4b78fd 434 $this->str->configure = get_string('configuration');
6d0bd10c 435 $this->str->assignroles = get_string('assignroles', 'role');
0f3fe4b6 436 }
437
b4483b91 438 // RTL support - exchange right and left arrows
439 if (right_to_left()) {
666e8458 440 $rightarrow = 't/left';
441 $leftarrow = 't/right';
b4483b91 442 } else {
666e8458 443 $rightarrow = 't/right';
444 $leftarrow = 't/left';
b4483b91 445 }
446
96803c88 447 $movebuttons = '<div class="commands">';
0f3fe4b6 448
c7e3bc51 449 if ($this->instance->visible) {
666e8458 450 $icon = 't/hide';
0f3fe4b6 451 $title = $this->str->hide;
c7e3bc51 452 } else {
666e8458 453 $icon = 't/show';
0f3fe4b6 454 $title = $this->str->show;
455 }
456
3179b000 457 $page = $this->page;
f4d38d20 458 $script = $page->url->out(false, array('instanceid' => $this->instance->id, 'sesskey' => sesskey()));
dd8f4910 459
3179b000 460 $movebuttons .= '<a class="icon roles" title="'. $this->str->assignroles .'" href="'.$CFG->wwwroot.'/'.$CFG->admin.'/roles/assign.php?contextid='.$context->id.'">' .
6b608f8f 461 '<img src="'.$OUTPUT->old_icon_url('i/roles') . '" alt="'.$this->str->assignroles.'" /></a>';
3179b000 462
e03c0c1d 463 // TODO MDL-19010 fix and re-enable.
464 if (false && $this->user_can_edit()) {
2a4e13c5 465 $movebuttons .= '<a class="icon hide" title="'. $title .'" href="'.$script.'&amp;blockaction=toggle">' .
666e8458 466 '<img src="'. $OUTPUT->old_icon_url($icon) .'" alt="'.$title.'" /></a>';
2a4e13c5 467 }
0f3fe4b6 468
11306331 469 if ($options & BLOCK_CONFIGURE && $this->user_can_edit()) {
5a46b156 470 $movebuttons .= '<a class="icon edit" title="'. $this->str->configure .'" href="'.$script.'&amp;blockaction=config">' .
6b608f8f 471 '<img src="'. $OUTPUT->old_icon_url('t/edit') . '" alt="'. $this->str->configure .'" /></a>';
9b4b78fd 472 }
473
2a4e13c5 474 if ($this->user_can_addto($page)) {
475 $movebuttons .= '<a class="icon delete" title="'. $this->str->delete .'" href="'.$script.'&amp;blockaction=delete">' .
6b608f8f 476 '<img src="'. $OUTPUT->old_icon_url('t/delete') . '" alt="'. $this->str->delete .'" /></a>';
2a4e13c5 477 }
0f3fe4b6 478
479 if ($options & BLOCK_MOVE_LEFT) {
5a46b156 480 $movebuttons .= '<a class="icon left" title="'. $this->str->moveleft .'" href="'.$script.'&amp;blockaction=moveleft">' .
666e8458 481 '<img src="'. $OUTPUT->old_icon_url($leftarrow).'" alt="'. $this->str->moveleft .'" /></a>';
0f3fe4b6 482 }
483 if ($options & BLOCK_MOVE_UP) {
5a46b156 484 $movebuttons .= '<a class="icon up" title="'. $this->str->moveup .'" href="'.$script.'&amp;blockaction=moveup">' .
6b608f8f 485 '<img src="'. $OUTPUT->old_icon_url('t/up') . '" alt="'. $this->str->moveup .'" /></a>';
0f3fe4b6 486 }
487 if ($options & BLOCK_MOVE_DOWN) {
5a46b156 488 $movebuttons .= '<a class="icon down" title="'. $this->str->movedown .'" href="'.$script.'&amp;blockaction=movedown">' .
6b608f8f 489 '<img src="'. $OUTPUT->old_icon_url('t/down') . '" alt="'. $this->str->movedown .'" /></a>';
0f3fe4b6 490 }
491 if ($options & BLOCK_MOVE_RIGHT) {
5a46b156 492 $movebuttons .= '<a class="icon right" title="'. $this->str->moveright .'" href="'.$script.'&amp;blockaction=moveright">' .
666e8458 493 '<img src="'. $OUTPUT->old_icon_url($rightarrow).'" alt="'. $this->str->moveright .'" /></a>';
0f3fe4b6 494 }
495
496 $movebuttons .= '</div>';
497 $this->edit_controls = $movebuttons;
498 }
499
c7e3bc51 500 /**
501 * Tests if this block has been implemented correctly.
502 * Also, $errors isn't used right now
503 *
504 * @return boolean
505 */
506
0f3fe4b6 507 function _self_test() {
508 // Tests if this block has been implemented correctly.
509 // Also, $errors isn't used right now
510 $errors = array();
511
512 $correct = true;
c7e3bc51 513 if ($this->get_title() === NULL) {
0f3fe4b6 514 $errors[] = 'title_not_set';
515 $correct = false;
516 }
ccd3dd0c 517 if (!in_array($this->get_content_type(), array(BLOCK_TYPE_LIST, BLOCK_TYPE_TEXT))) {
0f3fe4b6 518 $errors[] = 'invalid_content_type';
519 $correct = false;
520 }
17e5635c 521 //following selftest was not working when roles&capabilities were used from block
35a518c5 522/* if ($this->get_content() === NULL) {
0f3fe4b6 523 $errors[] = 'content_not_set';
524 $correct = false;
35a518c5 525 }*/
c7e3bc51 526 if ($this->get_version() === NULL) {
0f3fe4b6 527 $errors[] = 'version_not_set';
528 $correct = false;
529 }
2b0d60ec 530
531 $formats = $this->applicable_formats();
c7e3bc51 532 if (empty($formats) || array_sum($formats) === 0) {
8a47e075 533 $errors[] = 'no_formats';
0f3fe4b6 534 $correct = false;
535 }
2b0d60ec 536
0f3fe4b6 537 $width = $this->preferred_width();
c7e3bc51 538 if (!is_int($width) || $width <= 0) {
0f3fe4b6 539 $errors[] = 'invalid_width';
540 $correct = false;
541 }
542 return $correct;
543 }
544
c7e3bc51 545 /**
546 * Subclasses should override this and return true if the
547 * subclass block has a config_global.html file.
548 *
549 * @return boolean
550 */
0f3fe4b6 551 function has_config() {
552 return false;
553 }
c7e3bc51 554
555 /**
556 * Default behavior: print the config_global.html file
557 * You don't need to override this if you're satisfied with the above
558 *
559 * @uses $CFG
c7e3bc51 560 * @return boolean
561 */
f8582e3e 562 function config_print() {
9b4b78fd 563 // Default behavior: print the config_global.html file
c7e3bc51 564 // You don't need to override this if you're satisfied with the above
565 if (!$this->has_config()) {
9b4b78fd 566 return false;
567 }
0705dcc0 568 global $CFG;
569 print_simple_box_start('center', '', '', 5, 'blockconfigglobal');
59b29207 570 include($CFG->dirroot.'/blocks/'. $this->name() .'/config_global.html');
9b4b78fd 571 print_simple_box_end();
572 return true;
0f3fe4b6 573 }
59b29207 574
c7e3bc51 575 /**
576 * Default behavior: save all variables as $CFG properties
577 * You don't need to override this if you 're satisfied with the above
578 *
f8582e3e 579 * @param array $data
c7e3bc51 580 * @return boolean
581 */
f8582e3e 582 function config_save($data) {
f8582e3e 583 foreach ($data as $name => $value) {
9b4b78fd 584 set_config($name, $value);
585 }
586 return true;
0f3fe4b6 587 }
59b29207 588
c7e3bc51 589 /**
590 * Default case: the block can be used in all course types
591 * @return array
592 * @todo finish documenting this function
593 */
0f3fe4b6 594 function applicable_formats() {
d232b8c7 595 // Default case: the block can be used in courses and site index, but not in activities
9591bc3c 596 return array('all' => true, 'mod' => false, 'tag' => false);
0f3fe4b6 597 }
59b29207 598
c7e3bc51 599
600 /**
601 * Default case: the block wants to be 180 pixels wide
602 * @return int
603 */
0f3fe4b6 604 function preferred_width() {
0f3fe4b6 605 return 180;
606 }
59b29207 607
c7e3bc51 608 /**
609 * Default return is false - header will be shown
610 * @return boolean
611 */
0f3fe4b6 612 function hide_header() {
0f3fe4b6 613 return false;
614 }
c7e3bc51 615
616 /**
11306331 617 * Default case: an id with the instance and a class with our name in it
c7e3bc51 618 * @return array
619 * @todo finish documenting this function
620 */
c5507e52 621 function html_attributes() {
2f747639 622 return array(
623 'id' => 'inst'.$this->instance->id,
624 'class' => 'block_'. $this->name().
625 ($this->edit_controls ? ' block_with_controls' :'')
626 );
c5507e52 627 }
59b29207 628
c7e3bc51 629 /**
630 * Given an instance set the class var $instance to it and
631 * load class var $config
632 * @param block $instance
633 * @todo add additional documentation to further explain the format of instance and config
634 */
3179b000 635 function _load_instance($instance, $page) {
c7e3bc51 636 if (!empty($instance->configdata)) {
9b4b78fd 637 $this->config = unserialize(base64_decode($instance->configdata));
638 }
673c1b2f 639 // [pj] This line below is supposed to be an optimization (we don't need configdata anymore)
640 // but what it does is break in PHP5 because the same instance object will be passed to
641 // this function twice in each page view, and the second time it won't have any configdata
642 // so it won't work correctly. Thus it's commented out.
643 // unset($instance->configdata);
9b4b78fd 644 $this->instance = $instance;
3179b000 645 $this->page = $page;
9b4b78fd 646 $this->specialization();
647 }
59b29207 648
43038ce6 649 /**
650 * This function is called on your subclass right after an instance is loaded
651 * Use this function to act on instance data just after it's loaded and before anything else is done
67677908 652 * For instance: if your block will have different title's depending on location (site, course, blog, etc)
43038ce6 653 */
9b4b78fd 654 function specialization() {
655 // Just to make sure that this method exists.
9b4b78fd 656 }
657
c7e3bc51 658 /**
f032aa7a 659 * Is each block of this type going to have instance-specific configuration?
660 * Normally, this setting is controlled by {@link instance_allow_multiple}: if multiple
661 * instances are allowed, then each will surely need its own configuration. However, in some
662 * cases it may be necessary to provide instance configuration to blocks that do not want to
663 * allow multiple instances. In that case, make this function return true.
664 * I stress again that this makes a difference ONLY if {@link instance_allow_multiple} returns false.
665 * @return boolean
666 * @todo finish documenting this function by explaining per-instance configuration further
667 */
668 function instance_allow_config() {
669 return false;
670 }
671
672 /**
673 * Are you going to allow multiple instances of each block?
c7e3bc51 674 * If yes, then it is assumed that the block WILL USE per-instance configuration
675 * @return boolean
676 * @todo finish documenting this function by explaining per-instance configuration further
677 */
9b4b78fd 678 function instance_allow_multiple() {
679 // Are you going to allow multiple instances of each block?
680 // If yes, then it is assumed that the block WILL USE per-instance configuration
681 return false;
682 }
59b29207 683
c7e3bc51 684 /**
685 * Default behavior: print the config_instance.html file
686 * You don't need to override this if you're satisfied with the above
687 *
688 * @uses $CFG
c7e3bc51 689 * @return boolean
690 * @todo finish documenting this function
691 */
9b4b78fd 692 function instance_config_print() {
f28f2d90 693 global $CFG, $DB;
9b4b78fd 694 // Default behavior: print the config_instance.html file
e1b8bdf8 695 // You don't need to override this if you're satisfied with the above
f032aa7a 696 if (!$this->instance_allow_multiple() && !$this->instance_allow_config()) {
9b4b78fd 697 return false;
698 }
9b4b78fd 699
c7e3bc51 700 if (is_file($CFG->dirroot .'/blocks/'. $this->name() .'/config_instance.html')) {
0705dcc0 701 print_simple_box_start('center', '', '', 5, 'blockconfiginstance');
6195e04a 702 include($CFG->dirroot .'/blocks/'. $this->name() .'/config_instance.html');
9b4b78fd 703 print_simple_box_end();
6195e04a 704 } else {
9b4b78fd 705 notice(get_string('blockconfigbad'), str_replace('blockaction=', 'dummy=', qualified_me()));
706 }
707
708 return true;
709 }
c7e3bc51 710
711 /**
712 * Serialize and store config data
c7e3bc51 713 */
f474a4e5 714 function instance_config_save($data, $nolongerused = false) {
a5d424df 715 global $DB;
f474a4e5 716 $DB->set_field('block_instances', 'configdata', base64_encode(serialize($data)),
e03c0c1d 717 array('id' => $this->instance->id));
9b4b78fd 718 }
719
0144a0a7 720 /**
721 * Replace the instance's configuration data with those currently in $this->config;
722 * @return boolean
723 * @todo finish documenting this function
724 */
f474a4e5 725 function instance_config_commit($nolongerused = false) {
a5d424df 726 global $DB;
f474a4e5 727 $this->instance_config_save($this->config);
0144a0a7 728 }
729
b33dd23a 730 /**
731 * Do any additional initialization you may need at the time a new block instance is created
732 * @return boolean
733 * @todo finish documenting this function
734 */
735 function instance_create() {
736 return true;
737 }
738
739 /**
740 * Delete everything related to this instance if you have been using persistent storage other than the configdata field.
741 * @return boolean
742 * @todo finish documenting this function
743 */
744 function instance_delete() {
745 return true;
746 }
747
11306331 748 /**
749 * Allows the block class to have a say in the user's ability to edit (i.e., configure) blocks of this type.
750 * The framework has first say in whether this will be allowed (e.g., no editing allowed unless in edit mode)
751 * but if the framework does allow it, the block can still decide to refuse.
752 * @return boolean
753 * @todo finish documenting this function
754 */
755 function user_can_edit() {
756 return true;
757 }
758
759 /**
760 * Allows the block class to have a say in the user's ability to create new instances of this block.
761 * The framework has first say in whether this will be allowed (e.g., no adding allowed unless in edit mode)
762 * but if the framework does allow it, the block can still decide to refuse.
763 * This function has access to the complete page object, the creation related to which is being determined.
764 * @return boolean
765 * @todo finish documenting this function
766 */
767 function user_can_addto(&$page) {
11306331 768 return true;
769 }
770
f432bebf 771 function get_extra_capabilities() {
44df8fa9 772 return array('moodle/block:view');
f432bebf 773 }
0f3fe4b6 774}
775
c7e3bc51 776/**
3ef642d9 777 * Specialized class for displaying a block with a list of icons/text labels
778 *
779 * @author Jon Papaioannou
780 * @package blocks
781 */
782
783class block_list extends block_base {
784 var $content_type = BLOCK_TYPE_LIST;
785
786 function is_empty() {
25a7d980 787
f474a4e5 788 // TODO - temporary hack to get the block context only if it already exists.
789 global $DB;
790 if ($DB->record_exists('context', array('contextlevel' => CONTEXT_BLOCK, 'instanceid' => $this->instance->id))) {
5c10879f 791 $context = get_context_instance(CONTEXT_BLOCK, $this->instance->id);
792 } else {
793 $context = get_context_instance(CONTEXT_SYSTEM); // pinned blocks do not have own context
794 }
3179b000 795
25a7d980 796 if ( !has_capability('moodle/block:view', $context) ) {
797 return true;
798 }
799
3ef642d9 800 $this->get_content();
801 return (empty($this->content->items) && empty($this->content->footer));
802 }
803
804 function _print_block() {
61240489 805 global $COURSE;
0a0bb380 806
3ef642d9 807 // is_empty() includes a call to get_content()
28e7967a 808 if ($this->is_empty() && empty($COURSE->javascriptportal)) {
3ef642d9 809 if (empty($this->edit_controls)) {
810 // No content, no edit controls, so just shut up
76a8339a 811 return;
3ef642d9 812 } else {
813 // No content but editing, so show something at least
814 $this->_print_shadow();
815 }
816 } else {
817 if ($this->hide_header() && empty($this->edit_controls)) {
818 // Header wants to hide, no edit controls to show, so no header it is
0a0bb380 819 print_side_block(NULL, '', $this->content->items, $this->content->icons,
820 $this->content->footer, $this->html_attributes());
3ef642d9 821 } else {
78279204 822 // The full treatment, please. Include the title text.
0a0bb380 823 print_side_block($this->_title_html(), '', $this->content->items, $this->content->icons,
824 $this->content->footer, $this->html_attributes(), $this->title);
825 }
3ef642d9 826 }
827 }
828
829}
830
d0b59e3b 831?>