[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/lib/ -> blocklib.php (source)

   1  <?php //$Id: blocklib.php,v 1.129.2.4 2008/08/12 04:11:56 tjhunt Exp $
   2  
   3  //This library includes all the necessary stuff to use blocks in course pages
   4  
   5  define('BLOCK_MOVE_LEFT',   0x01);
   6  define('BLOCK_MOVE_RIGHT',  0x02);
   7  define('BLOCK_MOVE_UP',     0x04);
   8  define('BLOCK_MOVE_DOWN',   0x08);
   9  define('BLOCK_CONFIGURE',   0x10);
  10  
  11  define('BLOCK_POS_LEFT',  'l');
  12  define('BLOCK_POS_RIGHT', 'r');
  13  
  14  define('BLOCKS_PINNED_TRUE',0);
  15  define('BLOCKS_PINNED_FALSE',1);
  16  define('BLOCKS_PINNED_BOTH',2);
  17  
  18  require_once($CFG->libdir.'/pagelib.php');
  19  require_once($CFG->dirroot.'/course/lib.php'); // needed to solve all those: Call to undefined function: print_recent_activity() when adding Recent Activity
  20  
  21  // Returns false if this block is incompatible with the current version of Moodle.
  22  function block_is_compatible($blockname) {
  23      global $CFG;
  24  
  25      $file = @file($CFG->dirroot.'/blocks/'.$blockname.'/block_'.$blockname.'.php'); // ignore errors when file does not exist
  26      if(empty($file)) {
  27          return NULL;
  28      }
  29  
  30      foreach($file as $line) {
  31          // If you find MoodleBlock (appearing in the class declaration) it's not compatible
  32          if(strpos($line, 'MoodleBlock')) {
  33              return false;
  34          }
  35          // But if we find a { it means the class declaration is over, so it's compatible
  36          else if(strpos($line, '{')) {
  37              return true;
  38          }
  39      }
  40  
  41      return NULL;
  42  }
  43  
  44  // Returns the case-sensitive name of the class' constructor function. This includes both
  45  // PHP5- and PHP4-style constructors. If no appropriate constructor can be found, returns NULL.
  46  // If there is no such class, returns boolean false.
  47  function get_class_constructor($classname) {
  48      // Caching
  49      static $constructors = array();
  50  
  51      if(!class_exists($classname)) {
  52          return false;
  53      }
  54  
  55      // Tests indicate this doesn't hurt even in PHP5.
  56      $classname = strtolower($classname);
  57  
  58      // Return cached value, if exists
  59      if(isset($constructors[$classname])) {
  60          return $constructors[$classname];
  61      }
  62  
  63      // Get a list of methods. After examining several different ways of
  64      // doing the check, (is_callable, method_exists, function_exists etc)
  65      // it seems that this is the most reliable one.
  66      $methods = get_class_methods($classname);
  67  
  68      // PHP5 constructor?
  69      if(phpversion() >= '5') {
  70          if(in_array('__construct', $methods)) {
  71              return $constructors[$classname] = '__construct';
  72          }
  73      }
  74  
  75      // If we have PHP5 but no magic constructor, we have to lowercase the methods
  76      $methods = array_map('strtolower', $methods);
  77  
  78      if(in_array($classname, $methods)) {
  79          return $constructors[$classname] = $classname;
  80      }
  81  
  82      return $constructors[$classname] = NULL;
  83  }
  84  
  85  //This function retrieves a method-defined property of a class WITHOUT instantiating an object
  86  function block_method_result($blockname, $method, $param = NULL) {
  87      if(!block_load_class($blockname)) {
  88          return NULL;
  89      }
  90      return call_user_func(array('block_'.$blockname, $method), $param);
  91  }
  92  
  93  //This function creates a new object of the specified block class
  94  function block_instance($blockname, $instance = NULL) {
  95      if(!block_load_class($blockname)) {
  96          return false;
  97      }
  98      $classname = 'block_'.$blockname;
  99      $retval = new $classname;
 100      if($instance !== NULL) {
 101          $retval->_load_instance($instance);
 102      }
 103      return $retval;
 104  }
 105  
 106  //This function loads the necessary class files for a block
 107  //Whenever you want to load a block, use this first
 108  function block_load_class($blockname) {
 109      global $CFG;
 110  
 111      if(empty($blockname)) {
 112          return false;
 113      }
 114  
 115      $classname = 'block_'.$blockname;
 116  
 117      if(class_exists($classname)) {
 118          return true;
 119      }
 120  
 121      require_once($CFG->dirroot.'/blocks/moodleblock.class.php');
 122      @include_once($CFG->dirroot.'/blocks/'.$blockname.'/block_'.$blockname.'.php'); // do not throw errors if block code not present
 123  
 124      return class_exists($classname);
 125  }
 126  
 127  // This function returns an array with the IDs of any blocks that you can add to your page.
 128  // Parameters are passed by reference for speed; they are not modified at all.
 129  function blocks_get_missing(&$page, &$pageblocks) {
 130  
 131      $missingblocks = array();
 132      $allblocks = blocks_get_record();
 133      $pageformat = $page->get_format_name();
 134  
 135      if(!empty($allblocks)) {
 136          foreach($allblocks as $block) {
 137              if($block->visible && (!blocks_find_block($block->id, $pageblocks) || $block->multiple)) {
 138                  // And if it's applicable for display in this format...
 139                  if(blocks_name_allowed_in_format($block->name, $pageformat)) {
 140                      // ...add it to the missing blocks
 141                      $missingblocks[] = $block->id;
 142                  }
 143              }
 144          }
 145      }
 146      return $missingblocks;
 147  }
 148  
 149  function blocks_remove_inappropriate($page) {
 150      $pageblocks = blocks_get_by_page($page);
 151  
 152      if(empty($pageblocks)) {
 153          return;
 154      }
 155  
 156      if(($pageformat = $page->get_format_name()) == NULL) {
 157          return;
 158      }
 159  
 160      foreach($pageblocks as $position) {
 161          foreach($position as $instance) {
 162              $block = blocks_get_record($instance->blockid);
 163              if(!blocks_name_allowed_in_format($block->name, $pageformat)) {
 164                 blocks_delete_instance($instance);
 165              }
 166          }
 167      }
 168  }
 169  
 170  function blocks_name_allowed_in_format($name, $pageformat) {
 171  
 172      $accept  = NULL;
 173      $depth   = -1;
 174      if ($formats = block_method_result($name, 'applicable_formats')) {
 175          foreach($formats as $format => $allowed) {
 176              $thisformat = '^'.str_replace('*', '[^-]*', $format).'.*$';
 177              if(ereg($thisformat, $pageformat)) {
 178                  if(($scount = substr_count($format, '-')) > $depth) {
 179                      $depth  = $scount;
 180                      $accept = $allowed;
 181                  }
 182              }
 183          }
 184      }
 185      if($accept === NULL) {
 186          $accept = !empty($formats['all']);
 187      }
 188      return $accept;
 189  }
 190  
 191  function blocks_delete_instance($instance,$pinned=false) {
 192      global $CFG;
 193  
 194      // Get the block object and call instance_delete() if possible
 195      if($record = blocks_get_record($instance->blockid)) {
 196          if($obj = block_instance($record->name, $instance)) {
 197              // Return value ignored
 198              $obj->instance_delete();
 199          }
 200      }
 201  
 202      if (!empty($pinned)) {
 203           delete_records('block_pinned', 'id', $instance->id);
 204          // And now, decrement the weight of all blocks after this one
 205          execute_sql('UPDATE '.$CFG->prefix.'block_pinned SET weight = weight - 1 WHERE pagetype = \''.$instance->pagetype.
 206                      '\' AND position = \''.$instance->position.
 207                      '\' AND weight > '.$instance->weight, false);
 208      } else {
 209          // Now kill the db record;
 210          delete_records('block_instance', 'id', $instance->id);
 211          // And now, decrement the weight of all blocks after this one
 212          execute_sql('UPDATE '.$CFG->prefix.'block_instance SET weight = weight - 1 WHERE pagetype = \''.$instance->pagetype.
 213                      '\' AND pageid = '.$instance->pageid.' AND position = \''.$instance->position.
 214                      '\' AND weight > '.$instance->weight, false);
 215      }
 216      return true;
 217  }
 218  
 219  // Accepts an array of block instances and checks to see if any of them have content to display
 220  // (causing them to calculate their content in the process). Returns true or false. Parameter passed
 221  // by reference for speed; the array is actually not modified.
 222  function blocks_have_content(&$pageblocks, $position) {
 223  
 224      if (empty($pageblocks) || !is_array($pageblocks) || !array_key_exists($position,$pageblocks)) {
 225          return false;
 226      }
 227      // use a for() loop to get references to the array elements
 228      // foreach() cannot fetch references in PHP v4.x
 229      for ($n=0; $n<count($pageblocks[$position]);$n++) {
 230          $instance = &$pageblocks[$position][$n];
 231          if (empty($instance->visible)) {
 232              continue;
 233          }
 234          if(!$record = blocks_get_record($instance->blockid)) {
 235              continue;
 236          }
 237          if(!$obj = block_instance($record->name, $instance)) {
 238              continue;
 239          }
 240          if(!$obj->is_empty()) {
 241              // cache rec and obj
 242              // for blocks_print_group()
 243              $instance->rec = $record;
 244              $instance->obj = $obj;
 245              return true;
 246          }
 247      }
 248  
 249      return false;
 250  }
 251  
 252  // This function prints one group of blocks in a page
 253  // Parameters passed by reference for speed; they are not modified.
 254  function blocks_print_group(&$page, &$pageblocks, $position) {
 255      global $COURSE, $CFG, $USER;
 256  
 257      if (empty($pageblocks[$position])) {
 258          $groupblocks = array();
 259          $maxweight = 0;
 260      } else {
 261          $groupblocks = $pageblocks[$position];
 262          $maxweight = max(array_keys($groupblocks));
 263      }
 264  
 265  
 266      foreach ($groupblocks as $instance) {
 267          if (!empty($instance->pinned)) {
 268              $maxweight--;
 269          }
 270      }
 271  
 272      $isediting = $page->user_is_editing();
 273  
 274  
 275      foreach($groupblocks as $instance) {
 276  
 277  
 278          // $instance may have ->rec and ->obj
 279          // cached from when we walked $pageblocks
 280          // in blocks_have_content()
 281          if (empty($instance->rec)) {
 282              if (empty($instance->blockid)) {
 283                  continue;   // Can't do anything
 284              }
 285              $block = blocks_get_record($instance->blockid);
 286          } else {
 287              $block = $instance->rec;
 288          }
 289  
 290          if (empty($block)) {
 291              // Block doesn't exist! We should delete this instance!
 292              continue;
 293          }
 294  
 295          if (empty($block->visible)) {
 296              // Disabled by the admin
 297              continue;
 298          }
 299  
 300          if (empty($instance->obj)) {
 301              if (!$obj = block_instance($block->name, $instance)) {
 302                  // Invalid block
 303                  continue;
 304              }
 305          } else {
 306              $obj = $instance->obj;
 307          }
 308  
 309          $editalways = $page->edit_always();
 310  
 311  
 312          if (($isediting  && empty($instance->pinned)) || !empty($editalways)) {
 313              $options = 0;
 314              // The block can be moved up if it's NOT the first one in its position. If it is, we look at the OR clause:
 315              // the first block might still be able to move up if the page says so (i.e., it will change position)
 316              $options |= BLOCK_MOVE_UP    * ($instance->weight != 0          || ($page->blocks_move_position($instance, BLOCK_MOVE_UP)   != $instance->position));
 317              // Same thing for downward movement
 318              $options |= BLOCK_MOVE_DOWN  * ($instance->weight != $maxweight || ($page->blocks_move_position($instance, BLOCK_MOVE_DOWN) != $instance->position));
 319              // For left and right movements, it's up to the page to tell us whether they are allowed
 320              $options |= BLOCK_MOVE_RIGHT * ($page->blocks_move_position($instance, BLOCK_MOVE_RIGHT) != $instance->position);
 321              $options |= BLOCK_MOVE_LEFT  * ($page->blocks_move_position($instance, BLOCK_MOVE_LEFT ) != $instance->position);
 322              // Finally, the block can be configured if the block class either allows multiple instances, or if it specifically
 323              // allows instance configuration (multiple instances override that one). It doesn't have anything to do with what the
 324              // administrator has allowed for this block in the site admin options.
 325              $options |= BLOCK_CONFIGURE * ( $obj->instance_allow_multiple() || $obj->instance_allow_config() );
 326              $obj->_add_edit_controls($options);
 327          }
 328  
 329          if (!$instance->visible && empty($COURSE->javascriptportal)) {
 330              if ($isediting) {
 331                  $obj->_print_shadow();
 332              }
 333          } else {
 334              global $COURSE;
 335              if(!empty($COURSE->javascriptportal)) {
 336                   $COURSE->javascriptportal->currentblocksection = $position;
 337              }
 338              $obj->_print_block();
 339          }
 340          if (!empty($COURSE->javascriptportal)
 341                      && (empty($instance->pinned) || !$instance->pinned)) {
 342              $COURSE->javascriptportal->block_add('inst'.$instance->id, !$instance->visible);
 343          }
 344      } // End foreach
 345  
 346      //  Check if
 347      //    we are on the default position/side AND
 348      //    we're editing the page AND
 349      //    (
 350      //      we have the capability to manage blocks OR
 351      //      we are in myMoodle page AND have the capibility to manage myMoodle blocks
 352      //    )
 353  
 354      // for constant PAGE_MY_MOODLE
 355      include_once($CFG->dirroot.'/my/pagelib.php');
 356  
 357      $coursecontext = get_context_instance(CONTEXT_COURSE, $COURSE->id);
 358      $myownblogpage = (isset($page->filtertype) && isset($page->filterselect) && $page->type=='blog-view' && $page->filtertype=='user' && $page->filterselect == $USER->id);
 359  
 360      $managecourseblocks = has_capability('moodle/site:manageblocks', $coursecontext);
 361      $editmymoodle = $page->type == PAGE_MY_MOODLE && has_capability('moodle/my:manageblocks', $coursecontext);
 362  
 363      if ($page->blocks_default_position() == $position &&
 364          $page->user_is_editing() &&
 365          ($managecourseblocks || $editmymoodle || $myownblogpage)) {
 366  
 367          blocks_print_adminblock($page, $pageblocks);
 368      }
 369  }
 370  
 371  // This iterates over an array of blocks and calculates the preferred width
 372  // Parameter passed by reference for speed; it's not modified.
 373  function blocks_preferred_width(&$instances) {
 374      $width = 0;
 375  
 376      if(empty($instances) || !is_array($instances)) {
 377          return 0;
 378      }
 379  
 380      $blocks = blocks_get_record();
 381  
 382      foreach($instances as $instance) {
 383          if(!$instance->visible) {
 384              continue;
 385          }
 386  
 387          if (!array_key_exists($instance->blockid, $blocks)) {
 388              // Block doesn't exist! We should delete this instance!
 389              continue;
 390          }
 391  
 392          if(!$blocks[$instance->blockid]->visible) {
 393              continue;
 394          }
 395          $pref = block_method_result($blocks[$instance->blockid]->name, 'preferred_width');
 396          if($pref === NULL) {
 397              continue;
 398          }
 399          if($pref > $width) {
 400              $width = $pref;
 401          }
 402      }
 403      return $width;
 404  }
 405  
 406  function blocks_get_record($blockid = NULL, $invalidate = false) {
 407      static $cache = NULL;
 408  
 409      if($invalidate || empty($cache)) {
 410          $cache = get_records('block');
 411      }
 412  
 413      if($blockid === NULL) {
 414          return $cache;
 415      }
 416  
 417      return (isset($cache[$blockid])? $cache[$blockid] : false);
 418  }
 419  
 420  function blocks_find_block($blockid, $blocksarray) {
 421      if (empty($blocksarray)) {
 422          return false;
 423      }
 424      foreach($blocksarray as $blockgroup) {
 425          if (empty($blockgroup)) {
 426              continue;
 427          }
 428          foreach($blockgroup as $instance) {
 429              if($instance->blockid == $blockid) {
 430                  return $instance;
 431              }
 432          }
 433      }
 434      return false;
 435  }
 436  
 437  function blocks_find_instance($instanceid, $blocksarray) {
 438      foreach($blocksarray as $subarray) {
 439          foreach($subarray as $instance) {
 440              if($instance->id == $instanceid) {
 441                  return $instance;
 442              }
 443          }
 444      }
 445      return false;
 446  }
 447  
 448  // Simple entry point for anyone that wants to use blocks
 449  function blocks_setup(&$PAGE,$pinned=BLOCKS_PINNED_FALSE) {
 450      switch ($pinned) {
 451      case BLOCKS_PINNED_TRUE:
 452          $pageblocks = blocks_get_pinned($PAGE);
 453          break;
 454      case BLOCKS_PINNED_BOTH:
 455          $pageblocks = blocks_get_by_page_pinned($PAGE);
 456          break;
 457      case BLOCKS_PINNED_FALSE:
 458      default:
 459          $pageblocks = blocks_get_by_page($PAGE);
 460          break;
 461      }
 462      blocks_execute_url_action($PAGE, $pageblocks,($pinned==BLOCKS_PINNED_TRUE));
 463      return $pageblocks;
 464  }
 465  
 466  function blocks_execute_action($page, &$pageblocks, $blockaction, $instanceorid, $pinned=false, $redirect=true) {
 467      global $CFG;
 468  
 469      if (is_int($instanceorid)) {
 470          $blockid = $instanceorid;
 471      } else if (is_object($instanceorid)) {
 472          $instance = $instanceorid;
 473      }
 474  
 475      switch($blockaction) {
 476          case 'config':
 477              global $USER;
 478              $block = blocks_get_record($instance->blockid);
 479              // Hacky hacky tricky stuff to get the original human readable block title,
 480              // even if the block has configured its title to be something else.
 481              // Create the object WITHOUT instance data.
 482              $blockobject = block_instance($block->name);
 483              if ($blockobject === false) {
 484                  break;
 485              }
 486  
 487              // First of all check to see if the block wants to be edited
 488              if(!$blockobject->user_can_edit()) {
 489                  break;
 490              }
 491  
 492              // Now get the title and AFTER that load up the instance
 493              $blocktitle = $blockobject->get_title();
 494              $blockobject->_load_instance($instance);
 495  
 496              optional_param('submitted', 0, PARAM_INT);
 497  
 498              // Define the data we're going to silently include in the instance config form here,
 499              // so we can strip them from the submitted data BEFORE serializing it.
 500              $hiddendata = array(
 501                  'sesskey' => $USER->sesskey,
 502                  'instanceid' => $instance->id,
 503                  'blockaction' => 'config'
 504              );
 505  
 506              // To this data, add anything the page itself needs to display
 507              $hiddendata = array_merge($hiddendata, $page->url_get_parameters());
 508  
 509              if($data = data_submitted()) {
 510                  $remove = array_keys($hiddendata);
 511                  foreach($remove as $item) {
 512                      unset($data->$item);
 513                  }
 514                  if(!$blockobject->instance_config_save($data,$pinned)) {
 515                      error('Error saving block configuration');
 516                  }
 517                  // And nothing more, continue with displaying the page
 518              }
 519              else {
 520                  // We need to show the config screen, so we highjack the display logic and then die
 521                  $strheading = get_string('blockconfiga', 'moodle', $blocktitle);
 522                  $page->print_header(get_string('pageheaderconfigablock', 'moodle'), array($strheading => ''));
 523  
 524                  echo '<div class="block-config" id="'.$block->name.'">';   /// Make CSS easier
 525  
 526                  print_heading($strheading);
 527                  echo '<form method="post" name="block-config" action="'. $page->url_get_path() .'">';
 528                  echo '<p>';
 529                  foreach($hiddendata as $name => $val) {
 530                      echo '<input type="hidden" name="'. $name .'" value="'. $val .'" />';
 531                  }
 532                  echo '</p>';
 533                  $blockobject->instance_config_print();
 534                  echo '</form>';
 535  
 536                  echo '</div>';
 537                  $CFG->pagepath = 'blocks/' . $block->name;
 538                  print_footer();
 539                  die(); // Do not go on with the other page-related stuff
 540              }
 541          break;
 542          case 'toggle':
 543              if(empty($instance))  {
 544                  error('Invalid block instance for '.$blockaction);
 545              }
 546              $instance->visible = ($instance->visible) ? 0 : 1;
 547              if (!empty($pinned)) {
 548                  update_record('block_pinned', $instance);
 549              } else {
 550                  update_record('block_instance', $instance);
 551              }
 552          break;
 553          case 'delete':
 554              if(empty($instance))  {
 555                  error('Invalid block instance for '. $blockaction);
 556              }
 557              blocks_delete_instance($instance, $pinned);
 558          break;
 559          case 'moveup':
 560              if(empty($instance))  {
 561                  error('Invalid block instance for '. $blockaction);
 562              }
 563  
 564              if($instance->weight == 0) {
 565                  // The block is the first one, so a move "up" probably means it changes position
 566                  // Where is the instance going to be moved?
 567                  $newpos = $page->blocks_move_position($instance, BLOCK_MOVE_UP);
 568                  $newweight = (empty($pageblocks[$newpos]) ? 0 : max(array_keys($pageblocks[$newpos])) + 1);
 569  
 570                  blocks_execute_repositioning($instance, $newpos, $newweight, $pinned);
 571              }
 572              else {
 573                  // The block is just moving upwards in the same position.
 574                  // This configuration will make sure that even if somehow the weights
 575                  // become not continuous, block move operations will eventually bring
 576                  // the situation back to normal without printing any warnings.
 577                  if(!empty($pageblocks[$instance->position][$instance->weight - 1])) {
 578                      $other = $pageblocks[$instance->position][$instance->weight - 1];
 579                  }
 580                  if(!empty($other)) {
 581                      ++$other->weight;
 582                      if (!empty($pinned)) {
 583                          update_record('block_pinned', $other);
 584                      } else {
 585                          update_record('block_instance', $other);
 586                      }
 587                  }
 588                  --$instance->weight;
 589                  if (!empty($pinned)) {
 590                      update_record('block_pinned', $instance);
 591                  } else {
 592                      update_record('block_instance', $instance);
 593                  }
 594              }
 595          break;
 596          case 'movedown':
 597              if(empty($instance))  {
 598                  error('Invalid block instance for '. $blockaction);
 599              }
 600  
 601              if($instance->weight == max(array_keys($pageblocks[$instance->position]))) {
 602                  // The block is the last one, so a move "down" probably means it changes position
 603                  // Where is the instance going to be moved?
 604                  $newpos = $page->blocks_move_position($instance, BLOCK_MOVE_DOWN);
 605                  $newweight = (empty($pageblocks[$newpos]) ? 0 : max(array_keys($pageblocks[$newpos])) + 1);
 606  
 607                  blocks_execute_repositioning($instance, $newpos, $newweight, $pinned);
 608              }
 609              else {
 610                  // The block is just moving downwards in the same position.
 611                  // This configuration will make sure that even if somehow the weights
 612                  // become not continuous, block move operations will eventually bring
 613                  // the situation back to normal without printing any warnings.
 614                  if(!empty($pageblocks[$instance->position][$instance->weight + 1])) {
 615                      $other = $pageblocks[$instance->position][$instance->weight + 1];
 616                  }
 617                  if(!empty($other)) {
 618                      --$other->weight;
 619                      if (!empty($pinned)) {
 620                          update_record('block_pinned', $other);
 621                      } else {
 622                          update_record('block_instance', $other);
 623                      }
 624                  }
 625                  ++$instance->weight;
 626                  if (!empty($pinned)) {
 627                      update_record('block_pinned', $instance);
 628                  } else {
 629                      update_record('block_instance', $instance);
 630                  }
 631              }
 632          break;
 633          case 'moveleft':
 634              if(empty($instance))  {
 635                  error('Invalid block instance for '. $blockaction);
 636              }
 637  
 638              // Where is the instance going to be moved?
 639              $newpos = $page->blocks_move_position($instance, BLOCK_MOVE_LEFT);
 640              $newweight = (empty($pageblocks[$newpos]) ? 0 : max(array_keys($pageblocks[$newpos])) + 1);
 641  
 642              blocks_execute_repositioning($instance, $newpos, $newweight, $pinned);
 643          break;
 644          case 'moveright':
 645              if(empty($instance))  {
 646                  error('Invalid block instance for '. $blockaction);
 647              }
 648  
 649              // Where is the instance going to be moved?
 650              $newpos    = $page->blocks_move_position($instance, BLOCK_MOVE_RIGHT);
 651              $newweight = (empty($pageblocks[$newpos]) ? 0 : max(array_keys($pageblocks[$newpos])) + 1);
 652  
 653              blocks_execute_repositioning($instance, $newpos, $newweight, $pinned);
 654          break;
 655          case 'add':
 656              // Add a new instance of this block, if allowed
 657              $block = blocks_get_record($blockid);
 658  
 659              if(empty($block) || !$block->visible) {
 660                  // Only allow adding if the block exists and is enabled
 661                  break;
 662              }
 663  
 664              if(!$block->multiple && blocks_find_block($blockid, $pageblocks) !== false) {
 665                  // If no multiples are allowed and we already have one, return now
 666                  break;
 667              }
 668  
 669              if(!block_method_result($block->name, 'user_can_addto', $page)) {
 670                  // If the block doesn't want to be added...
 671                  break;
 672              }
 673  
 674              $newpos = $page->blocks_default_position();
 675              if (!empty($pinned)) {
 676                  $sql = 'SELECT 1, max(weight) + 1 AS nextfree FROM '. $CFG->prefix .'block_pinned WHERE '
 677                      .' pagetype = \''. $page->get_type() .'\' AND position = \''. $newpos .'\'';
 678              } else {
 679                  $sql = 'SELECT 1, max(weight) + 1 AS nextfree FROM '. $CFG->prefix .'block_instance WHERE pageid = '. $page->get_id()
 680                      .' AND pagetype = \''. $page->get_type() .'\' AND position = \''. $newpos .'\'';
 681              }
 682              $weight = get_record_sql($sql);
 683  
 684              $newinstance = new stdClass;
 685              $newinstance->blockid    = $blockid;
 686              if (empty($pinned)) {
 687                  $newinstance->pageid = $page->get_id();
 688              }
 689              $newinstance->pagetype   = $page->get_type();
 690              $newinstance->position   = $newpos;
 691              $newinstance->weight     = empty($weight->nextfree) ? 0 : $weight->nextfree;
 692              $newinstance->visible    = 1;
 693              $newinstance->configdata = '';
 694              if (!empty($pinned)) {
 695                  $newinstance->id = insert_record('block_pinned', $newinstance);
 696              } else {
 697                  $newinstance->id = insert_record('block_instance', $newinstance);
 698              }
 699  
 700              // If the new instance was created, allow it to do additional setup
 701              if($newinstance && ($obj = block_instance($block->name, $newinstance))) {
 702                  // Return value ignored
 703                  $obj->instance_create();
 704              }
 705  
 706          break;
 707      }
 708  
 709      if ($redirect) {
 710          // In order to prevent accidental duplicate actions, redirect to a page with a clean url
 711          redirect($page->url_get_full());
 712      }
 713  }
 714  
 715  // You can use this to get the blocks to respond to URL actions without much hassle
 716  function blocks_execute_url_action(&$PAGE, &$pageblocks,$pinned=false) {
 717      $blockaction = optional_param('blockaction', '', PARAM_ALPHA);
 718  
 719      if (empty($blockaction) || !$PAGE->user_allowed_editing() || !confirm_sesskey()) {
 720          return;
 721      }
 722  
 723      $instanceid  = optional_param('instanceid', 0, PARAM_INT);
 724      $blockid     = optional_param('blockid',    0, PARAM_INT);
 725  
 726      if (!empty($blockid)) {
 727          blocks_execute_action($PAGE, $pageblocks, strtolower($blockaction), $blockid, $pinned);
 728  
 729      }
 730      else if (!empty($instanceid)) {
 731          $instance = blocks_find_instance($instanceid, $pageblocks);
 732          blocks_execute_action($PAGE, $pageblocks, strtolower($blockaction), $instance, $pinned);
 733      }
 734  }
 735  
 736  // This shouldn't be used externally at all, it's here for use by blocks_execute_action()
 737  // in order to reduce code repetition.
 738  function blocks_execute_repositioning(&$instance, $newpos, $newweight, $pinned=false) {
 739      global $CFG;
 740  
 741      // If it's staying where it is, don't do anything, unless overridden
 742      if ($newpos == $instance->position) {
 743          return;
 744      }
 745  
 746      // Close the weight gap we 'll leave behind
 747      if (!empty($pinned)) {
 748          $sql = 'UPDATE '. $CFG->prefix .'block_instance SET weight = weight - 1 '.
 749                          'WHERE pagetype = \''. $instance->pagetype.
 750                          '\' AND position = \'' .$instance->position.
 751                          '\' AND weight > '. $instance->weight;
 752      } else {
 753          $sql = 'UPDATE '. $CFG->prefix .'block_instance SET weight = weight - 1 '.
 754                          'WHERE pagetype = \''. $instance->pagetype.
 755                          '\' AND pageid = '. $instance->pageid .
 756                          ' AND position = \'' .$instance->position.
 757                          '\' AND weight > '. $instance->weight;
 758      }
 759      execute_sql($sql,false);
 760  
 761      $instance->position = $newpos;
 762      $instance->weight   = $newweight;
 763  
 764      if (!empty($pinned)) {
 765          update_record('block_pinned', $instance);
 766      } else {
 767          update_record('block_instance', $instance);
 768      }
 769  }
 770  
 771  
 772  /**
 773   * Moves a block to the new position (column) and weight (sort order).
 774   * @param $instance - The block instance to be moved.
 775   * @param $destpos - BLOCK_POS_LEFT or BLOCK_POS_RIGHT. The destination column.
 776   * @param $destweight - The destination sort order. If NULL, we add to the end
 777   *                      of the destination column.
 778   * @param $pinned - Are we moving pinned blocks? We can only move pinned blocks
 779   *                  to a new position withing the pinned list. Likewise, we
 780   *                  can only moved non-pinned blocks to a new position within
 781   *                  the non-pinned list.
 782   * @return boolean (success or failure).
 783   */
 784  function blocks_move_block($page, &$instance, $destpos, $destweight=NULL, $pinned=false) {
 785      global $CFG;
 786  
 787      if ($pinned) {
 788          $blocklist = blocks_get_pinned($page);
 789      } else {
 790          $blocklist = blocks_get_by_page($page);
 791      }
 792  
 793      if ($blocklist[$instance->position][$instance->weight]->id != $instance->id) {
 794          // The source block instance is not where we think it is.
 795          return false;
 796      }
 797  
 798      // First we close the gap that will be left behind when we take out the
 799      // block from it's current column.
 800      if ($pinned) {
 801          $closegapsql = "UPDATE {$CFG->prefix}block_instance
 802                             SET weight = weight - 1
 803                           WHERE weight > '$instance->weight'
 804                             AND position = '$instance->position'
 805                             AND pagetype = '$instance->pagetype'";
 806      } else {
 807          $closegapsql = "UPDATE {$CFG->prefix}block_instance
 808                             SET weight = weight - 1
 809                           WHERE weight > '$instance->weight'
 810                             AND position = '$instance->position'
 811                             AND pagetype = '$instance->pagetype'
 812                             AND pageid = '$instance->pageid'";
 813      }
 814      if (!execute_sql($closegapsql, false)) {
 815          return false;
 816      }
 817  
 818      // Now let's make space for the block being moved.
 819      if ($pinned) {
 820          $opengapsql = "UPDATE {$CFG->prefix}block_instance
 821                             SET weight = weight + 1
 822                           WHERE weight >= '$destweight'
 823                             AND position = '$destpos'
 824                             AND pagetype = '$instance->pagetype'";
 825      } else {
 826          $opengapsql = "UPDATE {$CFG->prefix}block_instance
 827                             SET weight = weight + 1
 828                           WHERE weight >= '$destweight'
 829                             AND position = '$destpos'
 830                             AND pagetype = '$instance->pagetype'
 831                             AND pageid = '$instance->pageid'";
 832      }
 833      if (!execute_sql($opengapsql, false)) {
 834          return false;
 835      }
 836  
 837      // Move the block.
 838      $instance->position = $destpos;
 839      $instance->weight   = $destweight;
 840  
 841      if ($pinned) {
 842          $table = 'block_pinned';
 843      } else {
 844          $table = 'block_instance';
 845      }
 846      return update_record($table, $instance);
 847  }
 848  
 849  
 850  /**
 851   * Returns an array consisting of 2 arrays:
 852   * 1) Array of pinned blocks for position BLOCK_POS_LEFT
 853   * 2) Array of pinned blocks for position BLOCK_POS_RIGHT
 854   */
 855  function blocks_get_pinned($page) {
 856  
 857      $visible = true;
 858  
 859      if (method_exists($page,'edit_always')) {
 860          if ($page->edit_always()) {
 861              $visible = false;
 862          }
 863      }
 864  
 865      $blocks = get_records_select('block_pinned', 'pagetype = \''. $page->get_type() .
 866                      '\''.(($visible) ? 'AND visible = 1' : ''), 'position, weight');
 867  
 868      $positions = $page->blocks_get_positions();
 869      $arr = array();
 870  
 871      foreach($positions as $key => $position) {
 872          $arr[$position] = array();
 873      }
 874  
 875      if(empty($blocks)) {
 876          return $arr;
 877      }
 878  
 879      foreach($blocks as $block) {
 880          $block->pinned = true; // so we know we can't move it.
 881          // make up an instanceid if we can..
 882          $block->pageid = $page->get_id();
 883          $arr[$block->position][$block->weight] = $block;
 884      }
 885  
 886      return $arr;
 887  }
 888  
 889  
 890  /**
 891   * Similar to blocks_get_by_page(), except that, the array returned includes
 892   * pinned blocks as well. Pinned blocks are always appended before normal
 893   * block instances.
 894   */
 895  function blocks_get_by_page_pinned($page) {
 896      $pinned = blocks_get_pinned($page);
 897      $user = blocks_get_by_page($page);
 898  
 899      $weights = array();
 900  
 901      foreach ($pinned as $pos => $arr) {
 902          $weights[$pos] = count($arr);
 903      }
 904  
 905      foreach ($user as $pos => $blocks) {
 906          if (!array_key_exists($pos,$pinned)) {
 907               $pinned[$pos] = array();
 908          }
 909          if (!array_key_exists($pos,$weights)) {
 910              $weights[$pos] = 0;
 911          }
 912          foreach ($blocks as $block) {
 913              $pinned[$pos][$weights[$pos]] = $block;
 914              $weights[$pos]++;
 915          }
 916      }
 917      return $pinned;
 918  }
 919  
 920  
 921  /**
 922   * Returns an array of blocks for the page. Pinned blocks are excluded.
 923   */
 924  function blocks_get_by_page($page) {
 925      $blocks = get_records_select('block_instance', "pageid = '". $page->get_id() .
 926                  "' AND pagetype = '". $page->get_type() ."'", 'position, weight');
 927  
 928      $positions = $page->blocks_get_positions();
 929      $arr = array();
 930      foreach($positions as $key => $position) {
 931          $arr[$position] = array();
 932      }
 933  
 934      if(empty($blocks)) {
 935          return $arr;
 936      }
 937  
 938      foreach($blocks as $block) {
 939          $arr[$block->position][$block->weight] = $block;
 940      }
 941      return $arr;
 942  }
 943  
 944  
 945  //This function prints the block to admin blocks as necessary
 946  function blocks_print_adminblock(&$page, &$pageblocks) {
 947      global $USER;
 948  
 949      $missingblocks = blocks_get_missing($page, $pageblocks);
 950  
 951      if (!empty($missingblocks)) {
 952          $strblocks = '<div class="title"><h2>';
 953          $strblocks .= get_string('blocks');
 954          $strblocks .= '</h2></div>';
 955          $stradd    = get_string('add');
 956          foreach ($missingblocks as $blockid) {
 957              $block = blocks_get_record($blockid);
 958              $blockobject = block_instance($block->name);
 959              if ($blockobject === false) {
 960                  continue;
 961              }
 962              if(!$blockobject->user_can_addto($page)) {
 963                  continue;
 964              }
 965              $menu[$block->id] = $blockobject->get_title();
 966          }
 967          asort($menu);
 968  
 969          $target = $page->url_get_full(array('sesskey' => $USER->sesskey, 'blockaction' => 'add'));
 970          $content = popup_form($target.'&amp;blockid=', $menu, 'add_block', '', $stradd .'...', '', '', true);
 971          print_side_block($strblocks, $content, NULL, NULL, NULL, array('class' => 'block_adminblock'));
 972      }
 973  }
 974  
 975  function blocks_repopulate_page($page) {
 976      global $CFG;
 977  
 978      $allblocks = blocks_get_record();
 979  
 980      if(empty($allblocks)) {
 981          error('Could not retrieve blocks from the database');
 982      }
 983  
 984      // Assemble the information to correlate block names to ids
 985      $idforname = array();
 986      foreach($allblocks as $block) {
 987          $idforname[$block->name] = $block->id;
 988      }
 989  
 990      /// If the site override has been defined, it is the only valid one.
 991      if (!empty($CFG->defaultblocks_override)) {
 992          $blocknames = $CFG->defaultblocks_override;
 993      }
 994      else {
 995          $blocknames = $page->blocks_get_default();
 996      }
 997  
 998      $positions = $page->blocks_get_positions();
 999      $posblocks = explode(':', $blocknames);
1000  
1001      // Now one array holds the names of the positions, and the other one holds the blocks
1002      // that are going to go in each position. Luckily for us, both arrays are numerically
1003      // indexed and the indexes match, so we can work straight away... but CAREFULLY!
1004  
1005      // Ready to start creating block instances, but first drop any existing ones
1006      delete_records('block_instance', 'pageid', $page->get_id(), 'pagetype', $page->get_type());
1007  
1008      // Here we slyly count $posblocks and NOT $positions. This can actually make a difference
1009      // if the textual representation has undefined slots in the end. So we only work with as many
1010      // positions were retrieved, not with all the page says it has available.
1011      $numpositions = count($posblocks);
1012      for($i = 0; $i < $numpositions; ++$i) {
1013          $position = $positions[$i];
1014          $blocknames = explode(',', $posblocks[$i]);
1015          $weight = 0;
1016          foreach($blocknames as $blockname) {
1017              $newinstance = new stdClass;
1018              $newinstance->blockid    = $idforname[$blockname];
1019              $newinstance->pageid     = $page->get_id();
1020              $newinstance->pagetype   = $page->get_type();
1021              $newinstance->position   = $position;
1022              $newinstance->weight     = $weight;
1023              $newinstance->visible    = 1;
1024              $newinstance->configdata = '';
1025  
1026              if(!empty($newinstance->blockid)) {
1027                  // Only add block if it was recognized
1028                  insert_record('block_instance', $newinstance);
1029                  ++$weight;
1030              }
1031          }
1032      }
1033  
1034      return true;
1035  }
1036  
1037  function upgrade_blocks_db($continueto) {
1038  /// This function upgrades the blocks tables, if necessary
1039  /// It's called from admin/index.php
1040  
1041      global $CFG, $db;
1042  
1043      require_once ($CFG->dirroot .'/blocks/version.php');  // Get code versions
1044  
1045      if (empty($CFG->blocks_version)) {                  // Blocks have never been installed.
1046          $strdatabaseupgrades = get_string('databaseupgrades');
1047          print_header($strdatabaseupgrades, $strdatabaseupgrades,
1048                  build_navigation(array(array('name' => $strdatabaseupgrades, 'link' => null, 'type' => 'misc'))), '',
1049                  upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
1050  
1051          upgrade_log_start();
1052          print_heading('blocks');
1053          $db->debug=true;
1054  
1055      /// Both old .sql files and new install.xml are supported
1056      /// but we priorize install.xml (XMLDB) if present
1057          $status = false;
1058          if (file_exists($CFG->dirroot . '/blocks/db/install.xml')) {
1059              $status = install_from_xmldb_file($CFG->dirroot . '/blocks/db/install.xml'); //New method
1060          } else if (file_exists($CFG->dirroot . '/blocks/db/' . $CFG->dbtype . '.sql')) {
1061              $status = modify_database($CFG->dirroot . '/blocks/db/' . $CFG->dbtype . '.sql'); //Old method
1062          }
1063  
1064          $db->debug = false;
1065          if ($status) {
1066              if (set_config('blocks_version', $blocks_version)) {
1067                  notify(get_string('databasesuccess'), 'notifysuccess');
1068                  notify(get_string('databaseupgradeblocks', '', $blocks_version), 'notifysuccess');
1069                  print_continue($continueto);
1070                  print_footer('none');
1071                  exit;
1072              } else {
1073                  error('Upgrade of blocks system failed! (Could not update version in config table)');
1074              }
1075          } else {
1076              error('Blocks tables could NOT be set up successfully!');
1077          }
1078      }
1079  
1080  /// Upgrading code starts here
1081      $oldupgrade = false;
1082      $newupgrade = false;
1083      if (is_readable($CFG->dirroot . '/blocks/db/' . $CFG->dbtype . '.php')) {
1084          include_once($CFG->dirroot . '/blocks/db/' . $CFG->dbtype . '.php');  // defines old upgrading function
1085          $oldupgrade = true;
1086      }
1087      if (is_readable($CFG->dirroot . '/blocks/db/upgrade.php')) {
1088          include_once($CFG->dirroot . '/blocks/db/upgrade.php');  // defines new upgrading function
1089          $newupgrade = true;
1090      }
1091  
1092      if ($blocks_version > $CFG->blocks_version) {       // Upgrade tables
1093          $strdatabaseupgrades = get_string('databaseupgrades');
1094          print_header($strdatabaseupgrades, $strdatabaseupgrades,
1095                  build_navigation(array(array('name' => $strdatabaseupgrades, 'link' => null, 'type' => 'misc'))), '', upgrade_get_javascript());
1096  
1097          upgrade_log_start();
1098          print_heading('blocks');
1099  
1100      /// Run de old and new upgrade functions for the module
1101          $oldupgrade_function = 'blocks_upgrade';
1102          $newupgrade_function = 'xmldb_blocks_upgrade';
1103  
1104      /// First, the old function if exists
1105          $oldupgrade_status = true;
1106          if ($oldupgrade && function_exists($oldupgrade_function)) {
1107              $db->debug = true;
1108              $oldupgrade_status = $oldupgrade_function($CFG->blocks_version);
1109          } else if ($oldupgrade) {
1110              notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' .
1111                       '/blocks/db/' . $CFG->dbtype . '.php');
1112          }
1113  
1114      /// Then, the new function if exists and the old one was ok
1115          $newupgrade_status = true;
1116          if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) {
1117              $db->debug = true;
1118              $newupgrade_status = $newupgrade_function($CFG->blocks_version);
1119          } else if ($newupgrade) {
1120              notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
1121                       '/blocks/db/upgrade.php');
1122          }
1123  
1124          $db->debug=false;
1125      /// Now analyze upgrade results
1126          if ($oldupgrade_status && $newupgrade_status) {    // No upgrading failed
1127              if (set_config('blocks_version', $blocks_version)) {
1128                  notify(get_string('databasesuccess'), 'notifysuccess');
1129                  notify(get_string('databaseupgradeblocks', '', $blocks_version), 'notifysuccess');
1130                  print_continue($continueto);
1131                  print_footer('none');
1132                  exit;
1133              } else {
1134                  error('Upgrade of blocks system failed! (Could not update version in config table)');
1135              }
1136          } else {
1137              error('Upgrade failed!  See blocks/version.php');
1138          }
1139  
1140      } else if ($blocks_version < $CFG->blocks_version) {
1141          upgrade_log_start();
1142          notify('WARNING!!!  The Blocks version you are using is OLDER than the version that made these databases!');
1143      }
1144      upgrade_log_finish();
1145  }
1146  
1147  //This function finds all available blocks and install them
1148  //into blocks table or do all the upgrade process if newer
1149  function upgrade_blocks_plugins($continueto) {
1150  
1151      global $CFG, $db;
1152  
1153      $blocktitles = array();
1154      $invalidblocks = array();
1155      $validblocks = array();
1156      $notices = array();
1157  
1158      //Count the number of blocks in db
1159      $blockcount = count_records('block');
1160      //If there isn't records. This is the first install, so I remember it
1161      if ($blockcount == 0) {
1162          $first_install = true;
1163      } else {
1164          $first_install = false;
1165      }
1166  
1167      $site = get_site();
1168  
1169      if (!$blocks = get_list_of_plugins('blocks', 'db') ) {
1170          error('No blocks installed!');
1171      }
1172  
1173      include_once($CFG->dirroot .'/blocks/moodleblock.class.php');
1174      if(!class_exists('block_base')) {
1175          error('Class block_base is not defined or file not found for /blocks/moodleblock.class.php');
1176      }
1177  
1178      foreach ($blocks as $blockname) {
1179  
1180          if ($blockname == 'NEWBLOCK') {   // Someone has unzipped the template, ignore it
1181              continue;
1182          }
1183  
1184          if(!block_is_compatible($blockname)) {
1185              // This is an old-style block
1186              //$notices[] = 'Block '. $blockname .' is not compatible with the current version of Mooodle and needs to be updated by a programmer.';
1187              $invalidblocks[] = $blockname;
1188              continue;
1189          }
1190  
1191          $fullblock = $CFG->dirroot .'/blocks/'. $blockname;
1192  
1193          if ( is_readable($fullblock.'/block_'.$blockname.'.php')) {
1194              include_once($fullblock.'/block_'.$blockname.'.php');
1195          } else {
1196              $notices[] = 'Block '. $blockname .': '. $fullblock .'/block_'. $blockname .'.php was not readable';
1197              continue;
1198          }
1199  
1200          $oldupgrade = false;
1201          $newupgrade = false;
1202          if ( @is_dir($fullblock .'/db/')) {
1203              if ( @is_readable($fullblock .'/db/'. $CFG->dbtype .'.php')) {
1204                  include_once($fullblock .'/db/'. $CFG->dbtype .'.php');  // defines old upgrading function
1205                  $oldupgrade = true;
1206              }
1207              if ( @is_readable($fullblock .'/db/upgrade.php')) {
1208                  include_once ($fullblock .'/db/upgrade.php');  // defines new upgrading function
1209                  $newupgrade = true;
1210              }
1211          }
1212  
1213          $classname = 'block_'.$blockname;
1214          if(!class_exists($classname)) {
1215              $notices[] = 'Block '. $blockname .': '. $classname .' not implemented';
1216              continue;
1217          }
1218  
1219          // Here is the place to see if the block implements a constructor (old style),
1220          // an init() function (new style) or nothing at all (error time).
1221  
1222          $constructor = get_class_constructor($classname);
1223          if(empty($constructor)) {
1224              // No constructor
1225              $notices[] = 'Block '. $blockname .': class does not have a constructor';
1226              $invalidblocks[] = $blockname;
1227              continue;
1228          }
1229  
1230          $block    = new stdClass;     // This may be used to update the db below
1231          $blockobj = new $classname;   // This is what we 'll be testing
1232  
1233          // Inherits from block_base?
1234          if(!is_subclass_of($blockobj, 'block_base')) {
1235              $notices[] = 'Block '. $blockname .': class does not inherit from block_base';
1236              continue;
1237          }
1238  
1239          // OK, it's as we all hoped. For further tests, the object will do them itself.
1240          if(!$blockobj->_self_test()) {
1241              $notices[] = 'Block '. $blockname .': self test failed';
1242              continue;
1243          }
1244          $block->version = $blockobj->get_version();
1245  
1246          if (!isset($block->version)) {
1247              $notices[] = 'Block '. $blockname .': has no version support. It must be updated by a programmer.';
1248              continue;
1249          }
1250  
1251          $block->name = $blockname;   // The name MUST match the directory
1252          $blocktitle = $blockobj->get_title();
1253  
1254          if ($currblock = get_record('block', 'name', $block->name)) {
1255              if ($currblock->version == $block->version) {
1256                  // do nothing
1257              } else if ($currblock->version < $block->version) {
1258                  if (empty($updated_blocks)) {
1259                      $strblocksetup    = get_string('blocksetup');
1260                      print_header($strblocksetup, $strblocksetup,
1261                              build_navigation(array(array('name' => $strblocksetup, 'link' => null, 'type' => 'misc'))), '',
1262                              upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
1263                  }
1264                  $updated_blocks = true;
1265                  upgrade_log_start();
1266                  print_heading('New version of '.$blocktitle.' ('.$block->name.') exists');
1267                  @set_time_limit(0);  // To allow slow databases to complete the long SQL
1268  
1269              /// Run de old and new upgrade functions for the module
1270                  $oldupgrade_function = $block->name .'_upgrade';
1271                  $newupgrade_function = 'xmldb_block_' . $block->name .'_upgrade';
1272  
1273              /// First, the old function if exists
1274                  $oldupgrade_status = true;
1275                  if ($oldupgrade && function_exists($oldupgrade_function)) {
1276                      $db->debug = true;
1277                      $oldupgrade_status = $oldupgrade_function($currblock->version, $block);
1278                  } else if ($oldupgrade) {
1279                      notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' .
1280                               $fullblock . '/db/' . $CFG->dbtype . '.php');
1281                  }
1282  
1283              /// Then, the new function if exists and the old one was ok
1284                  $newupgrade_status = true;
1285                  if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) {
1286                      $db->debug = true;
1287                      $newupgrade_status = $newupgrade_function($currblock->version, $block);
1288                  } else if ($newupgrade) {
1289                      notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
1290                               $fullblock . '/db/upgrade.php');
1291                  }
1292  
1293                  $db->debug=false;
1294              /// Now analyze upgrade results
1295                  if ($oldupgrade_status && $newupgrade_status) {    // No upgrading failed
1296  
1297                      // Set the block cron on upgrade
1298                      $block->cron = !empty($blockobj->cron) ? $blockobj->cron : 0;
1299  
1300                      // OK so far, now update the block record
1301                      $block->id = $currblock->id;
1302                      if (! update_record('block', $block)) {
1303                          error('Could not update block '. $block->name .' record in block table!');
1304                      }
1305                      $component = 'block/'.$block->name;
1306                      if (!update_capabilities($component)) {
1307                          error('Could not update '.$block->name.' capabilities!');
1308                      }
1309  
1310                      events_update_definition($component);
1311                      notify(get_string('blocksuccess', '', $blocktitle), 'notifysuccess');
1312                  } else {
1313                      notify('Upgrading block '. $block->name .' from '. $currblock->version .' to '. $block->version .' FAILED!');
1314                  }
1315                  echo '<hr />';
1316              } else {
1317                  upgrade_log_start();
1318                  error('Version mismatch: block '. $block->name .' can\'t downgrade '. $currblock->version .' -> '. $block->version .'!');
1319              }
1320  
1321          } else {    // block not installed yet, so install it
1322  
1323              // If it allows multiples, start with it enabled
1324              if ($blockobj->instance_allow_multiple()) {
1325                  $block->multiple = 1;
1326              }
1327  
1328              // Set the block cron on install
1329              $block->cron = !empty($blockobj->cron) ? $blockobj->cron : 0;
1330  
1331              // [pj] Normally this would be inline in the if, but we need to
1332              //      check for NULL (necessary for 4.0.5 <= PHP < 4.2.0)
1333              $conflictblock = array_search($blocktitle, $blocktitles);
1334              if($conflictblock !== false && $conflictblock !== NULL) {
1335                  // Duplicate block titles are not allowed, they confuse people
1336                  // AND PHP's associative arrays ;)
1337                  error('<strong>Naming conflict</strong>: block <strong>'.$block->name.'</strong> has the same title with an existing block, <strong>'.$conflictblock.'</strong>!');
1338              }
1339              if (empty($updated_blocks)) {
1340                  $strblocksetup    = get_string('blocksetup');
1341                  print_header($strblocksetup, $strblocksetup,
1342                          build_navigation(array(array('name' => $strblocksetup, 'link' => null, 'type' => 'misc'))), '',
1343                          upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
1344              }
1345              $updated_blocks = true;
1346              upgrade_log_start();
1347              print_heading($block->name);
1348              $db->debug = true;
1349              @set_time_limit(0);  // To allow slow databases to complete the long SQL
1350  
1351          /// Both old .sql files and new install.xml are supported
1352          /// but we priorize install.xml (XMLDB) if present
1353              $status = false;
1354              if (file_exists($fullblock . '/db/install.xml')) {
1355                  $status = install_from_xmldb_file($fullblock . '/db/install.xml'); //New method
1356              } else if (file_exists($fullblock .'/db/'. $CFG->dbtype .'.sql')) {
1357                  $status = modify_database($fullblock .'/db/'. $CFG->dbtype .'.sql'); //Old method
1358              } else {
1359                  $status = true;
1360              }
1361  
1362              $db->debug = false;
1363              if ($status) {
1364                  if ($block->id = insert_record('block', $block)) {
1365                      $blockobj->after_install();
1366                      $component = 'block/'.$block->name;
1367                      if (!update_capabilities($component)) {
1368                          notify('Could not set up '.$block->name.' capabilities!');
1369                      }
1370  
1371                      events_update_definition($component);
1372                      notify(get_string('blocksuccess', '', $blocktitle), 'notifysuccess');
1373                      echo '<hr />';
1374                  } else {
1375                      error($block->name .' block could not be added to the block list!');
1376                  }
1377              } else {
1378                  error('Block '. $block->name .' tables could NOT be set up successfully!');
1379              }
1380          }
1381  
1382          $blocktitles[$block->name] = $blocktitle;
1383      }
1384  
1385      if(!empty($notices)) {
1386          upgrade_log_start();
1387          foreach($notices as $notice) {
1388              notify($notice);
1389          }
1390      }
1391  
1392      // Finally, if we are in the first_install of BLOCKS (this means that we are
1393      // upgrading from Moodle < 1.3), put blocks in all existing courses.
1394      if ($first_install) {
1395          upgrade_log_start();
1396          //Iterate over each course
1397          if ($courses = get_records('course')) {
1398              foreach ($courses as $course) {
1399                  $page = page_create_object(PAGE_COURSE_VIEW, $course->id);
1400                  blocks_repopulate_page($page);
1401              }
1402          }
1403      }
1404  
1405      if (!empty($CFG->siteblocksadded)) {     /// This is a once-off hack to make a proper upgrade
1406          upgrade_log_start();
1407          $page = page_create_object(PAGE_COURSE_VIEW, SITEID);
1408          blocks_repopulate_page($page);
1409          delete_records('config', 'name', 'siteblocksadded');
1410      }
1411  
1412      upgrade_log_finish();
1413  
1414      if (!empty($updated_blocks)) {
1415          print_continue($continueto);
1416          print_footer('none');
1417          die;
1418      }
1419  }
1420  
1421  ?>


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7