content->items). Optionally include footer text in $this->content->footer. */ define('BLOCK_TYPE_LIST', 1); /** * 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. */ define('BLOCK_TYPE_TEXT', 2); /** * Block type of nuke. Compitibility with post nuke blocks. Basically treated as BLOCK_TYPE_TEXT. */ define('BLOCK_TYPE_NUKE', 3); /** * Class for describing a moodle block, all Moodle blocks derive from this class * * @author Jon Papaioannou * @package blocks */ class block_base { /** * Internal var for storing/caching translated strings * @var string $str */ var $str; /** * The title of the block to be displayed in the block title area. * @var string $title */ var $title = NULL; /** * The type of content that this block creates. Currently support options - BLOCK_TYPE_LIST, BLOCK_TYPE_TEXT, BLOCK_TYPE_NUKE * @var int $content_type */ var $content_type = NULL; /** * An object to contain the information to be displayed in the block. * @var stdObject $content */ var $content = NULL; /** * A string generated by {@link _add_edit_controls()} to display block manipulation links when the user is in editing mode. * @var string $edit_controls */ var $edit_controls = NULL; /** * The current version that the block type defines. * @var string $version */ var $version = NULL; /** * The initialized instance of this block object. * @var block $instance */ var $instance = NULL; /** * An object containing the instance configuration information for the current instance of this block. * @var stdObject $config */ var $config = NULL; /// Class Functions /** * The class constructor * */ function block_base() { $this->init(); } /** * Fake constructor to keep PHP5 happy * */ function __construct() { $this->block_base(); } /** * Returns the block name, as present in the class name, * the database, the block directory, etc etc. * * @return string */ function name() { // Returns the block name, as present in the class name, // the database, the block directory, etc etc. static $myname; if ($myname === NULL) { $myname = strtolower(get_class($this)); $myname = substr($myname, strpos($myname, '_') + 1); } return $myname; } /** * Parent class version of this function simply returns NULL * This should be implemented by the derived class to return * the content object. * * @return stdObject */ function get_content() { // This should be implemented by the derived class. return NULL; } /** * Returns the class $title var value. * * Intentionally doesn't check if a title is set. * This is already done in {@link _self_test()} * * @return string $this->title */ function get_title() { // Intentionally doesn't check if a title is set. This is already done in _self_test() return $this->title; } /** * Returns the class $content_type var value. * * Intentionally doesn't check if content_type is set. * This is already done in {@link _self_test()} * * @return string $this->content_type */ function get_content_type() { // Intentionally doesn't check if a content_type is set. This is already done in _self_test() return $this->content_type; } /** * Returns the class $version var value. * * Intentionally doesn't check if a version is set. * This is already done in {@link _self_test()} * * @return string $this->version */ function get_version() { // Intentionally doesn't check if a version is set. This is already done in _self_test() return $this->version; } /** * First sets the current value of $this->content to NULL * then calls the block's {@link get_content()} function * to set its value back. * * @return stdObject */ function refresh_content() { // Nothing special here, depends on content() $this->content = NULL; return $this->get_content(); } /** * Display the block! */ function _print_block() { // Wrap the title in a floating DIV, in case we have edit controls to display // These controls will always be wrapped on a right-floating DIV $title = '
'.$this->title.'
'; if ($this->edit_controls !== NULL) { $title .= $this->edit_controls; } $this->get_content(); if (!isset($this->content->footer)) { $this->content->footer = ''; } switch($this->content_type) { case BLOCK_TYPE_NUKE: case BLOCK_TYPE_TEXT: if (empty($this->content->text) && empty($this->content->footer)) { if (empty($this->edit_controls)) { // No content, no edit controls, so just shut up break; } else { // No content but editing, so show something at least $this->_print_shadow(); } } else { if ($this->hide_header() && empty($this->edit_controls)) { // Header wants to hide, no edit controls to show, so no header it is print_side_block(NULL, $this->content->text, NULL, NULL, $this->content->footer, $this->html_attributes()); } else { // The full treatment, please print_side_block($title, $this->content->text, NULL, NULL, $this->content->footer, $this->html_attributes()); } } break; case BLOCK_TYPE_LIST: if (empty($this->content->items) && empty($this->content->footer)) { if (empty($this->edit_controls)) { // No content, no edit controls, so just shut up break; } else { // No content but editing, so show something at least $this->_print_shadow(); } } else { if ($this->hide_header() && empty($this->edit_controls)) { // Header wants to hide, no edit controls to show, so no header it is print_side_block(NULL, '', $this->content->items, $this->content->icons, $this->content->footer, $this->html_attributes()); } else { // The full treatment, please print_side_block($title, '', $this->content->items, $this->content->icons, $this->content->footer, $this->html_attributes()); } } break; } } /** * Block contents are missing. Simply display an empty block so that * edit controls are accessbile to the user and they are aware that this * block is in place, even if empty. */ function _print_shadow() { $title = '
'.$this->title.'
'; if ($this->edit_controls !== NULL) { $title .= $this->edit_controls; } print_side_block($title, ' ', NULL, NULL, ''); } /** * Sets class $edit_controls var with correct block manipulation links. * * @uses $CFG * @uses $USER * @param stdObject $options ? * @todo complete documenting this function. Define $options. */ function _add_edit_controls($options) { global $CFG, $USER; if (!isset($this->str)) { $this->str->delete = get_string('delete'); $this->str->moveup = get_string('moveup'); $this->str->movedown = get_string('movedown'); $this->str->moveright = get_string('moveright'); $this->str->moveleft = get_string('moveleft'); $this->str->hide = get_string('hide'); $this->str->show = get_string('show'); $this->str->configure = get_string('configuration'); } $movebuttons = '
'; if ($this->instance->visible) { $icon = '/t/hide.gif'; $title = $this->str->hide; } else { $icon = '/t/show.gif'; $title = $this->str->show; } $page = page_create_object($this->instance->pagetype, $this->instance->pageid); $script = $page->url_get_full(array('instanceid' => $this->instance->id, 'sesskey' => $USER->sesskey)); $movebuttons .= '' . ''.$title.''; if ($options & BLOCK_CONFIGURE) { $movebuttons .= '' . ''. $this->str->configure .''; } $movebuttons .= '' . ''. $this->str->delete .' '; if ($options & BLOCK_MOVE_LEFT) { $movebuttons .= '' . ''. $this->str->moveleft .''; } if ($options & BLOCK_MOVE_UP) { $movebuttons .= '' . ''. $this->str->moveup .''; } if ($options & BLOCK_MOVE_DOWN) { $movebuttons .= '' . ''. $this->str->movedown .''; } if ($options & BLOCK_MOVE_RIGHT) { $movebuttons .= '' . ''. $this->str->moveright .''; } $movebuttons .= '
'; $this->edit_controls = $movebuttons; } /** * Tests if this block has been implemented correctly. * Also, $errors isn't used right now * * @return boolean */ function _self_test() { // Tests if this block has been implemented correctly. // Also, $errors isn't used right now $errors = array(); $correct = true; if ($this->get_title() === NULL) { $errors[] = 'title_not_set'; $correct = false; } if (!in_array($this->get_content_type(), array(BLOCK_TYPE_LIST, BLOCK_TYPE_TEXT, BLOCK_TYPE_NUKE))) { $errors[] = 'invalid_content_type'; $correct = false; } if ($this->get_content() === NULL) { $errors[] = 'content_not_set'; $correct = false; } if ($this->get_version() === NULL) { $errors[] = 'version_not_set'; $correct = false; } $formats = $this->applicable_formats(); if (empty($formats) || array_sum($formats) === 0) { $errors[] = 'no_course_formats'; $correct = false; } $width = $this->preferred_width(); if (!is_int($width) || $width <= 0) { $errors[] = 'invalid_width'; $correct = false; } return $correct; } /** * Subclasses should override this and return true if the * subclass block has a config_global.html file. * * @return boolean */ function has_config() { return false; } /** * Default behavior: print the config_global.html file * You don't need to override this if you're satisfied with the above * * @uses $CFG * @return boolean */ function config_print() { // Default behavior: print the config_global.html file // You don't need to override this if you're satisfied with the above if (!$this->has_config()) { return false; } global $CFG; print_simple_box_start('center', '', '', 5, 'blockconfigglobal'); include($CFG->dirroot.'/blocks/'. $this->name() .'/config_global.html'); print_simple_box_end(); return true; } /** * Default behavior: save all variables as $CFG properties * You don't need to override this if you 're satisfied with the above * * @param array $data * @return boolean */ function config_save($data) { // Default behavior: save all variables as $CFG properties // You don't need to override this if you 're satisfied with the above foreach ($data as $name => $value) { set_config($name, $value); } return true; } /** * Default case: the block can be used in all course types * @return array * @todo finish documenting this function */ function applicable_formats() { // Default case: the block can be used in all course types and not in quizzes return array('all' => true, 'quiz' => false); } /** * Default case: the block wants to be 180 pixels wide * @return int */ function preferred_width() { // Default case: the block wants to be 180 pixels wide return 180; } /** * Default return is false - header will be shown * @return boolean */ function hide_header() { //Default, false--> the header is shown return false; } /** * Default case: just an id for the block, with our name in it * @return array * @todo finish documenting this function */ function html_attributes() { // Default case: just an id for the block, with our name in it return array('id' => 'block_'. $this->name()); } /** * Given an instance set the class var $instance to it and * load class var $config * @param block $instance * @todo add additional documentation to further explain the format of instance and config */ function _load_instance($instance) { if (!empty($instance->configdata)) { $this->config = unserialize(base64_decode($instance->configdata)); } // [pj] This line below is supposed to be an optimization (we don't need configdata anymore) // but what it does is break in PHP5 because the same instance object will be passed to // this function twice in each page view, and the second time it won't have any configdata // so it won't work correctly. Thus it's commented out. // unset($instance->configdata); $this->instance = $instance; $this->specialization(); } /** * This function is called on your subclass right after an instance is loaded * Use this function to act on instance data just after it's loaded and before anything else is done * For instance: if your block will have different title's depending on location (site, course, blog, etc) */ function specialization() { // Just to make sure that this method exists. } /** * Is each block of this type going to have instance-specific configuration? * Normally, this setting is controlled by {@link instance_allow_multiple}: if multiple * instances are allowed, then each will surely need its own configuration. However, in some * cases it may be necessary to provide instance configuration to blocks that do not want to * allow multiple instances. In that case, make this function return true. * I stress again that this makes a difference ONLY if {@link instance_allow_multiple} returns false. * @return boolean * @todo finish documenting this function by explaining per-instance configuration further */ function instance_allow_config() { return false; } /** * Are you going to allow multiple instances of each block? * If yes, then it is assumed that the block WILL USE per-instance configuration * @return boolean * @todo finish documenting this function by explaining per-instance configuration further */ function instance_allow_multiple() { // Are you going to allow multiple instances of each block? // If yes, then it is assumed that the block WILL USE per-instance configuration return false; } /** * Default behavior: print the config_instance.html file * You don't need to override this if you're satisfied with the above * * @uses $CFG * @return boolean * @todo finish documenting this function */ function instance_config_print() { // Default behavior: print the config_instance.html file // You don't need to override this if you're satisfied with the above if (!$this->instance_allow_multiple() && !$this->instance_allow_config()) { return false; } global $CFG; if (is_file($CFG->dirroot .'/blocks/'. $this->name() .'/config_instance.html')) { print_simple_box_start('center', '', '', 5, 'blockconfiginstance'); include($CFG->dirroot .'/blocks/'. $this->name() .'/config_instance.html'); print_simple_box_end(); } else { notice(get_string('blockconfigbad'), str_replace('blockaction=', 'dummy=', qualified_me())); } return true; } /** * Serialize and store config data * @return boolean * @todo finish documenting this function */ function instance_config_save($data) { $data = stripslashes_recursive($data); $this->config = $data; return set_field('block_instance', 'configdata', base64_encode(serialize($data)), 'id', $this->instance->id); } /** * Replace the instance's configuration data with those currently in $this->config; * @return boolean * @todo finish documenting this function */ function instance_config_commit() { return set_field('block_instance', 'configdata', base64_encode(serialize($this->config)), 'id', $this->instance->id); } } /** * Class for supporting a postnuke style block as a moodle block * * @author Jon Papaioannou * @package blocks */ class block_nuke extends block_base { function get_content() { if ($this->content !== NULL) { return $this->content; } global $CFG; $this->content = &New stdClass; // This whole thing begs to be written for PHP >= 4.3.0 using glob(); $dir = $CFG->dirroot .'/blocks/'. $this->name() .'/nuke/'; if ($dh = @opendir($dir)) { while (($file = readdir($dh)) !== false) { $regs = array(); if (ereg('^block\-(.*)\.php$', $file, $regs)) { // Found it! Let's prepare the environment... $oldvals = array(); if (isset($GLOBALS['admin'])) { $oldvals['admin'] = $GLOBALS['admin']; } $GLOBALS['admin'] = isteacher($this->course->id); @include($dir.$file); foreach($oldvals as $key => $val) { $GLOBALS[$key] = $val; } // We should have $content set now if (!isset($content)) { return NULL; } return $this->content->text = $content; } } } // If we reached here, we couldn't find the nuke block for some reason return $this->content->text = get_string('blockmissingnuke'); } } ?>