Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/grade/import/csv/index.php
Go to the documentation of this file.
00001 <?php
00002 
00003 // This file is part of Moodle - http://moodle.org/
00004 //
00005 // Moodle is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // Moodle is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
00017 
00018 require_once '../../../config.php';
00019 require_once $CFG->libdir.'/gradelib.php';
00020 require_once $CFG->dirroot.'/grade/lib.php';
00021 require_once '../grade_import_form.php';
00022 require_once '../lib.php';
00023 
00024 $id            = required_param('id', PARAM_INT); // course id
00025 $separator     = optional_param('separator', '', PARAM_ALPHA);
00026 $verbosescales = optional_param('verbosescales', 1, PARAM_BOOL);
00027 
00028 $url = new moodle_url('/grade/import/csv/index.php', array('id'=>$id));
00029 if ($separator !== '') {
00030     $url->param('separator', $separator);
00031 }
00032 if ($verbosescales !== 1) {
00033     $url->param('verbosescales', $verbosescales);
00034 }
00035 $PAGE->set_url($url);
00036 
00037 define('GRADE_CSV_LINE_LENGTH', 4096);
00038 
00039 if (!$course = $DB->get_record('course', array('id'=>$id))) {
00040     print_error('nocourseid');
00041 }
00042 
00043 require_login($course);
00044 $context = get_context_instance(CONTEXT_COURSE, $id);
00045 require_capability('moodle/grade:import', $context);
00046 require_capability('gradeimport/csv:view', $context);
00047 
00048 $separatemode = (groups_get_course_groupmode($COURSE) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context));
00049 $currentgroup = groups_get_course_group($course);
00050 
00051 // sort out delimiter
00052 if (isset($CFG->CSV_DELIMITER)) {
00053     $csv_delimiter = $CFG->CSV_DELIMITER;
00054 
00055     if (isset($CFG->CSV_ENCODE)) {
00056         $csv_encode = '/\&\#' . $CFG->CSV_ENCODE . '/';
00057     }
00058 } else if ($separator == 'tab') {
00059     $csv_delimiter = "\t";
00060     $csv_encode = "";
00061 } else {
00062     $csv_delimiter = ",";
00063     $csv_encode = '/\&\#44/';
00064 }
00065 
00066 print_grade_page_head($course->id, 'import', 'csv', get_string('importcsv', 'grades'));
00067 
00068 // set up import form
00069 $mform = new grade_import_form(null, array('includeseparator'=>!isset($CFG->CSV_DELIMITER), 'verbosescales'=>true));
00070 
00071 // set up grade import mapping form
00072 $header = '';
00073 $gradeitems = array();
00074 if ($id) {
00075     if ($grade_items = grade_item::fetch_all(array('courseid'=>$id))) {
00076         foreach ($grade_items as $grade_item) {
00077             // skip course type and category type
00078             if ($grade_item->itemtype == 'course' || $grade_item->itemtype == 'category') {
00079                 continue;
00080             }
00081 
00082             $displaystring = null;
00083             if (!empty($grade_item->itemmodule)) {
00084                 $displaystring = get_string('modulename', $grade_item->itemmodule).': '.$grade_item->get_name();
00085             } else {
00086                 $displaystring = $grade_item->get_name();
00087             }
00088             $gradeitems[$grade_item->id] = $displaystring;
00089         }
00090     }
00091 }
00092 
00093 if ($importcode = optional_param('importcode', '', PARAM_FILE)) {
00094     $filename = $CFG->tempdir.'/gradeimport/cvs/'.$USER->id.'/'.$importcode;
00095     $fp = fopen($filename, "r");
00096     $headers = fgets($fp, GRADE_CSV_LINE_LENGTH);
00097     $header = explode($csv_delimiter, $headers);
00098     fclose($fp);
00099 }
00100 
00101 $mform2 = new grade_import_mapping_form(null, array('gradeitems'=>$gradeitems, 'header'=>$header));
00102 
00103 // if import form is submitted
00104 if ($formdata = $mform->get_data()) {
00105 
00106     // Large files are likely to take their time and memory. Let PHP know
00107     // that we'll take longer, and that the process should be recycled soon
00108     // to free up memory.
00109     @set_time_limit(0);
00110     raise_memory_limit(MEMORY_EXTRA);
00111 
00112     // use current (non-conflicting) time stamp
00113     $importcode = get_new_importcode();
00114     $filename = make_temp_directory('gradeimport/cvs/'.$USER->id);
00115     $filename = $filename.'/'.$importcode;
00116 
00117     $text = $mform->get_file_content('userfile');
00118     // trim utf-8 bom
00119     $textlib = textlib_get_instance();
00121     $text = $textlib->convert($text, $formdata->encoding);
00122     $text = $textlib->trim_utf8_bom($text);
00123     // Fix mac/dos newlines
00124     $text = preg_replace('!\r\n?!',"\n",$text);
00125     $fp = fopen($filename, "w");
00126     fwrite($fp,$text);
00127     fclose($fp);
00128 
00129     $fp = fopen($filename, "r");
00130 
00131     // --- get header (field names) ---
00132     $header = explode($csv_delimiter, fgets($fp, GRADE_CSV_LINE_LENGTH));
00133 
00134     // print some preview
00135     $numlines = 0; // 0 preview lines displayed
00136 
00137     echo $OUTPUT->heading(get_string('importpreview', 'grades'));
00138     echo '<table>';
00139     echo '<tr>';
00140     foreach ($header as $h) {
00141         $h = clean_param($h, PARAM_RAW);
00142         echo '<th>'.$h.'</th>';
00143     }
00144     echo '</tr>';
00145     while (!feof ($fp) && $numlines <= $formdata->previewrows) {
00146         $lines = explode($csv_delimiter, fgets($fp, GRADE_CSV_LINE_LENGTH));
00147         echo '<tr>';
00148         foreach ($lines as $line) {
00149             echo '<td>'.$line.'</td>';
00150         }
00151         $numlines ++;
00152         echo '</tr>';
00153     }
00154     echo '</table>';
00155 
00156     // display the mapping form with header info processed
00157     $mform2 = new grade_import_mapping_form(null, array('gradeitems'=>$gradeitems, 'header'=>$header));
00158     $mform2->set_data(array('importcode'=>$importcode, 'id'=>$id, 'verbosescales'=>$verbosescales, 'separator'=>$separator));
00159     $mform2->display();
00160 
00161 //} else if (($formdata = data_submitted()) && !empty($formdata->map)) {
00162 
00163 // else if grade import mapping form is submitted
00164 } else if ($formdata = $mform2->get_data()) {
00165 
00166     $importcode = clean_param($formdata->importcode, PARAM_FILE);
00167     $filename = $CFG->tempdir.'/gradeimport/cvs/'.$USER->id.'/'.$importcode;
00168 
00169     if (!file_exists($filename)) {
00170         print_error('cannotuploadfile');
00171     }
00172 
00173     if ($fp = fopen($filename, "r")) {
00174         // --- get header (field names) ---
00175         $header = explode($csv_delimiter, clean_param(fgets($fp,GRADE_CSV_LINE_LENGTH), PARAM_RAW));
00176 
00177         foreach ($header as $i => $h) {
00178             $h = trim($h); $header[$i] = $h; // remove whitespace
00179         }
00180     } else {
00181         print_error('cannotopenfile');
00182     }
00183 
00184     $map = array();
00185     // loops mapping_0, mapping_1 .. mapping_n and construct $map array
00186     foreach ($header as $i => $head) {
00187         if (isset($formdata->{'mapping_'.$i})) {
00188             $map[$i] = $formdata->{'mapping_'.$i};
00189         }
00190     }
00191 
00192     // if mapping information is supplied
00193     $map[clean_param($formdata->mapfrom, PARAM_RAW)] = clean_param($formdata->mapto, PARAM_RAW);
00194 
00195     // check for mapto collisions
00196     $maperrors = array();
00197     foreach ($map as $i => $j) {
00198         if ($j == 0) {
00199             // you can have multiple ignores
00200             continue;
00201         } else {
00202             if (!isset($maperrors[$j])) {
00203                 $maperrors[$j] = true;
00204             } else {
00205                 // collision
00206                 fclose($fp);
00207                 unlink($filename); // needs to be uploaded again, sorry
00208                 print_error('cannotmapfield', '', '', $j);
00209             }
00210         }
00211     }
00212 
00213     // Large files are likely to take their time and memory. Let PHP know
00214     // that we'll take longer, and that the process should be recycled soon
00215     // to free up memory.
00216     @set_time_limit(0);
00217     raise_memory_limit(MEMORY_EXTRA);
00218 
00219     // we only operate if file is readable
00220     if ($fp = fopen($filename, "r")) {
00221 
00222         // read the first line makes sure this doesn't get read again
00223         $header = explode($csv_delimiter, fgets($fp, GRADE_CSV_LINE_LENGTH));
00224 
00225         $newgradeitems = array(); // temporary array to keep track of what new headers are processed
00226         $status = true;
00227 
00228         while (!feof ($fp)) {
00229             // add something
00230             $line = explode($csv_delimiter, fgets($fp, GRADE_CSV_LINE_LENGTH));
00231 
00232             if(count($line) <= 1){
00233                 // there is no data on this line, move on
00234                 continue;
00235             }
00236 
00237             // array to hold all grades to be inserted
00238             $newgrades = array();
00239             // array to hold all feedback
00240             $newfeedbacks = array();
00241             // each line is a student record
00242             foreach ($line as $key => $value) {
00243                 //decode encoded commas
00244                 $value = clean_param($value, PARAM_RAW);
00245                 $value = trim($value);
00246                 if (!empty($csv_encode)) {
00247                     $value = preg_replace($csv_encode, $csv_delimiter, $value);
00248                 }
00249 
00250                 /*
00251                  * the options are
00252                  * 1) userid, useridnumber, usermail, username - used to identify user row
00253                  * 2) new - new grade item
00254                  * 3) id - id of the old grade item to map onto
00255                  * 3) feedback_id - feedback for grade item id
00256                  */
00257 
00258                 $t = explode("_", $map[$key]);
00259                 $t0 = $t[0];
00260                 if (isset($t[1])) {
00261                     $t1 = (int)$t[1];
00262                 } else {
00263                     $t1 = '';
00264                 }
00265 
00266                 switch ($t0) {
00267                     case 'userid': //
00268                         if (!$user = $DB->get_record('user', array('id' => $value))) {
00269                             // user not found, abort whole import
00270                             import_cleanup($importcode);
00271                             echo $OUTPUT->notification("user mapping error, could not find user with id \"$value\"");
00272                             $status = false;
00273                             break 3;
00274                         }
00275                         $studentid = $value;
00276                     break;
00277                     case 'useridnumber':
00278                         if (!$user = $DB->get_record('user', array('idnumber' => $value))) {
00279                              // user not found, abort whole import
00280                             import_cleanup($importcode);
00281                             echo $OUTPUT->notification("user mapping error, could not find user with idnumber \"$value\"");
00282                             $status = false;
00283                             break 3;
00284                         }
00285                         $studentid = $user->id;
00286                     break;
00287                     case 'useremail':
00288                         if (!$user = $DB->get_record('user', array('email' => $value))) {
00289                             import_cleanup($importcode);
00290                             echo $OUTPUT->notification("user mapping error, could not find user with email address \"$value\"");
00291                             $status = false;
00292                             break 3;
00293                         }
00294                         $studentid = $user->id;
00295                     break;
00296                     case 'username':
00297                         if (!$user = $DB->get_record('user', array('username' => $value))) {
00298                             import_cleanup($importcode);
00299                             echo $OUTPUT->notification("user mapping error, could not find user with username \"$value\"");
00300                             $status = false;
00301                             break 3;
00302                         }
00303                         $studentid = $user->id;
00304                     break;
00305                     case 'new':
00306                         // first check if header is already in temp database
00307 
00308                         if (empty($newgradeitems[$key])) {
00309 
00310                             $newgradeitem = new stdClass();
00311                             $newgradeitem->itemname = $header[$key];
00312                             $newgradeitem->importcode = $importcode;
00313                             $newgradeitem->importer   = $USER->id;
00314 
00315                             // insert into new grade item buffer
00316                             $newgradeitems[$key] = $DB->insert_record('grade_import_newitem', $newgradeitem);
00317                         }
00318                         $newgrade = new stdClass();
00319                         $newgrade->newgradeitem = $newgradeitems[$key];
00320 
00321                         // if the user has a grade for this grade item
00322                         if (trim($value) != '-') {
00323                             // instead of omitting the grade we could insert one with finalgrade set to 0
00324                             // we do not have access to grade item min grade
00325                             $newgrade->finalgrade   = $value;
00326                             $newgrades[] = $newgrade;
00327                         }
00328                     break;
00329                     case 'feedback':
00330                         if ($t1) {
00331                             // case of an id, only maps id of a grade_item
00332                             // this was idnumber
00333                             if (!$gradeitem = new grade_item(array('id'=>$t1, 'courseid'=>$course->id))) {
00334                                 // supplied bad mapping, should not be possible since user
00335                                 // had to pick mapping
00336                                 $status = false;
00337                                 import_cleanup($importcode);
00338                                 echo $OUTPUT->notification(get_string('importfailed', 'grades'));
00339                                 break 3;
00340                             }
00341 
00342                             // t1 is the id of the grade item
00343                             $feedback = new stdClass();
00344                             $feedback->itemid   = $t1;
00345                             $feedback->feedback = $value;
00346                             $newfeedbacks[] = $feedback;
00347                         }
00348                     break;
00349                     default:
00350                         // existing grade items
00351                         if (!empty($map[$key])) {
00352                             // case of an id, only maps id of a grade_item
00353                             // this was idnumber
00354                             if (!$gradeitem = new grade_item(array('id'=>$map[$key], 'courseid'=>$course->id))) {
00355                                 // supplied bad mapping, should not be possible since user
00356                                 // had to pick mapping
00357                                 $status = false;
00358                                 import_cleanup($importcode);
00359                                 echo $OUTPUT->notification(get_string('importfailed', 'grades'));
00360                                 break 3;
00361                             }
00362 
00363                             // check if grade item is locked if so, abort
00364                             if ($gradeitem->is_locked()) {
00365                                 $status = false;
00366                                 import_cleanup($importcode);
00367                                 echo $OUTPUT->notification(get_string('gradeitemlocked', 'grades'));
00368                                 break 3;
00369                             }
00370 
00371                             $newgrade = new stdClass();
00372                             $newgrade->itemid     = $gradeitem->id;
00373                             if ($gradeitem->gradetype == GRADE_TYPE_SCALE and $verbosescales) {
00374                                 if ($value === '' or $value == '-') {
00375                                     $value = null; // no grade
00376                                 } else {
00377                                     $scale = $gradeitem->load_scale();
00378                                     $scales = explode(',', $scale->scale);
00379                                     $scales = array_map('trim', $scales); //hack - trim whitespace around scale options
00380                                     array_unshift($scales, '-'); // scales start at key 1
00381                                     $key = array_search($value, $scales);
00382                                     if ($key === false) {
00383                                         echo "<br/>t0 is $t0";
00384                                         echo "<br/>grade is $value";
00385                                         $status = false;
00386                                         import_cleanup($importcode);
00387                                         echo $OUTPUT->notification(get_string('badgrade', 'grades'));
00388                                         break 3;
00389                                     }
00390                                     $value = $key;
00391                                 }
00392                                 $newgrade->finalgrade = $value;
00393                             } else {
00394                                 if ($value === '' or $value == '-') {
00395                                     $value = null; // no grade
00396 
00397                                 } else if (!is_numeric($value)) {
00398                                 // non numeric grade value supplied, possibly mapped wrong column
00399                                     echo "<br/>t0 is $t0";
00400                                     echo "<br/>grade is $value";
00401                                     $status = false;
00402                                     import_cleanup($importcode);
00403                                     echo $OUTPUT->notification(get_string('badgrade', 'grades'));
00404                                     break 3;
00405                                 }
00406                                 $newgrade->finalgrade = $value;
00407                             }
00408                             $newgrades[] = $newgrade;
00409                         } // otherwise, we ignore this column altogether
00410                           // because user has chosen to ignore them (e.g. institution, address etc)
00411                     break;
00412                 }
00413             }
00414 
00415             // no user mapping supplied at all, or user mapping failed
00416             if (empty($studentid) || !is_numeric($studentid)) {
00417                 // user not found, abort whole import
00418                 $status = false;
00419                 import_cleanup($importcode);
00420                 echo $OUTPUT->notification('user mapping error, could not find user!');
00421                 break;
00422             }
00423 
00424             if ($separatemode and !groups_is_member($currentgroup, $studentid)) {
00425                 // not allowed to import into this group, abort
00426                 $status = false;
00427                 import_cleanup($importcode);
00428                 echo $OUTPUT->notification('user not member of current group, can not update!');
00429                 break;
00430             }
00431 
00432             // insert results of this students into buffer
00433             if ($status and !empty($newgrades)) {
00434 
00435                 foreach ($newgrades as $newgrade) {
00436 
00437                     // check if grade_grade is locked and if so, abort
00438                     if (!empty($newgrade->itemid) and $grade_grade = new grade_grade(array('itemid'=>$newgrade->itemid, 'userid'=>$studentid))) {
00439                         if ($grade_grade->is_locked()) {
00440                             // individual grade locked
00441                             $status = false;
00442                             import_cleanup($importcode);
00443                             echo $OUTPUT->notification(get_string('gradelocked', 'grades'));
00444                             break 2;
00445                         }
00446                     }
00447 
00448                     $newgrade->importcode = $importcode;
00449                     $newgrade->userid     = $studentid;
00450                     $newgrade->importer   = $USER->id;
00451                     $DB->insert_record('grade_import_values', $newgrade);
00452                 }
00453             }
00454 
00455             // updating/inserting all comments here
00456             if ($status and !empty($newfeedbacks)) {
00457                 foreach ($newfeedbacks as $newfeedback) {
00458                     $sql = "SELECT *
00459                               FROM {grade_import_values}
00460                              WHERE importcode=? AND userid=? AND itemid=? AND importer=?";
00461                     if ($feedback = $DB->get_record_sql($sql, array($importcode, $studentid, $newfeedback->itemid, $USER->id))) {
00462                         $newfeedback->id = $feedback->id;
00463                         $DB->update_record('grade_import_values', $newfeedback);
00464 
00465                     } else {
00466                         // the grade item for this is not updated
00467                         $newfeedback->importcode = $importcode;
00468                         $newfeedback->userid     = $studentid;
00469                         $newfeedback->importer   = $USER->id;
00470                         $DB->insert_record('grade_import_values', $newfeedback);
00471                     }
00472                 }
00473             }
00474         }
00475 
00477         if ($status) {
00478             grade_import_commit($course->id, $importcode);
00479         }
00480         // temporary file can go now
00481         fclose($fp);
00482         unlink($filename);
00483     } else {
00484         print_error('cannotreadfile');
00485     }
00486 
00487 } else {
00488     groups_print_course_menu($course, 'index.php?id='.$id);
00489     echo '<div class="clearer"></div>';
00490 
00491     // display the standard upload file form
00492     $mform->display();
00493 }
00494 
00495 echo $OUTPUT->footer();
00496 
 All Data Structures Namespaces Files Functions Variables Enumerations