|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00026 00027 00031 define('BLOCK_TYPE_LIST', 1); 00032 00036 define('BLOCK_TYPE_TEXT', 2); 00040 define('BLOCK_TYPE_TREE', 3); 00041 00048 class block_base { 00049 00054 var $str; 00055 00060 var $title = NULL; 00061 00066 var $content_type = BLOCK_TYPE_TEXT; 00067 00072 var $content = NULL; 00073 00078 var $edit_controls = NULL; 00079 00084 var $instance = NULL; 00085 00090 public $page = NULL; 00091 00096 public $context = NULL; 00097 00102 var $config = NULL; 00103 00109 var $cron = NULL; 00110 00112 00117 function __construct() { 00118 $this->init(); 00119 } 00120 00125 function before_delete() { 00126 } 00127 00134 function name() { 00135 // Returns the block name, as present in the class name, 00136 // the database, the block directory, etc etc. 00137 static $myname; 00138 if ($myname === NULL) { 00139 $myname = strtolower(get_class($this)); 00140 $myname = substr($myname, strpos($myname, '_') + 1); 00141 } 00142 return $myname; 00143 } 00144 00152 function get_content() { 00153 // This should be implemented by the derived class. 00154 return NULL; 00155 } 00156 00165 function get_title() { 00166 // Intentionally doesn't check if a title is set. This is already done in _self_test() 00167 return $this->title; 00168 } 00169 00178 function get_content_type() { 00179 // Intentionally doesn't check if a content_type is set. This is already done in _self_test() 00180 return $this->content_type; 00181 } 00182 00189 function is_empty() { 00190 if ( !has_capability('moodle/block:view', $this->context) ) { 00191 return true; 00192 } 00193 00194 $this->get_content(); 00195 return(empty($this->content->text) && empty($this->content->footer)); 00196 } 00197 00205 function refresh_content() { 00206 // Nothing special here, depends on content() 00207 $this->content = NULL; 00208 return $this->get_content(); 00209 } 00210 00223 public function get_content_for_output($output) { 00224 global $CFG; 00225 00226 $bc = new block_contents($this->html_attributes()); 00227 00228 $bc->blockinstanceid = $this->instance->id; 00229 $bc->blockpositionid = $this->instance->blockpositionid; 00230 00231 if ($this->instance->visible) { 00232 $bc->content = $this->formatted_contents($output); 00233 if (!empty($this->content->footer)) { 00234 $bc->footer = $this->content->footer; 00235 } 00236 } else { 00237 $bc->add_class('invisible'); 00238 } 00239 00240 if (!$this->hide_header()) { 00241 $bc->title = $this->title; 00242 } 00243 00244 if ($this->page->user_is_editing()) { 00245 $bc->controls = $this->page->blocks->edit_controls($this); 00246 } else { 00247 // we must not use is_empty on hidden blocks 00248 if ($this->is_empty() && !$bc->controls) { 00249 return null; 00250 } 00251 } 00252 00253 if (empty($CFG->allowuserblockhiding) || 00254 (empty($bc->content) && empty($bc->footer))) { 00255 $bc->collapsible = block_contents::NOT_HIDEABLE; 00256 } else if (get_user_preferences('block' . $bc->blockinstanceid . 'hidden', false)) { 00257 $bc->collapsible = block_contents::HIDDEN; 00258 } else { 00259 $bc->collapsible = block_contents::VISIBLE; 00260 } 00261 00262 $bc->annotation = ''; // TODO MDL-19398 need to work out what to say here. 00263 00264 return $bc; 00265 } 00266 00279 protected function formatted_contents($output) { 00280 $this->get_content(); 00281 $this->get_required_javascript(); 00282 if (!empty($this->content->text)) { 00283 return $this->content->text; 00284 } else { 00285 return ''; 00286 } 00287 } 00288 00296 function _self_test() { 00297 // Tests if this block has been implemented correctly. 00298 // Also, $errors isn't used right now 00299 $errors = array(); 00300 00301 $correct = true; 00302 if ($this->get_title() === NULL) { 00303 $errors[] = 'title_not_set'; 00304 $correct = false; 00305 } 00306 if (!in_array($this->get_content_type(), array(BLOCK_TYPE_LIST, BLOCK_TYPE_TEXT, BLOCK_TYPE_TREE))) { 00307 $errors[] = 'invalid_content_type'; 00308 $correct = false; 00309 } 00310 //following selftest was not working when roles&capabilities were used from block 00311 /* if ($this->get_content() === NULL) { 00312 $errors[] = 'content_not_set'; 00313 $correct = false; 00314 }*/ 00315 $formats = $this->applicable_formats(); 00316 if (empty($formats) || array_sum($formats) === 0) { 00317 $errors[] = 'no_formats'; 00318 $correct = false; 00319 } 00320 00321 $width = $this->preferred_width(); 00322 if (!is_int($width) || $width <= 0) { 00323 $errors[] = 'invalid_width'; 00324 $correct = false; 00325 } 00326 return $correct; 00327 } 00328 00335 function has_config() { 00336 return false; 00337 } 00338 00346 function config_save($data) { 00347 foreach ($data as $name => $value) { 00348 set_config($name, $value); 00349 } 00350 return true; 00351 } 00352 00364 function applicable_formats() { 00365 // Default case: the block can be used in courses and site index, but not in activities 00366 return array('all' => true, 'mod' => false, 'tag' => false); 00367 } 00368 00369 00374 function hide_header() { 00375 return false; 00376 } 00377 00397 function html_attributes() { 00398 $attributes = array( 00399 'id' => 'inst' . $this->instance->id, 00400 'class' => 'block_' . $this->name(). ' block' 00401 ); 00402 if ($this->instance_can_be_docked() && get_user_preferences('docked_block_instance_'.$this->instance->id, 0)) { 00403 $attributes['class'] .= ' dock_on_load'; 00404 } 00405 return $attributes; 00406 } 00407 00415 function _load_instance($instance, $page) { 00416 if (!empty($instance->configdata)) { 00417 $this->config = unserialize(base64_decode($instance->configdata)); 00418 } 00419 $this->instance = $instance; 00420 $this->context = get_context_instance(CONTEXT_BLOCK, $instance->id); 00421 $this->page = $page; 00422 $this->specialization(); 00423 } 00424 00425 function get_required_javascript() { 00426 if ($this->instance_can_be_docked() && !$this->hide_header()) { 00427 $this->page->requires->js_init_call('M.core_dock.init_genericblock', array($this->instance->id)); 00428 user_preference_allow_ajax_update('docked_block_instance_'.$this->instance->id, PARAM_INT); 00429 } 00430 } 00431 00437 function specialization() { 00438 // Just to make sure that this method exists. 00439 } 00440 00450 function instance_allow_config() { 00451 return false; 00452 } 00453 00459 function instance_allow_multiple() { 00460 // Are you going to allow multiple instances of each block? 00461 // If yes, then it is assumed that the block WILL USE per-instance configuration 00462 return false; 00463 } 00464 00472 function instance_config_print() { 00473 global $CFG, $DB, $OUTPUT; 00474 // Default behavior: print the config_instance.html file 00475 // You don't need to override this if you're satisfied with the above 00476 if (!$this->instance_allow_multiple() && !$this->instance_allow_config()) { 00477 return false; 00478 } 00479 00480 if (is_file($CFG->dirroot .'/blocks/'. $this->name() .'/config_instance.html')) { 00481 echo $OUTPUT->box_start('generalbox boxaligncenter blockconfiginstance'); 00482 include($CFG->dirroot .'/blocks/'. $this->name() .'/config_instance.html'); 00483 echo $OUTPUT->box_end(); 00484 } else { 00485 notice(get_string('blockconfigbad'), str_replace('blockaction=', 'dummy=', qualified_me())); 00486 } 00487 00488 return true; 00489 } 00490 00494 function instance_config_save($data, $nolongerused = false) { 00495 global $DB; 00496 $DB->set_field('block_instances', 'configdata', base64_encode(serialize($data)), 00497 array('id' => $this->instance->id)); 00498 } 00499 00503 function instance_config_commit($nolongerused = false) { 00504 global $DB; 00505 $this->instance_config_save($this->config); 00506 } 00507 00512 function instance_create() { 00513 return true; 00514 } 00515 00520 function instance_delete() { 00521 return true; 00522 } 00523 00530 function user_can_edit() { 00531 global $USER; 00532 00533 if (has_capability('moodle/block:edit', $this->context)) { 00534 return true; 00535 } 00536 00537 // The blocks in My Moodle are a special case. We want them to inherit from the user context. 00538 if (!empty($USER->id) 00539 && $this->instance->parentcontextid == $this->page->context->id // Block belongs to this page 00540 && $this->page->context->contextlevel == CONTEXT_USER // Page belongs to a user 00541 && $this->page->context->instanceid == $USER->id) { // Page belongs to this user 00542 return has_capability('moodle/my:manageblocks', $this->page->context); 00543 } 00544 00545 return false; 00546 } 00547 00557 function user_can_addto($page) { 00558 global $USER; 00559 00560 if (has_capability('moodle/block:edit', $page->context)) { 00561 return true; 00562 } 00563 00564 // The blocks in My Moodle are a special case and use a different capability. 00565 if (!empty($USER->id) 00566 && $page->context->contextlevel == CONTEXT_USER // Page belongs to a user 00567 && $page->context->instanceid == $USER->id) { // Page belongs to this user 00568 return has_capability('moodle/my:manageblocks', $page->context); 00569 } 00570 00571 return false; 00572 } 00573 00574 function get_extra_capabilities() { 00575 return array('moodle/block:view', 'moodle/block:edit'); 00576 } 00577 00578 // Methods deprecated in Moodle 2.0 ======================================== 00579 00585 function preferred_width() { 00586 return 180; 00587 } 00588 00590 function _print_block() { 00591 throw new coding_exception('_print_block is no longer used. It was a private ' . 00592 'method of the block class, only for use by the blocks system. You ' . 00593 'should not have been calling it anyway.'); 00594 } 00595 00597 function _print_shadow() { 00598 throw new coding_exception('_print_shadow is no longer used. It was a private ' . 00599 'method of the block class, only for use by the blocks system. You ' . 00600 'should not have been calling it anyway.'); 00601 } 00602 00604 function _title_html() { 00605 throw new coding_exception('_title_html is no longer used. It was a private ' . 00606 'method of the block class, only for use by the blocks system. You ' . 00607 'should not have been calling it anyway.'); 00608 } 00609 00611 function _add_edit_controls() { 00612 throw new coding_exception('_add_edit_controls is no longer used. It was a private ' . 00613 'method of the block class, only for use by the blocks system. You ' . 00614 'should not have been calling it anyway.'); 00615 } 00616 00618 function config_print() { 00619 throw new coding_exception('config_print() can no longer be used. Blocks should use a settings.php file.'); 00620 } 00621 00627 public function instance_can_be_docked() { 00628 global $CFG; 00629 return (!empty($CFG->allowblockstodock) && $this->page->theme->enable_dock); 00630 } 00631 00638 public function instance_can_be_hidden() { 00639 return true; 00640 } 00641 00643 public static function comment_template($options) { 00644 $ret = <<<EOD 00645 <div class="comment-userpicture">___picture___</div> 00646 <div class="comment-content"> 00647 ___name___ - <span>___time___</span> 00648 <div>___content___</div> 00649 </div> 00650 EOD; 00651 return $ret; 00652 } 00653 public static function comment_permissions($options) { 00654 return array('view'=>true, 'post'=>true); 00655 } 00656 public static function comment_url($options) { 00657 return null; 00658 } 00659 public static function comment_display($comments, $options) { 00660 return $comments; 00661 } 00662 public static function comment_add(&$comments, $options) { 00663 return true; 00664 } 00665 } 00666 00677 class block_list extends block_base { 00678 var $content_type = BLOCK_TYPE_LIST; 00679 00680 function is_empty() { 00681 if ( !has_capability('moodle/block:view', $this->context) ) { 00682 return true; 00683 } 00684 00685 $this->get_content(); 00686 return (empty($this->content->items) && empty($this->content->footer)); 00687 } 00688 00689 protected function formatted_contents($output) { 00690 $this->get_content(); 00691 $this->get_required_javascript(); 00692 if (!empty($this->content->items)) { 00693 return $output->list_block_contents($this->content->icons, $this->content->items); 00694 } else { 00695 return ''; 00696 } 00697 } 00698 00699 function html_attributes() { 00700 $attributes = parent::html_attributes(); 00701 $attributes['class'] .= ' list_block'; 00702 return $attributes; 00703 } 00704 00705 } 00706 00723 class block_tree extends block_list { 00724 00730 public $content_type = BLOCK_TYPE_TREE; 00731 00740 protected function formatted_contents($output) { 00741 // based of code in admin_tree 00742 global $PAGE; // TODO change this when there is a proper way for blocks to get stuff into head. 00743 static $eventattached; 00744 if ($eventattached===null) { 00745 $eventattached = true; 00746 } 00747 if (!$this->content) { 00748 $this->content = new stdClass; 00749 $this->content->items = array(); 00750 } 00751 $this->get_required_javascript(); 00752 $this->get_content(); 00753 $content = $output->tree_block_contents($this->content->items,array('class'=>'block_tree list')); 00754 if (isset($this->id) && !is_numeric($this->id)) { 00755 $content = $output->box($content, 'block_tree_box', $this->id); 00756 } 00757 return $content; 00758 } 00759 }