/** * Validates the answer key file * @param unknown $data * @return multitype:Ambigous <string, lang_string> |multitype:string Ambigous <string, lang_string> */ private function get_answerkey_file_errors($data) { global $USER, $COURSE; $errors = array(); // We get the draftid from the form. $draftid = file_get_submitted_draft_itemid('answerkeyfile'); $usercontext = context_user::instance($USER->id); $fs = get_file_storage(); $files = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftid); $tempdir = emarking_get_temp_dir_path($COURSE->id); emarking_initialize_directory($tempdir, true); $numpagesprevious = -1; $exampdfs = array(); foreach ($files as $uploadedfile) { if ($uploadedfile->is_directory()) { continue; } if ($uploadedfile->get_mimetype() !== 'application/pdf') { $errors['exam_files'] = get_string('invalidfilenotpdf', 'mod_emarking') . '_' . $uploadedfile->get_mimetype() . '_' . $uploadedfile->get_filename(); return $errors; } $filename = $uploadedfile->get_filename(); $filename = emarking_clean_filename($filename); $newfilename = $tempdir . '/' . $filename; $pdffile = emarking_get_path_from_hash($tempdir, $uploadedfile->get_pathnamehash()); // Executes pdftk burst to get all pages separated. $numpages = emarking_pdf_count_pages($newfilename, $tempdir, false); if (!is_numeric($numpages) || $numpages < 1) { $errors['exam_files'] = get_string('invalidpdfnopages', 'mod_emarking'); return $errors; } if ($numpagesprevious >= 0 && $numpagesprevious != $numpages) { $errors['exam_files'] = get_string('invalidpdfnumpagesforms', 'mod_emarking'); return $errors; } $exampdfs[] = array('pathname' => $pdffile, 'filename' => $filename); } if (count($exampdfs) == 0 && $data['exam'] == 0) { $errors['exam_files'] = get_string('filerequiredtosendnewprintorder', 'mod_emarking'); return $errors; } return $errors; }
/** * Saves a new instance of the emarking into the database * * Given an object containing all the necessary data, * (defined by the form in mod_form.php) this function * will create a new instance and return the id number * of the new instance. * * @param object $emarking * An object from the form in mod_form.php * @param mod_emarking_mod_form $mform * @return int The id of the newly inserted emarking record */ function emarking_add_instance(stdClass $data, mod_emarking_mod_form $mform = null) { global $DB, $CFG, $COURSE, $USER; $data->timecreated = time(); $id = $DB->insert_record('emarking', $data); $data->id = $id; emarking_grade_item_update($data); if ($data->type == EMARKING_TYPE_MARKER_TRAINING) { return $id; } foreach ($data as $k => $v) { $parts = explode('-', $k); if (count($parts) > 1 && $parts[0] === 'marker') { $markerid = intval($parts[1]); $marker = new stdClass(); $marker->emarking = $id; $marker->marker = $markerid; $marker->qualitycontrol = 1; $DB->insert_record('emarking_markers', $marker); } } $context = context_course::instance($COURSE->id); $examid = 0; // If there's no previous exam to associate, and we are creating a new // e-marking, we need the PDF file if ($data->exam == 0) { // We get the draftid from the form $draftid = file_get_submitted_draft_itemid('exam_files'); $usercontext = context_user::instance($USER->id); $fs = get_file_storage(); $files = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftid); $tempdir = emarking_get_temp_dir_path($COURSE->id); emarking_initialize_directory($tempdir, true); $numpagesprevious = -1; $exampdfs = array(); foreach ($files as $uploadedfile) { if ($uploadedfile->get_mimetype() !== 'application/pdf') { continue; } $filename = $uploadedfile->get_filename(); $filename = emarking_clean_filename($filename); $newfilename = $tempdir . '/' . $filename; $pdffile = emarking_get_path_from_hash($tempdir, $uploadedfile->get_pathnamehash()); // Executes pdftk burst to get all pages separated $numpages = emarking_pdf_count_pages($newfilename, $tempdir, false); $exampdfs[] = array('pathname' => $pdffile, 'filename' => $filename); } } else { $examid = $data->exam; } $studentsnumber = emarking_get_students_count_for_printing($COURSE->id); // A new exam object is created and its attributes filled from form data if ($examid == 0) { $exam = new stdClass(); $exam->course = $COURSE->id; $exam->courseshortname = $COURSE->shortname; $exam->name = $mform->get_data()->name; $exam->examdate = $mform->get_data()->examdate; $exam->emarking = $id; $exam->headerqr = isset($mform->get_data()->headerqr) ? 1 : 0; $exam->printrandom = isset($mform->get_data()->printrandom) ? 1 : 0; $exam->printlist = isset($mform->get_data()->printlist) ? 1 : 0; $exam->extrasheets = $mform->get_data()->extrasheets; $exam->extraexams = $mform->get_data()->extraexams; $exam->usebackside = isset($mform->get_data()->printdoublesided) ? 1 : 0; if ($examid == 0) { $exam->timecreated = time(); } $exam->timemodified = time(); $exam->requestedby = $USER->id; $exam->totalstudents = $studentsnumber; // Get the enrolments as a comma separated values $enrollist = array(); if (!empty($mform->get_data()->enrolments)) { $enrolments = $mform->get_data()->enrolments; foreach ($enrolments as $key => $enrolment) { if (!empty($enrolment)) { $enrollist[] = $key; } } } $exam->enrolments = implode(",", $enrollist); $exam->printdate = 0; $exam->status = EMARKING_EXAM_UPLOADED; // Calculate total pages for exam $exam->totalpages = $numpages; $exam->id = $DB->insert_record('emarking_exams', $exam); foreach ($exampdfs as $exampdf) { // Save the submitted file to check if it's a PDF $filerecord = array('component' => 'mod_emarking', 'filearea' => 'exams', 'contextid' => $context->id, 'itemid' => $exam->id, 'filepath' => '/', 'filename' => $exampdf['filename']); $file = $fs->create_file_from_pathname($filerecord, $exampdf['pathname']); } // Update exam object to store the PDF's file id $exam->file = $file->get_id(); if (!$DB->update_record('emarking_exams', $exam)) { $fs->delete_area_files($contextid, 'emarking', 'exams', $exam->id); print_error(get_string('errorsavingpdf', 'mod_emarking')); } // Send new print order notification emarking_send_newprintorder_notification($exam, $COURSE); // If it is a multi-course submission, insert several exams if (!empty($mform->get_data()->multicourse)) { $multicourse = $mform->get_data()->multicourse; foreach ($multicourse as $key => $mcourse) { if (!empty($key)) { if ($thiscourse = $DB->get_record('course', array('shortname' => $key))) { $studentsnumber = emarking_get_students_count_for_printing($thiscourse->id); $newexam = $exam; $newexam->id = null; $newexam->totalstudents = $studentsnumber; $newexam->course = $thiscourse->id; $newexam->courseshortname = $thiscourse->shortname; $newexam->emarking = 0; $newexam->id = $DB->insert_record('emarking_exams', $newexam); $thiscontext = context_course::instance($thiscourse->id); // Create file records for all new exams foreach ($exampdfs as $exampdf) { // Save the submitted file to check if it's a PDF $filerecord = array('component' => 'mod_emarking', 'filearea' => 'exams', 'contextid' => $thiscontext->id, 'itemid' => $newexam->id, 'filepath' => '/', 'filename' => $exampdf['filename']); $file = $fs->create_file_from_pathname($filerecord, $exampdf['pathname']); } // Send new print order notification emarking_send_newprintorder_notification($newexam, $thiscourse); } } } } } else { $exam = $DB->get_record("emarking_exams", array("id" => $examid)); $exam->emarking = $id; $exam->timemodified = time(); $DB->update_record('emarking_exams', $exam); } $headerqr = isset($mform->get_data()->headerqr) ? 1 : 0; setcookie("emarking_headerqr", $headerqr, time() + 3600 * 24 * 365 * 10, '/'); $defaultexam = new stdClass(); $defaultexam->headerqr = $exam->headerqr; $defaultexam->printrandom = $exam->printrandom; $defaultexam->printlist = $exam->printlist; $defaultexam->extrasheets = $exam->extrasheets; $defaultexam->extraexams = $exam->extraexams; $defaultexam->usebackside = $exam->usebackside; $defaultexam->enrolments = $exam->enrolments; setcookie("emarking_exam_defaults", json_encode($defaultexam), time() + 3600 * 24 * 365 * 10, '/'); return $id; }
function validation($data, $files) { global $CFG, $COURSE, $USER, $DB; require_once $CFG->dirroot . "/mod/emarking/print/locallib.php"; if ($data["type"] < 0 || $data["type"] > 5) { return array("type" => get_string("markingtypemandatory", "mod_emarking")); } // Calculates context for validating permissions // If we have the module available, we use it, otherwise we fallback to course $ctx = context_course::instance($COURSE->id); if ($this->current && $this->current->coursemodule) { $cm = get_coursemodule_from_id('emarking', $this->current->module, $COURSE->id); if ($cm) { $ctx = context_module::instance($cm->id); } } $errors = array(); // Verify that we have enough markers if ($data['type'] == EMARKING_TYPE_MARKER_TRAINING) { // Get all users with permission to grade in emarking $markers = get_enrolled_users($ctx, 'mod/emarking:grade'); $totalmarkers = 0; foreach ($markers as $marker) { if (has_capability('mod/emarking:supervisegrading', $ctx, $marker)) { continue; } $totalmarkers++; } if ($totalmarkers < 2) { $errors['type'] = get_string('notenoughmarkersfortraining', 'mod_emarking'); return $errors; } return $errors; } // Get the exam if we are updating an emarking activity $exam = null; if (isset($data['exam']) && $data['exam'] > 0) { if (!($exam = $DB->get_record("emarking_exams", array("id" => $data["exam"])))) { $errors["exam"] = "Invalid data from form"; } } // If there is no associated exam yet if (!$exam) { // The exam date comes from the date selector $examdate = new DateTime(); $examdate->setTimestamp(usertime($data['examdate'])); // Day of week from 0 Sunday to 6 Saturday $examw = date("w", $examdate->getTimestamp()); // Hour of the day un 00 to 23 format $examh = date("H", $examdate->getTimestamp()); // If minimum days for printing is enabled if (isset($CFG->emarking_minimumdaysbeforeprinting) && $CFG->emarking_minimumdaysbeforeprinting > 0) { // Sundays are forbidden, saturdays from 6am to 4pm TODO: Move this settings to eMarking settings if ($examw == 0 || $examw == 6 && ($examh < 6 || $examh > 16)) { $errors['examdate'] = get_string('examdateinvaliddayofweek', 'mod_emarking'); } // User date. Important because the user sees a date selector based on her timezone settings, not the server's $date = usertime(time()); // Today is the date according to the user's timezone $today = new DateTime(); $today->setTimestamp($date); // We have a minimum difference otherwise we wouldn't be in this part of the code $mindiff = intval($CFG->emarking_minimumdaysbeforeprinting); // If today is saturday or sunday, demand for a bigger difference $todayw = date("w", $today->getTimestamp()); $todayw = $todayw ? $todayw : 7; if ($todayw > 5) { $mindiff += $todayw - 5; } // DateInterval calculated with diff $diff = $today->diff($examdate, false); // The difference using the invert from DateInterval so we know it is in the past $realdiff = $diff->days * ($diff->invert ? -1 : 1); // If the difference is not enough, show an error if ($realdiff < $mindiff) { $a = new stdClass(); $a->mindays = $mindiff; $errors['examdate'] = get_string('examdateinvalid', 'mod_emarking', $a); } } } // If there's no previous exam to associate, and we are creating a new // e-marking, we need the PDF file if ($data["exam"] == 0 && !$this->_instance) { // We get the draftid from the form $draftid = file_get_submitted_draft_itemid('exam_files'); $usercontext = context_user::instance($USER->id); $fs = get_file_storage(); $files = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftid); $tempdir = emarking_get_temp_dir_path($COURSE->id); emarking_initialize_directory($tempdir, true); $numpagesprevious = -1; $exampdfs = array(); foreach ($files as $uploadedfile) { if ($uploadedfile->get_mimetype() !== 'application/pdf') { continue; } $filename = $uploadedfile->get_filename(); $filename = emarking_clean_filename($filename); $newfilename = $tempdir . '/' . $filename; $pdffile = emarking_get_path_from_hash($tempdir, $uploadedfile->get_pathnamehash()); // Executes pdftk burst to get all pages separated $numpages = emarking_pdf_count_pages($newfilename, $tempdir, false); if (!is_numeric($numpages) || $numpages < 1) { $errors["exam_files"] = get_string('invalidpdfnopages', 'mod_emarking'); return $errors; } if ($numpagesprevious >= 0 && $numpagesprevious != $numpages) { $errors["exam_files"] = get_string('invalidpdfnumpagesforms', 'mod_emarking'); return $errors; } $exampdfs[] = array('pathname' => $pdffile, 'filename' => $filename); } if (count($exampdfs) == 0) { $errors["exam_files"] = get_string('invalidpdfnopages', 'mod_emarking'); return $errors; } } // Validate the adjusted slope $adjustslope = isset($data['adjustslope']) ? $data['adjustslope'] : false; $adjustslopescore = isset($data['adjustslopescore']) ? $data['adjustslopescore'] : 0; $adjustslopegrade = isset($data['adjustslopegrade']) ? $data['adjustslopegrade'] : 0; $grademin = $data['grademin']; $grademax = $data['grade']; $regradesopendate = $data['regradesopendate']; $regradesclosedate = $data['regradesclosedate']; // Make sure the minimum score is not greater than the maximum score if ($grademin >= $grademax) { $errors['grademin'] = get_string('gradescheck', 'mod_emarking'); $errors['grade'] = get_string('gradescheck', 'mod_emarking'); } // If we are adjusting the slope if ($adjustslope) { // Make sure the grade is greater than the minimum grade if ($adjustslopegrade <= $grademin) { $errors['adjustslopegrade'] = get_string('adjustslopegrademustbegreaterthanmin', 'mod_emarking'); } // Make sure the grade is lower than the maximum grade if ($adjustslopegrade > $grademax) { $errors['adjustslopegrade'] = get_string('adjustslopegrademustbelowerthanmax', 'mod_emarking'); } // And that the score for adjusting is greater than 0 if ($adjustslopescore <= 0) { $errors['adjustslopescore'] = get_string('adjustslopescoregreaterthanzero', 'mod_emarking'); } } // Validate regrade dates if ($regradesopendate > $regradesclosedate) { $errors['regradesopendate'] = get_string('verifyregradedate', 'mod_emarking'); $errors['regradesclosedate'] = get_string('verifyregradedate', 'mod_emarking'); } // Validate custom marks $custommarks = isset($data['custommarks']) ? $data['custommarks'] : ''; $custommarks = str_replace('\\r\\n', '\\n', $custommarks); if (strlen($custommarks) > 0) { $parts = explode("\n", $custommarks); $linenumber = 0; foreach ($parts as $line) { $linenumber++; if (strlen(trim($line)) == 0) { continue; } $subparts = explode("#", $line); if (count($subparts) != 2) { if (!isset($errors['custommarks'])) { $errors['custommarks'] = get_string('invalidcustommarks', 'mod_emarking'); } $errors['custommarks'] .= "{$linenumber} "; } } } $qualitycontrol = isset($data['enablequalitycontrol']) ? $data['enablequalitycontrol'] : false; if ($data['type'] == EMARKING_TYPE_NORMAL && $qualitycontrol) { // Get all users with permission to grade in emarking // Get all users with permission to grade in emarking $markers = get_enrolled_users($ctx, 'mod/emarking:grade'); $totalmarkers = 0; foreach ($markers as $marker) { if (isset($data['marker-' . $marker->id])) { $totalmarkers++; } } if ($totalmarkers == 0) { $errors['markers'] = get_string('notenoughmarkersforqualitycontrol', 'mod_emarking'); } } if ($data["exam"] > 0 && $this->_instance) { $previousexam = $DB->get_record("emarking_exams", array("emarking" => $this->_instance)); if ($previousexam && $previousexam->id != $data["exam"]) { $errors["exam"] = "An exam is already assigned for this emarking activity"; } } return $errors; }
/** * Validates if the draft files uploaded by a user are valid PDF exams * * @return array list of valid PDF exam files */ function emarking_validate_exam_files_from_draft() { global $USER, $COURSE; // We get the draftid from the form. $draftid = file_get_submitted_draft_itemid('exam_files'); $usercontext = context_user::instance($USER->id); $fs = get_file_storage(); $files = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftid); $tempdir = emarking_get_temp_dir_path($COURSE->id); emarking_initialize_directory($tempdir, true); $numpagesprevious = -1; $exampdfs = array(); foreach ($files as $uploadedfile) { if ($uploadedfile->is_directory() || $uploadedfile->get_mimetype() !== 'application/pdf') { continue; } $filename = $uploadedfile->get_filename(); $filename = emarking_clean_filename($filename); $newfilename = $tempdir . '/' . $filename; $pdffile = emarking_get_path_from_hash($tempdir, $uploadedfile->get_pathnamehash()); // Executes pdftk burst to get all pages separated. $numpages = emarking_pdf_count_pages($newfilename, $tempdir, false); $exampdfs[] = array('pathname' => $pdffile, 'filename' => $filename, 'numpages' => $numpages); } return $exampdfs; }
$fs = get_file_storage(); $files = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftid); $tempdir = emarking_get_temp_dir_path($course->id); emarking_initialize_directory($tempdir, true); $numpagesprevious = -1; $exampdfs = array(); foreach ($files as $uploadedfile) { if ($uploadedfile->get_mimetype() !== 'application/pdf') { continue; } $filename = $uploadedfile->get_filename(); $filename = emarking_clean_filename($filename); $newfilename = $tempdir . '/' . $filename; $pdffile = emarking_get_path_from_hash($tempdir, $uploadedfile->get_pathnamehash()); // Executes pdftk burst to get all pages separated $numpages = emarking_pdf_count_pages($newfilename, $tempdir, false); if (!is_numeric($numpages) || $numpages < 1 || $numpagesprevious >= 0 && $numpagesprevious != $numpages) { echo $OUTPUT->header(); echo $OUTPUT->heading(get_string('error')); echo $OUTPUT->error_text(get_string('invalidpdfnopages', 'mod_emarking')); echo $OUTPUT->continue_button($cancelurl); die; } $exampdfs[] = array('pathname' => $pdffile, 'filename' => $filename); } $studentsnumber = emarking_get_students_count_for_printing($course->id); // A new exam object is created and its attributes filled from form data if ($examid == 0) { $exam = new stdClass(); } $exam->course = $course->id;