polished.
[moodle.git] / blocks / moodleblock.class.php
CommitLineData
56e29ea0 1<?php // $Id$
0f3fe4b6 2
3define('BLOCK_TYPE_LIST', 1);
4define('BLOCK_TYPE_TEXT', 2);
828c4e09 5define('BLOCK_TYPE_NUKE', 3);
0f3fe4b6 6
7class MoodleBlock {
8 var $str;
9b4b78fd 9 var $title = NULL;
10 var $course = NULL;
11 var $content_type = NULL;
12 var $content = NULL;
0f3fe4b6 13 var $edit_controls = NULL;
9b4b78fd 14 var $version = NULL;
15 var $instance = NULL;
16 var $config = NULL;
17
18 function MoodleBlock() {
19 $this->init();
20 }
0f3fe4b6 21
22 function name() {
23 // Returns the block name, as present in the class name,
24 // the database, the block directory, etc etc.
25 static $myname;
26 if($myname === NULL) {
27 $myname = strtolower(get_class($this));
28 $myname = substr($myname, strpos($myname, '_') + 1);
29 }
30 return $myname;
31 }
32
33 function get_content() {
34 // This should be implemented by the derived class.
35 return NULL;
36 }
37 function get_title() {
6195e04a 38 // Intentionally doesn't check if a title is set. This is already done in _self_test()
0f3fe4b6 39 return $this->title;
40 }
41 function get_content_type() {
6195e04a 42 // Intentionally doesn't check if a content_type is set. This is already done in _self_test()
0f3fe4b6 43 return $this->content_type;
44 }
45 function get_version() {
6195e04a 46 // Intentionally doesn't check if a version is set. This is already done in _self_test()
0f3fe4b6 47 return $this->version;
48 }
49 function get_header() {
6195e04a 50 // Intentionally doesn't check if a header is set. This is already done in _self_test()
0f3fe4b6 51 return $this->header;
52 }
53 function refresh_content() {
54 // Nothing special here, depends on content()
55 $this->content = NULL;
56 return $this->get_content();
57 }
58 function print_block() {
ca319818 59 // Wrap the title in a floating DIV, in case we have edit controls to display
60 // These controls will always be wrapped on a right-floating DIV
0f3fe4b6 61 $title = '<div style="float: left;">'.$this->title.'</div>';
62 if($this->edit_controls !== NULL) {
63 $title .= $this->edit_controls;
64 }
ca319818 65
0f3fe4b6 66 $this->get_content();
4153708f 67 if(!isset($this->content->footer)) {
68 $this->content->footer = '';
69 }
0f3fe4b6 70
71 switch($this->content_type) {
828c4e09 72 case BLOCK_TYPE_NUKE:
0f3fe4b6 73 case BLOCK_TYPE_TEXT:
d7baedda 74 if(empty($this->content->text) && empty($this->content->footer)) {
22931cf4 75 if(empty($this->edit_controls)) {
76 // No content, no edit controls, so just shut up
77 break;
78 }
79 else {
80 // No content but editing, so show something at least
81 $this->print_shadow();
82 }
ca319818 83 }
22931cf4 84 else {
85 if($this->hide_header() && empty($this->edit_controls)) {
86 // Header wants to hide, no edit controls to show, so no header it is
87 print_side_block(NULL, $this->content->text, NULL, NULL, $this->content->footer, $this->html_attributes());
88 }
89 else {
90 // The full treatment, please
91 print_side_block($title, $this->content->text, NULL, NULL, $this->content->footer, $this->html_attributes());
92 }
0f3fe4b6 93 }
94 break;
95 case BLOCK_TYPE_LIST:
e48550e0 96 if(empty($this->content->items) && empty($this->content->footer)) {
22931cf4 97 if(empty($this->edit_controls)) {
98 // No content, no edit controls, so just shut up
99 break;
100 }
101 else {
102 // No content but editing, so show something at least
103 $this->print_shadow();
104 }
ca319818 105 }
22931cf4 106 else {
107 if($this->hide_header() && empty($this->edit_controls)) {
108 // Header wants to hide, no edit controls to show, so no header it is
109 print_side_block(NULL, '', $this->content->items, $this->content->icons, $this->content->footer, $this->html_attributes());
110 }
111 else {
112 // The full treatment, please
113 print_side_block($title, '', $this->content->items, $this->content->icons, $this->content->footer, $this->html_attributes());
114 }
0f3fe4b6 115 }
116 break;
117 }
118 }
119 function print_shadow() {
120 $title = '<div style="float: left;">'.$this->title.'</div>';
121 if($this->edit_controls !== NULL) {
122 $title .= $this->edit_controls;
123 }
124 print_side_block($title, '&nbsp;', NULL, NULL, '');
125 }
89adb174 126
9b4b78fd 127 function add_edit_controls($options) {
5b224948 128 global $CFG, $THEME, $USER;
0f3fe4b6 129
0f3fe4b6 130 if (!isset($this->str)) {
131 $this->str->delete = get_string('delete');
132 $this->str->moveup = get_string('moveup');
133 $this->str->movedown = get_string('movedown');
134 $this->str->moveright = get_string('moveright');
135 $this->str->moveleft = get_string('moveleft');
136 $this->str->hide = get_string('hide');
137 $this->str->show = get_string('show');
9b4b78fd 138 $this->str->configure = get_string('configuration');
0f3fe4b6 139 }
140
141 $path = $CFG->wwwroot.'/course';
142
143 if (empty($THEME->custompix)) {
144 $pixpath = $path.'/../pix';
145 } else {
146 $pixpath = $path.'/../theme/'.$CFG->theme.'/pix';
147 }
5b224948 148
149 $sesskeystr = '&amp;sesskey='.$USER->sesskey;
0f3fe4b6 150
151 $movebuttons = '<div style="float: right;">';
152
9b4b78fd 153 if($this->instance->visible) {
0f3fe4b6 154 $icon = '/t/hide.gif';
155 $title = $this->str->hide;
156 }
157 else {
158 $icon = '/t/show.gif';
159 $title = $this->str->show;
160 }
161
9b4b78fd 162 $page = new stdClass;
163 $page->id = $this->instance->pageid;
164 $page->type = $this->instance->pagetype;
165 $script = page_source_script($page);
166
59b29207 167 $movebuttons .= '<a style="margin-right: 6px; margin-left: 2px;" title="'. $title .'" href="'.$script.'&amp;blockaction=toggle&amp;instanceid='. $this->instance->id . $sesskeystr .'">' .
168 '<img src="'. $pixpath.$icon .'" alt=\"\" /></a>';
0f3fe4b6 169
9b4b78fd 170 if($options & BLOCK_CONFIGURE) {
59b29207 171 $movebuttons .= '<a style="margin-right: 6px; margin-left: 2px;" title="'. $this->str->configure .'" href="'. $script .'&amp;blockaction=config&amp;instanceid='. $this->instance->id.$sesskeystr .'">' .
172 '<img src="'. $pixpath .'/t/edit.gif" alt=\"\" /></a>';
9b4b78fd 173 }
174
59b29207 175 $movebuttons .= '<a style="margin-right: 2px; margin-left: 2px;" title="'. $this->str->delete .'" href="'. $script .'&amp;blockaction=delete&amp;instanceid='. $this->instance->id.$sesskeystr .'">' .
176 '<img src="'. $pixpath .'/t/delete.gif" alt=\"\" /></a> ';
0f3fe4b6 177
178 if ($options & BLOCK_MOVE_LEFT) {
59b29207 179 $movebuttons .= '<a style="margin-right: 2px; margin-left: 2px;" title="'. $this->str->moveleft .'" href="'. $script .'&amp;blockaction=moveleft&amp;instanceid='. $this->instance->id.$sesskeystr .'">' .
180 '<img src="'. $pixpath .'/t/left.gif" alt=\"\" /></a>';
0f3fe4b6 181 }
182 if ($options & BLOCK_MOVE_UP) {
59b29207 183 $movebuttons .= '<a style="margin-right: 2px; margin-left: 2px;" title="'. $this->str->moveup .'" href="'. $script .'&amp;blockaction=moveup&amp;instanceid='. $this->instance->id.$sesskeystr .'">' .
184 '<img src="'. $pixpath .'/t/up.gif" alt=\"\" /></a>';
0f3fe4b6 185 }
186 if ($options & BLOCK_MOVE_DOWN) {
59b29207 187 $movebuttons .= '<a style="margin-right: 2px; margin-left: 2px;" title="'. $this->str->movedown .'" href="'. $script .'&amp;blockaction=movedown&amp;instanceid='. $this->instance->id.$sesskeystr .'">' .
188 '<img src="'. $pixpath .'/t/down.gif" alt=\"\" /></a>';
0f3fe4b6 189 }
190 if ($options & BLOCK_MOVE_RIGHT) {
59b29207 191 $movebuttons .= '<a style="margin-right: 2px; margin-left: 2px;" title="'. $this->str->moveright .'" href="'. $script .'&amp;blockaction=moveright&amp;instanceid='. $this->instance->id.$sesskeystr .'">' .
192 '<img src="'. $pixpath .'/t/right.gif" alt=\"\" /></a>';
0f3fe4b6 193 }
194
195 $movebuttons .= '</div>';
196 $this->edit_controls = $movebuttons;
197 }
198
199 function _self_test() {
200 // Tests if this block has been implemented correctly.
201 // Also, $errors isn't used right now
202 $errors = array();
203
204 $correct = true;
205 if($this->get_title() === NULL) {
206 $errors[] = 'title_not_set';
207 $correct = false;
208 }
828c4e09 209 if(!in_array($this->get_content_type(), array(BLOCK_TYPE_LIST, BLOCK_TYPE_TEXT, BLOCK_TYPE_NUKE))) {
0f3fe4b6 210 $errors[] = 'invalid_content_type';
211 $correct = false;
212 }
213 if($this->get_content() === NULL) {
214 $errors[] = 'content_not_set';
215 $correct = false;
216 }
217 if($this->get_version() === NULL) {
218 $errors[] = 'version_not_set';
219 $correct = false;
220 }
2b0d60ec 221
222 $formats = $this->applicable_formats();
223 if(empty($formats) || array_sum($formats) === 0) {
0f3fe4b6 224 $errors[] = 'no_course_formats';
225 $correct = false;
226 }
2b0d60ec 227
0f3fe4b6 228 $width = $this->preferred_width();
229 if(!is_int($width) || $width <= 0) {
230 $errors[] = 'invalid_width';
231 $correct = false;
232 }
233 return $correct;
234 }
235
236 function has_config() {
237 return false;
238 }
239 function print_config() {
9b4b78fd 240 // Default behavior: print the config_global.html file
241 // You don't need to override this if you 're satisfied with the above
242 if(!$this->has_config()) {
243 return false;
244 }
245 global $CFG, $USER, $THEME;
246 print_simple_box_start('center', '', $THEME->cellheading);
59b29207 247 include($CFG->dirroot.'/blocks/'. $this->name() .'/config_global.html');
9b4b78fd 248 print_simple_box_end();
249 return true;
0f3fe4b6 250 }
59b29207 251
9b4b78fd 252 function handle_config($config) {
253 // Default behavior: save all variables as $CFG properties
254 // You don't need to override this if you 're satisfied with the above
255 if(!$this->has_config()) {
256 return false;
257 }
258 foreach ($config as $name => $value) {
259 set_config($name, $value);
260 }
261 return true;
0f3fe4b6 262 }
59b29207 263
0f3fe4b6 264 function applicable_formats() {
265 // Default case: the block can be used in all course types
2b0d60ec 266 return array('all' => true);
0f3fe4b6 267 }
59b29207 268
0f3fe4b6 269 function preferred_width() {
270 // Default case: the block wants to be 180 pixels wide
271 return 180;
272 }
59b29207 273
0f3fe4b6 274 function hide_header() {
4e60e777 275 //Default, false--> the header is shown
0f3fe4b6 276 return false;
277 }
59b29207 278
c5507e52 279 function html_attributes() {
89adb174 280 // Default case: just an id for the block, with our name in it
59b29207 281 return array('id' => 'block_'. $this->name());
c5507e52 282 }
59b29207 283
9b4b78fd 284 function load_instance($instance) {
285 if(!empty($instance->configdata)) {
286 $this->config = unserialize(base64_decode($instance->configdata));
287 }
288 unset($instance->configdata);
289 $this->instance = $instance;
290 $this->specialization();
291 }
59b29207 292
43038ce6 293 /**
294 * This function is called on your subclass right after an instance is loaded
295 * Use this function to act on instance data just after it's loaded and before anything else is done
296 * For instance: if your block will have different title's dependant on location (site, course, blog, etc)
297 */
9b4b78fd 298 function specialization() {
299 // Just to make sure that this method exists.
300 return;
301 }
302
303 function instance_allow_multiple() {
304 // Are you going to allow multiple instances of each block?
305 // If yes, then it is assumed that the block WILL USE per-instance configuration
306 return false;
307 }
59b29207 308
9b4b78fd 309 function instance_config_print() {
310 // Default behavior: print the config_instance.html file
e1b8bdf8 311 // You don't need to override this if you're satisfied with the above
9b4b78fd 312 if(!$this->instance_allow_multiple()) {
313 return false;
314 }
315 global $CFG, $USER, $THEME;
316
6195e04a 317 if(is_file($CFG->dirroot .'/blocks/'. $this->name() .'/config_instance.html')) {
9b4b78fd 318 print_simple_box_start('center', '', $THEME->cellheading);
6195e04a 319 include($CFG->dirroot .'/blocks/'. $this->name() .'/config_instance.html');
9b4b78fd 320 print_simple_box_end();
6195e04a 321 } else {
9b4b78fd 322 notice(get_string('blockconfigbad'), str_replace('blockaction=', 'dummy=', qualified_me()));
323 }
324
325 return true;
326 }
e1b8bdf8 327
9b4b78fd 328 function instance_config_save($data) {
329 $data = stripslashes_recursive($data);
330 $this->config = $data;
331 return set_field('block_instance', 'configdata', base64_encode(serialize($data)), 'id', $this->instance->id);
332 }
333
0f3fe4b6 334}
335
828c4e09 336class MoodleBlock_Nuke extends MoodleBlock {
337 function get_content() {
338
d4950608 339 if($this->content !== NULL) {
340 return $this->content;
341 }
828c4e09 342
343 global $CFG;
d4950608 344 $this->content = &New stdClass;
345
346 // This whole thing begs to be written for PHP >= 4.3.0 using glob();
59b29207 347 $dir = $CFG->dirroot .'/blocks/'. $this->name() .'/nuke/';
828c4e09 348 if($dh = @opendir($dir)) {
349 while (($file = readdir($dh)) !== false) {
350 $regs = array();
351 if(ereg('^block\-(.*)\.php$', $file, $regs)) {
d4950608 352 // Found it! Let's prepare the environment...
828c4e09 353
d4950608 354 $oldvals = array();
355 if(isset($GLOBALS['admin'])) {
356 $oldvals['admin'] = $GLOBALS['admin'];
357 }
358
359 $GLOBALS['admin'] = isteacher($this->course->id);
828c4e09 360 @include($dir.$file);
d4950608 361
362 foreach($oldvals as $key => $val) {
363 $GLOBALS[$key] = $val;
364 }
828c4e09 365
366 // We should have $content set now
828c4e09 367 if(!isset($content)) {
368 return NULL;
369 }
370 return $this->content->text = $content;
371 }
372 }
373 }
d4950608 374
375 // If we reached here, we couldn't find the nuke block for some reason
376 return $this->content->text = get_string('blockmissingnuke');
828c4e09 377 }
378}
379
59b29207 380?>