Changes for XHTML and accessibility compliance
[moodle.git] / lib / blocklib.php
CommitLineData
dcb1bd3c 1<?php //$Id$
0f3fe4b6 2
3//This library includes all the necessary stuff to use blocks in course pages
4
5define('BLOCK_LEFT', 11);
6define('BLOCK_RIGHT', 12);
7define('BLOCK_MOVE_LEFT', 0x01);
8define('BLOCK_MOVE_RIGHT', 0x02);
9define('BLOCK_MOVE_UP', 0x04);
10define('BLOCK_MOVE_DOWN', 0x08);
11
0e9af917 12function block_remove_inappropriate_from_course(&$course) {
13 $blocks = $course->blockinfo;
14
15 $delimpos = strpos($blocks, ':');
16
17 if($delimpos === false) {
18 // No ':' found, we have all left blocks
19 $leftblocks = explode(',', $blocks);
20 $rightblocks = array();
21 }
22 else if($delimpos === 0) {
23 // ':' at start of string, we have all right blocks
24 $blocks = substr($blocks, 1);
25 $leftblocks = array();
26 $rightblocks = explode(',', $blocks);
27 }
28 else {
29 // Both left and right blocks
30 $leftpart = substr($blocks, 0, $delimpos);
31 $rightpart = substr($blocks, $delimpos + 1);
32 $leftblocks = explode(',', $leftpart);
33 $rightblocks = explode(',', $rightpart);
34 }
35
36 $allblocks = get_records('blocks');
37 if(!empty($leftblocks)) {
38 foreach($leftblocks as $key => $id) {
39 $positiveid = abs($id);
40 $formats = block_method_result($allblocks[$positiveid]->name, 'applicable_formats');
41 if( !(isset($formats[$course->format]) ? $formats[$course->format] : !empty($formats['all']))) {
42 unset($leftblocks[$key]);
43 }
44 }
45 }
46 if(!empty($rightblocks)) {
47 foreach($rightblocks as $key => $id) {
48 $positiveid = abs($id);
49 $formats = block_method_result($allblocks[$positiveid]->name, 'applicable_formats');
50 if( !(isset($formats[$course->format]) ? $formats[$course->format] : !empty($formats['all']))) {
51 unset($rightblocks[$key]);
52 }
53 }
54 }
55
56 $course->blockinfo = implode(',', $leftblocks);
57 if(!empty($rightblocks)) {
58 $course->blockinfo .= ':' . implode(',', $rightblocks);
59 }
60}
0f3fe4b6 61
33bee34c 62// Returns the case-sensitive name of the class' constructor function. This includes both
63// PHP5- and PHP4-style constructors. If no appropriate constructor can be found, returns NULL.
64// If there is no such class, returns boolean false.
65function get_class_constructor($classname) {
66 // Caching
67 static $constructors = array();
68
69 if(!class_exists($classname)) {
70 return false;
71 }
72
73 // Tests indicate this doesn't hurt even in PHP5.
74 $classname = strtolower($classname);
75
76 // Return cached value, if exists
77 if(isset($constructors[$classname])) {
78 return $constructors[$classname];
79 }
80
81 // Get a list of methods. After examining several different ways of
82 // doing the check, (is_callable, method_exists, function_exists etc)
83 // it seems that this is the most reliable one.
84 $methods = get_class_methods($classname);
85
86 // PHP5 constructor?
87 if(phpversion() >= '5') {
88 if(in_array('__construct', $methods)) {
89 return $constructors[$classname] = '__construct';
90 }
91 }
92
93 // If we have PHP5 but no magic constructor, we have to lowercase the methods
94 $methods = array_map('strtolower', $methods);
95
96 if(in_array($classname, $methods)) {
97 return $constructors[$classname] = $classname;
98 }
99
100 return $constructors[$classname] = NULL;
101}
102
0f3fe4b6 103//This function retrieves a method-defined property of a class WITHOUT instantiating an object
104//It seems that the only way to use the :: operator with variable class names is eval() :(
105//For caveats with this technique, see the PHP docs on operator ::
106function block_method_result($blockname, $method) {
107 if(!block_load_class($blockname)) {
108 return NULL;
109 }
110 return eval('return CourseBlock_'.$blockname.'::'.$method.'();');
111}
112
113//This function creates a new object of the specified block class
114function block_instance($blockname, $argument) {
115 if(!block_load_class($blockname)) {
116 return false;
117 }
118 $classname = 'CourseBlock_'.$blockname;
119 return New $classname($argument);
120}
121
122//This function loads the necessary class files for a block
123//Whenever you want to load a block, use this first
124function block_load_class($blockname) {
125 global $CFG;
126
127 @include_once($CFG->dirroot.'/blocks/moodleblock.class.php');
128 $classname = 'CourseBlock_'.$blockname;
129 @include_once($CFG->dirroot.'/blocks/'.$blockname.'/block_'.$blockname.'.php');
130
131 // After all this, return value indicating success or failure
132 return class_exists($classname);
133}
134
135//This function determines if there is some active block in an array of blocks
136function block_have_active($array) {
137 foreach($array as $blockid) {
138 if($blockid > 0) {
139 return true;
140 }
141 }
142 return false;
143}
144
145//This function print the one side of blocks in course main page
146function print_course_blocks(&$course, $blocksarray, $side) {
147 global $CFG;
148
149 $isediting = isediting($course->id);
150 $ismoving = ismoving($course->id);
151 $isteacheredit = isteacheredit($course->id);
152
153 if(!empty($blocksarray)) {
154 // Include the base class
155 @include_once($CFG->dirroot.'/blocks/moodleblock.class.php');
156 if(!class_exists('moodleblock')) {
157 error('Class MoodleBlock is not defined or file not found for /course/blocks/moodleblock.class.php');
158 }
159
160 $blockdata = get_records('blocks', 'visible', 1);
161 if($blockdata !== false) {
162
163 $lastblock = end($blocksarray);
164 $firstblock = reset($blocksarray);
165
166 foreach($blocksarray as $blockid) {
167 if(!isset($blockdata[abs($blockid)])) {
168 // This block is hidden. Don't show it.
169 continue;
170 }
171
172 $blockname = $blockdata[abs($blockid)]->name;
173 $block = block_instance($blockname, $course);
174 if($block === false) {
175 // Something went wrong
176 continue;
177 }
178
179 // There are various sanity checks commented out below
180 // because the block detection code should have already done them long ago.
181
182 /*
183 if(!is_subclass_of($block, 'MoodleBlock')) {
184 // Error: you have to derive from MoodleBlock
185 continue;
186 }
187
188 if($content === NULL || $title === NULL) {
189 // Error: This shouldn't have happened
190 continue;
191 }
192 */
193 if ($isediting && !$ismoving && $isteacheredit) {
194 $options = 0;
195 $options |= BLOCK_MOVE_UP * ($blockid != $firstblock);
196 $options |= BLOCK_MOVE_DOWN * ($blockid != $lastblock);
197 $options |= ($side == BLOCK_LEFT) ? BLOCK_MOVE_RIGHT : BLOCK_MOVE_LEFT;
198 $block->add_edit_controls($options, $blockid);
199 }
200
201 if($blockid < 0) {
202 // We won't print this block...
203 if($isediting) {
204 // Unless we 're in editing mode, in which case we 'll print a 'shadow'
205 $block->print_shadow();
206 }
207 continue;
208 }
209 // So simple...
210 $block->print_block();
211 }
212 }
213 }
214}
215
216//This iterates over an array of blocks and calculates the preferred width
217function blocks_preferred_width($blockarray, $blockinfos) {
218 $width = 0;
219
220 if(!is_array($blockarray) || empty($blockarray)) {
221 return 0;
222 }
223 foreach($blockarray as $blockid) {
0c9c6363 224 if($blockid < 0) {
225 // Invisible block
fe78a3dc 226 continue;
0c9c6363 227 }
0f3fe4b6 228 if(isset($blockinfos[$blockid])) {
229 $blockname = $blockinfos[$blockid]->name;
230 $pref = block_method_result($blockname, 'preferred_width');
231 if($pref === NULL) {
232 continue;
233 }
234 if($pref > $width) {
235 $width = $pref;
236 }
237 }
238 }
239 return $width;
240}
241
242
243// $course passed by reference for speed
244// $leftblocks, $rightblocks passed by reference because block_action() needs to
245// update the arrays so that the change can be shown immediately.
246
247function block_action(&$course, &$leftblocks, &$rightblocks, $blockaction, $blockid) {
248
249 $blockid = abs(intval($blockid)); // Just to make sure
250
251 switch($blockaction) {
252 case 'toggle':
253 $block = block_find($blockid, $leftblocks, $rightblocks);
254 if($block !== false) {
255 if($block->side == BLOCK_LEFT) {
256 $leftblocks[$block->position] = -$leftblocks[$block->position];
257 }
258 else {
259 $rightblocks[$block->position] = -$rightblocks[$block->position];
260 }
261 }
262 break;
263 case 'delete':
264 $block = block_find($blockid, $leftblocks, $rightblocks);
265 if($block !== false) {
266 if($block->side == BLOCK_LEFT) {
267 unset($leftblocks[$block->position]);
268 }
269 else {
270 unset($rightblocks[$block->position]);
271 }
272 }
273 break;
274 case 'add':
275 // Toggle to enabled, or add it if it doesn't exist at all
276 $block = block_find($blockid, $leftblocks, $rightblocks);
277 if($block === false) {
278 // It doesn't exist at all, so add it
279 $rightblocks[] = $blockid;
280 }
281 else if($block->enabled == false) {
282 // Enable it
283 if($block->side == BLOCK_LEFT) {
284 $leftblocks[$block->position] = -$leftblocks[$block->position];
285 }
286 else {
287 $rightblocks[$block->position] = -$rightblocks[$block->position];
288 }
289 }
290 break;
291 case 'moveup':
292 $block = block_find($blockid, $leftblocks, $rightblocks);
293 if($block !== false) {
294 if($block->side == BLOCK_LEFT) {
295 if(isset($leftblocks[$block->position - 1])) {
296 // We can move it upwards
297 $oldblock = $leftblocks[$block->position - 1];
298 $leftblocks[$block->position - 1] = $leftblocks[$block->position]; // not $blockid, as this loses the sign
299 $leftblocks[$block->position] = $oldblock;
300 }
301 }
302 else {
303 if(isset($rightblocks[$block->position - 1])) {
304 // We can move it upwards
305 $oldblock = $rightblocks[$block->position - 1];
306 $rightblocks[$block->position - 1] = $rightblocks[$block->position]; // not $blockid, as this loses the sign
307 $rightblocks[$block->position] = $oldblock;
308 }
309 }
310 }
311 break;
312 case 'movedown':
313 $block = block_find($blockid, $leftblocks, $rightblocks);
314 if($block !== false) {
315 if($block->side == BLOCK_LEFT) {
316 if(isset($leftblocks[$block->position + 1])) {
317 // We can move it downwards
318 $oldblock = $leftblocks[$block->position + 1];
319 $leftblocks[$block->position + 1] = $leftblocks[$block->position]; // not $blockid, as this loses the sign
320 $leftblocks[$block->position] = $oldblock;
321 }
322 }
323 else {
324 if(isset($rightblocks[$block->position + 1])) {
325 // We can move it downwards
326 $oldblock = $rightblocks[$block->position + 1];
327 $rightblocks[$block->position + 1] = $rightblocks[$block->position]; // not $blockid, as this loses the sign
328 $rightblocks[$block->position] = $oldblock;
329 }
330 }
331 }
332 break;
333 case 'moveside':
334 $block = block_find($blockid, $leftblocks, $rightblocks);
335 if($block !== false) {
336 if($block->side == BLOCK_LEFT) {
337 unset($leftblocks[$block->position]);
338 $rightblocks[] = $block->enabled ? $blockid : -$blockid;
339 }
340 else {
341 unset($rightblocks[$block->position]);
342 $leftblocks[] = $block->enabled ? $blockid : -$blockid;
343 }
344 }
345 break;
346 }
347
348 $course->blockinfo = implode(',', $leftblocks).':'.implode(',',$rightblocks);
349 set_field('course', 'blockinfo', $course->blockinfo, 'id', $course->id);
350
351}
352
353// Searches for the block with ID $blockid in one or more of the two
354// blocks arrays. If not found, returns boolean false. Otherwise,
355// returns an object $finding where:
356// $finding->side = BLOCK_LEFT or BLOCK_RIGHT
357// $finding->enabled = true or false
358// $finding->position = index of corresponding array where found
359
360function block_find($blockid, $leftblocks, $rightblocks) {
361
362 if(($blockid = abs($blockid)) == 0) {
363 return false;
364 }
365
366 $finding->side = BLOCK_LEFT;
367 $finding->enabled = true;
368 $finding->position = NULL;
369
370 // First, search for the "enabled" block, since that's what we
371 // will be doing most of the time.
372
373 $key = array_search($blockid, $leftblocks);
374 if($key !== false && $key !== NULL) {
375 $finding->position = $key;
376 return $finding;
377 }
378 $key = array_search($blockid, $rightblocks);
379 if($key !== false && $key !== NULL) {
380 $finding->position = $key;
381 $finding->side = BLOCK_RIGHT;
382 return $finding;
383 }
384
385 // "enabled" block not found. Now search for the disabled block.
386 $finding->enabled = false;
387 $blockid = -$blockid;
388
389 $key = array_search($blockid, $leftblocks);
390 if($key !== false && $key !== NULL) {
391 $finding->position = $key;
392 return $finding;
393 }
394 $key = array_search($blockid, $rightblocks);
395 if($key !== false && $key !== NULL) {
396 $finding->position = $key;
397 $finding->side = BLOCK_RIGHT;
398 return $finding;
399 }
400
401 // Nothing found :(
402
403 return false;
404}
405
c598d270 406//This function prints the block to admin blocks as necessary
36a2d0f5 407function block_print_blocks_admin(&$course, $missingblocks) {
5b224948 408
409 global $USER;
410
6236ed99 411 if (isediting($course->id)) {
c598d270 412 $strblocks = get_string('blocks');
413 $stradd = get_string('add');
414 if (!empty($missingblocks)) {
0f3fe4b6 415 $blockdata = get_records_list('blocks', 'id', implode(',', $missingblocks));
c598d270 416 if ($blockdata !== false) {
417 foreach ($blockdata as $block) {
36a2d0f5 418 $blockobject = block_instance($block->name, $course);
c598d270 419 if ($blockobject === false) {
0f3fe4b6 420 continue;
421 }
422 $menu[$block->id] = $blockobject->get_title();
423 }
89adb174 424
a06f9887 425 if(!$course->category) {
89adb174 426 $target = 'index.php';
427 }
428 else {
429 $target = 'view.php';
430 }
5b224948 431 $content = popup_form($target.'?id='.$course->id.'&amp;blockaction=add&amp;sesskey='.$USER->sesskey.'&amp;blockid=',
c598d270 432 $menu, 'add_block', '', "$stradd...", '', '', true);
0f3fe4b6 433 $content = '<div align="center">'.$content.'</div>';
c598d270 434 print_side_block($strblocks, $content, NULL, NULL, NULL);
0f3fe4b6 435 }
436 }
437 }
438}
439
440function upgrade_blocks_db($continueto) {
441/// This function upgrades the blocks tables, if necessary
442/// It's called from admin/index.php
443
444 global $CFG, $db;
445
446 require_once ("$CFG->dirroot/blocks/version.php"); // Get code versions
447
448 if (empty($CFG->blocks_version)) { // Blocks have never been installed.
449 $strdatabaseupgrades = get_string("databaseupgrades");
450 print_header($strdatabaseupgrades, $strdatabaseupgrades, $strdatabaseupgrades,
451 "", "", false, "&nbsp;", "&nbsp;");
452
453 $db->debug=true;
454 if (modify_database("$CFG->dirroot/blocks/db/$CFG->dbtype.sql")) {
455 $db->debug = false;
456 if (set_config("blocks_version", $blocks_version)) {
457 notify(get_string("databasesuccess"), "green");
458 notify(get_string("databaseupgradeblocks", "", $blocks_version));
459 print_continue($continueto);
460 exit;
461 } else {
462 error("Upgrade of blocks system failed! (Could not update version in config table)");
463 }
464 } else {
465 error("Blocks tables could NOT be set up successfully!");
466 }
467 }
468
469
470 if ($blocks_version > $CFG->blocks_version) { // Upgrade tables
471 $strdatabaseupgrades = get_string("databaseupgrades");
472 print_header($strdatabaseupgrades, $strdatabaseupgrades, $strdatabaseupgrades);
473
474 require_once ("$CFG->dirroot/blocks/db/$CFG->dbtype.php");
475
476 $db->debug=true;
477 if (blocks_upgrade($CFG->blocks_version)) {
478 $db->debug=false;
479 if (set_config("blocks_version", $blocks_version)) {
480 notify(get_string("databasesuccess"), "green");
481 notify(get_string("databaseupgradeblocks", "", $blocks_version));
482 print_continue($continueto);
483 exit;
484 } else {
485 error("Upgrade of blocks system failed! (Could not update version in config table)");
486 }
487 } else {
488 $db->debug=false;
489 error("Upgrade failed! See blocks/version.php");
490 }
491
492 } else if ($blocks_version < $CFG->blocks_version) {
493 notify("WARNING!!! The code you are using is OLDER than the version that made these databases!");
494 }
495}
496
497//This function finds all available blocks and install them
498//into blocks table or do all the upgrade process if newer
499function upgrade_blocks_plugins($continueto) {
500
501 global $CFG;
502
503 $blocktitles = array();
504 $invalidblocks = array();
505 $validblocks = array();
506 $notices = array();
507
508 //Count the number of blocks in db
509 $blockcount = count_records("blocks");
510 //If there isn't records. This is the first install, so I remember it
511 if ($blockcount == 0) {
512 $first_install = true;
513 } else {
514 $first_install = false;
515 }
516
517 $site = get_site();
518
0cb77f5a 519 if (!$blocks = get_list_of_plugins("blocks", "db") ) {
0f3fe4b6 520 error("No blocks installed!");
521 }
522
828c4e09 523 include_once($CFG->dirroot."/blocks/moodleblock.class.php");
0f3fe4b6 524 if(!class_exists('moodleblock')) {
525 error('Class MoodleBlock is not defined or file not found for /blocks/moodleblock.class.php');
526 }
527
528 foreach ($blocks as $blockname) {
529
5216e2c6 530 if ($blockname == "NEWBLOCK") { // Someone has unzipped the template, ignore it
0f3fe4b6 531 continue;
532 }
533
534 $fullblock = "$CFG->dirroot/blocks/$blockname";
535
536 if ( is_readable($fullblock."/block_".$blockname.".php")) {
537 include_once($fullblock."/block_".$blockname.".php");
538 } else {
539 $notices[] = "Block $blockname: ".$fullblock."/block_".$blockname.".php was not readable";
540 continue;
541 }
542
828c4e09 543 if ( is_dir("$fullblock/db/")) {
544 if ( is_readable("$fullblock/db/$CFG->dbtype.php")) {
545 include_once("$fullblock/db/$CFG->dbtype.php"); # defines upgrading function
546 } else {
547 $notices[] ="Block $blockname: $fullblock/db/$CFG->dbtype.php was not readable";
548 continue;
549 }
0f3fe4b6 550 }
551
552 $classname = 'CourseBlock_'.$blockname;
553 if(!class_exists($classname)) {
554 $notices[] = "Block $blockname: $classname not implemented";
555 continue;
556 }
557
558 // Let's see if it supports some basic methods
33bee34c 559 $constructor = get_class_constructor($classname);
560 if(empty($constructor)) {
0f3fe4b6 561 // No constructor
562 $notices[] = "Block $blockname: class does not have a constructor";
563 $invalidblocks[] = $blockname;
564 continue;
565 }
566
567 unset($block);
568
569 $blockobj = New $classname($site);
570
571 // Inherits from MoodleBlock?
33bee34c 572 if(!is_subclass_of($blockobj, 'moodleblock')) {
0f3fe4b6 573 $notices[] = "Block $blockname: class does not inherit from MoodleBlock";
574 continue;
575 }
576
577 // OK, it's as we all hoped. For further tests, the object will do them itself.
578 if(!$blockobj->_self_test()) {
579 $notices[] = "Block $blockname: self test failed";
580 continue;
581 }
582 $block->version = $blockobj->get_version();
583
584 if (!isset($block->version)) {
585 $notices[] = "Block $blockname: hasn't version support";
586 continue;
587 }
588
589 $block->name = $blockname; // The name MUST match the directory
590 $blocktitle = $blockobj->get_title();
591
592 if ($currblock = get_record("blocks", "name", $block->name)) {
593 if ($currblock->version == $block->version) {
594 // do nothing
595 } else if ($currblock->version < $block->version) {
596 if (empty($updated_blocks)) {
597 $strblocksetup = get_string("blocksetup");
598 print_header($strblocksetup, $strblocksetup, $strblocksetup, "", "", false, "&nbsp;", "&nbsp;");
599 }
b88f7004 600 print_heading('New version of '.$blocktitle.' ('.$block->name.') exists');
601 $upgrade_function = $block->name.'_upgrade';
0f3fe4b6 602 if (function_exists($upgrade_function)) {
603 $db->debug=true;
604 if ($upgrade_function($currblock->version, $block)) {
b88f7004 605
606 $upgradesuccess = true;
0f3fe4b6 607 } else {
b88f7004 608 $upgradesuccess = false;
609 }
610 $db->debug=false;
611 }
612 else {
613 $upgradesuccess = true;
614 }
615 if(!$upgradesuccess) {
616 notify("Upgrading block $block->name from $currblock->version to $block->version FAILED!");
617 }
618 else {
619 // OK so far, now update the blocks record
620 $block->id = $currblock->id;
621 if (! update_record('blocks', $block)) {
622 error("Could not update block $block->name record in blocks table!");
0f3fe4b6 623 }
b88f7004 624 notify(get_string('blocksuccess', '', $blocktitle), 'green');
625 echo '<hr />';
0f3fe4b6 626 }
627 $updated_blocks = true;
628 } else {
629 error("Version mismatch: block $block->name can't downgrade $currblock->version -> $block->version !");
630 }
631
632 } else { // block not installed yet, so install it
633
634 // [pj] Normally this would be inline in the if, but we need to
635 // check for NULL (necessary for 4.0.5 <= PHP < 4.2.0)
636 $conflictblock = array_search($blocktitle, $blocktitles);
637 if($conflictblock !== false && $conflictblock !== NULL) {
638
639 // Duplicate block titles are not allowed, they confuse people
640 // AND PHP's associative arrays ;)
641 error('<strong>Naming conflict</strong>: block <strong>'.$block->name.'</strong> has the same title with an existing block, <strong>'.$conflictblock.'</strong>!');
642 }
643 if (empty($updated_blocks)) {
644 $strblocksetup = get_string("blocksetup");
645 print_header($strblocksetup, $strblocksetup, $strblocksetup, "", "", false, "&nbsp;", "&nbsp;");
646 }
647 print_heading($block->name);
648 $updated_blocks = true;
649 $db->debug = true;
a71bfa1c 650 @set_time_limit(0); // To allow slow databases to complete the long SQL
828c4e09 651 if (!is_dir("$fullblock/db/") || modify_database("$fullblock/db/$CFG->dbtype.sql")) {
0f3fe4b6 652 $db->debug = false;
653 if ($block->id = insert_record('blocks', $block)) {
654 notify(get_string('blocksuccess', '', $blocktitle), 'green');
9a58f7cb 655 echo "<hr />";
0f3fe4b6 656 } else {
657 error("$block->name block could not be added to the block list!");
658 }
659 } else {
660 error("Block $block->name tables could NOT be set up successfully!");
661 }
662 }
663
664 $blocktitles[$block->name] = $blocktitle;
665 }
666
667 if(!empty($notices)) {
668 foreach($notices as $notice) {
669 notify($notice);
670 }
671 }
672
673 //Finally, if we are in the first_install, update every course blockinfo field with
674 //default values.
675 if ($first_install) {
676 //Iterate over each course
677 if ($courses = get_records("course")) {
678 foreach ($courses as $course) {
e02c35b2 679 //Depending of the format, insert some values
25d18413 680 $blockinfo = blocks_get_default_blocks ($course->id,
681 blocks_get_config_default($course->format));
0f3fe4b6 682 if ($CFG->debug) {
dcb1bd3c 683 echo 'Updating blockinfo for course: '.$course->shortname.'('.$blockinfo.')<br />';
0f3fe4b6 684 }
685 }
686 }
687 }
688
e02c35b2 689 if (!empty($CFG->siteblocksadded)) { /// This is a once-off hack to make a proper upgrade
25d18413 690 blocks_get_default_blocks(SITEID, blocks_get_config_default()); // Add blockinfo to the site course
e02c35b2 691 delete_records('config', 'name', 'siteblocksadded');
692 }
693
0f3fe4b6 694 if (!empty($updated_blocks)) {
695 print_continue($continueto);
696 die;
697 }
698}
699
700//This function returns the number of courses currently using the block
701function blocks_get_courses_using_block_by_id($blockid) {
702
703 $num = 0;
704
705 if ($courses = get_records("course")) {
706 foreach($courses as $course) {
707 $blocks = str_replace(":",",",$course->blockinfo);
708 $blocksarr = explode(",",$blocks);
709 if (block_find($blockid,$blocksarr,array())) {
710 $num++;
711 }
712 }
713 }
714
715 return $num;
716}
717
718//This function hides a block in all courses using it
719function blocks_update_every_block_by_id($blockid,$action) {
720
721 if ($courses = get_records("course")) {
722 foreach($courses as $course) {
723 //Calculate left and right blocks
724 $blocks = $course->blockinfo;
725 $delimpos = strpos($blocks, ':');
726
727 if($delimpos === false) {
728 // No ':' found, we have all left blocks
729 $leftblocks = explode(',', $blocks);
730 $rightblocks = array();
731 } else if($delimpos === 0) {
732 // ':' at start of string, we have all right blocks
733 $blocks = substr($blocks, 1);
734 $leftblocks = array();
735 $rightblocks = explode(',', $blocks);
736 }
737 else {
738 // Both left and right blocks
739 $leftpart = substr($blocks, 0, $delimpos);
740 $rightpart = substr($blocks, $delimpos + 1);
741 $leftblocks = explode(',', $leftpart);
742 $rightblocks = explode(',', $rightpart);
743 }
744
745 switch($action) {
746 case 'show':
747 $block = block_find($blockid, $leftblocks, $rightblocks);
748 if($block !== false) {
749 if($block->side == BLOCK_LEFT) {
750 $leftblocks[$block->position] = abs($leftblocks[$block->position]);
751 }
752 else {
753 $rightblocks[$block->position] = abs($rightblocks[$block->position]);
754 }
755 }
756 break;
757 case 'hide':
758 $block = block_find($blockid, $leftblocks, $rightblocks);
759 if($block !== false) {
760 if($block->side == BLOCK_LEFT) {
761 $leftblocks[$block->position] = -abs($leftblocks[$block->position]);
762 }
763 else {
764 $rightblocks[$block->position] = -abs($rightblocks[$block->position]);
765 }
766 }
767 break;
768 case 'delete':
769 $block = block_find($blockid, $leftblocks, $rightblocks);
770 if($block !== false) {
771 if($block->side == BLOCK_LEFT) {
772 unset($leftblocks[$block->position]);
773 }
774 else {
775 unset($rightblocks[$block->position]);
776 }
777 }
778 break;
779 }
780 $course->blockinfo = implode(',', $leftblocks).':'.implode(',',$rightblocks);
781 set_field('course', 'blockinfo', $course->blockinfo, 'id', $course->id);
782 }
783 }
784}
785
786// [pj] I didn't like the block_get_X_by_Y() functions because
787// we should be able to do without them with clever coding,
788// so I set out to see if they could be removed somehow.
789// Only block_get_default_blocks() depends on them, and that
790// one is used nowhere at the moment. So I 'm commenting
791// them out until a use IS found.
792// [el] Uncommented to be used in the installation process, when
793// inserting new courses and when restoring courses. Perhaps
794// they can be modified, but previously related processes
795// will use them since now.
796
797//This function returns the id of the block, searching it by name
798function block_get_id_by_name ($blockname) {
799
800 if ($block = get_record("blocks","name",$blockname)) {
801 return $block->id;
802 } else {
803 return 0;
804 }
805}
806
807//This function returns the name of the block, searching it by id
808function block_get_name_by_id ($blockid) {
809
810 if ($block = get_record("blocks","id",$blockid)) {
811 return $block->name;
812 } else {
813 return NULL;
814 }
815}
816
817//This function return the necessary contents to update course->blockinfo
818//with default values. It accepts a list of block_names as parameter. They
819//will be converted to their blockids equivalent. If a course is specified
820//then the function will update the field too!
821
e02c35b2 822function blocks_get_default_blocks ($courseid = NULL, $blocknames = '') {
89adb174 823
a7b44978 824 global $CFG;
825
826 if (empty($blocknames)) {
25d18413 827 if (!empty($CFG->defaultblocks_override)) {
828 $blocknames = $CFG->defaultblocks_override;
a7b44978 829 } else {
25d18413 830 $blocknames = $CFG->defaultblocks;
a7b44978 831 }
832 }
0f3fe4b6 833
834 //Calculate left and right blocks
835 $blocksn = $blocknames;
836 $delimpos = strpos($blocksn, ':');
837
838 if($delimpos === false) {
839 // No ':' found, we have all left blocks
840 $leftblocksn = explode(',', $blocksn);
841 $rightblocksn = array();
842 } else if($delimpos === 0) {
843 // ':' at start of string, we have all right blocks
844 $blocksn = substr($blocksn, 1);
845 $leftblocksn = array();
846 $rightblocksn = explode(',', $blocksn);
847 }
848 else {
849 // Both left and right blocks
850 $leftpartn = substr($blocksn, 0, $delimpos);
851 $rightpartn = substr($blocksn, $delimpos + 1);
852 $leftblocksn = explode(',', $leftpartn);
853 $rightblocksn = explode(',', $rightpartn);
854 }
855
856 //Now I have blocks separated
857
858 $leftblocks = array();
859 $rightblocks = array();
860
861 if ($leftblocksn) {
862 foreach($leftblocksn as $leftblockn) {
863 //Convert blockname to id
229f852a 864 $leftblock = block_get_id_by_name(str_replace("-","",$leftblockn));
0f3fe4b6 865 if ($leftblock) {
866 //Check it's visible
867 if($block = get_record("blocks","id",$leftblock,"visible","1")) {
229f852a 868 //Check if the module was hidden at course level
869 if (substr($leftblockn,0,1) == "-") {
870 $leftblocks[] = -$leftblock;
871 } else {
872 $leftblocks[] = $leftblock;
873 }
0f3fe4b6 874 }
875 }
876 }
877 }
878
879 if ($rightblocksn) {
880 foreach($rightblocksn as $rightblockn) {
881 //Convert blockname to id
229f852a 882 $rightblock = block_get_id_by_name(str_replace("-","",$rightblockn));
0f3fe4b6 883 if ($rightblock) {
884 //Check it's visible
885 if($block = get_record("blocks","id",$rightblock,"visible","1")) {
229f852a 886 //Check if the module was hidden at course level
887 if (substr($rightblockn,0,1) == "-") {
888 $rightblocks[] = -$rightblock;
889 } else {
890 $rightblocks[] = $rightblock;
891 }
0f3fe4b6 892 }
893 }
894 }
895 }
896
897 //Calculate the blockinfo field
898 if ($leftblocks || $rightblocks) {
899 $blockinfo = '';
900 if ($leftblocks) {
901 $blockinfo .= implode(",", $leftblocks);
902 }
903 if ($rightblocks) {
904 $blockinfo .= ':'.implode(",",$rightblocks);
905 }
906 } else {
907 $blockinfo = '';
908 }
909
910 //If a course has been specified, update it
911 if ($courseid) {
912 set_field('course', "blockinfo", $blockinfo, "id", $courseid);
913 }
914
915 //Returns the blockinfo
916 return $blockinfo;
917}
918
25d18413 919// This function returns the appropriate block default configuration string
920// according to the $format argument. It will return the site override defined
921// in the site config, a format override defined in the site config, a specific
922// config defined in the course format config, or the site default.
923// To request the site format, leave $format blank.
924function blocks_get_config_default ($cformat='') {
925
926 global $CFG;
927
928 /// If the site override has been defined, it is the only valid one.
929 if (!empty($CFG->defaultblocks_override)) {
930 return $CFG->defaultblocks_override;
931 }
932 /// If not format is specified, return the site default.
3d90760a 933 else if ($cformat == '' || $cformat == 'site') {
25d18413 934 if (!empty($CFG->defaultblocks_site)) {
935 return $CFG->defaultblocks_site;
936 }
658724df 937 /// Failsafe - in case nothing was defined.
25d18413 938 else {
658724df 939 return 'site_main_menu,admin,course_list:course_summary,calendar_month';
25d18413 940 }
941 }
942 /// Return the appropriate block string for the format.
943 else if (!empty($CFG->{'defaultblocks_'.$cformat})) {
944 return $CFG->{'defaultblocks_'.$cformat};
945 }
946 else {
947 $format_config = $CFG->dirroot.'/course/format/'.$cformat.'/config.php';
eceb9c5c 948 if (@is_file($format_config) && is_readable($format_config)) {
25d18413 949 require($format_config);
950 }
951 if (!empty($format['defaultblocks'])) {
952 return $format['defaultblocks'];
953 }
658724df 954 else if (!empty($CFG->defaultblocks)){
25d18413 955 return $CFG->defaultblocks;
956 }
658724df 957 /// Failsafe - in case nothing was defined.
958 else {
959 return 'participants,activity_modules,search_forums,admin,course_list:news_items,calendar_upcoming,recent_activity';
960 }
25d18413 961 }
962}
963
229f852a 964//This function will return the names representation of the blockinfo field.
965//It's used to include that info in backups. To restore we'll use the
966//blocks_get_block_ids() function. It makes the opposite conversion
967//(from names to ids)
968function blocks_get_block_names ($blockinfo) {
969
970 //Calculate left and right blocks
971 $blocksn = $blockinfo;
972 $delimpos = strpos($blocksn, ':');
973
974 if($delimpos === false) {
975 // No ':' found, we have all left blocks
976 $leftblocksn = explode(',', $blocksn);
977 $rightblocksn = array();
978 } else if($delimpos === 0) {
979 // ':' at start of string, we have all right blocks
980 $blocksn = substr($blocksn, 1);
981 $leftblocksn = array();
982 $rightblocksn = explode(',', $blocksn);
983 }
984 else {
985 // Both left and right blocks
986 $leftpartn = substr($blocksn, 0, $delimpos);
987 $rightpartn = substr($blocksn, $delimpos + 1);
988 $leftblocksn = explode(',', $leftpartn);
989 $rightblocksn = explode(',', $rightpartn);
990 }
991
992 //Now I have blocks separated
993
994 $leftblocks = array();
995 $rightblocks = array();
996
997 if ($leftblocksn) {
998 foreach($leftblocksn as $leftblockn) {
999 //Convert id to blockname
1000 $leftblock = block_get_name_by_id(abs($leftblockn));
1001 if ($leftblock) {
1002 //Check it's visible
1003 if($block = get_record("blocks","name",$leftblock,"visible","1")) {
1004 //Check if it's hidden oe no in the course
1005 if($leftblockn<0) {
1006 $leftblocks[] = '-'.$leftblock;
1007 } else {
1008 $leftblocks[] = $leftblock;
1009 }
1010 }
1011 }
1012 }
1013 }
1014
1015 if ($rightblocksn) {
1016 foreach($rightblocksn as $rightblockn) {
1017 //Convert id to blockname
1018 $rightblock = block_get_name_by_id(abs($rightblockn));
1019 if ($rightblock) {
1020 //Check it's visible
1021 if($block = get_record("blocks","name",$rightblock,"visible","1")) {
1022 //Check if it's hidden oe no in the course
1023 if($rightblockn<0) {
1024 $rightblocks[] = '-'.$rightblock;
1025 } else {
1026 $rightblocks[] = $rightblock;
1027 }
1028 }
1029 }
1030 }
1031 }
1032
1033 //Calculate the blockinfo field
1034 if ($leftblocks || $rightblocks) {
1035 $blockinfo = '';
1036 if ($leftblocks) {
1037 $blockinfo .= implode(",", $leftblocks);
1038 }
1039 if ($rightblocks) {
1040 $blockinfo .= ':'.implode(",",$rightblocks);
1041 }
1042 } else {
1043 $blockinfo = '';
1044 }
1045
1046 //Returns the blockinfo
1047 return $blockinfo;
1048}
1049
1050//This function will return the ids representation of the blockinfo field.
1051//It's used to load that info from backups. This function is the opposite
1052//to the blocks_get_block_names() used in backup
1053function blocks_get_block_ids ($blockinfo) {
1054
1055 //Just call this with the appropiate parammeters.
1056 return blocks_get_default_blocks(NULL,$blockinfo);
1057}
0784eb7e 1058
1059// This is used to register the blocks that are displayed in the course page.
0c9c6363 1060// Set in course/view.php or /index.php, and read from any other place.
0784eb7e 1061function blocks_used($blocks = NULL, $records = NULL) {
1062 static $used = NULL;
1063
1064 if(!empty($blocks) && !empty($records)) {
1065 $used = array();
1066 foreach($blocks as $val) {
1067 if($val > 0 && isset($records[$val])) {
1068 $used[] = $records[$val]->name;
1069 }
1070 }
1071 }
1072
1073 return $used;
1074}
1075
0f3fe4b6 1076?>