[ Index ]

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

title

Body

[close]

/backup/ -> backuplib.php (source)

   1  <?php //$Id: backuplib.php,v 1.179.2.33 2008/09/08 14:25:18 stronk7 Exp $
   2      //This file contains all the function needed in the backup utility
   3      //except the mod-related funtions that are into every backuplib.php inside
   4      //every mod directory
   5  
   6      /**
   7       * This function calculates the users to be added to backup based in the
   8       * settings defined at backup. All the resulting user ids are sent to
   9       * backup_ids for later usage.
  10       * @param int $courseid id of the course to backup
  11       * @param int $backup_unique_code unique code of the backup being executed
  12       * @param int $backup_unique_code setting specifying what users to export (0=all, 1=needed, 2=none)
  13       * @param int $backup_messages flag (true/false) defining if messages must be
  14       *                             considered to extract needed users
  15       * @param int $backup_blogs flag (true/false) defining if blogs must be
  16       *                          considered to extract needed users
  17       * @return array one array (key, value) sumarizing the result of the function (number of users)
  18       */
  19      function user_check_backup($courseid,$backup_unique_code,$backup_users,$backup_messages,$backup_blogs) {
  20  
  21          $context = get_context_instance(CONTEXT_COURSE, $courseid);
  22          $count_users = 0;
  23          $backupable_users = array();
  24  
  25          if ($backup_users == 0) { /// All users
  26              $backupable_users = backup_get_all_users();
  27  
  28          } else if ($backup_users == 1) { /// Needed users
  29  
  30          /// Calculate needed users (calling every xxxx_get_participants function + scales users
  31          /// + messages users + blogs users)
  32              $needed_users = backup_get_needed_users($courseid, $backup_messages, $backup_blogs);
  33  
  34          /// Calculate enrolled users (having course:view cap)
  35              $enrolled_users = backup_get_enrolled_users($courseid);
  36  
  37          /// Calculate backupable users (needed + enrolled)
  38          /// First, needed
  39              $backupable_users = $needed_users;
  40  
  41          /// Now, enrolled
  42              if ($enrolled_users) {
  43                  foreach ($enrolled_users as $enrolled_user) {
  44                      $backupable_users[$enrolled_user->id]->id = $enrolled_user->id;
  45                  }
  46              }
  47          }
  48  
  49      /// If we have backupable users
  50          if ($backupable_users) {
  51          /// Iterate over users putting their roles
  52              foreach ($backupable_users as $backupable_user) {
  53                  $backupable_user->info = "";
  54  
  55              /// Is needed user or enrolled user, mark it as needed
  56                  if (isset($needed_users[$backupable_user->id]) || isset($enrolled_users[$backupable_user->id])) {
  57                      $backupable_user->info .= "needed";
  58                  }   ///  Yu: also needed because they can view course
  59                      /// might need another variable
  60  
  61              /// Now create the backup_id record
  62                  $backupids_rec->backup_code = $backup_unique_code;
  63                  $backupids_rec->table_name = "user";
  64                  $backupids_rec->old_id = $backupable_user->id;
  65                  $backupids_rec->info = $backupable_user->info;
  66  
  67              /// TODO: Change this call inserting to a standard backup_putid() call
  68              /// And read data acordingly with backup_getid() when needed.
  69              /// TODO: Also analyse it the "needed" info is really needed for anything. Drop if not.
  70              /// Insert the user to the backup_ids table. backup_user_info() will use that info
  71                  $status = insert_record('backup_ids', $backupids_rec, false);
  72                  $count_users++;
  73              }
  74          /// Do some output
  75              backup_flush(30);
  76          }
  77  
  78        /// Prepare Info
  79        /// Gets the user data
  80          $info[0][0] = get_string("users");
  81          $info[0][1] = $count_users;
  82  
  83          return $info;
  84      }
  85  
  86      //Returns every needed user (participant) in a course
  87      //It uses the xxxx_get_participants() function
  88      //plus users needed to backup scales.
  89      //Also it search for users having messages and
  90      //users having blogs
  91      //WARNING: It returns only NEEDED users, not every
  92      //   every student and teacher in the course, so it
  93      //must be merged with backup_get_enrrolled_users !!
  94  
  95      function backup_get_needed_users ($courseid, $includemessages=false, $includeblogs=false) {
  96  
  97          global $CFG;
  98  
  99          $result = false;
 100  
 101          $course_modules = get_records_sql ("SELECT cm.id, m.name, cm.instance
 102                                              FROM {$CFG->prefix}modules m,
 103                                                   {$CFG->prefix}course_modules cm
 104                                              WHERE m.id = cm.module and
 105                                                    cm.course = '$courseid'");
 106  
 107          if ($course_modules) {
 108              //Iterate over each module
 109              foreach ($course_modules as $course_module) {
 110                  $modlib = "$CFG->dirroot/mod/$course_module->name/lib.php";
 111                  $modgetparticipants = $course_module->name."_get_participants";
 112                  if (file_exists($modlib)) {
 113                      include_once($modlib);
 114                      if (function_exists($modgetparticipants)) {
 115                          $module_participants = $modgetparticipants($course_module->instance);
 116                          //Add them to result
 117                          if ($module_participants) {
 118                              foreach ($module_participants as $module_participant) {
 119                                  $result[$module_participant->id]->id = $module_participant->id;
 120                              }
 121                          }
 122                      }
 123                   }
 124              }
 125          }
 126  
 127          //Now, add scale users (from site and course scales)
 128          //Get users
 129          $scaleusers = get_records_sql("SELECT DISTINCT userid,userid
 130                                         FROM {$CFG->prefix}scale
 131                                         WHERE courseid = '0' or courseid = '$courseid'");
 132          //Add scale users to results
 133          if ($scaleusers) {
 134              foreach ($scaleusers as $scaleuser) {
 135                  //If userid != 0
 136                  if ($scaleuser->userid != 0) {
 137                      $result[$scaleuser->userid]->id = $scaleuser->userid;
 138                  }
 139              }
 140          }
 141  
 142          //Now, add message users if necessary
 143          if ($includemessages) {
 144              include_once("$CFG->dirroot/message/lib.php");
 145              //Get users
 146              $messageusers = message_get_participants();
 147              //Add message users to results
 148              if ($messageusers) {
 149                  foreach ($messageusers as $messageuser) {
 150                      //If id != 0
 151                      if ($messageuser->id !=0) {
 152                          $result[$messageuser->id]->id = $messageuser->id;
 153                      }
 154                  }
 155              }
 156          }
 157  
 158          //Now, add blog users if necessary
 159          if ($includeblogs) {
 160              include_once("$CFG->dirroot/blog/lib.php");
 161              //Get users
 162              $blogusers = blog_get_participants();
 163              //Add blog users to results
 164              if ($blogusers) {
 165                  foreach ($blogusers as $bloguser) {
 166                      //If id != 0
 167                      if ($bloguser->id !=0) {
 168                          $result[$bloguser->id]->id = $bloguser->id;
 169                      }
 170                  }
 171              }
 172          }
 173  
 174          return $result;
 175  
 176      }
 177  
 178      //Returns every enrolled user (student and teacher) in a course
 179  
 180      function backup_get_enrolled_users ($courseid) {
 181  
 182          global $CFG;
 183  
 184          // get all users with moodle/course:view capability, this will include people
 185          // assigned at cat level, or site level
 186          // but it should be ok if they have no direct assignment at course, mod, block level
 187          return get_users_by_capability(get_context_instance(CONTEXT_COURSE, $courseid), 'moodle/course:view');
 188      }
 189  
 190      //Returns all users ids (every record in users table)
 191      function backup_get_all_users() {
 192  
 193          return get_records('user', '', '', '', 'id, id');
 194      }
 195  
 196      //Calculate the number of log entries to backup
 197      //Return an array of info (name,value)
 198      function log_check_backup($course) {
 199  
 200          global $CFG;
 201  
 202          //Now execute the count
 203          $ids = count_records("log","course",$course);
 204  
 205          //Gets the user data
 206          $info[0][0] = get_string("logs");
 207          if ($ids) {
 208              $info[0][1] = $ids;
 209          } else {
 210              $info[0][1] = 0;
 211          }
 212  
 213          return $info;
 214      }
 215  
 216      //Calculate the number of user files to backup
 217      //Under $CFG->dataroot/users
 218      //Return an array of info (name,value)
 219      function user_files_check_backup($course,$backup_unique_code) {
 220  
 221          global $CFG;
 222          $count = 0;
 223          
 224          $backup_users = get_recordset_select("backup_ids",
 225              "backup_code='$backup_unique_code' AND table_name='user'", "", "id, old_id");
 226   
 227          while ($user = rs_fetch_next_record($backup_users)) {               
 228              //Is this user needed in the backup?
 229              $userdir = make_user_directory($user->old_id, true);
 230              if (check_dir_exists($userdir)) {
 231                  $count++;
 232              }
 233              //Do some output
 234              backup_flush(30);
 235          }
 236          rs_close($backup_users);
 237          //Gets the user data
 238          $info[0][0] = get_string("userswithfiles");
 239          $info[0][1] = $count;
 240  
 241          return $info;
 242      }
 243  
 244      /**
 245       * Calculate the number of course files to backup
 246       * under $CFG->dataroot/$course, except $CFG->moddata, and backupdata
 247       * and put them (their path) in backup_ids
 248       * Return an array of info (name,value)
 249       */
 250      function course_files_check_backup($course, $backup_unique_code) {
 251  
 252          global $CFG;
 253  
 254          $rootdir = $CFG->dataroot."/$course";
 255          //Check if directory exists
 256          if (is_dir($rootdir)) {
 257              //Get files and directories without descend
 258              $coursedirs = get_directory_list($rootdir,$CFG->moddata,false,true,true);
 259              $backupdata_dir = "backupdata";
 260              foreach ($coursedirs as $dir) {
 261                  //Check it isn't backupdata_dir
 262                  if (strpos($dir,$backupdata_dir)!==0) {
 263                      //Insert them into backup_files
 264                      $status = execute_sql("INSERT INTO {$CFG->prefix}backup_files
 265                                                    (backup_code, file_type, path)
 266                                             VALUES
 267                                                ('$backup_unique_code','course','".addslashes($dir)."')",false);
 268                  }
 269              //Do some output
 270              backup_flush(30);
 271              }
 272          }
 273  
 274          //Now execute the select
 275          $ids = get_records_sql("SELECT DISTINCT b.path, b.old_id
 276                                  FROM {$CFG->prefix}backup_files b
 277                                  WHERE backup_code = '$backup_unique_code' AND
 278                                        file_type = 'course'");
 279          //Gets the user data
 280          $info = array();
 281          $info[0] = array();
 282          $info[0][0] = get_string("files");
 283          if ($ids) {
 284              $info[0][1] = count($ids);
 285          } else {
 286              $info[0][1] = 0;
 287          }
 288  
 289          return $info;
 290      }
 291  
 292      /**
 293       * Calculate the number of site files to backup
 294       * under $CFG->dataroot/SITEID
 295       * Their path is already in backup_ids, put there by modules check_backup functions.
 296       * Modules only put in paths of files that are used.
 297       *
 298       * Return an array of info (name,value)
 299       */
 300      function site_files_check_backup($course, $backup_unique_code) {
 301          global $CFG;
 302  
 303          //execute the select, records have been inserted by modules during their ****_check_backup_mods function.
 304          $ids = get_records_sql("SELECT DISTINCT b.path
 305                                  FROM {$CFG->prefix}backup_files b
 306                                  WHERE backup_code = '$backup_unique_code' AND
 307                                        file_type = 'site'");
 308          //Gets the user data
 309          $info = array();
 310          $info[0] = array();
 311          $info[0][0] = get_string('files');
 312          if ($ids) {
 313              $info[0][1] = count($ids);
 314          } else {
 315              $info[0][1] = 0;
 316          }
 317  
 318          return $info;
 319      }
 320  
 321      //Function to check and create the needed moddata dir to
 322      //save all the mod backup files. We always name it moddata
 323      //to be able to restore it, but in restore we check for
 324      //$CFG->moddata !!
 325      function check_and_create_moddata_dir($backup_unique_code) {
 326  
 327          global $CFG;
 328  
 329          $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/moddata",true);
 330  
 331          return $status;
 332      }
 333  
 334      //Function to check and create the "user_files" dir to
 335      //save all the user files we need from "users" dir
 336      function check_and_create_user_files_dir($backup_unique_code) {
 337  
 338          global $CFG;
 339  
 340          $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/user_files",true);
 341  
 342          return $status;
 343      }
 344  
 345      //Function to check and create the "group_files" dir to
 346      //save all the user files we need from "groups" dir
 347      function check_and_create_group_files_dir($backup_unique_code) {
 348  
 349          global $CFG;
 350  
 351          $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/group_files",true);
 352  
 353          return $status;
 354      }
 355  
 356      //Function to check and create the "course_files" dir to
 357      //save all the course files we need from "CFG->datadir/course" dir
 358      function check_and_create_course_files_dir($backup_unique_code) {
 359  
 360          global $CFG;
 361  
 362          $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/course_files",true);
 363  
 364          return $status;
 365      }
 366  
 367      //Function to check and create the "site_files" dir to
 368      //save all the course files we need from "CFG->datadir/SITEID" dir
 369      function check_and_create_site_files_dir($backup_unique_code) {
 370  
 371          global $CFG;
 372  
 373          $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/site_files",true);
 374  
 375          return $status;
 376      }
 377  
 378      //Function to create, open and write header of the xml file
 379      function backup_open_xml($backup_unique_code) {
 380  
 381          global $CFG;
 382  
 383          $status = true;
 384  
 385          //Open for writing
 386  
 387          $file = $CFG->dataroot."/temp/backup/".$backup_unique_code."/moodle.xml";
 388          $backup_file = fopen($file,"w");
 389          //Writes the header
 390          $status = fwrite ($backup_file,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
 391          if ($status) {
 392              $status = fwrite ($backup_file,start_tag("MOODLE_BACKUP",0,true));
 393          }
 394          if ($status) {
 395              return $backup_file;
 396          } else {
 397              return false;
 398          }
 399      }
 400  
 401      //Close the file
 402      function backup_close_xml($backup_file) {
 403          $status = fwrite ($backup_file,end_tag("MOODLE_BACKUP",0,true));
 404          return fclose($backup_file);
 405      }
 406  
 407      //Return the xml start tag
 408      function start_tag($tag,$level=0,$endline=false,$attributes=null) {
 409          if ($endline) {
 410             $endchar = "\n";
 411          } else {
 412             $endchar = "";
 413          }
 414          $attrstring = '';
 415          if (!empty($attributes) && is_array($attributes)) {
 416              foreach ($attributes as $key => $value) {
 417                  $attrstring .= " ".xml_tag_safe_content($key)."=\"".
 418                      xml_tag_safe_content($value)."\"";
 419              }
 420          }
 421          return str_repeat(" ",$level*2)."<".strtoupper($tag).$attrstring.">".$endchar;
 422      }
 423  
 424      //Return the xml end tag
 425      function end_tag($tag,$level=0,$endline=true) {
 426          if ($endline) {
 427             $endchar = "\n";
 428          } else {
 429             $endchar = "";
 430          }
 431          return str_repeat(" ",$level*2)."</".strtoupper($tag).">".$endchar;
 432      }
 433  
 434      //Return the start tag, the contents and the end tag
 435      function full_tag($tag,$level=0,$endline=true,$content,$attributes=null) {
 436  
 437          global $CFG;
 438          //Here we encode absolute links
 439          // MDL-10770
 440          if (is_null($content)) {
 441              $content = '$@NULL@$'; 
 442          } else {
 443              $content = backup_encode_absolute_links($content);
 444          }
 445          $st = start_tag($tag,$level,$endline,$attributes);
 446  
 447          $co = xml_tag_safe_content($content);
 448  
 449          $et = end_tag($tag,0,true);
 450  
 451          return $st.$co.$et;
 452      }
 453  
 454  
 455      function xml_tag_safe_content($content) {
 456          global $CFG;
 457          //If enabled, we strip all the control chars (\x0-\x1f) from the text but tabs (\x9),
 458          //newlines (\xa) and returns (\xd). The delete control char (\x7f) is also included.
 459          //because they are forbiden in XML 1.0 specs. The expression below seems to be
 460          //UTF-8 safe too because it simply ignores the rest of characters.
 461          $content = preg_replace("/[\x-\x8\xb-\xc\xe-\x1f\x7f]/is","",$content);
 462          $content = preg_replace("/\r\n|\r/", "\n", htmlspecialchars($content));
 463          return $content;
 464      }
 465  
 466      //Prints General info about the course
 467      //name, moodle_version (internal and release), backup_version, date, info in file...
 468      function backup_general_info ($bf,$preferences) {
 469  
 470          global $CFG;
 471  
 472          fwrite ($bf,start_tag("INFO",1,true));
 473  
 474          //The name of the backup
 475          fwrite ($bf,full_tag("NAME",2,false,$preferences->backup_name));
 476          //The moodle_version
 477          fwrite ($bf,full_tag("MOODLE_VERSION",2,false,$preferences->moodle_version));
 478          fwrite ($bf,full_tag("MOODLE_RELEASE",2,false,$preferences->moodle_release));
 479          //The backup_version
 480          fwrite ($bf,full_tag("BACKUP_VERSION",2,false,$preferences->backup_version));
 481          fwrite ($bf,full_tag("BACKUP_RELEASE",2,false,$preferences->backup_release));
 482          //The date
 483          fwrite ($bf,full_tag("DATE",2,false,$preferences->backup_unique_code));
 484          //The original site wwwroot
 485          fwrite ($bf,full_tag("ORIGINAL_WWWROOT",2,false,$CFG->wwwroot));
 486          //The zip method used
 487          if (!empty($CFG->zip)) {
 488              $zipmethod = 'external';
 489          } else {
 490              $zipmethod = 'internal';
 491          }
 492          //Indicate if it includes external MNET users
 493          $sql = "SELECT b.old_id
 494                     FROM   {$CFG->prefix}backup_ids b
 495                       JOIN {$CFG->prefix}user       u ON b.old_id=u.id
 496                     WHERE b.backup_code = '$preferences->backup_unique_code'
 497                           AND b.table_name = 'user' AND u.mnethostid != '{$CFG->mnet_localhost_id}'";
 498          if (record_exists_sql($sql)) {
 499              fwrite ($bf,full_tag("MNET_REMOTEUSERS",2,false,'true'));
 500          }
 501          fwrite ($bf,full_tag("ZIP_METHOD",2,false,$zipmethod));
 502          //Te includes tag
 503          fwrite ($bf,start_tag("DETAILS",2,true));
 504          //Now, go to mod element of preferences to print its status
 505          foreach ($preferences->mods as $element) {
 506              //Calculate info
 507              $included = "false";
 508              $userinfo = "false";
 509              if ($element->backup) {
 510                  $included = "true";
 511                  if ($element->userinfo) {
 512                      $userinfo = "true";
 513                  }
 514              }
 515              //Prints the mod start
 516              fwrite ($bf,start_tag("MOD",3,true));
 517              fwrite ($bf,full_tag("NAME",4,false,$element->name));
 518              fwrite ($bf,full_tag("INCLUDED",4,false,$included));
 519              fwrite ($bf,full_tag("USERINFO",4,false,$userinfo));
 520  
 521              if (isset($preferences->mods[$element->name]->instances)
 522                  && is_array($preferences->mods[$element->name]->instances)
 523                  && count($preferences->mods[$element->name]->instances)) {
 524                  fwrite ($bf, start_tag("INSTANCES",4,true));
 525                  foreach ($preferences->mods[$element->name]->instances as $id => $object) {
 526                      if (!empty($object->backup)) {
 527                          //Calculate info
 528                          $included = "false";
 529                          $userinfo = "false";
 530                          if ($object->backup) {
 531                              $included = "true";
 532                              if ($object->userinfo) {
 533                                  $userinfo = "true";
 534                              }
 535                          }
 536                          fwrite ($bf, start_tag("INSTANCE",5,true));
 537                          fwrite ($bf, full_tag("ID",5,false,$id));
 538                          fwrite ($bf, full_tag("NAME",5,false,$object->name));
 539                          fwrite ($bf, full_tag("INCLUDED",5,false,$included)) ;
 540                          fwrite ($bf, full_tag("USERINFO",5,false,$userinfo));
 541                          fwrite ($bf, end_tag("INSTANCE",5,true));
 542                      }
 543                  }
 544                  fwrite ($bf, end_tag("INSTANCES",4,true));
 545              }
 546  
 547  
 548              //Print the end
 549              fwrite ($bf,end_tag("MOD",3,true));
 550          }
 551          //The metacourse in backup
 552          if ($preferences->backup_metacourse == 1) {
 553              fwrite ($bf,full_tag("METACOURSE",3,false,"true"));
 554          } else {
 555              fwrite ($bf,full_tag("METACOURSE",3,false,"false"));
 556          }
 557          //The user in backup
 558          if ($preferences->backup_users == 1) {
 559              fwrite ($bf,full_tag("USERS",3,false,"course"));
 560          } else if ($preferences->backup_users == 0) {
 561              fwrite ($bf,full_tag("USERS",3,false,"all"));
 562          } else {
 563              fwrite ($bf,full_tag("USERS",3,false,"none"));
 564          }
 565          //The logs in backup
 566          if ($preferences->backup_logs == 1) {
 567              fwrite ($bf,full_tag("LOGS",3,false,"true"));
 568          } else {
 569              fwrite ($bf,full_tag("LOGS",3,false,"false"));
 570          }
 571          //The user files
 572          if ($preferences->backup_user_files == 1) {
 573              fwrite ($bf,full_tag("USERFILES",3,false,"true"));
 574          } else {
 575              fwrite ($bf,full_tag("USERFILES",3,false,"false"));
 576          }
 577          //The course files
 578          if ($preferences->backup_course_files == 1) {
 579              fwrite ($bf,full_tag("COURSEFILES",3,false,"true"));
 580          } else {
 581              fwrite ($bf,full_tag("COURSEFILES",3,false,"false"));
 582          }
 583          //The site files
 584          if ($preferences->backup_site_files == 1) {
 585              fwrite ($bf,full_tag("SITEFILES",3,false,"true"));
 586          } else {
 587              fwrite ($bf,full_tag("SITEFILES",3,false,"false"));
 588          }
 589          //The gradebook histories
 590          if ($preferences->backup_gradebook_history == 1) {
 591              fwrite ($bf,full_tag("GRADEBOOKHISTORIES",3,false,"true"));
 592          } else {
 593              fwrite ($bf,full_tag("GRADEBOOKHISTORIES",3,false,"false"));
 594          }
 595          //The messages in backup
 596          if ($preferences->backup_messages == 1 && $preferences->backup_course == SITEID) {
 597              fwrite ($bf,full_tag("MESSAGES",3,false,"true"));
 598          } else {
 599              fwrite ($bf,full_tag("MESSAGES",3,false,"false"));
 600          }
 601          //The blogs in backup
 602          if ($preferences->backup_blogs == 1 && $preferences->backup_course == SITEID) {
 603              fwrite ($bf,full_tag("BLOGS",3,false,"true"));
 604          } else {
 605              fwrite ($bf,full_tag("BLOGS",3,false,"false"));
 606          }
 607          //The mode of writing the block data
 608          fwrite ($bf,full_tag('BLOCKFORMAT',3,false,'instances'));
 609          fwrite ($bf,end_tag("DETAILS",2,true));
 610  
 611          $status = fwrite ($bf,end_tag("INFO",1,true));
 612  
 613          ///Roles stuff goes in here
 614  
 615          fwrite ($bf, start_tag('ROLES', 1, true));
 616          $roles = backup_fetch_roles($preferences);
 617  
 618          $sitecontext = get_context_instance(CONTEXT_SYSTEM);
 619          $coursecontext = get_context_instance(CONTEXT_COURSE, $preferences->backup_course);
 620  
 621          foreach ($roles as $role) {
 622              fwrite ($bf,start_tag('ROLE',2,true));
 623              fwrite ($bf,full_tag('ID', 3, false, $role->id));
 624              fwrite ($bf,full_tag('NAME',3,false,$role->name));
 625              fwrite ($bf,full_tag('SHORTNAME',3,false,$role->shortname));
 626          /// Calculate $role name in course
 627              $nameincourse = role_get_name($role, $coursecontext);
 628              if ($nameincourse != $role->name) {
 629                  fwrite ($bf,full_tag('NAMEINCOURSE', 3, false, $nameincourse));
 630              }
 631              // find and write all default capabilities
 632              fwrite ($bf,start_tag('CAPABILITIES',3,true));
 633              // pull out all default (site context) capabilities
 634              if ($capabilities = role_context_capabilities($role->id, $sitecontext)) {
 635                  foreach ($capabilities as $capability=>$value) {
 636                      fwrite ($bf,start_tag('CAPABILITY',4,true));
 637                      fwrite ($bf,full_tag('NAME', 5, false, $capability));
 638                      fwrite ($bf,full_tag('PERMISSION', 5, false, $value));
 639                      // use this to pull out the other info (timemodified and modifierid)
 640  
 641                      $cap = get_record_sql("SELECT *
 642                                             FROM {$CFG->prefix}role_capabilities
 643                                             WHERE capability = '$capability'
 644                                                   AND contextid = $sitecontext->id
 645                                                   AND roleid = $role->id");
 646                      fwrite ($bf, full_tag("TIMEMODIFIED", 5, false, $cap->timemodified));
 647                      fwrite ($bf, full_tag("MODIFIERID", 5, false, $cap->modifierid));
 648                      fwrite ($bf,end_tag('CAPABILITY',4,true));
 649                  }
 650              }
 651              fwrite ($bf,end_tag('CAPABILITIES',3,true));
 652              fwrite ($bf,end_tag('ROLE',2,true));
 653          }
 654          fwrite ($bf,end_tag('ROLES', 1, true));
 655          return $status;
 656      }
 657  
 658      //Prints course's general info (table course)
 659      function backup_course_start ($bf,$preferences) {
 660  
 661          global $CFG;
 662  
 663          $status = true;
 664  
 665          //Course open tag
 666          fwrite ($bf,start_tag("COURSE",1,true));
 667          //Header open tag
 668          fwrite ($bf,start_tag("HEADER",2,true));
 669  
 670          //Get info from course
 671          $course = get_record("course","id",$preferences->backup_course);
 672          $context = get_context_instance(CONTEXT_COURSE, $course->id);
 673          if ($course) {
 674              //Prints course info
 675              fwrite ($bf,full_tag("ID",3,false,$course->id));
 676              //Obtain the category
 677              $category = get_record("course_categories","id","$course->category");
 678              if ($category) {
 679                  //Prints category info
 680                  fwrite ($bf,start_tag("CATEGORY",3,true));
 681                  fwrite ($bf,full_tag("ID",4,false,$course->category));
 682                  fwrite ($bf,full_tag("NAME",4,false,$category->name));
 683                  fwrite ($bf,end_tag("CATEGORY",3,true));
 684              }
 685              //Continues with the course
 686              fwrite ($bf,full_tag("PASSWORD",3,false,$course->password));
 687              fwrite ($bf,full_tag("FULLNAME",3,false,$course->fullname));
 688              fwrite ($bf,full_tag("SHORTNAME",3,false,$course->shortname));
 689              fwrite ($bf,full_tag("IDNUMBER",3,false,$course->idnumber));
 690              fwrite ($bf,full_tag("SUMMARY",3,false,$course->summary));
 691              fwrite ($bf,full_tag("FORMAT",3,false,$course->format));
 692              fwrite ($bf,full_tag("SHOWGRADES",3,false,$course->showgrades));
 693              fwrite ($bf,full_tag("NEWSITEMS",3,false,$course->newsitems));
 694              fwrite ($bf,full_tag("TEACHER",3,false,$course->teacher));
 695              fwrite ($bf,full_tag("TEACHERS",3,false,$course->teachers));
 696              fwrite ($bf,full_tag("STUDENT",3,false,$course->student));
 697              fwrite ($bf,full_tag("STUDENTS",3,false,$course->students));
 698              fwrite ($bf,full_tag("GUEST",3,false,$course->guest));
 699              fwrite ($bf,full_tag("STARTDATE",3,false,$course->startdate));
 700              fwrite ($bf,full_tag("NUMSECTIONS",3,false,$course->numsections));
 701              //fwrite ($bf,full_tag("SHOWRECENT",3,false,$course->showrecent));    INFO: This is out in 1.3
 702              fwrite ($bf,full_tag("MAXBYTES",3,false,$course->maxbytes));
 703              fwrite ($bf,full_tag("SHOWREPORTS",3,false,$course->showreports));
 704              fwrite ($bf,full_tag("GROUPMODE",3,false,$course->groupmode));
 705              fwrite ($bf,full_tag("GROUPMODEFORCE",3,false,$course->groupmodeforce));
 706              fwrite ($bf,full_tag("DEFAULTGROUPINGID",3,false,$course->defaultgroupingid));
 707              fwrite ($bf,full_tag("LANG",3,false,$course->lang));
 708              fwrite ($bf,full_tag("THEME",3,false,$course->theme));
 709              fwrite ($bf,full_tag("COST",3,false,$course->cost));
 710              fwrite ($bf,full_tag("CURRENCY",3,false,$course->currency));
 711              fwrite ($bf,full_tag("MARKER",3,false,$course->marker));
 712              fwrite ($bf,full_tag("VISIBLE",3,false,$course->visible));
 713              fwrite ($bf,full_tag("HIDDENSECTIONS",3,false,$course->hiddensections));
 714              fwrite ($bf,full_tag("TIMECREATED",3,false,$course->timecreated));
 715              fwrite ($bf,full_tag("TIMEMODIFIED",3,false,$course->timemodified));
 716              //If not selected, force metacourse to 0
 717              if (!$preferences->backup_metacourse) {
 718                  $status = fwrite ($bf,full_tag("METACOURSE",3,false,'0'));
 719              //else, export the field as is in DB
 720              } else {
 721                  $status = fwrite ($bf,full_tag("METACOURSE",3,false,$course->metacourse));
 722              }
 723              fwrite ($bf,full_tag("EXPIRENOTIFY",3,false,$course->expirynotify));
 724              fwrite ($bf,full_tag("NOTIFYSTUDENTS",3,false,$course->notifystudents));
 725              fwrite ($bf,full_tag("EXPIRYTHRESHOLD",3,false,$course->expirythreshold));
 726              fwrite ($bf,full_tag("ENROLLABLE",3,false,$course->enrollable));
 727              fwrite ($bf,full_tag("ENROLSTARTDATE",3,false,$course->enrolstartdate));
 728              fwrite ($bf,full_tag("ENROLENDDATE",3,false,$course->enrolenddate));
 729              fwrite ($bf,full_tag("ENROLPERIOD",3,false,$course->enrolperiod));
 730  
 731              /// write local course overrides here?
 732              write_role_overrides_xml($bf, $context, 3);
 733              /// write role_assign code here
 734              write_role_assignments_xml($bf, $preferences, $context, 3);
 735              //Print header end
 736              fwrite ($bf,end_tag("HEADER",2,true));
 737          } else {
 738             $status = false;
 739          }
 740  
 741         return $status;
 742      }
 743  
 744      //Prints course's end tag
 745      function backup_course_end ($bf,$preferences) {
 746  
 747          //Course end tag
 748          $status = fwrite ($bf,end_tag("COURSE",1,true));
 749  
 750          return $status;
 751  
 752      }
 753  
 754      //Prints course's metacourse info (table course_meta)
 755      function backup_course_metacourse ($bf,$preferences) {
 756  
 757          global $CFG;
 758  
 759          $status = true;
 760  
 761          //Get info from meta
 762          $parents = get_records_sql ("SELECT m.*, c.idnumber, c.shortname
 763                                       FROM {$CFG->prefix}course_meta m,
 764                                            {$CFG->prefix}course c
 765                                            WHERE m.child_course = '$preferences->backup_course' AND
 766                                                  m.parent_course = c.id");
 767          $childs =  get_records_sql ("SELECT m.*, c.idnumber, c.shortname
 768                                       FROM {$CFG->prefix}course_meta m,
 769                                            {$CFG->prefix}course c
 770                                            WHERE m.parent_course = '$preferences->backup_course' AND
 771                                                  m.child_course = c.id");
 772  
 773          if ($parents || $childs) {
 774              //metacourse open tag
 775              fwrite ($bf,start_tag("METACOURSE",2,true));
 776              if ($parents) {
 777                  fwrite($bf, start_tag("PARENTS",3,true));
 778                  //Iterate over every parent
 779                  foreach ($parents as $parent) {
 780                      //Begin parent
 781                      fwrite ($bf,start_tag("PARENT",4,true));
 782                      fwrite ($bf,full_tag("ID",5,false,$parent->parent_course));
 783                      fwrite ($bf,full_tag("IDNUMBER",5,false,$parent->idnumber));
 784                      fwrite ($bf,full_tag("SHORTNAME",5,false,$parent->shortname));
 785                      //End parent
 786                      fwrite ($bf,end_tag("PARENT",4,true));
 787                  }
 788                  fwrite ($bf,end_tag("PARENTS",3,true));
 789              }
 790              if ($childs) {
 791                  fwrite($bf, start_tag("CHILDS",3,true));
 792                  //Iterate over every child
 793                  foreach ($childs as $child) {
 794                      //Begin parent
 795                      fwrite ($bf,start_tag("CHILD",4,true));
 796                      fwrite ($bf,full_tag("ID",5,false,$child->child_course));
 797                      fwrite ($bf,full_tag("IDNUMBER",5,false,$child->idnumber));
 798                      fwrite ($bf,full_tag("SHORTNAME",5,false,$child->shortname));
 799                      //End parent
 800                      fwrite ($bf,end_tag("CHILD",4,true));
 801                  }
 802                  fwrite ($bf,end_tag("CHILDS",3,true));
 803              }
 804              //metacourse close tag
 805              $status = fwrite ($bf,end_tag("METACOURSE",3,true));
 806          }
 807  
 808          return $status;
 809  
 810      }
 811  
 812      //Prints course's messages info (tables message, message_read and message_contacts)
 813      function backup_messages ($bf,$preferences) {
 814  
 815          global $CFG;
 816  
 817          $status = true;
 818  
 819      /// Check we have something to backup
 820          $unreads = count_records ('message');
 821          $reads   = count_records ('message_read');
 822          $contacts= count_records ('message_contacts');
 823  
 824          if ($unreads || $reads || $contacts) {
 825              $counter = 0;
 826          /// message open tag
 827              fwrite ($bf,start_tag("MESSAGES",2,true));
 828  
 829              if ($unreads) {
 830                  $rs_unreads = get_recordset('message');
 831              /// Iterate over every unread
 832                  while ($unread = rs_fetch_next_record($rs_unreads)) {
 833                  /// start message
 834                      fwrite($bf, start_tag("MESSAGE",3,true));
 835                      fwrite ($bf,full_tag("ID",4,false,$unread->id));
 836                      fwrite ($bf,full_tag("STATUS",4,false,"UNREAD"));
 837                      fwrite ($bf,full_tag("USERIDFROM",4,false,$unread->useridfrom));
 838                      fwrite ($bf,full_tag("USERIDTO",4,false,$unread->useridto));
 839                      fwrite ($bf,full_tag("MESSAGE",4,false,$unread->message));
 840                      fwrite ($bf,full_tag("FORMAT",4,false,$unread->format));
 841                      fwrite ($bf,full_tag("TIMECREATED",4,false,$unread->timecreated));
 842                      fwrite ($bf,full_tag("MESSAGETYPE",4,false,$unread->messagetype));
 843                  /// end message
 844                      fwrite ($bf,end_tag("MESSAGE",3,true));
 845  
 846                  /// Do some output
 847                      $counter++;
 848                      if ($counter % 20 == 0) {
 849                          echo ".";
 850                          if ($counter % 400 == 0) {
 851                              echo "<br />";
 852                          }
 853                          backup_flush(300);
 854                      }
 855                  }
 856                  rs_close($rs_unreads);
 857              }
 858  
 859              if ($reads) {
 860                  $rs_reads = get_recordset('message_read');
 861              /// Iterate over every unread
 862                  while ($read = rs_fetch_next_record($rs_reads)) {
 863                  /// start message
 864                      fwrite($bf, start_tag("MESSAGE",3,true));
 865                      fwrite ($bf,full_tag("ID",4,false,$read->id));
 866                      fwrite ($bf,full_tag("STATUS",4,false,"READ"));
 867                      fwrite ($bf,full_tag("USERIDFROM",4,false,$read->useridfrom));
 868                      fwrite ($bf,full_tag("USERIDTO",4,false,$read->useridto));
 869                      fwrite ($bf,full_tag("MESSAGE",4,false,$read->message));
 870                      fwrite ($bf,full_tag("FORMAT",4,false,$read->format));
 871                      fwrite ($bf,full_tag("TIMECREATED",4,false,$read->timecreated));
 872                      fwrite ($bf,full_tag("MESSAGETYPE",4,false,$read->messagetype));
 873                      fwrite ($bf,full_tag("TIMEREAD",4,false,$read->timeread));
 874                      fwrite ($bf,full_tag("MAILED",4,false,$read->mailed));
 875                  /// end message
 876                      fwrite ($bf,end_tag("MESSAGE",3,true));
 877  
 878                  /// Do some output
 879                      $counter++;
 880                      if ($counter % 20 == 0) {
 881                          echo ".";
 882                          if ($counter % 400 == 0) {
 883                              echo "<br />";
 884                          }
 885                          backup_flush(300);
 886                      }
 887                  }
 888                  rs_close($rs_reads);
 889              }
 890  
 891              if ($contacts) {
 892                  fwrite($bf, start_tag("CONTACTS",3,true));
 893                  $rs_contacts = get_recordset('message_contacts');
 894              /// Iterate over every contact
 895                  while ($contact = rs_fetch_next_record($rs_contacts)) {
 896                  /// start contact
 897                      fwrite($bf, start_tag("CONTACT",4,true));
 898                      fwrite ($bf,full_tag("ID",5,false,$contact->id));
 899                      fwrite ($bf,full_tag("USERID",5,false,$contact->userid));
 900                      fwrite ($bf,full_tag("CONTACTID",5,false,$contact->contactid));
 901                      fwrite ($bf,full_tag("BLOCKED",5,false,$contact->blocked));
 902                  /// end contact
 903                      fwrite ($bf,end_tag("CONTACT",4,true));
 904  
 905                  /// Do some output
 906                      $counter++;
 907                      if ($counter % 20 == 0) {
 908                          echo ".";
 909                          if ($counter % 400 == 0) {
 910                              echo "<br />";
 911                          }
 912                          backup_flush(300);
 913                      }
 914                  }
 915                  rs_close($rs_contacts);
 916                  fwrite($bf, end_tag("CONTACTS",3,true));
 917              }
 918  
 919          /// messages close tag
 920              $status = fwrite ($bf,end_tag("MESSAGES",2,true));
 921          }
 922  
 923          return $status;
 924  
 925      }
 926  
 927      //Print blogs info (post table, module=blog, course=0)
 928      function backup_blogs($bf, $preferences) {
 929  
 930          global $CFG;
 931  
 932          $status = true;
 933  
 934      /// Check we have something to backup
 935          $siteblogs = count_records('post', 'module', 'blog', 'courseid', 0);
 936  
 937          if ($siteblogs) {
 938              $counter = 0;
 939          /// blogs open tag
 940              fwrite ($bf, start_tag("BLOGS",2,true));
 941  
 942              if ($siteblogs) {
 943                  $rs_blogs = get_recordset_sql("SELECT * from {$CFG->prefix}post
 944                                                  WHERE module = 'blog'
 945                                                    AND courseid = 0");
 946              /// Iterate over every blog
 947                  while ($blog = rs_fetch_next_record($rs_blogs)) {
 948                  /// start blog
 949                      fwrite($bf, start_tag("BLOG",3,true));
 950                  /// blog body
 951                      fwrite ($bf,full_tag("ID",4,false,$blog->id));
 952                      fwrite ($bf,full_tag("MODULE",4,false,$blog->module));
 953                      fwrite ($bf,full_tag("USERID",4,false,$blog->userid));
 954                      fwrite ($bf,full_tag("COURSEID",4,false,$blog->courseid));
 955                      fwrite ($bf,full_tag("GROUPID",4,false,$blog->groupid));
 956                      fwrite ($bf,full_tag("MODULEID",4,false,$blog->moduleid));
 957                      fwrite ($bf,full_tag("COURSEMODULEID",4,false,$blog->coursemoduleid));
 958                      fwrite ($bf,full_tag("SUBJECT",4,false,$blog->subject));
 959                      fwrite ($bf,full_tag("SUMMARY",4,false,$blog->summary));
 960                      fwrite ($bf,full_tag("CONTENT",4,false,$blog->content));
 961                      fwrite ($bf,full_tag("UNIQUEHASH",4,false,$blog->uniquehash));
 962                      fwrite ($bf,full_tag("RATING",4,false,$blog->rating));
 963                      fwrite ($bf,full_tag("FORMAT",4,false,$blog->format));
 964                      fwrite ($bf,full_tag("ATTACHMENT",4,false,$blog->attachment));
 965                      fwrite ($bf,full_tag("PUBLISHSTATE",4,false,$blog->publishstate));
 966                      fwrite ($bf,full_tag("LASTMODIFIED",4,false,$blog->lastmodified));
 967                      fwrite ($bf,full_tag("CREATED",4,false,$blog->created));
 968                      fwrite ($bf,full_tag("USERMODIFIED",4,false,$blog->usermodified));
 969  
 970                  /// Blog tags
 971                  /// Check if we have blog tags to backup
 972                      if (!empty($CFG->usetags)) {
 973                          if ($tags = tag_get_tags('post', $blog->id)) { //This return them ordered by default
 974                          /// Start BLOG_TAGS tag
 975                              fwrite ($bf,start_tag("BLOG_TAGS",4,true));
 976                          /// Write blog tags fields
 977                              foreach ($tags as $tag) {
 978                                  fwrite ($bf,start_tag("BLOG_TAG",5,true));
 979                                  fwrite ($bf,full_tag("NAME",6,false,$tag->name));
 980                                  fwrite ($bf,full_tag("RAWNAME",6,false,$tag->rawname));
 981                                  fwrite ($bf,end_tag("BLOG_TAG",5,true));
 982                              }
 983                          /// End BLOG_TAGS tag
 984                              fwrite ($bf,end_tag("BLOG_TAGS",4,true));
 985                          }
 986                      }
 987  
 988                  /// Blog comments
 989                      /// TODO: Blog comments go here (2.0)
 990  
 991                  /// end blog
 992                      fwrite($bf, end_tag("BLOG",3,true));
 993  
 994                  /// Do some output
 995                      $counter++;
 996                      if ($counter % 20 == 0) {
 997                          echo ".";
 998                          if ($counter % 400 == 0) {
 999                              echo "<br />";
1000                          }
1001                          backup_flush(300);
1002                      }
1003                  }
1004                  rs_close($rs_blogs);
1005              }
1006          /// blogs close tag
1007              $status = fwrite($bf, end_tag("BLOGS",2,true));
1008          }
1009  
1010          return $status;
1011      }
1012  
1013      //Prints course's blocks info (table block_instance)
1014      function backup_course_blocks ($bf,$preferences) {
1015  
1016          global $CFG;
1017  
1018          $status = true;
1019  
1020          // Read all of the block table
1021          $blocks = blocks_get_record();
1022  
1023          $pages = array();
1024          $pages[] = page_create_object(PAGE_COURSE_VIEW, $preferences->backup_course);
1025  
1026          if (!empty($CFG->showblocksonmodpages)) {
1027              // get course structure
1028              $course  = get_record('course', 'id', $preferences->backup_course);
1029              $modinfo =& get_fast_modinfo($course);
1030  
1031              foreach($preferences->mods as $module) {
1032                  if (!$module->backup) {
1033                      continue;
1034                  }
1035  
1036                  if (empty($modinfo->instances[$module->name])) {
1037                      continue;
1038                  }
1039  
1040                  $pagetypes = page_import_types('mod/'.$module->name.'/');
1041                  if (empty($pagetypes)) {
1042                      continue;
1043                  }
1044  
1045                  foreach($pagetypes as $pagetype) {
1046                      foreach($modinfo->instances[$module->name] as $cm) {
1047                          if (!empty($module->instances[$cm->instance]->backup)) {
1048                              $pages[] = page_create_object($pagetype, $cm->instance);
1049                          }
1050                      }
1051                  }
1052              }
1053          }
1054  
1055          //Blocks open tag
1056          fwrite ($bf,start_tag('BLOCKS',2,true));
1057  
1058          foreach($pages as $page) {
1059              if ($instances = blocks_get_by_page($page)) {
1060                  //Iterate over every block
1061                  foreach ($instances as $position) {
1062                      foreach ($position as $instance) {
1063  
1064                          //If we somehow have a block with an invalid id, skip it
1065                          if(empty($blocks[$instance->blockid]->name)) {
1066                              continue;
1067                          }
1068                          $blockname = $blocks[$instance->blockid]->name;
1069  
1070                          if (!$blockobj = block_instance($blockname, $instance)) {
1071                              // Invalid block
1072                              continue;
1073                          }
1074  
1075                          // encode absolute links in block config
1076                          $instance->configdata = $blockobj->get_backup_encoded_config();
1077  
1078                          //Begin Block
1079                          fwrite ($bf,start_tag('BLOCK',3,true));
1080                          fwrite ($bf,full_tag('ID', 4, false,$instance->id));
1081                          fwrite ($bf,full_tag('NAME',4,false,$blockname));
1082                          fwrite ($bf,full_tag('PAGEID',4,false,$instance->pageid));
1083                          fwrite ($bf,full_tag('PAGETYPE',4,false,$instance->pagetype));
1084                          fwrite ($bf,full_tag('POSITION',4,false,$instance->position));
1085                          fwrite ($bf,full_tag('WEIGHT',4,false,$instance->weight));
1086                          fwrite ($bf,full_tag('VISIBLE',4,false,$instance->visible));
1087                          fwrite ($bf,full_tag('CONFIGDATA',4,false,$instance->configdata));
1088                          // Write instance data if needed
1089                          if ($blockobj->backuprestore_instancedata_used()) {
1090                              fwrite ($bf,start_tag('INSTANCEDATA',4,true));
1091                              $status = $blockobj->instance_backup($bf, $preferences);
1092                              fwrite ($bf,end_tag('INSTANCEDATA',4,true));
1093                          }
1094                          $context = get_context_instance(CONTEXT_BLOCK, $instance->id);
1095                          write_role_overrides_xml($bf, $context, 4);
1096                          /// write role_assign code here
1097                          write_role_assignments_xml($bf, $preferences, $context, 4);
1098                          //End Block
1099                          fwrite ($bf,end_tag('BLOCK',3,true));
1100                      }
1101                  }
1102              }
1103          }
1104  
1105          //Blocks close tag
1106          $status = fwrite ($bf,end_tag('BLOCKS',2,true));
1107  
1108          return $status;
1109  
1110      }
1111  
1112      //Prints course's sections info (table course_sections)
1113      function backup_course_sections ($bf,$preferences) {
1114  
1115          global $CFG;
1116  
1117          $status = true;
1118  
1119  
1120          //Get info from sections
1121          $section=false;
1122          if ($sections = get_records("course_sections","course",$preferences->backup_course,"section")) {
1123              //Section open tag
1124              fwrite ($bf,start_tag("SECTIONS",2,true));
1125              //Iterate over every section (ordered by section)
1126              foreach ($sections as $section) {
1127                  //Begin Section
1128                  fwrite ($bf,start_tag("SECTION",3,true));
1129                  fwrite ($bf,full_tag("ID",4,false,$section->id));
1130                  fwrite ($bf,full_tag("NUMBER",4,false,$section->section));
1131                  fwrite ($bf,full_tag("SUMMARY",4,false,$section->summary));
1132                  fwrite ($bf,full_tag("VISIBLE",4,false,$section->visible));
1133                  //Now print the mods in section
1134                  backup_course_modules ($bf,$preferences,$section);
1135                  //End section
1136                  fwrite ($bf,end_tag("SECTION",3,true));
1137              }
1138              //Section close tag
1139              $status = fwrite ($bf,end_tag("SECTIONS",2,true));
1140          }
1141  
1142          return $status;
1143  
1144      }
1145  
1146      //Prints course's format data (any data the format might want to save).
1147      function backup_format_data ($bf,$preferences) {
1148          global $CFG;
1149  
1150          // Check course format
1151          if(!($format=get_field('course','format','id',$preferences->backup_course))) {
1152                  return false;
1153          }
1154          // Write appropriate tag. Note that we always put this tag there even if
1155          // blank, it makes parsing easier
1156          fwrite ($bf,start_tag("FORMATDATA",2,true));
1157  
1158          $file=$CFG->dirroot."/course/format/$format/backuplib.php";
1159          if(file_exists($file)) {
1160              // If the file is there, the function must be or it's an error.
1161              require_once($file);
1162              $function=$format.'_backup_format_data';
1163              if(!function_exists($function)) {
1164                      return false;
1165              }
1166              if(!$function($bf,$preferences)) {
1167                      return false;
1168              }
1169          }
1170  
1171          // This last return just checks the file writing has been ok (ish)
1172          return fwrite ($bf,end_tag("FORMATDATA",2,true));
1173      }
1174  
1175      //Prints course's modules info (table course_modules)
1176      //Only for selected mods in preferences
1177      function backup_course_modules ($bf,$preferences,$section) {
1178  
1179          global $CFG;
1180  
1181          $status = true;
1182  
1183          $first_record = true;
1184  
1185          //Now print the mods in section
1186          //Extracts mod id from sequence
1187          $tok = strtok($section->sequence,",");
1188          while ($tok) {
1189             //Get module's type
1190             $moduletype = get_module_type ($preferences->backup_course,$tok);
1191             //Check if we've selected to backup that type
1192             if ($moduletype and $preferences->mods[$moduletype]->backup) {
1193                 $selected = true;
1194             } else {
1195                 $selected = false;
1196             }
1197  
1198             if ($selected) {
1199                 $context = get_context_instance(CONTEXT_MODULE, $tok);
1200                 //Gets course_module data from db - verify activity exists and is enabled!
1201                 $sql = "SELECT cm.*
1202                           FROM {$CFG->prefix}course_modules cm
1203                                JOIN {$CFG->prefix}modules m     ON m.id = cm.module
1204                                JOIN {$CFG->prefix}$moduletype a ON a.id = cm.instance
1205                          WHERE m.visible = 1 AND cm.id = $tok";
1206                 if (!$course_module = get_record_sql($sql)) {
1207                     // cm exists but activity instance missing - probably caused by double clicking
1208                     $tok = strtok(",");
1209                     continue;
1210                 }
1211  
1212                 //If it's the first, pring MODS tag
1213                 if ($first_record) {
1214                     fwrite ($bf,start_tag("MODS",4,true));
1215                     $first_record = false;
1216                 }
1217                 // if we're doing selected instances, check that too.
1218                 if (is_array($preferences->mods[$moduletype]->instances)
1219                     && count($preferences->mods[$moduletype]->instances)
1220                     && (!array_key_exists($course_module->instance,$preferences->mods[$moduletype]->instances)
1221                         || empty($preferences->mods[$moduletype]->instances[$course_module->instance]->backup))) {
1222                     $tok = strtok(",");
1223                     continue;
1224                 }
1225  
1226                 // find all role values that has an override in this context
1227                 $roles = get_records('role_capabilities', 'contextid', $context->id);
1228  
1229                 //Print mod info from course_modules
1230                 fwrite ($bf,start_tag("MOD",5,true));
1231                 //Save neccesary info to backup_ids
1232                 fwrite ($bf,full_tag("ID",6,false,$tok));
1233                 fwrite ($bf,full_tag("TYPE",6,false,$moduletype));
1234                 fwrite ($bf,full_tag("INSTANCE",6,false,$course_module->instance));
1235                 fwrite ($bf,full_tag("ADDED",6,false,$course_module->added));
1236                 fwrite ($bf,full_tag("SCORE",6,false,$course_module->score));
1237                 fwrite ($bf,full_tag("INDENT",6,false,$course_module->indent));
1238                 fwrite ($bf,full_tag("VISIBLE",6,false,$course_module->visible));
1239                 fwrite ($bf,full_tag("GROUPMODE",6,false,$course_module->groupmode));
1240                 fwrite ($bf,full_tag("GROUPINGID",6,false,$course_module->groupingid));
1241                 fwrite ($bf,full_tag("GROUPMEMBERSONLY",6,false,$course_module->groupmembersonly));
1242                 fwrite ($bf,full_tag("IDNUMBER",6,false,$course_module->idnumber));
1243                 // get all the role_capabilities overrides in this mod
1244                 write_role_overrides_xml($bf, $context, 6);
1245                 /// write role_assign code here
1246                 write_role_assignments_xml($bf, $preferences, $context, 6);
1247                 /// write role_assign code here
1248  
1249                 fwrite ($bf,end_tag("MOD",5,true));
1250             }
1251             //check for next
1252             $tok = strtok(",");
1253          }
1254  
1255          //Si ha habido modulos, final de MODS
1256          if (!$first_record) {
1257              $status =fwrite ($bf,end_tag("MODS",4,true));
1258          }
1259  
1260          return $status;
1261      }
1262  
1263      //Print users to xml
1264      //Only users previously calculated in backup_ids will output
1265      //
1266      function backup_user_info ($bf,$preferences) {
1267  
1268          global $CFG;
1269          require_once ($CFG->dirroot.'/tag/lib.php');
1270  
1271          $status = true;
1272  
1273          // Use a recordset to for the memory handling on to
1274          // the DB and run faster
1275          $users = get_recordset_sql("SELECT b.old_id, b.table_name, b.info,
1276                                             u.*, m.wwwroot
1277                                      FROM   {$CFG->prefix}backup_ids b
1278                                        JOIN {$CFG->prefix}user       u ON b.old_id=u.id
1279                                        JOIN {$CFG->prefix}mnet_host  m ON u.mnethostid=m.id
1280                                      WHERE b.backup_code = '$preferences->backup_unique_code' AND
1281                                            b.table_name = 'user'");
1282  
1283          //If we have users to backup
1284          if ($users && !rs_EOF($users)) {
1285              //Begin Users tag
1286              fwrite ($bf,start_tag("USERS",2,true));
1287              $counter = 0;
1288              //With every user
1289              while ($user = rs_fetch_next_record($users)) {
1290                  //Begin User tag
1291                  fwrite ($bf,start_tag("USER",3,true));
1292                  //Output all user data
1293                  fwrite ($bf,full_tag("ID",4,false,$user->id));
1294                  fwrite ($bf,full_tag("AUTH",4,false,$user->auth));
1295                  fwrite ($bf,full_tag("CONFIRMED",4,false,$user->confirmed));
1296                  fwrite ($bf,full_tag("POLICYAGREED",4,false,$user->policyagreed));
1297                  fwrite ($bf,full_tag("DELETED",4,false,$user->deleted));
1298                  fwrite ($bf,full_tag("USERNAME",4,false,$user->username));
1299                  fwrite ($bf,full_tag("PASSWORD",4,false,$user->password));
1300                  fwrite ($bf,full_tag("IDNUMBER",4,false,$user->idnumber));
1301                  fwrite ($bf,full_tag("FIRSTNAME",4,false,$user->firstname));
1302                  fwrite ($bf,full_tag("LASTNAME",4,false,$user->lastname));
1303                  fwrite ($bf,full_tag("EMAIL",4,false,$user->email));
1304                  fwrite ($bf,full_tag("EMAILSTOP",4,false,$user->emailstop));
1305                  fwrite ($bf,full_tag("ICQ",4,false,$user->icq));
1306                  fwrite ($bf,full_tag("SKYPE",4,false,$user->skype));
1307                  fwrite ($bf,full_tag("YAHOO",4,false,$user->yahoo));
1308                  fwrite ($bf,full_tag("AIM",4,false,$user->aim));
1309                  fwrite ($bf,full_tag("MSN",4,false,$user->msn));
1310                  fwrite ($bf,full_tag("PHONE1",4,false,$user->phone1));
1311                  fwrite ($bf,full_tag("PHONE2",4,false,$user->phone2));
1312                  fwrite ($bf,full_tag("INSTITUTION",4,false,$user->institution));
1313                  fwrite ($bf,full_tag("DEPARTMENT",4,false,$user->department));
1314                  fwrite ($bf,full_tag("ADDRESS",4,false,$user->address));
1315                  fwrite ($bf,full_tag("CITY",4,false,$user->city));
1316                  fwrite ($bf,full_tag("COUNTRY",4,false,$user->country));
1317                  fwrite ($bf,full_tag("LANG",4,false,$user->lang));
1318                  fwrite ($bf,full_tag("THEME",4,false,$user->theme));
1319                  fwrite ($bf,full_tag("TIMEZONE",4,false,$user->timezone));
1320                  fwrite ($bf,full_tag("FIRSTACCESS",4,false,$user->firstaccess));
1321                  fwrite ($bf,full_tag("LASTACCESS",4,false,$user->lastaccess));
1322                  fwrite ($bf,full_tag("LASTLOGIN",4,false,$user->lastlogin));
1323                  fwrite ($bf,full_tag("CURRENTLOGIN",4,false,$user->currentlogin));
1324                  fwrite ($bf,full_tag("LASTIP",4,false,$user->lastip));
1325                  fwrite ($bf,full_tag("SECRET",4,false,$user->secret));
1326                  fwrite ($bf,full_tag("PICTURE",4,false,$user->picture));
1327                  fwrite ($bf,full_tag("URL",4,false,$user->url));
1328                  fwrite ($bf,full_tag("DESCRIPTION",4,false,$user->description));
1329                  fwrite ($bf,full_tag("MAILFORMAT",4,false,$user->mailformat));
1330                  fwrite ($bf,full_tag("MAILDIGEST",4,false,$user->maildigest));
1331                  fwrite ($bf,full_tag("MAILDISPLAY",4,false,$user->maildisplay));
1332                  fwrite ($bf,full_tag("HTMLEDITOR",4,false,$user->htmleditor));
1333                  fwrite ($bf,full_tag("AJAX",4,false,$user->ajax));
1334                  fwrite ($bf,full_tag("AUTOSUBSCRIBE",4,false,$user->autosubscribe));
1335                  fwrite ($bf,full_tag("TRACKFORUMS",4,false,$user->trackforums));
1336                  if ($user->mnethostid != $CFG->mnet_localhost_id) {
1337                      fwrite ($bf,full_tag("MNETHOSTURL",4,false,$user->wwwroot));
1338                  }
1339                  fwrite ($bf,full_tag("TIMEMODIFIED",4,false,$user->timemodified));
1340  
1341                  /// write assign/override code for context_userid
1342  
1343                  $user->isneeded = strpos($user->info,"needed");
1344  
1345                  fwrite ($bf,start_tag("ROLES",4,true));
1346                  if ($user->info != "needed" && $user->info!="") {
1347                      //PRINT ROLE INFO
1348                      $roles = explode(",", $user->info);
1349                      foreach ($roles as $role) {
1350                          if ($role!="" && $role!="needed") {
1351                              fwrite ($bf,start_tag("ROLE",5,true));
1352                              //Print Role info
1353                              fwrite ($bf,full_tag("TYPE",6,false,$role));
1354                              //Print ROLE end
1355                              fwrite ($bf,end_tag("ROLE",5,true));
1356                          }
1357                      }
1358                  }
1359                      //Needed
1360                  if ($user->isneeded!==false) {
1361                      //Print ROLE start
1362                      fwrite ($bf,start_tag("ROLE",5,true));
1363                      //Print Role info
1364                      fwrite ($bf,full_tag("TYPE",6,false,"needed"));
1365                      //Print ROLE end
1366                      fwrite ($bf,end_tag("ROLE",5,true));
1367                  }
1368  
1369                      //End ROLES tag
1370                  fwrite ($bf,end_tag("ROLES",4,true));
1371  
1372                  //Check if we have custom profile fields to backup
1373                  if ($cpfields = get_records_sql("SELECT uif.shortname, uif.datatype, uid.data
1374                                                   FROM {$CFG->prefix}user_info_field uif,
1375                                                        {$CFG->prefix}user_info_data uid
1376                                                   WHERE uif.id = uid.fieldid
1377                                                     AND uid.userid = $user->id")) {
1378                      //Start USER_CUSTOM_PROFILE_FIELDS tag
1379                      fwrite ($bf,start_tag("USER_CUSTOM_PROFILE_FIELDS",4,true));
1380                      //Write custom profile fields
1381                      foreach ($cpfields as $cpfield) {
1382                          fwrite ($bf,start_tag("USER_CUSTOM_PROFILE_FIELD",5,true));
1383                          fwrite ($bf,full_tag("FIELD_NAME",6,false,$cpfield->shortname));
1384                          fwrite ($bf,full_tag("FIELD_TYPE",6,false,$cpfield->datatype));
1385                          fwrite ($bf,full_tag("FIELD_DATA",6,false,$cpfield->data));
1386                          fwrite ($bf,end_tag("USER_CUSTOM_PROFILE_FIELD",5,true));
1387                      }
1388                      //End USER_CUSTOM_PROFILE_FIELDS tag
1389                      fwrite ($bf,end_tag("USER_CUSTOM_PROFILE_FIELDS",4,true));
1390                  }
1391  
1392                  //Check if we have user tags to backup
1393                  if (!empty($CFG->usetags)) {
1394                      if ($tags = tag_get_tags('user', $user->id)) { //This return them ordered by default
1395                          //Start USER_TAGS tag
1396                          fwrite ($bf,start_tag("USER_TAGS",4,true));
1397                          //Write user tags fields
1398                          foreach ($tags as $tag) {
1399                              fwrite ($bf,start_tag("USER_TAG",5,true));
1400                              fwrite ($bf,full_tag("NAME",6,false,$tag->name));
1401                              fwrite ($bf,full_tag("RAWNAME",6,false,$tag->rawname));
1402                              fwrite ($bf,end_tag("USER_TAG",5,true));
1403                          }
1404                          //End USER_TAGS tag
1405                          fwrite ($bf,end_tag("USER_TAGS",4,true));
1406                      }
1407                  }
1408  
1409                  //Check if we have user_preferences to backup
1410                  if ($preferences_data = get_records("user_preferences","userid",$user->old_id)) {
1411                      //Start USER_PREFERENCES tag
1412                      fwrite ($bf,start_tag("USER_PREFERENCES",4,true));
1413                      //Write each user_preference
1414                      foreach ($preferences_data as $user_preference) {
1415                          fwrite ($bf,start_tag("USER_PREFERENCE",5,true));
1416                          fwrite ($bf,full_tag("NAME",6,false,$user_preference->name));
1417                          fwrite ($bf,full_tag("VALUE",6,false,$user_preference->value));
1418                          fwrite ($bf,end_tag("USER_PREFERENCE",5,true));
1419                      }
1420                          //End USER_PREFERENCES tag
1421                      fwrite ($bf,end_tag("USER_PREFERENCES",4,true));
1422                  }
1423  
1424                  $context = get_context_instance(CONTEXT_USER, $user->old_id);
1425  
1426                  write_role_overrides_xml($bf, $context, 4);
1427                  /// write role_assign code here
1428                  write_role_assignments_xml($bf, $preferences, $context, 4);
1429                  //End User tag
1430                  fwrite ($bf,end_tag("USER",3,true));
1431                  //Do some output
1432                  $counter++;
1433                  if ($counter % 10 == 0) {
1434                      echo ".";
1435                      if ($counter % 200 == 0) {
1436                          echo "<br />";
1437                      }
1438                      backup_flush(300);
1439                  }
1440              }
1441              //End Users tag
1442              fwrite ($bf,end_tag("USERS",2,true));
1443          } else {
1444              // There aren't any users.
1445              $status = true;
1446          }
1447  
1448          if ($users) {
1449              rs_close($users);
1450          }
1451  
1452          return $status;
1453      }
1454  
1455      //Backup log info (time ordered)
1456      function backup_log_info($bf,$preferences) {
1457  
1458          global $CFG;
1459  
1460          //Number of records to get in every chunk
1461          $recordset_size = 1000;
1462  
1463          $status = true;
1464  
1465          //Counter, points to current record
1466          $counter = 0;
1467  
1468          //Count records
1469          $count_logs = count_records("log","course",$preferences->backup_course);
1470  
1471          //Pring logs header
1472          if ($count_logs > 0 ) {
1473              fwrite ($bf,start_tag("LOGS",2,true));
1474          }
1475          while ($counter < $count_logs) {
1476              //Get a chunk of records
1477              $logs = get_records ("log","course",$preferences->backup_course,"time","*",$counter,$recordset_size);
1478  
1479              //We have logs
1480              if ($logs) {
1481                  //Iterate
1482                  foreach ($logs as $log) {
1483                      //See if it is a valid module to backup
1484                      if ($log->module == "course" or
1485                          $log->module == "user" or
1486                          (array_key_exists($log->module, $preferences->mods) and $preferences->mods[$log->module]->backup == 1)) {
1487                          // logs with 'upload' in module field are ignored, there is no restore code anyway
1488                          //Begin log tag
1489                           fwrite ($bf,start_tag("LOG",3,true));
1490  
1491                          //Output log tag
1492                          fwrite ($bf,full_tag("ID",4,false,$log->id));
1493                          fwrite ($bf,full_tag("TIME",4,false,$log->time));
1494                          fwrite ($bf,full_tag("USERID",4,false,$log->userid));
1495                          fwrite ($bf,full_tag("IP",4,false,$log->ip));
1496                          fwrite ($bf,full_tag("MODULE",4,false,$log->module));
1497                          fwrite ($bf,full_tag("CMID",4,false,$log->cmid));
1498                          fwrite ($bf,full_tag("ACTION",4,false,$log->action));
1499                          fwrite ($bf,full_tag("URL",4,false,$log->url));
1500                          fwrite ($bf,full_tag("INFO",4,false,$log->info));
1501  
1502                          //End log tag
1503                           fwrite ($bf,end_tag("LOG",3,true));
1504                      }
1505                      //Do some output
1506                      $counter++;
1507                      if ($counter % 20 == 0) {
1508                          echo ".";
1509                          if ($counter % 400 == 0) {
1510                              echo "<br />";
1511                          }
1512                          backup_flush(300);
1513                      }
1514                  }
1515              }
1516          }
1517          //End logs tag
1518          if ($count_logs > 0 ) {
1519              $status = fwrite ($bf,end_tag("LOGS",2,true));
1520          }
1521          return $status;
1522      }
1523  
1524      //Backup gradebook info
1525      function backup_gradebook_info($bf, $preferences) {
1526          global $CFG;
1527          require_once($CFG->libdir.'/gradelib.php');
1528  
1529          //first make sure items are properly sorted and everything is ok
1530          grade_category::fetch_course_tree($preferences->backup_course, true);
1531          grade_regrade_final_grades($preferences->backup_course);
1532  
1533          $status = true;
1534  
1535          // see if ALL grade items of type mod of this course are being backed up
1536          // if not, we do not need to backup grade category and associated grade items/grades
1537          $backupall = true;
1538  
1539          if ($grade_items = get_records_sql("SELECT *
1540                                                FROM {$CFG->prefix}grade_items
1541                                               WHERE courseid = $preferences->backup_course
1542                                                     AND itemtype = 'mod'")) {
1543              foreach ($grade_items as $grade_item) {
1544                  // get module information
1545                  // if some activities not selected, we do not backup categories at all
1546                  if (!backup_mod_selected($preferences,$grade_item->itemmodule,$grade_item->iteminstance)) {
1547                      $backupall = false;
1548                      break;
1549                  }
1550              }
1551              unset($grade_items); //free memory
1552          }
1553  
1554          //Gradebook header
1555          fwrite ($bf,start_tag("GRADEBOOK",2,true));
1556  
1557          $status = backup_gradebook_outcomes_info($bf, $preferences);
1558          $status = backup_gradebook_grade_letters_info($bf,$preferences);
1559  
1560          // Now backup grade_item (inside grade_category)
1561          if ($backupall) {
1562              $status = backup_gradebook_category_info($bf,$preferences);
1563          }
1564  
1565          $status = backup_gradebook_item_info($bf,$preferences, $backupall);
1566  
1567          // backup gradebook histories
1568          if ($preferences->backup_gradebook_history) {
1569              $status = backup_gradebook_outcomes_history($bf, $preferences);
1570              $status = backup_gradebook_categories_history_info($bf, $preferences);
1571              $status = backup_gradebook_items_history_info($bf, $preferences);
1572              $status = backup_gradebook_grades_history_info($bf, $preferences);
1573          }
1574  
1575          //Gradebook footer
1576          $status = fwrite ($bf,end_tag("GRADEBOOK",2,true));
1577          return $status;
1578      }
1579  
1580      function backup_gradebook_category_info($bf, $preferences) {
1581          global $CFG;
1582          $status = true;
1583  
1584          // get grade categories in proper order - specified in category grade items
1585          $course_item = grade_item::fetch_course_item($preferences->backup_course);
1586          $grade_categories = get_records_sql("SELECT gc.*, gi.sortorder
1587                                                 FROM {$CFG->prefix}grade_categories gc
1588                                                      JOIN {$CFG->prefix}grade_items gi
1589                                                        ON (gi.iteminstance = gc.id)
1590                                                WHERE gc.courseid = $preferences->backup_course
1591                                                      AND (gi.itemtype='course' OR gi.itemtype='category')
1592                                             ORDER BY gi.sortorder ASC");
1593  
1594          if ($grade_categories) {
1595              //Begin grade_categories tag
1596              fwrite ($bf,start_tag("GRADE_CATEGORIES",3,true));
1597              //Iterate for each category
1598              foreach ($grade_categories as $grade_category) {
1599                  //Begin grade_category
1600                  fwrite ($bf,start_tag("GRADE_CATEGORY",4,true));
1601                  //Output individual fields
1602                  fwrite ($bf,full_tag("ID",5,false,$grade_category->id));
1603  
1604                  // not keeping path and depth because they can be derived
1605                  fwrite ($bf,full_tag("PARENT",5,false,$grade_category->parent));
1606                  fwrite ($bf,full_tag("FULLNAME",5,false,$grade_category->