Search moodle.org's
Developer Documentation


  • Bug fixes for general core bugs in 2.8.x ended 9 November 2015 (12 months).
  • Bug fixes for security issues in 2.8.x ended 9 May 2016 (18 months).
  • minimum PHP 5.4.4 (always use latest PHP 5.4.x or 5.5.x on Windows - http://windows.php.net/download/), PHP 7 is NOT supported
  • Differences Between: [Versions 28 and 32] [Versions 28 and 33] [Versions 28 and 34] [Versions 28 and 35] [Versions 28 and 36] [Versions 28 and 37]

       1  <?php
       2  // This file is part of Moodle - http://moodle.org/
       3  //
       4  // Moodle is free software: you can redistribute it and/or modify
       5  // it under the terms of the GNU General Public License as published by
       6  // the Free Software Foundation, either version 3 of the License, or
       7  // (at your option) any later version.
       8  //
       9  // Moodle is distributed in the hope that it will be useful,
      10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12  // GNU General Public License for more details.
      13  //
      14  // You should have received a copy of the GNU General Public License
      15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
      16  
      17  /**
      18   * Import outcomes from a file
      19   *
      20   * @package   core_grades
      21   * @copyright 2008 Moodle Pty Ltd (http://moodle.com)
      22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
      23   */
      24  
      25  require_once(dirname(__FILE__).'/../../../config.php');
      26  require_once($CFG->dirroot.'/lib/formslib.php');
      27  require_once($CFG->dirroot.'/grade/lib.php');
      28  require_once($CFG->libdir.'/gradelib.php');
      29  require_once ('import_outcomes_form.php');
      30  
      31  $courseid = optional_param('courseid', 0, PARAM_INT);
      32  $action   = optional_param('action', '', PARAM_ALPHA);
      33  $scope    = optional_param('scope', 'custom', PARAM_ALPHA);
      34  
      35  $PAGE->set_url('/grade/edit/outcome/import.php', array('courseid' => $courseid));
      36  $PAGE->set_pagelayout('admin');
      37  
      38  /// Make sure they can even access this course
      39  if ($courseid) {
      40      if (!$course = $DB->get_record('course', array('id' => $courseid))) {
      41          print_error('nocourseid');
      42      }
      43      require_login($course);
      44      $context = context_course::instance($course->id);
      45  
      46      if (empty($CFG->enableoutcomes)) {
      47          redirect('../../index.php?id='.$courseid);
      48      }
      49  
      50  } else {
      51      require_once $CFG->libdir.'/adminlib.php';
      52      admin_externalpage_setup('outcomes');
      53      $context = context_system::instance();
      54  }
      55  
      56  require_capability('moodle/grade:manageoutcomes', $context);
      57  
      58  $navigation = grade_build_nav(__FILE__, get_string('outcomes', 'grades'), $courseid);
      59  
      60  $upload_form = new import_outcomes_form();
      61  
      62  // display import form
      63  if (!$upload_form->get_data()) {
      64      print_grade_page_head($courseid, 'outcome', 'import', get_string('importoutcomes', 'grades'));
      65      $upload_form->display();
      66      echo $OUTPUT->footer();
      67      die;
      68  }
      69  print_grade_page_head($courseid, 'outcome', 'import', get_string('importoutcomes', 'grades'));
      70  
      71  $imported_file = $CFG->tempdir . '/outcomeimport/importedfile_'.time().'.csv';
      72  make_temp_directory('outcomeimport');
      73  
      74  // copying imported file
      75  if (!$upload_form->save_file('userfile', $imported_file, true)) {
      76      redirect('import.php'. ($courseid ? "?courseid=$courseid" : ''), get_string('importfilemissing', 'grades'));
      77  }
      78  
      79  /// which scope are we importing the outcomes in?
      80  if (isset($courseid) && ($scope  == 'custom')) {
      81      // custom scale
      82      $local_scope = true;
      83  } elseif (($scope == 'global') && has_capability('moodle/grade:manage', context_system::instance())) {
      84      // global scale
      85      $local_scope = false;
      86  } else {
      87      // shouldn't happen .. user might be trying to access this script without the right permissions.
      88      redirect('index.php', get_string('importerror', 'grades'));
      89  }
      90  
      91  // open the file, start importing data
      92  if ($handle = fopen($imported_file, 'r')) {
      93      $line = 0; // will keep track of current line, to give better error messages.
      94      $file_headers = '';
      95  
      96      // $csv_data needs to have at least these columns, the value is the default position in the data file.
      97      $headers = array('outcome_name' => 0, 'outcome_shortname' => 1, 'scale_name' => 3, 'scale_items' => 4);
      98      $optional_headers = array('outcome_description'=>2, 'scale_description' => 5);
      99      $imported_headers = array(); // will later be initialized with the values found in the file
     100  
     101      $fatal_error = false;
     102  
     103      // data should be separated by a ';'.  *NOT* by a comma!  TODO: version 2.0
     104      // or whenever we can depend on PHP5, set the second parameter (8192) to 0 (unlimited line length) : the database can store over 128k per line.
     105      while ( $csv_data = fgetcsv($handle, 8192, ';', '"')) { // if the line is over 8k, it won't work...
     106          $line++;
     107  
     108          // be tolerant on input, as fgetcsv returns "an array comprising a single null field" on blank lines
     109          if ($csv_data == array(null)) {
     110              continue;
     111          }
     112  
     113          // on first run, grab and analyse the header
     114          if ($file_headers == '') {
     115  
     116              $file_headers = array_flip($csv_data); // save the header line ... TODO: use the header line to let import work with columns in arbitrary order
     117  
     118              $error = false;
     119              foreach($headers as $key => $value) {
     120                  // sanity check #1: make sure the file contains all the mandatory headers
     121                  if (!array_key_exists($key, $file_headers)) {
     122                      $error = true;
     123                      break;
     124                  }
     125              }
     126              if ($error) {
     127                  echo $OUTPUT->box_start('generalbox importoutcomenofile buttons');
     128                  echo get_string('importoutcomenofile', 'grades', $line);
     129                  echo $OUTPUT->single_button(new moodle_url('/grade/edit/outcome/import.php', array('courseid'=> $courseid)), get_string('back'), 'get');
     130                  echo $OUTPUT->box_end();
     131                  $fatal_error = true;
     132                  break;
     133              }
     134  
     135              foreach(array_merge($headers, $optional_headers) as $header => $position) {
     136                  // match given columns to expected columns *into* $headers
     137                  $imported_headers[$header] = $file_headers[$header];
     138              }
     139  
     140              continue; // we don't import headers
     141          }
     142  
     143          // sanity check #2: every line must have the same number of columns as there are
     144          // headers.  If not, processing stops.
     145          if ( count($csv_data) != count($file_headers) ) {
     146              echo $OUTPUT->box_start('generalbox importoutcomenofile');
     147              echo get_string('importoutcomenofile', 'grades', $line);
     148              echo $OUTPUT->single_button(new moodle_url('/grade/edit/outcome/import.php', array('courseid'=> $courseid)), get_string('back'), 'get');
     149              echo $OUTPUT->box_end();
     150              $fatal_error = true;
     151              //echo $OUTPUT->box(var_export($csv_data, true) ."<br />". var_export($header, true));
     152              break;
     153          }
     154  
     155          // sanity check #3: all required fields must be present on the current line.
     156          foreach ($headers as $header => $position) {
     157              if ($csv_data[$imported_headers[$header]] == '') {
     158                  echo $OUTPUT->box_start('generalbox importoutcomenofile');
     159                  echo get_string('importoutcomenofile', 'grades', $line);
     160                  echo $OUTPUT->single_button(new moodle_url('/grade/edit/outcome/import.php', array('courseid'=> $courseid)), get_string('back'), 'get');
     161                  echo $OUTPUT->box_end();
     162                  $fatal_error = true;
     163                  break;
     164              }
     165          }
     166  
     167          // MDL-17273 errors in csv are not preventing import from happening. We break from the while loop here
     168          if ($fatal_error) {
     169              break;
     170          }
     171          $params = array($csv_data[$imported_headers['outcome_shortname']]);
     172          $wheresql = 'shortname = ? ';
     173  
     174          if ($local_scope) {
     175              $params[] = $courseid;
     176              $wheresql .= ' AND courseid = ?';
     177          } else {
     178              $wheresql .= ' AND courseid IS NULL';
     179          }
     180  
     181          $outcome = $DB->get_records_select('grade_outcomes', $wheresql, $params);
     182  
     183          if ($outcome) {
     184              // already exists, print a message and skip.
     185              echo $OUTPUT->box(get_string('importskippedoutcome', 'grades', $csv_data[$imported_headers['outcome_shortname']]));
     186              continue;
     187          }
     188  
     189          // new outcome will be added, search for compatible existing scale...
     190          $params = array($csv_data[$imported_headers['scale_name']], $csv_data[$imported_headers['scale_items']], $courseid);
     191          $wheresql = 'name = ? AND scale = ? AND (courseid = ? OR courseid = 0)';
     192          $scale = $DB->get_records_select('scale', $wheresql, $params);
     193  
     194          if ($scale) {
     195              // already exists in the right scope: use it.
     196              $scale_id = key($scale);
     197          } else {
     198              if (!has_capability('moodle/course:managescales', $context)) {
     199                  echo $OUTPUT->box(get_string('importskippednomanagescale', 'grades', $csv_data[$imported_headers['outcome_shortname']]));
     200                  continue;
     201              } else {
     202                  // scale doesn't exists : create it.
     203                  $scale_data = array('name' => $csv_data[$imported_headers['scale_name']],
     204                          'scale' => $csv_data[$imported_headers['scale_items']],
     205                          'description' => $csv_data[$imported_headers['scale_description']],
     206                          'userid' => $USER->id);
     207  
     208                  if ($local_scope) {
     209                      $scale_data['courseid'] = $courseid;
     210                  } else {
     211                      $scale_data['courseid'] = 0; // 'global' : scale use '0', outcomes use null
     212                  }
     213                  $scale = new grade_scale($scale_data);
     214                  $scale_id = $scale->insert();
     215              }
     216          }
     217  
     218          // add outcome
     219          $outcome_data = array('shortname' => $csv_data[$imported_headers['outcome_shortname']],
     220                  'fullname' => $csv_data[$imported_headers['outcome_name']],
     221                  'scaleid' => $scale_id,
     222                  'description' => $csv_data[$imported_headers['outcome_description']],
     223                  'usermodified' => $USER->id);
     224  
     225          if ($local_scope) {
     226              $outcome_data['courseid'] = $courseid;
     227          } else {
     228              $outcome_data['courseid'] = null; // 'global' : scale use '0', outcomes use null
     229          }
     230          $outcome = new grade_outcome($outcome_data);
     231          $outcome_id = $outcome->insert();
     232  
     233          $outcome_success_strings = new StdClass();
     234          $outcome_success_strings->name = $outcome_data['fullname'];
     235          $outcome_success_strings->id = $outcome_id;
     236          echo $OUTPUT->box(get_string('importoutcomesuccess', 'grades', $outcome_success_strings));
     237      }
     238  } else {
     239      echo $OUTPUT->box(get_string('importoutcomenofile', 'grades', 0));
     240  }
     241  
     242  // finish
     243  fclose($handle);
     244  // delete temp file
     245  unlink($imported_file);
     246  
     247  echo $OUTPUT->footer();
    

    Search This Site: