[ Index ]

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

title

Body

[close]

/mod/data/ -> lib.php (source)

   1  <?php  // $Id: lib.php,v 1.137.2.37 2008/07/24 21:58:06 skodak Exp $
   2  ///////////////////////////////////////////////////////////////////////////
   3  //                                                                       //
   4  // NOTICE OF COPYRIGHT                                                   //
   5  //                                                                       //
   6  // Moodle - Modular Object-Oriented Dynamic Learning Environment         //
   7  //          http://moodle.org                                            //
   8  //                                                                       //
   9  // Copyright (C) 2005 Moodle Pty Ltd    http://moodle.com                //
  10  //                                                                       //
  11  // This program is free software; you can redistribute it and/or modify  //
  12  // it under the terms of the GNU General Public License as published by  //
  13  // the Free Software Foundation; either version 2 of the License, or     //
  14  // (at your option) any later version.                                   //
  15  //                                                                       //
  16  // This program is distributed in the hope that it will be useful,       //
  17  // but WITHOUT ANY WARRANTY; without even the implied warranty of        //
  18  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
  19  // GNU General Public License for more details:                          //
  20  //                                                                       //
  21  //          http://www.gnu.org/copyleft/gpl.html                         //
  22  //                                                                       //
  23  ///////////////////////////////////////////////////////////////////////////
  24  
  25  // Some constants
  26  define ('DATA_MAX_ENTRIES', 50);
  27  define ('DATA_PERPAGE_SINGLE', 1);
  28  define ('DATA_FIRSTNAME', -1);
  29  define ('DATA_LASTNAME', -2);
  30  define ('DATA_APPROVED', -3);
  31  define ('DATA_TIMEADDED', 0);
  32  define ('DATA_TIMEMODIFIED', -4);
  33  
  34  define ('DATA_CAP_EXPORT', 'mod/data:viewalluserpresets');
  35  // Users having assigned the default role "Non-editing teacher" can export database records
  36  // Using the mod/data capability "viewalluserpresets" for Moodle 1.9.x, so no change in the role system is required.
  37  // In Moodle >= 2, new roles may be introduced and used instead. 
  38  
  39  class data_field_base {     // Base class for Database Field Types (see field/*/field.class.php)
  40  
  41      var $type = 'unknown';  // Subclasses must override the type with their name
  42      var $data = NULL;       // The database object that this field belongs to
  43      var $field = NULL;      // The field object itself, if we know it
  44  
  45      var $iconwidth = 16;    // Width of the icon for this fieldtype
  46      var $iconheight = 16;   // Width of the icon for this fieldtype
  47  
  48  
  49  // Constructor function
  50      function data_field_base($field=0, $data=0) {   // Field or data or both, each can be id or object
  51          if (empty($field) && empty($data)) {
  52              error('Programmer error: You must specify field and/or data when defining field class. ');
  53          }
  54          if (!empty($field)) {
  55              if (is_object($field)) {
  56                  $this->field = $field;  // Programmer knows what they are doing, we hope
  57              } else if (!$this->field = get_record('data_fields','id',$field)) {
  58                  error('Bad field ID encountered: '.$field);
  59              }
  60              if (empty($data)) {
  61                  if (!$this->data = get_record('data','id',$this->field->dataid)) {
  62                      error('Bad data ID encountered in field data');
  63                  }
  64              }
  65          }
  66          if (empty($this->data)) {         // We need to define this properly
  67              if (!empty($data)) {
  68                  if (is_object($data)) {
  69                      $this->data = $data;  // Programmer knows what they are doing, we hope
  70                  } else if (!$this->data = get_record('data','id',$data)) {
  71                      error('Bad data ID encountered: '.$data);
  72                  }
  73              } else {                      // No way to define it!
  74                  error('Data id or object must be provided to field class');
  75              }
  76          }
  77          if (empty($this->field)) {         // We need to define some default values
  78              $this->define_default_field();
  79          }
  80      }
  81  
  82  
  83  // This field just sets up a default field object
  84      function define_default_field() {
  85          if (empty($this->data->id)) {
  86              notify('Programmer error: dataid not defined in field class');
  87          }
  88          $this->field = new object;
  89          $this->field->id = 0;
  90          $this->field->dataid = $this->data->id;
  91          $this->field->type   = $this->type;
  92          $this->field->param1 = '';
  93          $this->field->param2 = '';
  94          $this->field->param3 = '';
  95          $this->field->name = '';
  96          $this->field->description = '';
  97          return true;
  98      }
  99  
 100  // Set up the field object according to data in an object. Now is the time to clean it!
 101      function define_field($data) {
 102          $this->field->type        = $this->type;
 103          $this->field->dataid      = $this->data->id;
 104  
 105          $this->field->name        = trim($data->name);
 106          $this->field->description = trim($data->description);
 107  
 108          if (isset($data->param1)) {
 109              $this->field->param1 = trim($data->param1);
 110          }
 111          if (isset($data->param2)) {
 112              $this->field->param2 = trim($data->param2);
 113          }
 114          if (isset($data->param3)) {
 115              $this->field->param3 = trim($data->param3);
 116          }
 117          if (isset($data->param4)) {
 118              $this->field->param4 = trim($data->param4);
 119          }
 120          if (isset($data->param5)) {
 121              $this->field->param5 = trim($data->param5);
 122          }
 123  
 124          return true;
 125      }
 126  
 127  // Insert a new field in the database
 128  // We assume the field object is already defined as $this->field
 129      function insert_field() {
 130          if (empty($this->field)) {
 131              notify('Programmer error: Field has not been defined yet!  See define_field()');
 132              return false;
 133          }
 134  
 135          if (!$this->field->id = insert_record('data_fields',$this->field)){
 136              notify('Insertion of new field failed!');
 137              return false;
 138          }
 139          return true;
 140      }
 141  
 142  
 143  // Update a field in the database
 144      function update_field() {
 145          if (!update_record('data_fields', $this->field)) {
 146              notify('updating of new field failed!');
 147              return false;
 148          }
 149          return true;
 150      }
 151  
 152  // Delete a field completely
 153      function delete_field() {
 154          if (!empty($this->field->id)) {
 155              delete_records('data_fields', 'id', $this->field->id);
 156              $this->delete_content();
 157          }
 158          return true;
 159      }
 160  
 161  // Print the relevant form element in the ADD template for this field
 162      function display_add_field($recordid=0){
 163          if ($recordid){
 164              $content = get_field('data_content', 'content', 'fieldid', $this->field->id, 'recordid', $recordid);
 165          } else {
 166              $content = '';
 167          }
 168  
 169          $str = '<div title="'.s($this->field->description).'">';
 170          $str .= '<input style="width:300px;" type="text" name="field_'.$this->field->id.'" id="field_'.$this->field->id.'" value="'.s($content).'" />';
 171          $str .= '</div>';
 172  
 173          return $str;
 174      }
 175  
 176  // Print the relevant form element to define the attributes for this field
 177  // viewable by teachers only.
 178      function display_edit_field() {
 179          global $CFG;
 180  
 181          if (empty($this->field)) {   // No field has been defined yet, try and make one
 182              $this->define_default_field();
 183          }
 184          print_simple_box_start('center','80%');
 185  
 186          echo '<form id="editfield" action="'.$CFG->wwwroot.'/mod/data/field.php" method="post">'."\n";
 187          echo '<input type="hidden" name="d" value="'.$this->data->id.'" />'."\n";
 188          if (empty($this->field->id)) {
 189              echo '<input type="hidden" name="mode" value="add" />'."\n";
 190              $savebutton = get_string('add');
 191          } else {
 192              echo '<input type="hidden" name="fid" value="'.$this->field->id.'" />'."\n";
 193              echo '<input type="hidden" name="mode" value="update" />'."\n";
 194              $savebutton = get_string('savechanges');
 195          }
 196          echo '<input type="hidden" name="type" value="'.$this->type.'" />'."\n";
 197          echo '<input name="sesskey" value="'.sesskey().'" type="hidden" />'."\n";
 198  
 199          print_heading($this->name());
 200  
 201          require_once($CFG->dirroot.'/mod/data/field/'.$this->type.'/mod.html');
 202  
 203          echo '<div align="center">';
 204          echo '<input type="submit" value="'.$savebutton.'" />'."\n";
 205          echo '<input type="submit" name="cancel" value="'.get_string('cancel').'" />'."\n";
 206          echo '</div>';
 207  
 208          echo '</form>';
 209  
 210          print_simple_box_end();
 211      }
 212  
 213  // Display the content of the field in browse mode
 214      function display_browse_field($recordid, $template) {
 215          if ($content = get_record('data_content','fieldid', $this->field->id, 'recordid', $recordid)) {
 216              if (isset($content->content)) {
 217                  $options = new object();
 218                  if ($this->field->param1 == '1') {  // We are autolinking this field, so disable linking within us
 219                      //$content->content = '<span class="nolink">'.$content->content.'</span>';
 220                      //$content->content1 = FORMAT_HTML;
 221                      $options->filter=false;
 222                  }
 223                  $options->para = false;
 224                  $str = format_text($content->content, $content->content1, $options);
 225              } else {
 226                  $str = '';
 227              }
 228              return $str;
 229          }
 230          return false;
 231      }
 232  
 233  // Update the content of one data field in the data_content table
 234      function update_content($recordid, $value, $name='') {
 235          $content = new object();
 236          $content->fieldid = $this->field->id;
 237          $content->recordid = $recordid;
 238          $content->content = clean_param($value, PARAM_NOTAGS);
 239  
 240          if ($oldcontent = get_record('data_content','fieldid', $this->field->id, 'recordid', $recordid)) {
 241              $content->id = $oldcontent->id;
 242              return update_record('data_content', $content);
 243          } else {
 244              return insert_record('data_content', $content);
 245          }
 246      }
 247  
 248  // Delete all content associated with the field
 249      function delete_content($recordid=0) {
 250  
 251          $this->delete_content_files($recordid);
 252  
 253          if ($recordid) {
 254              return delete_records('data_content', 'fieldid', $this->field->id, 'recordid', $recordid);
 255          } else {
 256              return delete_records('data_content', 'fieldid', $this->field->id);
 257          }
 258      }
 259  
 260  // Deletes any files associated with this field
 261      function delete_content_files($recordid='') {
 262          global $CFG;
 263  
 264          require_once($CFG->libdir.'/filelib.php');
 265  
 266          $dir = $CFG->dataroot.'/'.$this->data->course.'/'.$CFG->moddata.'/data/'.$this->data->id.'/'.$this->field->id;
 267          if ($recordid) {
 268              $dir .= '/'.$recordid;
 269          }
 270  
 271          return fulldelete($dir);
 272      }
 273  
 274  
 275  // Check if a field from an add form is empty
 276      function notemptyfield($value, $name) {
 277          return !empty($value);
 278      }
 279  
 280  // Just in case a field needs to print something before the whole form
 281      function print_before_form() {
 282      }
 283  
 284  // Just in case a field needs to print something after the whole form
 285      function print_after_form() {
 286      }
 287  
 288  
 289  // Returns the sortable field for the content. By default, it's just content
 290  // but for some plugins, it could be content 1 - content4
 291      function get_sort_field() {
 292          return 'content';
 293      }
 294  
 295  // Returns the SQL needed to refer to the column.  Some fields may need to CAST() etc.
 296      function get_sort_sql($fieldname) {
 297          return $fieldname;
 298      }
 299  
 300  // Returns the name/type of the field
 301      function name() {
 302          return get_string('name'.$this->type, 'data');
 303      }
 304  
 305  // Prints the respective type icon
 306      function image() {
 307          global $CFG;
 308  
 309          $str = '<a href="field.php?d='.$this->data->id.'&amp;fid='.$this->field->id.'&amp;mode=display&amp;sesskey='.sesskey().'">';
 310          $str .= '<img src="'.$CFG->modpixpath.'/data/field/'.$this->type.'/icon.gif" ';
 311          $str .= 'height="'.$this->iconheight.'" width="'.$this->iconwidth.'" alt="'.$this->type.'" title="'.$this->type.'" /></a>';
 312          return $str;
 313      }
 314  
 315  //  Per default, it is assumed that fields support text exporting. Override this (return false) on fields not supporting text exporting. 
 316      function text_export_supported() {
 317          return true;
 318      }
 319  
 320  //  Per default, return the record's text value only from the "content" field. Override this in fields class if necesarry. 
 321      function export_text_value($record) {
 322          if ($this->text_export_supported()) {
 323              return $record->content;
 324          }
 325      }
 326  
 327  }
 328  
 329  
 330  /*
 331  /* Given a template and a dataid, generate a default case template
 332   * input @param template - addtemplate, singletemplate, listtempalte, rsstemplate
 333   *       @param dataid
 334   * output null
 335   */
 336  function data_generate_default_template(&$data, $template, $recordid=0, $form=false, $update=true) {
 337  
 338      if (!$data && !$template) {
 339          return false;
 340      }
 341      if ($template == 'csstemplate' or $template == 'jstemplate' ) {
 342          return '';
 343      }
 344  
 345      // get all the fields for that database
 346      if ($fields = get_records('data_fields', 'dataid', $data->id, 'id')) {
 347  
 348          $str = '<div class="defaulttemplate">';
 349          $str .= '<table cellpadding="5">';
 350  
 351          foreach ($fields as $field) {
 352  
 353              $str .= '<tr><td valign="top" align="right">';
 354              // Yu: commenting this out, the id was wrong and will fix later
 355              //if ($template == 'addtemplate') {
 356                  //$str .= '<label';
 357                  //if (!in_array($field->type, array('picture', 'checkbox', 'date', 'latlong', 'radiobutton'))) {
 358                  //    $str .= ' for="[['.$field->name.'#id]]"';
 359                  //}
 360                  //$str .= '>'.$field->name.'</label>';
 361                  
 362              //} else {
 363                  $str .= $field->name.': ';
 364              //}
 365              $str .= '</td>';
 366  
 367              $str .='<td>';
 368              if ($form) {   // Print forms instead of data
 369                  $fieldobj = data_get_field($field, $data);
 370                  $str .= $fieldobj->display_add_field($recordid);
 371  
 372              } else {           // Just print the tag
 373                  $str .= '[['.$field->name.']]';
 374              }
 375              $str .= '</td></tr>';
 376  
 377          }
 378          if ($template == 'listtemplate') {
 379              $str .= '<tr><td align="center" colspan="2">##edit##  ##more##  ##delete##  ##approve##</td></tr>';
 380          } else if ($template == 'singletemplate') {
 381              $str .= '<tr><td align="center" colspan="2">##edit##  ##delete##  ##approve##</td></tr>';
 382          } else if ($template == 'asearchtemplate') {
 383              $str .= '<tr><td valign="top" align="right">'.get_string('authorfirstname', 'data').': </td><td>##firstname##</td></tr>';
 384              $str .= '<tr><td valign="top" align="right">'.get_string('authorlastname', 'data').': </td><td>##lastname##</td></tr>';
 385          }
 386  
 387          $str .= '</table>';
 388          $str .= '</div>';
 389  
 390          if ($template == 'listtemplate'){
 391              $str .= '<hr />';
 392          }
 393  
 394          if ($update) {
 395              $newdata = new object();
 396              $newdata->id = $data->id;
 397              $newdata->{$template} = $str;
 398              if (!update_record('data', $newdata)) {
 399                  notify('Error updating template');
 400              } else {
 401                  $data->{$template} = $str;
 402              }
 403          }
 404  
 405          return $str;
 406      }
 407  }
 408  
 409  
 410  /***********************************************************************
 411   * Search for a field name and replaces it with another one in all the *
 412   * form templates. Set $newfieldname as '' if you want to delete the   *
 413   * field from the form.                                                *
 414   ***********************************************************************/
 415  function data_replace_field_in_templates($data, $searchfieldname, $newfieldname) {
 416      if (!empty($newfieldname)) {
 417          $prestring = '[[';
 418          $poststring = ']]';
 419          $idpart = '#id';
 420  
 421      } else {
 422          $prestring = '';
 423          $poststring = '';
 424          $idpart = '';
 425      }
 426  
 427      $newdata = new object();
 428      $newdata->id = $data->id;
 429      $newdata->singletemplate = addslashes(str_ireplace('[['.$searchfieldname.']]',
 430              $prestring.$newfieldname.$poststring, $data->singletemplate));
 431  
 432      $newdata->listtemplate = addslashes(str_ireplace('[['.$searchfieldname.']]',
 433              $prestring.$newfieldname.$poststring, $data->listtemplate));
 434  
 435      $newdata->addtemplate = addslashes(str_ireplace('[['.$searchfieldname.']]',
 436              $prestring.$newfieldname.$poststring, $data->addtemplate));
 437  
 438      $newdata->addtemplate = addslashes(str_ireplace('[['.$searchfieldname.'#id]]',
 439              $prestring.$newfieldname.$idpart.$poststring, $data->addtemplate));
 440  
 441      $newdata->rsstemplate = addslashes(str_ireplace('[['.$searchfieldname.']]',
 442              $prestring.$newfieldname.$poststring, $data->rsstemplate));
 443  
 444      return update_record('data', $newdata);
 445  }
 446  
 447  
 448  /********************************************************
 449   * Appends a new field at the end of the form template. *
 450   ********************************************************/
 451  function data_append_new_field_to_templates($data, $newfieldname) {
 452  
 453      $newdata = new object();
 454      $newdata->id = $data->id;
 455      $change = false;
 456  
 457      if (!empty($data->singletemplate)) {
 458          $newdata->singletemplate = addslashes($data->singletemplate.' [[' . $newfieldname .']]');
 459          $change = true;
 460      }
 461      if (!empty($data->addtemplate)) {
 462          $newdata->addtemplate = addslashes($data->addtemplate.' [[' . $newfieldname . ']]');
 463          $change = true;
 464      }
 465      if (!empty($data->rsstemplate)) {
 466          $newdata->rsstemplate = addslashes($data->singletemplate.' [[' . $newfieldname . ']]');
 467          $change = true;
 468      }
 469      if ($change) {
 470          update_record('data', $newdata);
 471      }
 472  }
 473  
 474  
 475  /************************************************************************
 476   * given a field name                                                   *
 477   * this function creates an instance of the particular subfield class   *
 478   ************************************************************************/
 479  function data_get_field_from_name($name, $data){
 480      $field = get_record('data_fields','name',$name);
 481      if ($field) {
 482          return data_get_field($field, $data);
 483      } else {
 484          return false;
 485      }
 486  }
 487  
 488  /************************************************************************
 489   * given a field id                                                     *
 490   * this function creates an instance of the particular subfield class   *
 491   ************************************************************************/
 492  function data_get_field_from_id($fieldid, $data) {
 493      $field = get_record('data_fields','id',$fieldid);
 494      if ($field) {
 495          return data_get_field($field, $data);
 496      } else {
 497          return false;
 498      }
 499  }
 500  
 501  /************************************************************************
 502   * given a field id                                                     *
 503   * this function creates an instance of the particular subfield class   *
 504   ************************************************************************/
 505  function data_get_field_new($type, $data) {
 506      global $CFG;
 507      require_once($CFG->dirroot.'/mod/data/field/'.$type.'/field.class.php');
 508      $newfield = 'data_field_'.$type;
 509      $newfield = new $newfield(0, $data);
 510      return $newfield;
 511  }
 512  
 513  /************************************************************************
 514   * returns a subclass field object given a record of the field, used to *
 515   * invoke plugin methods                                                *
 516   * input: $param $field - record from db                                *
 517   ************************************************************************/
 518  function data_get_field($field, $data) {
 519      global $CFG;
 520      if ($field) {
 521          require_once('field/'.$field->type.'/field.class.php');
 522          $newfield = 'data_field_'.$field->type;
 523          $newfield = new $newfield($field, $data);
 524          return $newfield;
 525      }
 526  }
 527  
 528  
 529  /***************************************************************************
 530   * given record id, returns true if the record belongs to the current user *
 531   * input @param $rid - record id                                           *
 532   * output bool                                                             *
 533   ***************************************************************************/
 534  function data_isowner($rid){
 535      global $USER;
 536      if (empty($USER->id)) {
 537          return false;
 538      }
 539  
 540      if ($record = get_record('data_records','id',$rid)) {
 541          return ($record->userid == $USER->id);
 542      }
 543  
 544      return false;
 545  }
 546  
 547  /***********************************************************************
 548   * has a user reached the max number of entries?                       *
 549   * input object $data                                                  *
 550   * output bool                                                         *
 551   ***********************************************************************/
 552  function data_atmaxentries($data) {
 553      if (!$data->maxentries) {
 554          return false;
 555      } else {
 556          return (data_numentries($data) >= $data->maxentries);
 557      }
 558  }
 559  
 560  /**********************************************************************
 561   * returns the number of entries already made by this user            *
 562   * input @param object $data                                          *
 563   * uses global $CFG, $USER                                            *
 564   * output int                                                         *
 565   **********************************************************************/
 566  function data_numentries($data) {
 567      global $USER;
 568      global $CFG;
 569      $sql = 'SELECT COUNT(*) FROM '.$CFG->prefix.'data_records WHERE dataid='.$data->id.' AND userid='.$USER->id;
 570      return count_records_sql($sql);
 571  }
 572  
 573  /****************************************************************
 574   * function that takes in a dataid and adds a record            *
 575   * this is used everytime an add template is submitted          *
 576   * input @param int $dataid, $groupid                           *
 577   * output bool                                                  *
 578   ****************************************************************/
 579  function data_add_record($data, $groupid=0) {
 580      global $USER;
 581      $cm = get_coursemodule_from_instance('data', $data->id);
 582      $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 583      $record = new object();
 584      $record->userid = $USER->id;
 585      $record->dataid = $data->id;
 586      $record->groupid = $groupid;
 587      $record->timecreated = $record->timemodified = time();
 588      if (has_capability('mod/data:approve', $context)) {
 589          $record->approved = 1;
 590      } else {
 591          $record->approved = 0;
 592      }
 593      return insert_record('data_records',$record);
 594  }
 595  
 596  /*******************************************************************
 597   * check the multple existence any tag in a template               *
 598   * input @param string                                             *
 599   * output true-valid, false-invalid                                *
 600   * check to see if there are 2 or more of the same tag being used. *
 601   * input @param int $dataid,                                       *
 602   *       @param string $template                                   *
 603   * output bool                                                     *
 604   *******************************************************************/
 605  function data_tags_check($dataid, $template) {
 606      // first get all the possible tags
 607      $fields = get_records('data_fields','dataid',$dataid);
 608      // then we generate strings to replace
 609      $tagsok = true; // let's be optimistic
 610      foreach ($fields as $field) {
 611          $pattern="/\[\[".$field->name."\]\]/i";
 612          if (preg_match_all($pattern, $template, $dummy)>1) {
 613              $tagsok = false;
 614              notify ('[['.$field->name.']] - '.get_string('multipletags','data'));
 615          }
 616      }
 617      // else return true
 618      return $tagsok;
 619  }
 620  
 621  /************************************************************************
 622   * Adds an instance of a data                                           *
 623   ************************************************************************/
 624  function data_add_instance($data) {
 625      global $CFG;
 626      if (empty($data->assessed)) {
 627          $data->assessed = 0;
 628      }
 629  
 630      $data->timemodified = time();
 631      if (! $data->id = insert_record('data', $data)) {
 632          return false;
 633      }
 634  
 635      $data = stripslashes_recursive($data);
 636      data_grade_item_update($data);
 637      return $data->id;
 638  }
 639  
 640  /************************************************************************
 641   * updates an instance of a data                                        *
 642   ************************************************************************/
 643  function data_update_instance($data) {
 644      global $CFG;
 645      $data->timemodified = time();
 646      $data->id = $data->instance;
 647  
 648      if (empty($data->assessed)) {
 649          $data->assessed = 0;
 650      }
 651      if (empty($data->notification)) {
 652          $data->notification = 0;
 653      }
 654      if (! update_record('data', $data)) {
 655          return false;
 656      }
 657  
 658      $data = stripslashes_recursive($data);
 659      data_grade_item_update($data);
 660      return true;
 661  }
 662  
 663  /************************************************************************
 664   * deletes an instance of a data                                        *
 665   ************************************************************************/
 666  function data_delete_instance($id) {    // takes the dataid
 667  
 668      global $CFG;
 669      if (! $data = get_record('data', 'id', $id)) {
 670          return false;
 671      }
 672  
 673      // Delete all the associated information
 674      // get all the records in this data
 675      $sql = 'SELECT c.* FROM '.$CFG->prefix.'data_records r LEFT JOIN '.
 676             $CFG->prefix.'data_content c ON c.recordid = r.id WHERE r.dataid = '.$id;
 677  
 678      if ($contents = get_records_sql($sql)) {
 679          foreach($contents as $content) {
 680              $field = get_record('data_fields','id',$content->fieldid);
 681              if ($g = data_get_field($field, $data)) {
 682                  $g->delete_content_files($id, $content->recordid, $content->content);
 683              }
 684              //delete the content itself
 685              delete_records('data_content','id', $content->id);
 686          }
 687      }
 688  
 689      // delete all the records and fields
 690      delete_records('data_records', 'dataid', $id);
 691      delete_records('data_fields','dataid',$id);
 692  
 693      // Delete the instance itself
 694      $result = delete_records('data', 'id', $id);
 695      data_grade_item_delete($data);
 696      return $result;
 697  }
 698  
 699  /************************************************************************
 700   * returns a summary of data activity of this user                      *
 701   ************************************************************************/
 702  function data_user_outline($course, $user, $mod, $data) {
 703      global $CFG;
 704      if ($countrecords = count_records('data_records', 'dataid', $data->id, 'userid', $user->id)) {
 705          $result = new object();
 706          $result->info = get_string('numrecords', 'data', $countrecords);
 707          $lastrecord   = get_record_sql('SELECT id,timemodified FROM '.$CFG->prefix.'data_records
 708                                           WHERE dataid = '.$data->id.' AND userid = '.$user->id.'
 709                                        ORDER BY timemodified DESC', true);
 710          $result->time = $lastrecord->timemodified;
 711          return $result;
 712      }
 713      return NULL;
 714  }
 715  
 716  /************************************************************************
 717   * Prints all the records uploaded by this user                         *
 718   ************************************************************************/
 719  function data_user_complete($course, $user, $mod, $data) {
 720      if ($records = get_records_select('data_records', 'dataid = '.$data->id.' AND userid = '.$user->id,
 721                                                        'timemodified DESC')) {
 722          data_print_template('singletemplate', $records, $data);
 723      }
 724  }
 725  
 726  /**
 727   * Return grade for given user or all users.
 728   *
 729   * @param int $dataid id of data
 730   * @param int $userid optional user id, 0 means all users
 731   * @return array array of grades, false if none
 732   */
 733  function data_get_user_grades($data, $userid=0) {
 734      global $CFG;
 735      $user = $userid ? "AND u.id = $userid" : "";
 736      $sql = "SELECT u.id, u.id AS userid, avg(drt.rating) AS rawgrade
 737                FROM {$CFG->prefix}user u, {$CFG->prefix}data_records dr,
 738                     {$CFG->prefix}data_ratings drt
 739               WHERE u.id = dr.userid AND dr.id = drt.recordid
 740                     AND drt.userid != u.id AND dr.dataid = $data->id
 741                     $user
 742            GROUP BY u.id";
 743      return get_records_sql($sql);
 744  }
 745  
 746  /**
 747   * Update grades by firing grade_updated event
 748   *
 749   * @param object $data null means all databases
 750   * @param int $userid specific user only, 0 mean all
 751   */
 752  function data_update_grades($data=null, $userid=0, $nullifnone=true) {
 753      global $CFG;
 754      if (!function_exists('grade_update')) { //workaround for buggy PHP versions
 755          require_once($CFG->libdir.'/gradelib.php');
 756      }
 757  
 758      if ($data != null) {
 759          if ($grades = data_get_user_grades($data, $userid)) {
 760              data_grade_item_update($data, $grades);
 761          } else if ($userid and $nullifnone) {
 762              $grade = new object();
 763              $grade->userid   = $userid;
 764              $grade->rawgrade = NULL;
 765              data_grade_item_update($data, $grade);
 766          } else {
 767              data_grade_item_update($data);
 768          }
 769      } else {
 770          $sql = "SELECT d.*, cm.idnumber as cmidnumber
 771                    FROM {$CFG->prefix}data d, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m
 772                   WHERE m.name='data' AND m.id=cm.module AND cm.instance=d.id";
 773          if ($rs = get_recordset_sql($sql)) {
 774              while ($data = rs_fetch_next_record($rs)) {
 775                  if ($data->assessed) {
 776                      data_update_grades($data, 0, false);
 777                  } else {
 778                      data_grade_item_update($data);
 779                  }
 780              }
 781              rs_close($rs);
 782          }
 783      }
 784  }
 785  
 786  /**
 787   * Update/create grade item for given data
 788   *
 789   * @param object $data object with extra cmidnumber
 790   * @param mixed optional array/object of grade(s); 'reset' means reset grades in gradebook
 791   * @return object grade_item
 792   */
 793  function data_grade_item_update($data, $grades=NULL) {
 794      global $CFG;
 795      if (!function_exists('grade_update')) { //workaround for buggy PHP versions
 796          require_once($CFG->libdir.'/gradelib.php');
 797      }
 798      $params = array('itemname'=>$data->name, 'idnumber'=>$data->cmidnumber);
 799      if (!$data->assessed or $data->scale == 0) {
 800          $params['gradetype'] = GRADE_TYPE_NONE;
 801      } else if ($data->scale > 0) {
 802          $params['gradetype'] = GRADE_TYPE_VALUE;
 803          $params['grademax']  = $data->scale;
 804          $params['grademin']  = 0;
 805      } else if ($data->scale < 0) {
 806          $params['gradetype'] = GRADE_TYPE_SCALE;
 807          $params['scaleid']   = -$data->scale;
 808      }
 809      if ($grades  === 'reset') {
 810          $params['reset'] = true;
 811          $grades = NULL;
 812      }
 813  
 814      return grade_update('mod/data', $data->course, 'mod', 'data', $data->id, 0, $grades, $params);
 815  }
 816  
 817  /**
 818   * Delete grade item for given data
 819   *
 820   * @param object $data object
 821   * @return object grade_item
 822   */
 823  function data_grade_item_delete($data) {
 824      global $CFG;
 825      require_once($CFG->libdir.'/gradelib.php');
 826      return grade_update('mod/data', $data->course, 'mod', 'data', $data->id, 0, NULL, array('deleted'=>1));
 827  }
 828  
 829  /************************************************************************
 830   * returns a list of participants of this database                      *
 831   ************************************************************************/
 832  function data_get_participants($dataid) {
 833  // Returns the users with data in one data
 834  // (users with records in data_records, data_comments and data_ratings)
 835      global $CFG;
 836      $records = get_records_sql("SELECT DISTINCT u.id, u.id
 837                                  FROM {$CFG->prefix}user u,
 838                                       {$CFG->prefix}data_records r
 839                                  WHERE r.dataid = '$dataid'
 840                                    AND u.id = r.userid");
 841      $comments = get_records_sql("SELECT DISTINCT u.id, u.id
 842                                   FROM {$CFG->prefix}user u,
 843                                        {$CFG->prefix}data_records r,
 844                                        {$CFG->prefix}data_comments c
 845                                   WHERE r.dataid = '$dataid'
 846                                     AND u.id = r.userid
 847                                     AND r.id = c.recordid");
 848      $ratings = get_records_sql("SELECT DISTINCT u.id, u.id
 849                                  FROM {$CFG->prefix}user u,
 850                                       {$CFG->prefix}data_records r,
 851                                       {$CFG->prefix}data_ratings a
 852                                  WHERE r.dataid = '$dataid'
 853                                    AND u.id = r.userid
 854                                    AND r.id = a.recordid");
 855      $participants = array();
 856      if ($records) {
 857          foreach ($records as $record) {
 858              $participants[$record->id] = $record;
 859          }
 860      }
 861      if ($comments) {
 862          foreach ($comments as $comment) {
 863              $participants[$comment->id] = $comment;
 864          }
 865      }
 866      if ($ratings) {
 867          foreach ($ratings as $rating) {
 868              $participants[$rating->id] = $rating;
 869          }
 870      }
 871      return $participants;
 872  }
 873  
 874  // junk functions
 875  /************************************************************************
 876   * takes a list of records, the current data, a search string,          *
 877   * and mode to display prints the translated template                   *
 878   * input @param array $records                                          *
 879   *       @param object $data                                            *
 880   *       @param string $search                                          *
 881   *       @param string $template                                        *
 882   * output null                                                          *
 883   ************************************************************************/
 884  function data_print_template($template, $records, $data, $search='',$page=0, $return=false) {
 885      global $CFG;
 886      $cm = get_coursemodule_from_instance('data', $data->id);
 887      $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 888      static $fields = NULL;
 889      static $isteacher;
 890      static $dataid = NULL;
 891      if (empty($dataid)) {
 892          $dataid = $data->id;
 893      } else if ($dataid != $data->id) {
 894          $fields = NULL;
 895      }
 896      if (empty($fields)) {
 897          $fieldrecords = get_records('data_fields','dataid', $data->id);
 898          foreach ($fieldrecords as $fieldrecord) {
 899              $fields[]= data_get_field($fieldrecord, $data);
 900          }
 901          $isteacher = has_capability('mod/data:managetemplates', $context);
 902      }
 903      if (empty($records)) {
 904          return;
 905      }
 906      foreach ($records as $record) {   // Might be just one for the single template
 907      // Replacing tags
 908          $patterns = array();
 909          $replacement = array();
 910      // Then we generate strings to replace for normal tags
 911          foreach ($fields as $field) {
 912              $patterns[]='[['.$field->field->name.']]';
 913              $replacement[] = highlight($search, $field->display_browse_field($record->id, $template));
 914          }
 915      // Replacing special tags (##Edit##, ##Delete##, ##More##)
 916          $patterns[]='##edit##';
 917          $patterns[]='##delete##';
 918          if (has_capability('mod/data:manageentries', $context) or data_isowner($record->id)) {
 919              $replacement[] = '<a href="'.$CFG->wwwroot.'/mod/data/edit.php?d='
 920                               .$data->id.'&amp;rid='.$record->id.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/edit.gif" class="iconsmall" alt="'.get_string('edit').'" title="'.get_string('edit').'" /></a>';
 921              $replacement[] = '<a href="'.$CFG->wwwroot.'/mod/data/view.php?d='
 922                               .$data->id.'&amp;delete='.$record->id.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/delete.gif" class="iconsmall" alt="'.get_string('delete').'" title="'.get_string('delete').'" /></a>';
 923          } else {
 924              $replacement[] = '';
 925              $replacement[] = '';
 926          }
 927          $patterns[]='##more##';
 928          $replacement[] = '<a href="'.$CFG->wwwroot.'/mod/data/view.php?d='.$data->id.'&amp;rid='.$record->id.'"><img src="'.$CFG->pixpath.'/i/search.gif" class="iconsmall" alt="'.get_string('more', 'data').'" title="'.get_string('more', 'data').'" /></a>';
 929  
 930          $patterns[]='##moreurl##';
 931          $replacement[] = $CFG->wwwroot.'/mod/data/view.php?d='.$data->id.'&amp;rid='.$record->id;
 932  
 933          $patterns[]='##user##';
 934          $replacement[] = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$record->userid.
 935                                 '&amp;course='.$data->course.'">'.fullname($record).'</a>';
 936          
 937          $patterns[] = '##timeadded##';
 938          $replacement[] = userdate($record->timecreated); 
 939  
 940          $patterns[] = '##timemodified##';
 941          $replacement [] = userdate($record->timemodified);
 942  
 943          $patterns[]='##approve##';
 944          if (has_capability('mod/data:approve', $context) && ($data->approval) && (!$record->approved)) {
 945              $replacement[] = '<span class="approve"><a href="'.$CFG->wwwroot.'/mod/data/view.php?d='.$data->id.'&amp;approve='.$record->id.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/i/approve.gif" class="icon" alt="'.get_string('approve').'" /></a></span>';
 946          } else {
 947              $replacement[] = '';
 948          }
 949  
 950          $patterns[]='##comments##';
 951          if (($template == 'listtemplate') && ($data->comments)) {
 952              $comments = count_records('data_comments','recordid',$record->id);
 953              $replacement[] = '<a href="view.php?rid='.$record->id.'#comments">'.get_string('commentsn','data', $comments).'</a>';
 954          } else {
 955              $replacement[] = '';
 956          }
 957  
 958          // actual replacement of the tags
 959          $newtext = str_ireplace($patterns, $replacement, $data->{$template});
 960  
 961          // no more html formatting and filtering - see MDL-6635
 962          if ($return) {
 963              return $newtext;
 964          } else {
 965              echo $newtext;
 966              // hack alert - return is always false in singletemplate anyway ;-)
 967              /**********************************
 968               *    Printing Ratings Form       *
 969               *********************************/
 970              if ($template == 'singletemplate') {    //prints ratings options
 971                  data_print_ratings($data, $record);
 972              }
 973              /**********************************
 974               *    Printing Ratings Form       *
 975               *********************************/
 976              if (($template == 'singletemplate') && ($data->comments)) {    //prints ratings options
 977                  data_print_comments($data, $record, $page);
 978              }
 979          }
 980      }
 981  }
 982  
 983  
 984  /************************************************************************
 985   * function that takes in the current data, number of items per page,   *
 986   * a search string and prints a preference box in view.php              *
 987   *                                                                      *
 988   * This preference box prints a searchable advanced search template if  *
 989   *     a) A template is defined                                         *
 990   *  b) The advanced search checkbox is checked.                         *
 991   *                                                                      *
 992   * input @param object $data                                            *
 993   *       @param int $perpage                                            *
 994   *       @param string $search                                          *
 995   * output null                                                          *
 996   ************************************************************************/
 997  function data_print_preference_form($data, $perpage, $search, $sort='', $order='ASC', $search_array = '', $advanced = 0, $mode= '') {
 998      global $CFG;
 999      $cm = get_coursemodule_from_instance('data', $data->id);
1000      $context = get_context_instance(CONTEXT_MODULE, $cm->id);
1001      echo '<br /><div class="datapreferences">';
1002      echo '<form id="options" action="view.php" method="get">';
1003      echo '<div>';
1004      echo '<input type="hidden" name="d" value="'.$data->id.'" />';
1005      if ($mode =='asearch') {
1006          $advanced = 1;
1007          echo '<input type="hidden" name="mode" value="list" />';
1008      }
1009      echo '<label for="pref_perpage">'.get_string('pagesize','data').'</label> ';
1010      $pagesizes = array(2=>2,3=>3,4=>4,5=>5,6=>6,7=>7,8=>8,9=>9,10=>10,15=>15,
1011                         20=>20,30=>30,40=>40,50=>50,100=>100,200=>200,300=>300,400=>400,500=>500,1000=>1000);
1012      choose_from_menu($pagesizes, 'perpage', $perpage, '', '', '0', false, false, 0, 'pref_perpage');
1013       echo '<div id="reg_search" style="display: ';
1014      if ($advanced) {
1015          echo 'none';
1016      }
1017      else {
1018          echo 'inline';
1019      }
1020      echo ';" >&nbsp;&nbsp;&nbsp;<label for="pref_search">'.get_string('search').'</label> <input type="text" size="16" name="search" id= "pref_search" value="'.s($search).'" /></div>';
1021      echo '&nbsp;&nbsp;&nbsp;<label for="pref_sortby">'.get_string('sortby').'</label> ';
1022      // foreach field, print the option
1023      echo '<select name="sort" id="pref_sortby">';
1024      if ($fields = get_records('data_fields','dataid',$data->id, 'name')) {
1025          echo '<optgroup label="'.get_string('fields', 'data').'">';
1026          foreach ($fields as $field) {
1027              if ($field->id == $sort) {
1028                  echo '<option value="'.$field->id.'" selected="selected">'.$field->name.'</option>';
1029              } else {
1030                  echo '<option value="'.$field->id.'">'.$field->name.'</option>';
1031              }
1032          }
1033          echo '</optgroup>';
1034      }
1035      $options = array();
1036      $options[DATA_TIMEADDED]    = get_string('timeadded', 'data');
1037      $options[DATA_TIMEMODIFIED] = get_string('timemodified', 'data');
1038      $options[DATA_FIRSTNAME]    = get_string('authorfirstname', 'data');
1039      $options[DATA_LASTNAME]     = get_string('authorlastname', 'data');
1040      if ($data->approval and has_capability('mod/data:approve', $context)) {
1041          $options[DATA_APPROVED] = get_string('approved', 'data');
1042      }
1043      echo '<optgroup label="'.get_string('other', 'data').'">';
1044      foreach ($options as $key => $name) {
1045          if ($key == $sort) {
1046              echo '<option value="'.$key.'" selected="selected">'.$name.'</option>';
1047          } else {
1048              echo '<option value="'.$key.'">'.$name.'</option>';
1049          }
1050      }
1051      echo '</optgroup>';
1052      echo '</select>';
1053      echo '<label for="pref_order" class="accesshide">'.get_string('order').'</label>';
1054      echo '<select id="pref_order" name="order">';
1055      if ($order == 'ASC') {
1056          echo '<option value="ASC" selected="selected">'.get_string('ascending','data').'</option>';
1057      } else {
1058          echo '<option value="ASC">'.get_string('ascending','data').'</option>';
1059      }
1060      if ($order == 'DESC') {
1061          echo '<option value="DESC" selected="selected">'.get_string('descending','data').'</option>';
1062      } else {
1063          echo '<option value="DESC">'.get_string('descending','data').'</option>';
1064      }
1065      echo '</select>';
1066  
1067      if ($advanced) {
1068          $checked = ' checked="checked" ';
1069      }
1070      else {
1071          $checked = '';
1072      }
1073      print '
1074          <script type="text/javascript">
1075          //<![CDATA[
1076          <!-- Start
1077          // javascript for hiding/displaying advanced search form
1078  
1079          function showHideAdvSearch(checked) {
1080              var divs = document.getElementsByTagName(\'div\');
1081              for(i=0;i<divs.length;i++) {
1082                  if(divs[i].id.match(\'data_adv_form\')) {
1083                      if(checked) {
1084                          divs[i].style.display = \'inline\';
1085                      }
1086                      else {
1087                          divs[i].style.display = \'none\';
1088                      }
1089                  }
1090                  else if (divs[i].id.match(\'reg_search\')) {
1091                      if (!checked) {
1092                          divs[i].style.display = \'inline\';
1093                      }
1094                      else {
1095                          divs[i].style.display = \'none\';
1096                      }
1097                  }
1098              }
1099          }
1100          //  End -->
1101          //]]>
1102          </script>';
1103      echo '&nbsp;<input type="hidden" name="advanced" value="0" />';
1104      echo '&nbsp;<input type="checkbox" id="advancedcheckbox" name="advanced" value="1" '.$checked.' onchange="showHideAdvSearch(this.checked);" /><label for="advancedcheckbox">'.get_string('advancedsearch', 'data').'</label>';
1105      echo '&nbsp;<input type="submit" value="'.get_string('savesettings','data').'" />';
1106      echo '<br />';
1107      echo '<div class="dataadvancedsearch" id="data_adv_form" style="display: ';
1108      if ($advanced) {
1109          echo 'inline';
1110      }
1111      else {
1112          echo 'none';
1113      }
1114      echo ';margin-left:auto;margin-right:auto;" >';
1115      echo '<table class="boxaligncenter">';
1116      // print ASC or DESC
1117      echo '<tr><td colspan="2">&nbsp;</td></tr>';
1118      $i = 0;
1119  
1120      // Determine if we are printing all fields for advanced search, or the template for advanced search
1121      // If a template is not defined, use the deafault template and display all fields.
1122      if(empty($data->asearchtemplate)) {
1123          data_generate_default_template($data, 'asearchtemplate');
1124      }
1125  
1126      static $fields = NULL;
1127      static $isteacher;
1128      static $dataid = NULL;
1129      if (empty($dataid)) {
1130          $dataid = $data->id;
1131      } else if ($dataid != $data->id) {
1132          $fields = NULL;
1133      }
1134  
1135      if (empty($fields)) {
1136          $fieldrecords = get_records('data_fields','dataid', $data->id);
1137          foreach ($fieldrecords as $fieldrecord) {
1138              $fields[]= data_get_field($fieldrecord, $data);
1139          }
1140          $isteacher = has_capability('mod/data:managetemplates', $context);
1141      }
1142  
1143      // Replacing tags
1144      $patterns = array();
1145      $replacement = array();
1146  
1147      // Then we generate strings to replace for normal tags
1148      foreach ($fields as $field) {
1149          $fieldname = $field->field->name;
1150          $fieldname = preg_quote($fieldname, '/');
1151          $patterns[] = "/\[\[$fieldname\]\]/i";
1152          $searchfield = data_get_field_from_id($field->field->id, $data);
1153          if (!empty($search_array[$field->field->id]->data)) {
1154              $replacement[] = $searchfield->display_search_field($search_array[$field->field->id]->data);
1155          } else {
1156              $replacement[] = $searchfield->display_search_field();
1157          }
1158      }
1159      $fn = !empty($search_array[DATA_FIRSTNAME]->data) ? $search_array[DATA_FIRSTNAME]->data : '';
1160      $ln = !empty($search_array[DATA_LASTNAME]->data) ? $search_array[DATA_LASTNAME]->data : '';
1161      $patterns[]    = '/##firstname##/';
1162      $replacement[] = '<input type="text" size="16" name="u_fn" value="'.$fn.'" />';
1163      $patterns[]    = '/##lastname##/';
1164      $replacement[] = '<input type="text" size="16" name="u_ln" value="'.$ln.'" />';
1165  
1166      // actual replacement of the tags
1167      $newtext = preg_replace($patterns, $replacement, $data->asearchtemplate);
1168      $options = new object();
1169      $options->para=false;
1170      $options->noclean=true;
1171      echo '<tr><td>';
1172      echo format_text($newtext, FORMAT_HTML, $options);
1173      echo '</td></tr>';
1174      echo '<tr><td colspan="4" style="text-align: center;"><br/><input type="submit" value="'.get_string('savesettings','data').'" /><input type="submit" name="resetadv" value="'.get_string('resetsettings','data').'" /></td></tr>';
1175      echo '</table>';
1176      echo '</div>';
1177      echo '</div>';
1178      echo '</form>';
1179      echo '</div>';
1180  }
1181  
1182  function data_print_ratings($data, $record) {
1183      global $USER;
1184  
1185      $cm = get_coursemodule_from_instance('data', $data->id);
1186      $context = get_context_instance(CONTEXT_MODULE, $cm->id);
1187      if ($data->assessed and !empty($USER->id) and (has_capability('mod/data:rate', $context) or has_capability('mod/data:viewrating', $context) or data_isowner($record->id))) {
1188          if ($ratingsscale = make_grades_menu($data->scale)) {
1189              $ratingsmenuused = false;
1190              echo '<div class="ratings" style="text-align:center">';
1191              echo '<form id="form" method="post" action="rate.php">';
1192              echo '<input type="hidden" name="dataid" value="'.$data->id.'" />';
1193              if (has_capability('mod/data:rate', $context) and !data_isowner($record->id)) {
1194                  data_print_ratings_mean($record->id, $ratingsscale, has_capability('mod/data:viewrating', $context));
1195                  echo '&nbsp;';
1196                  data_print_rating_menu($record->id, $USER->id, $ratingsscale);
1197                  $ratingsmenuused = true;
1198              } else {
1199                  data_print_ratings_mean($record->id, $ratingsscale, true);
1200              }
1201              if ($data->scale < 0) {
1202                  if ($scale = get_record('scale', 'id', abs($data->scale))) {
1203                      print_scale_menu_helpbutton($data->course, $scale );
1204                  }
1205              }
1206  
1207              if ($ratingsmenuused) {
1208                  echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
1209                  echo '<input type="submit" value="'.get_string('sendinratings', 'data').'" />';
1210              }
1211              echo '</form>';
1212              echo '</div>';
1213          }
1214      }
1215  }
1216  
1217  function data_print_ratings_mean($recordid, $scale, $link=true) {
1218  // Print the multiple ratings on a post given to the current user by others.
1219  // Scale is an array of ratings
1220  
1221      static $strrate;
1222      $mean = data_get_ratings_mean($recordid, $scale);
1223      if ($mean !== "") {
1224          if (empty($strratings)) {
1225              $strratings = get_string("ratings", "data");
1226          }
1227          echo "$strratings: ";
1228          if ($link) {
1229              link_to_popup_window ("/mod/data/report.php?id=$recordid", "ratings", $mean, 400, 600);
1230          } else {
1231              echo "$mean ";
1232          }
1233      }
1234  }
1235  
1236  
1237  function data_get_ratings_mean($recordid, $scale, $ratings=NULL) {
1238  // Return the mean rating of a post given to the current user by others.
1239  // Scale is an array of possible ratings in the scale
1240  // Ratings is an optional simple array of actual ratings (just integers)
1241      if (!$ratings) {
1242          $ratings = array();
1243          if ($rates = get_records("data_ratings", "recordid", $recordid)) {
1244              foreach ($rates as $rate) {
1245                  $ratings[] = $rate->rating;
1246              }
1247          }
1248      }
1249      $count = count($ratings);
1250      if ($count == 0) {
1251          return "";
1252      } else if ($count == 1) {
1253          return $scale[$ratings[0]];
1254      } else {
1255          $total = 0;
1256          foreach ($ratings as $rating) {
1257              $total += $rating;
1258          }
1259          $mean = round( ((float)$total/(float)$count) + 0.001);  // Little fudge factor so that 0.5 goes UP
1260          if (isset($scale[$mean])) {
1261              return $scale[$mean]." ($count)";
1262          } else {
1263              return "$mean ($count)";    // Should never happen, hopefully
1264          }
1265      }
1266  }
1267  
1268  
1269  function data_print_rating_menu($recordid, $userid, $scale) {
1270  // Print the menu of ratings as part of a larger form.
1271  // If the post has already been - set that value.
1272  // Scale is an array of ratings
1273      static $strrate;
1274      if (!$rating = get_record("data_ratings", "userid", $userid, "recordid", $recordid)) {
1275          $rating->rating = -999;
1276      }
1277      if (empty($strrate)) {
1278          $strrate = get_string("rate", "data");
1279      }
1280      choose_from_menu($scale, $recordid, $rating->rating, "$strrate...", '', -999);
1281  }
1282  
1283  
1284  function data_get_ratings($recordid, $sort="u.firstname ASC") {
1285  // Returns a list of ratings for a particular post - sorted.
1286      global $CFG;
1287      return get_records_sql("SELECT u.*, r.rating
1288                                FROM {$CFG->prefix}data_ratings r,
1289                                     {$CFG->prefix}user u
1290                               WHERE r.recordid = $recordid
1291                                 AND r.userid = u.id
1292                               ORDER BY $sort");
1293  }
1294  
1295  
1296  // prints all comments + a text box for adding additional comment
1297  function data_print_comments($data, $record, $page=0, $mform=false) {
1298      global $CFG;
1299      echo '<a name="comments"></a>';
1300      if ($comments = get_records('data_comments','recordid',$record->id)) {
1301          foreach ($comments as $comment) {
1302              data_print_comment($data, $comment, $page);
1303          }
1304          echo '<br />';
1305      }
1306      if (!isloggedin() or isguest()) {
1307          return;
1308      }
1309      $editor = optional_param('addcomment', 0, PARAM_BOOL);
1310      if (!$mform and !$editor) {
1311          echo '<div class="newcomment" style="text-align:center">';
1312          echo '<a href="view.php?d='.$data->id.'&amp;page='.$page.'&amp;mode=single&amp;addcomment=1">'.get_string('addcomment', 'data').'</a>';
1313          echo '</div>';
1314      } else {
1315          if (!$mform) {
1316              require_once ('comment_form.php');
1317              $mform = new mod_data_comment_form('comment.php');
1318              $mform->set_data(array('mode'=>'add', 'page'=>$page, 'rid'=>$record->id));
1319          }
1320          echo '<div class="newcomment" style="text-align:center">';
1321          $mform->display();
1322          echo '</div>';
1323      }
1324  }
1325  
1326  // prints a single comment entry
1327  function data_print_comment($data, $comment, $page=0) {
1328      global $USER, $CFG;
1329      $cm = get_coursemodule_from_instance('data', $data->id);
1330      $context = get_context_instance(CONTEXT_MODULE, $cm->id);
1331      $stredit = get_string('edit');
1332      $strdelete = get_string('delete');
1333      $user = get_record('user','id',$comment->userid);
1334      echo '<table cellspacing="0" align="center" width="50%" class="datacomment forumpost">';
1335      echo '<tr class="header"><td class="picture left">';
1336      print_user_picture($user, $data->course, $user->picture);
1337      echo '</td>';
1338      echo '<td class="topic starter" align="left"><div class="author">';
1339      $fullname = fullname($user, has_capability('moodle/site:viewfullnames', $context));
1340      $by = new object();
1341      $by->name = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.
1342                  $user->id.'&amp;course='.$data->course.'">'.$fullname.'</a>';
1343      $by->date = userdate($comment->modified);
1344      print_string('bynameondate', 'data', $by);
1345      echo '</div></td></tr>';
1346      echo '<tr><td class="left side">';
1347      if ($groups = groups_get_all_groups($data->course, $comment->userid, $cm->groupingid)) {
1348          print_group_picture($groups, $data->course, false, false, true);
1349      } else {
1350          echo '&nbsp;';
1351      }
1352  
1353  // Actual content
1354      echo '</td><td class="content" align="left">'."\n";
1355      // Print whole message
1356      echo format_text($comment->content, $comment->format);
1357  
1358  // Commands
1359      echo '<div class="commands">';
1360      if (data_isowner($comment->recordid) or has_capability('mod/data:managecomments', $context)) {
1361              echo '<a href="'.$CFG->wwwroot.'/mod/data/comment.php?rid='.$comment->recordid.'&amp;mode=edit&amp;commentid='.$comment->id.'&amp;page='.$page.'">'.$stredit.'</a>';
1362              echo '| <a href="'.$CFG->wwwroot.'/mod/data/comment.php?rid='.$comment->recordid.'&amp;mode=delete&amp;commentid='.$comment->id.'&amp;page='.$page.'">'.$strdelete.'</a>';
1363      }
1364  
1365      echo '</div>';
1366      echo '</td></tr></table>'."\n\n";
1367  }
1368  
1369  
1370  // For Participantion Reports
1371  function data_get_view_actions() {
1372      return array('view');
1373  }
1374  
1375  function data_get_post_actions() {
1376      return array('add','update','record delete');
1377  }
1378  
1379  function data_fieldname_exists($name, $dataid, $fieldid=0) {
1380      global $CFG;
1381      $LIKE = sql_ilike();
1382      if ($fieldid) {
1383          return record_exists_sql("SELECT * from {$CFG->prefix}data_fields df
1384                                    WHERE df.name $LIKE '$name' AND df.dataid = $dataid
1385                                      AND ((df.id < $fieldid) OR (df.id > $fieldid))");
1386      } else {
1387          return record_exists_sql("SELECT * from {$CFG->prefix}data_fields df
1388                                    WHERE df.name $LIKE '$name' AND df.dataid = $dataid");
1389      }
1390  }
1391  
1392  function data_convert_arrays_to_strings(&$fieldinput) {
1393      foreach ($fieldinput as $key => $val) {
1394          if (is_array($val)) {
1395              $str = '';
1396              foreach ($val as $inner) {
1397                  $str .= $inner . ',';
1398              }
1399              $str = substr($str, 0, -1);
1400              $fieldinput->$key = $str;
1401          }
1402      }
1403  }
1404  
1405  
1406  /**
1407   * Converts a database (module instance) to use the Roles System
1408   * @param $data         - a data object with the same attributes as a record
1409   *                        from the data database table
1410   * @param $datamodid    - the id of the data module, from the modules table
1411   * @param $teacherroles - array of roles that have moodle/legacy:teacher
1412   * @param $studentroles - array of roles that have moodle/legacy:student
1413   * @param $guestroles   - array of roles that have moodle/legacy:guest
1414   * @param $cmid         - the course_module id for this data instance
1415   * @return boolean      - data module was converted or not
1416   */
1417  function data_convert_to_roles($data, $teacherroles=array(), $studentroles=array(), $cmid=NULL) {
1418      global $CFG;
1419      if (!isset($data->participants) && !isset($data->assesspublic)
1420              && !isset($data->groupmode)) {
1421          // We assume that this database has already been converted to use the
1422          // Roles System. above fields get dropped the data module has been
1423          // upgraded to use Roles.
1424          return false;
1425      }
1426      if (empty($cmid)) {
1427          // We were not given the course_module id. Try to find it.
1428          if (!$cm = get_coursemodule_from_instance('data', $data->id)) {
1429              notify('Could not get the course module for the data');
1430              return false;
1431          } else {
1432              $cmid = $cm->id;
1433          }
1434      }
1435      $context = get_context_instance(CONTEXT_MODULE, $cmid);
1436  
1437      // $data->participants:
1438      // 1 - Only teachers can add entries
1439      // 3 - Teachers and students can add entries
1440      switch ($data->participants) {
1441          case 1:
1442              foreach ($studentroles as $studentrole) {
1443                  assign_capability('mod/data:writeentry', CAP_PREVENT, $studentrole->id, $context->id);
1444              }
1445              foreach ($teacherroles as $teacherrole) {
1446                  assign_capability('mod/data:writeentry', CAP_ALLOW, $teacherrole->id, $context->id);
1447              }
1448              break;
1449          case 3:
1450              foreach ($studentroles as $studentrole) {
1451                  assign_capability('mod/data:writeentry', CAP_ALLOW, $studentrole->id, $context->id);
1452              }
1453              foreach ($teacherroles as $teacherrole) {
1454                  assign_capability('mod/data:writeentry', CAP_ALLOW, $teacherrole->id, $context->id);
1455              }
1456              break;
1457      }
1458  
1459      // $data->assessed:
1460      // 2 - Only teachers can rate posts
1461      // 1 - Everyone can rate posts
1462      // 0 - No one can rate posts
1463      switch ($data->assessed) {
1464          case 0:
1465              foreach ($studentroles as $studentrole) {
1466                  assign_capability('mod/data:rate', CAP_PREVENT, $studentrole->id, $context->id);
1467              }
1468              foreach ($teacherroles as $teacherrole) {
1469                  assign_capability('mod/data:rate', CAP_PREVENT, $teacherrole->id, $context->id);
1470              }
1471              break;
1472          case 1:
1473              foreach ($studentroles as $studentrole) {
1474                  assign_capability('mod/data:rate', CAP_ALLOW, $studentrole->id, $context->id);
1475              }
1476              foreach ($teacherroles as $teacherrole) {
1477                  assign_capability('mod/data:rate', CAP_ALLOW, $teacherrole->id, $context->id);
1478              }
1479              break;
1480          case 2:
1481              foreach ($studentroles as $studentrole) {
1482                  assign_capability('mod/data:rate', CAP_PREVENT, $studentrole->id, $context->id);
1483              }
1484              foreach ($teacherroles as $teacherrole) {
1485                  assign_capability('mod/data:rate', CAP_ALLOW, $teacherrole->id, $context->id);
1486              }
1487              break;
1488      }
1489  
1490      // $data->assesspublic:
1491      // 0 - Students can only see their own ratings
1492      // 1 - Students can see everyone's ratings
1493      switch ($data->assesspublic) {
1494          case 0:
1495              foreach ($studentroles as $studentrole) {
1496                  assign_capability('mod/data:viewrating', CAP_PREVENT, $studentrole->id, $context->id);
1497              }
1498              foreach ($teacherroles as $teacherrole) {
1499                  assign_capability('mod/data:viewrating', CAP_ALLOW, $teacherrole->id, $context->id);
1500              }
1501              break;
1502          case 1:
1503              foreach ($studentroles as $studentrole) {
1504                  assign_capability('mod/data:viewrating', CAP_ALLOW, $studentrole->id, $context->id);
1505              }
1506              foreach ($teacherroles as $teacherrole) {
1507                  assign_capability('mod/data:viewrating', CAP_ALLOW, $teacherrole->id, $context->id);
1508              }
1509              break;
1510      }
1511  
1512      if (empty($cm)) {
1513          $cm = get_record('course_modules', 'id', $cmid);
1514      }
1515  
1516      switch ($cm->groupmode) {
1517          case NOGROUPS:
1518              break;
1519          case SEPARATEGROUPS:
1520              foreach ($studentroles as $studentrole) {
1521                  assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $studentrole->id, $context->id);
1522              }
1523              foreach ($teacherroles as $teacherrole) {
1524                  assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $teacherrole->id, $context->id);
1525              }
1526              break;
1527          case VISIBLEGROUPS:
1528              foreach ($studentroles as $studentrole) {
1529                  assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $studentrole->id, $context->id);
1530              }
1531              foreach ($teacherroles as $teacherrole) {
1532                  assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $teacherrole->id, $context->id);
1533              }
1534              break;
1535      }
1536      return true;
1537  }
1538  
1539  /*
1540   * Returns the best name to show for a preset
1541   */
1542  function data_preset_name($shortname, $path) {
1543  
1544      // We are looking inside the preset itself as a first choice, but also in normal data directory
1545      $string = get_string('modulename', 'datapreset_'.$shortname);
1546  
1547      if (substr($string, 0, 1) == '[') {
1548          return $shortname;
1549      } else {
1550          return $string;
1551      }
1552  }
1553  
1554  /*
1555   * Returns an array of all the available presets
1556   */
1557  function data_get_available_presets($context) {
1558      global $CFG, $USER;
1559      $presets = array();
1560      if ($dirs = get_list_of_plugins('mod/data/preset')) {
1561          foreach ($dirs as $dir) {
1562              $fulldir = $CFG->dirroot.'/mod/data/preset/'.$dir;
1563              if (is_directory_a_preset($fulldir)) {
1564                  $preset = new object;
1565                  $preset->path = $fulldir;
1566                  $preset->userid = 0;
1567                  $preset->shortname = $dir;
1568                  $preset->name = data_preset_name($dir, $fulldir);
1569                  if (file_exists($fulldir.'/screenshot.jpg')) {
1570                      $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.jpg';
1571                  } else if (file_exists($fulldir.'/screenshot.png')) {
1572                      $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.png';
1573                  } else if (file_exists($fulldir.'/screenshot.gif')) {
1574                      $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.gif';
1575                  }
1576                  $presets[] = $preset;
1577              }
1578          }
1579      }
1580  
1581      if ($userids = get_list_of_plugins('data/preset', '', $CFG->dataroot)) {
1582          foreach ($userids as $userid) {
1583              $fulldir = $CFG->dataroot.'/data/preset/'.$userid;
1584              if ($userid == 0 || $USER->id == $userid || has_capability('mod/data:viewalluserpresets', $context)) {
1585                  if ($dirs = get_list_of_plugins('data/preset/'.$userid, '', $CFG->dataroot)) {
1586                      foreach ($dirs as $dir) {
1587                          $fulldir = $CFG->dataroot.'/data/preset/'.$userid.'/'.$dir;
1588                          if (is_directory_a_preset($fulldir)) {
1589                              $preset = new object;
1590                              $preset->path = $fulldir;
1591                              $preset->userid = $userid;
1592                              $preset->shortname = $dir;
1593                              $preset->name = data_preset_name($dir, $fulldir);
1594                              if (file_exists($fulldir.'/screenshot.jpg')) {
1595                                  $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.jpg';
1596                              } else if (file_exists($fulldir.'/screenshot.png')) {
1597                                  $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.png';
1598                              } else if (file_exists($fulldir.'/screenshot.gif')) {
1599                                  $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.gif';
1600                              }
1601                              $presets[] = $preset;
1602                          }
1603                      }
1604                  }
1605              }
1606          }
1607      }
1608      return $presets;
1609  }
1610  
1611  
1612  function data_print_header($course, $cm, $data, $currenttab='') {
1613      global $CFG, $displaynoticegood, $displaynoticebad;
1614      $navigation = build_navigation('', $cm);
1615      print_header_simple($data->name, '', $navigation,
1616              '', '', true, update_module_button($cm->id, $course->id, get_string('modulename', 'data')),
1617              navmenu($course, $cm));
1618      print_heading(format_string($data->name));
1619  
1620  // Groups needed for Add entry tab
1621      $currentgroup = groups_get_activity_group($cm);
1622      $groupmode = groups_get_activity_groupmode($cm);
1623      // Print the tabs
1624      if ($currenttab) {
1625          include ('tabs.php');
1626      }
1627      // Print any notices
1628      if (!empty($displaynoticegood)) {
1629          notify($displaynoticegood, 'notifysuccess');    // good (usually green)
1630      } else if (!empty($displaynoticebad)) {
1631          notify($displaynoticebad);                     // bad (usuually red)
1632      }
1633  }
1634  
1635  function data_user_can_add_entry($data, $currentgroup, $groupmode) {
1636      global $USER;
1637      if (!$cm = get_coursemodule_from_instance('data', $data->id)) {
1638          error('Course Module ID was incorrect');
1639      }
1640      $context = get_context_instance(CONTEXT_MODULE, $cm->id);
1641      if (!has_capability('mod/data:writeentry', $context) and !has_capability('mod/data:manageentries',$context)) {
1642          return false;
1643      }
1644      if (!$groupmode or has_capability('moodle/site:accessallgroups', $context)) {
1645          return true;
1646      }
1647  
1648      if ($currentgroup) {
1649          return groups_is_member($currentgroup);
1650      } else {
1651          //else it might be group 0 in visible mode
1652          if ($groupmode == VISIBLEGROUPS){
1653              return true;
1654          } else {
1655              return false;
1656          }
1657      }
1658  }
1659  
1660  
1661  function is_directory_a_preset($directory) {
1662      $directory = rtrim($directory, '/\\') . '/';
1663      $status = file_exists($directory.'singletemplate.html') &&
1664                file_exists($directory.'listtemplate.html') &&
1665                file_exists($directory.'listtemplateheader.html') &&
1666                file_exists($directory.'listtemplatefooter.html') &&
1667                file_exists($directory.'addtemplate.html') &&
1668                file_exists($directory.'rsstemplate.html') &&
1669                file_exists($directory.'rsstitletemplate.html') &&
1670                file_exists($directory.'csstemplate.css') &&
1671                file_exists($directory.'jstemplate.js') &&
1672                file_exists($directory.'preset.xml');
1673      return $status;
1674  }
1675  
1676  
1677  function clean_preset($folder) {
1678      $status = @unlink($folder.'/singletemplate.html') &&
1679                @unlink($folder.'/listtemplate.html') &&
1680                @unlink($folder.'/listtemplateheader.html') &&
1681                @unlink($folder.'/listtemplatefooter.html') &&
1682                @unlink($folder.'/addtemplate.html') &&
1683                @unlink($folder.'/rsstemplate.html') &&
1684                @unlink($folder.'/rsstitletemplate.html') &&
1685                @unlink($folder.'/csstemplate.css') &&
1686                @unlink($folder.'/jstemplate.js') &&
1687                @unlink($folder.'/preset.xml');
1688  
1689      // optional
1690      @unlink($folder.'/asearchtemplate.html');
1691      return $status;
1692  }
1693  
1694  
1695  class PresetImporter {
1696      function PresetImporter($course, $cm, $data, $userid, $shortname) {
1697          global $CFG;
1698          $this->course = $course;
1699          $this->cm = $cm;
1700          $this->data = $data;
1701          $this->userid = $userid;
1702          $this->shortname = $shortname;
1703          $this->folder = data_preset_path($course, $userid, $shortname);
1704      }
1705  
1706      function get_settings() {
1707          global $CFG;
1708  
1709          if (!is_directory_a_preset($this->folder)) {
1710              error("$this->userid/$this->shortname Not a preset");
1711          }
1712  
1713          /* Grab XML */
1714          $presetxml = file_get_contents($this->folder.'/preset.xml');
1715          $parsedxml = xmlize($presetxml, 0);
1716  
1717          $allowed_settings = array('intro', 'comments', 'requiredentries', 'requiredentriestoview',
1718                                    'maxentries', 'rssarticles', 'approval', 'defaultsortdir', 'defaultsort');
1719  
1720          /* First, do settings. Put in user friendly array. */
1721          $settingsarray = $parsedxml['preset']['#']['settings'][0]['#'];
1722          $settings = new StdClass();
1723  
1724          foreach ($settingsarray as $setting => $value) {
1725              if (!is_array($value)) {
1726                  continue;
1727              }
1728              if (!in_array($setting, $allowed_settings)) {
1729                  // unsupported setting
1730                  continue;
1731              }
1732              $settings->$setting = $value[0]['#'];
1733          }
1734  
1735          /* Now work out fields to user friendly array */
1736          $fieldsarray = $parsedxml['preset']['#']['field'];
1737          $fields = array();
1738          foreach ($fieldsarray as $field) {
1739              if (!is_array($field)) {
1740                  continue;
1741              }
1742              $f = new StdClass();
1743              foreach ($field['#'] as $param => $value) {
1744                  if (!is_array($value)) {
1745                      continue;
1746                  }
1747                  $f->$param = addslashes($value[0]['#']);
1748              }
1749              $f->dataid = $this->data->id;
1750              $f->type = clean_param($f->type, PARAM_ALPHA);
1751              $fields[] = $f;
1752          }
1753          /* Now add the HTML templates to the settings array so we can update d */
1754          $settings->singletemplate     = file_get_contents($this->folder."/singletemplate.html");
1755          $settings->listtemplate       = file_get_contents($this->folder."/listtemplate.html");
1756          $settings->listtemplateheader = file_get_contents($this->folder."/listtemplateheader.html");
1757          $settings->listtemplatefooter = file_get_contents($this->folder."/listtemplatefooter.html");
1758          $settings->addtemplate        = file_get_contents($this->folder."/addtemplate.html");
1759          $settings->rsstemplate        = file_get_contents($this->folder."/rsstemplate.html");
1760          $settings->rsstitletemplate   = file_get_contents($this->folder."/rsstitletemplate.html");
1761          $settings->csstemplate        = file_get_contents($this->folder."/csstemplate.css");
1762          $settings->jstemplate         = file_get_contents($this->folder."/jstemplate.js");
1763  
1764          //optional
1765          if (file_exists($this->folder."/asearchtemplate.html")) {
1766              $settings->asearchtemplate = file_get_contents($this->folder."/asearchtemplate.html");
1767          } else {
1768              $settings->asearchtemplate = NULL;
1769          }
1770  
1771          $settings->instance = $this->data->id;
1772  
1773          /* Now we look at the current structure (if any) to work out whether we need to clear db
1774             or save the data */
1775          if (!$currentfields = get_records('data_fields', 'dataid', $this->data->id)) {
1776              $currentfields = array();
1777          }
1778  
1779          return array($settings, $fields, $currentfields);
1780      }
1781  
1782      function import_options() {
1783          if (!confirm_sesskey()) {
1784              error("Sesskey Invalid");
1785          }
1786          $strblank = get_string('blank', 'data');
1787          $strcontinue = get_string('continue');
1788          $strwarning = get_string('mappingwarning', 'data');
1789          $strfieldmappings = get_string('fieldmappings', 'data');
1790          $strnew = get_string('new');
1791          $sesskey = sesskey();
1792          list($settings, $newfields,  $currentfields) = $this->get_settings();
1793          echo '<div class="presetmapping"><form action="preset.php" method="post">';
1794          echo '<div>';
1795          echo '<input type="hidden" name="action" value="finishimport" />';
1796          echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
1797          echo '<input type="hidden" name="d" value="'.$this->data->id.'" />';
1798          echo '<input type="hidden" name="fullname" value="'.$this->userid.'/'.$this->shortname.'" />';
1799          if (!empty($currentfields) && !empty($newfields)) {
1800              echo "<h3>$strfieldmappings ";
1801              helpbutton('fieldmappings', $strfieldmappings, 'data');
1802              echo '</h3><table>';
1803              foreach ($newfields as $nid => $newfield) {
1804                  echo "<tr><td><label for=\"id_$newfield->name\">$newfield->name</label></td>";
1805                  echo '<td><select name="field_'.$nid.'" id="id_'.$newfield->name.'">';
1806                  $selected = false;
1807                  foreach ($currentfields as $cid => $currentfield) {
1808                      if ($currentfield->type == $newfield->type) {
1809                          if ($currentfield->name == $newfield->name) {
1810                              echo '<option value="'.$cid.'" selected="selected">'.$currentfield->name.'</option>';
1811                              $selected=true;
1812                          }
1813                          else {
1814                              echo '<option value="'.$cid.'">'.$currentfield->name.'</option>';
1815                          }
1816                      }
1817                  }
1818                  if ($selected)
1819                      echo '<option value="-1">-</option>';
1820                  else
1821                      echo '<option value="-1" selected="selected">-</option>';
1822                  echo '</select></td></tr>';
1823              }
1824              echo '</table>';
1825              echo "<p>$strwarning</p>";
1826          } else if (empty($newfields)) {
1827              error("New preset has no defined fields!");
1828          }
1829          echo '<div class="overwritesettings"><label for="overwritesettings">'.get_string('overwritesettings', 'data').'</label>';
1830          echo '<input id="overwritesettings" name="overwritesettings" type="checkbox" /></label></div>';
1831          echo '<input class="button" type="submit" value="'.$strcontinue.'" /></div></form></div>';
1832      }
1833  
1834      function import() {
1835          global $CFG;
1836          list($settings, $newfields, $currentfields) = $this->get_settings();
1837          $preservedfields = array();
1838          $overwritesettings = optional_param('overwritesettings', 0, PARAM_BOOL);
1839          /* Maps fields and makes new ones */
1840          if (!empty($newfields)) {
1841              /* We require an injective mapping, and need to know what to protect */
1842              foreach ($newfields as $nid => $newfield) {
1843                  $cid = optional_param("field_$nid", -1, PARAM_INT);
1844                  if ($cid == -1) continue;
1845                  if (array_key_exists($cid, $preservedfields)) error("Not an injective map");
1846                  else $preservedfields[$cid] = true;
1847              }
1848              foreach ($newfields as $nid => $newfield) {
1849                  $cid = optional_param("field_$nid", -1, PARAM_INT);
1850                  /* A mapping. Just need to change field params. Data kept. */
1851                  if ($cid != -1 and isset($currentfields[$cid])) {
1852                      $fieldobject = data_get_field_from_id($currentfields[$cid]->id, $this->data);
1853                      foreach ($newfield as $param => $value) {
1854                          if ($param != "id") {
1855                              $fieldobject->field->$param = $value;
1856                          }
1857                      }
1858                      unset($fieldobject->field->similarfield);
1859                      $fieldobject->update_field();
1860                      unset($fieldobject);
1861                  }
1862                  /* Make a new field */
1863                  else {
1864                      include_once("field/$newfield->type/field.class.php");
1865                      if (!isset($newfield->description)) {
1866                          $newfield->description = '';
1867                      }
1868                      $classname = 'data_field_'.$newfield->type;
1869                      $fieldclass = new $classname($newfield, $this->data);
1870                      $fieldclass->insert_field();
1871                      unset($fieldclass);
1872                  }
1873              }
1874          }
1875  
1876          /* Get rid of all old unused data */
1877          if (!empty($preservedfields)) {
1878              foreach ($currentfields as $cid => $currentfield) {
1879                  if (!array_key_exists($cid, $preservedfields)) {
1880                      /* Data not used anymore so wipe! */
1881                      print "Deleting field $currentfield->name<br />";
1882                      $id = $currentfield->id;
1883                      //Why delete existing data records and related comments/ratings??
1884  /*
1885                      if ($content = get_records('data_content', 'fieldid', $id)) {
1886                          foreach ($content as $item) {
1887                              delete_records('data_ratings', 'recordid', $item->recordid);
1888                              delete_records('data_comments', 'recordid', $item->recordid);
1889                              delete_records('data_records', 'id', $item->recordid);
1890                          }
1891                      }*/
1892                      delete_records('data_content', 'fieldid', $id);
1893                      delete_records('data_fields', 'id', $id);
1894                  }
1895              }
1896          }
1897  
1898      // handle special settings here
1899          if (!empty($settings->defaultsort)) {
1900              if (is_numeric($settings->defaultsort)) {
1901                  // old broken value
1902                  $settings->defaultsort = 0;
1903              } else {
1904                  $settings->defaultsort = (int)get_field('data_fields', 'id', 'dataid', $this->data->id, 'name', addslashes($settings->defaultsort));
1905              }
1906          } else {
1907              $settings->defaultsort = 0;
1908          }
1909  
1910          // do we want to overwrite all current database settings?
1911          if ($overwritesettings) {
1912              // all supported settings
1913              $overwrite = array_keys((array)$settings);
1914          } else {
1915              // only templates and sorting
1916              $overwrite = array('singletemplate', 'listtemplate', 'listtemplateheader', 'listtemplatefooter',
1917                                 'addtemplate', 'rsstemplate', 'rsstitletemplate', 'csstemplate', 'jstemplate',
1918                                 'asearchtemplate', 'defaultsortdir', 'defaultsort');
1919          }
1920  
1921          // now overwrite current data settings
1922          foreach ($this->data as $prop=>$unused) {
1923              if (in_array($prop, $overwrite)) {
1924                  $this->data->$prop = $settings->$prop;
1925              }
1926          }
1927  
1928          data_update_instance(addslashes_object($this->data));
1929          if (strstr($this->folder, '/temp/')) {
1930          // Removes the temporary files
1931              clean_preset($this->folder