Beispiel #1
0
/**
 * Serves the files from the emarking file areas
 * 
 * @package mod_emarking
 * @category files
 * @param stdClass $course
 *            the course object
 * @param stdClass $cm
 *            the course module object
 * @param stdClass $context
 *            the emarking's context
 * @param string $filearea
 *            the name of the file area
 * @param array $args
 *            extra arguments (itemid, path)
 * @param bool $forcedownload
 *            whether or not force download
 * @param array $options
 *            additional options affecting the file serving
 */
function emarking_pluginfile($course, $cm, $context, $filearea, array $args, $forcedownload, array $options = array())
{
    global $DB, $CFG, $USER;
    require_once $CFG->dirroot . '/mod/emarking/locallib.php';
    require_once $CFG->dirroot . '/mod/emarking/print/locallib.php';
    require_login();
    // send_file defaults.
    $lifetime = null;
    $filter = 0;
    $pathisstring = false;
    $forcedownload = false;
    $mimetype = '';
    $dontdie = false;
    // end of send_file defaults.
    $filename = array_pop($args);
    $itemid = array_pop($args);
    $contextcategory = context_coursecat::instance($course->category);
    $contextcourse = context_course::instance($course->id);
    // Security! We always protect the exams filearea.
    if ($filearea === 'exams') {
        send_file_not_found();
    }
    if ($filearea === 'pages') {
        $parts = explode('-', $filename);
        if (count($parts) != 3) {
            send_file_not_found();
        }
        if (!($parts[0] === intval($parts[0]) . "") || !($parts[1] === intval($parts[1]) . "")) {
            send_file_not_found();
        }
        $subparts = explode('.', $parts[2]);
        $isanonymous = substr($subparts[0], -strlen('_a')) === '_a';
        $imageuser = intval($parts[0]);
        $usercangrade = has_capability('mod/emarking:grade', $context);
        $bothenrolled = is_enrolled($contextcourse) && is_enrolled($contextcourse, $imageuser);
        if ($USER->id != $imageuser && !$usercangrade && !$isanonymous && !is_siteadmin($USER) && !$bothenrolled) {
            send_file_not_found();
        }
    }
    if ($filearea === 'response') {
        $parts = explode('_', $filename);
        if (count($parts) != 3) {
            send_file_not_found();
        }
        if (!($parts[0] === "response") || !($parts[1] === intval($parts[1]) . "")) {
            send_file_not_found();
        }
        $subparts = explode('.', $parts[2]);
        $studentid = intval($subparts[0]);
        $emarkingid = intval($parts[1]);
        if (!($emarking = $DB->get_record('emarking', array('id' => $emarkingid)))) {
            send_file_not_found();
        }
        if ($studentid != $USER->id && !is_siteadmin($USER) && !has_capability('mod/emarking:supervisegrading', $context)) {
            send_file_not_found();
        }
        $forcedownload = true;
        $mimetype = 'application/pdf';
    }
    if ($filearea === 'examstoprint') {
        if (!has_capability('mod/emarking:downloadexam', $contextcategory)) {
            // Add to Moodle log so some auditing can be done.
            \mod_emarking\event\invalidaccessdownload_attempted::create_from_exam($exam, $contextcourse)->trigger();
            send_file_not_found();
        }
        $token = required_param('token', PARAM_INT);
        if ($token > 9999 && $_SESSION[$USER->sesskey . "smstoken"] === $token) {
            if (!($exam = $DB->get_record('emarking_exams', array('emarking' => $itemid)))) {
                send_file_not_found();
            }
            $now = new DateTime();
            $tokendate = new DateTime();
            $tokendate->setTimestamp($_SESSION[$USER->sesskey . "smsdate"]);
            $diff = $now->diff($tokendate);
            if ($diff->i > 5 && false) {
                // Add to Moodle log so some auditing can be done.
                \mod_emarking\event\invalidtokendownload_attempted::create_from_exam($exam, $contextcourse)->trigger();
                send_file_not_found();
            }
            // Everything is fine, now we update the exam status and deliver the file.
            $exam->status = EMARKING_EXAM_SENT_TO_PRINT;
            $DB->update_record('emarking_exams', $exam);
        } else {
            // Add to Moodle log so some auditing can be done.
            \mod_emarking\event\invalidtokendownload_attempted::create_from_exam($exam, $contextcourse)->trigger();
            send_file_not_found();
        }
        // Notify everyone that the exam was downloaded.
        emarking_send_examdownloaded_notification($exam, $course, $USER);
        // Add to Moodle log so some auditing can be done.
        \mod_emarking\event\exam_downloaded::create_from_exam($exam, $contextcourse)->trigger();
    }
    $fs = get_file_storage();
    if (!($file = $fs->get_file($context->id, 'mod_emarking', $filearea, $itemid, '/', $filename))) {
        echo $context->id . ".." . $filearea . ".." . $itemid . ".." . $filename;
        echo "File really not found";
        send_file_not_found();
    }
    send_file($file, $filename, $lifetime, $filter, $pathisstring, $forcedownload, $mimetype = '', $dontdie);
}
Beispiel #2
0
/**
 * Creates a personalized exam file.
 *
 * @param unknown $examid            
 * @return NULL
 */
function emarking_download_exam($examid, $multiplepdfs = false, $groupid = null, progress_bar $pbar = null, $sendprintorder = false, $idprinter = null, $printanswersheet = false, $debugprinting = false, $savetofile = false)
{
    global $DB, $CFG, $USER, $OUTPUT;
    require_once $CFG->dirroot . '/mod/emarking/lib/openbub/ans_pdf_open.php';
    // Validate emarking exam object.
    if (!($downloadexam = $DB->get_record('emarking_exams', array('id' => $examid)))) {
        throw new Exception(get_string("invalidexamid", "mod_emarking"));
    }
    // Course context for capabilities checking.
    $context = context_course::instance($downloadexam->course);
    if (!has_capability('mod/emarking:downloadexam', $context) && false) {
        throw new Exception(get_string("invalidaccess", "mod_emarking"));
    }
    // Verify that remote printing is enable, otherwise disable a printing order.
    if ($sendprintorder && (!$CFG->emarking_enableprinting || $idprinter == null)) {
        throw new Exception('Printing is not enabled or printername was absent ' . $idprinter);
    }
    // Validate course.
    if (!($course = $DB->get_record('course', array('id' => $downloadexam->course)))) {
        throw new Exception(get_string("invalidcourse", "mod_emarking"));
    }
    // Validate course category.
    if (!($coursecat = $DB->get_record('course_categories', array('id' => $course->category)))) {
        throw new Exception(get_string("invalidcategoryid", "mod_emarking"));
    }
    // We tell the user we are setting up the printing.
    if ($pbar) {
        $pbar->update(0, 1, get_string('settingupprinting', 'mod_emarking'));
    }
    // Default value for enrols that will be included.
    if ($CFG->emarking_enrolincludes && strlen($CFG->emarking_enrolincludes) > 1) {
        $enrolincludes = $CFG->emarking_enrolincludes;
    }
    // If the exam sets enrolments, we use those.
    if (isset($downloadexam->enrolments) && strlen($downloadexam->enrolments) > 1) {
        $enrolincludes = $downloadexam->enrolments;
    }
    // Convert enrolments to array.
    $enrolincludes = explode(",", $enrolincludes);
    // Produce all PDFs first separatedly.
    $filedir = $CFG->dataroot . "/temp/emarking/{$context->id}";
    $fileimg = $filedir . "/qr";
    $userimgdir = $filedir . "/u";
    $pdfdir = $filedir . "/pdf";
    emarking_initialize_directory($filedir, true);
    emarking_initialize_directory($fileimg, true);
    emarking_initialize_directory($userimgdir, true);
    emarking_initialize_directory($pdfdir, true);
    // Get all the files uploaded as forms for this exam.
    $fs = get_file_storage();
    $files = $fs->get_area_files($context->id, 'mod_emarking', 'exams', $examid);
    // We filter only the PDFs.
    $pdffileshash = array();
    foreach ($files as $filepdf) {
        if ($filepdf->get_mimetype() === 'application/pdf') {
            $pdffileshash[] = array('hash' => $filepdf->get_pathnamehash(), 'filename' => $filepdf->get_filename(), 'path' => emarking_get_path_from_hash($filedir, $filepdf->get_pathnamehash()));
        }
    }
    // Verify that at least we have a PDF.
    if (count($pdffileshash) < 1) {
        throw new Exception(get_string("examhasnopdf", "mod_emarking"));
    }
    $students = emarking_get_students_for_printing($downloadexam->course);
    $studentinfo = array();
    $currenttemplate = 0;
    // Fill studentnames with student info (name, idnumber, id and picture).
    foreach ($students as $student) {
        $studentenrolments = explode(",", $student->enrol);
        // Verifies that the student is enrolled through a valid enrolment and that we haven't added her yet.
        if (count(array_intersect($studentenrolments, $enrolincludes)) == 0 || isset($studentinfo[$student->id])) {
            continue;
        }
        // We create a student info object.
        $studentobj = new stdClass();
        $studentobj->name = substr("{$student->lastname}, {$student->firstname}", 0, 65);
        $studentobj->idnumber = $student->idnumber;
        $studentobj->id = $student->id;
        $studentobj->picture = emarking_get_student_picture($student, $userimgdir);
        // Store student info in hash so every student is stored once.
        $studentinfo[$student->id] = $studentobj;
    }
    // We validate the number of students as we are filtering by enrolment.
    // type after getting the data.
    $numberstudents = count($studentinfo);
    if ($numberstudents == 0) {
        throw new Exception('No students to print/create the exam');
    }
    // Add the extra students to the list.
    for ($i = $numberstudents; $i < $numberstudents + $downloadexam->extraexams; $i++) {
        $studentobj = new stdClass();
        $studentobj->name = '..............................................................................';
        $studentobj->idnumber = 0;
        $studentobj->id = 0;
        $studentobj->picture = $CFG->dirroot . "/pix/u/f1.png";
        $studentinfo[] = $studentobj;
    }
    // Check if there is a logo file.
    $logofilepath = emarking_get_logo_file($filedir);
    // If asked to do so we create a PDF witht the students list.
    if ($downloadexam->printlist == 1) {
        $pdf = new FPDI();
        $pdf->SetPrintHeader(false);
        $pdf->SetPrintFooter(false);
        emarking_draw_student_list($pdf, $logofilepath, $downloadexam, $course, $studentinfo);
        $studentlistpdffile = $pdfdir . "/000-studentslist.pdf";
        $pdf->Output($studentlistpdffile, "F");
        // Se genera el nuevo pdf.
        $pdf = null;
    }
    // Here we produce a PDF file for each student.
    $currentstudent = 0;
    foreach ($studentinfo as $stinfo) {
        $studentrecord = $DB->get_record('user', array('id' => $stinfo->id));
        // If we have a progress bar, we notify the new PDF being created.
        if ($pbar) {
            $pbar->update($currentstudent + 1, count($studentinfo), $stinfo->name);
        }
        // We create the PDF file.
        $pdf = new FPDI();
        $pdf->SetPrintHeader(false);
        $pdf->SetPrintFooter(false);
        // We use the next form available from the list of PDF forms sent.
        if ($currenttemplate >= count($pdffileshash) - 1) {
            $currenttemplate = 0;
        } else {
            $currenttemplate++;
        }
        // Load the PDF from the filesystem as template.
        $path = $pdffileshash[$currenttemplate]['path'];
        $originalpdfpages = $pdf->setSourceFile($path);
        $pdf->SetAutoPageBreak(false);
        // Add all pages in the template, adding the header if it corresponds.
        for ($pagenumber = 1; $pagenumber <= $originalpdfpages + $downloadexam->extrasheets; $pagenumber++) {
            // Adding a page.
            $pdf->AddPage();
            // If the page is not an extra page, we import the page from the template.
            if ($pagenumber <= $originalpdfpages) {
                $template = $pdf->importPage($pagenumber);
                $pdf->useTemplate($template, 0, 0, 0, 0, true);
            }
            // If we have a personalized header, we add it.
            if ($downloadexam->headerqr) {
                emarking_draw_header($pdf, $stinfo, $downloadexam->name, $pagenumber, $fileimg, $logofilepath, $course, $originalpdfpages + $downloadexam->extrasheets);
            }
        }
        // The filename will be the student id - course id - page number.
        $qrstringtmp = $stinfo->id > 0 ? "{$stinfo->id}-{$course->id}-{$pagenumber}" : "NN{$currentstudent}+1-{$course->id}-{$pagenumber}";
        // Create the PDF file for the student.
        $pdffile = $pdfdir . "/" . $qrstringtmp . ".pdf";
        $pdf->Output($pdffile, "F");
        // Store the exam file for printing later.
        $stinfo->examfile = $pdffile;
        $stinfo->number = $currentstudent + 1;
        $stinfo->pdffilename = $qrstringtmp;
        $currentstudent++;
    }
    $sqlprinter = "SELECT id, name, command\n\t\t\tFROM {emarking_printers}\n\t\t\tWHERE id = ?";
    $printerinfo = $DB->get_record_sql($sqlprinter, array($idprinter));
    // If we have to print directly.
    $debugprintingmsg = '';
    if ($sendprintorder) {
        // Check if we have to print the students list.
        if ($downloadexam->printlist == 1) {
            $printresult = emarking_print_file($printerinfo->name, $printerinfo->command, $studentlistpdffile, $debugprinting);
            if (!$printresult) {
                $debugprintingmsg .= 'Problems printing ' . $studentlistpdffile . '<hr>';
            } else {
                $debugprintingmsg .= $printresult . '<hr>';
            }
        }
        // Print each student.
        $currentstudent = 0;
        foreach ($studentinfo as $stinfo) {
            $currentstudent++;
            if ($pbar != null) {
                $pbar->update($currentstudent, count($studentinfo), get_string('printing', 'mod_emarking') . ' ' . $stinfo->name);
            }
            if (!isset($stinfo->examfile) || !file_exists($stinfo->examfile)) {
                continue;
            }
            $printresult = emarking_print_file($printerinfo->name, $printerinfo->command, $stinfo->examfile, $debugprinting);
            if (!$printresult) {
                $debugprintingmsg .= 'Problems printing ' . $stinfo->examfile . '<hr>';
            } else {
                $debugprintingmsg .= $printresult . '<hr>';
            }
        }
        if ($CFG->debug || $debugprinting) {
            echo $debugprintingmsg;
        }
        // Notify everyone that the exam was printed.
        emarking_send_examprinted_notification($downloadexam, $course);
        $downloadexam->status = EMARKING_EXAM_PRINTED;
        $downloadexam->printdate = time();
        $DB->update_record('emarking_exams', $downloadexam);
        // Add to Moodle log so some auditing can be done.
        \mod_emarking\event\exam_downloaded::create_from_exam($downloadexam, $context)->trigger();
        return true;
    }
    $examfilename = emarking_clean_filename($course->shortname, true) . '_' . emarking_clean_filename($downloadexam->name, true);
    $zipdebugmsg = '';
    if ($multiplepdfs) {
        $zip = new ZipArchive();
        $zipfilename = $filedir . "/" . $examfilename . ".zip";
        if ($zip->open($zipfilename, ZipArchive::CREATE) !== true) {
            throw new Exception('Could not create zip file');
        }
        // Check if we have to print the students list.
        if ($downloadexam->printlist == 1) {
            $zip->addFile($studentlistpdffile);
        }
        // Add every student PDF to zip file.
        $currentstudent = 0;
        foreach ($studentinfo as $stinfo) {
            $currentstudent++;
            if ($pbar != null) {
                $pbar->update($currentstudent, count($studentinfo), get_string('printing', 'mod_emarking') . ' ' . $stinfo->name);
            }
            if (!isset($stinfo->examfile) || !file_exists($stinfo->examfile)) {
                continue;
            }
            if (!$zip->addFile($stinfo->examfile, $stinfo->pdffilename . '.pdf')) {
                $zipdebugmsg .= "Problems adding {$stinfo->examfile} to ZIP file using name {$stinfo->pdffilename} <hr>";
            }
        }
        $zip->close();
        if ($CFG->debug || $debugprinting) {
            echo $zipdebugmsg;
        }
        // Notify everyone that the exam was downloaded.
        emarking_send_examdownloaded_notification($downloadexam, $course, $USER);
        $downloadexam->status = EMARKING_EXAM_SENT_TO_PRINT;
        $downloadexam->printdate = time();
        $DB->update_record('emarking_exams', $downloadexam);
        // Add to Moodle log so some auditing can be done.
        \mod_emarking\event\exam_downloaded::create_from_exam($downloadexam, $context)->trigger();
        // Read zip file from disk and send to the browser.
        $filename = basename($zipfilename);
        header("Content-Type: application/zip");
        header("Content-Disposition: attachment; filename=" . $examfilename . ".zip");
        header("Content-Length: " . filesize($zipfilename));
        readfile($zipfilename);
        exit;
    }
    // We create the final big PDF file.
    $pdf = new FPDI();
    $pdf->SetPrintHeader(false);
    $pdf->SetPrintFooter(false);
    // We import the students list if required.
    if ($downloadexam->printlist) {
        emarking_import_pdf_into_pdf($pdf, $studentlistpdffile);
    }
    // Add every student PDF to zip file.
    $currentstudent = 0;
    foreach ($studentinfo as $stinfo) {
        $currentstudent++;
        if (!isset($stinfo->examfile) || !file_exists($stinfo->examfile)) {
            continue;
        }
        emarking_import_pdf_into_pdf($pdf, $stinfo->examfile);
    }
    if ($savetofile) {
        $savedfile = $filedir . '/' . $examfilename . '.pdf';
        $pdf->Output($savedfile, 'F');
        $requestedby = $DB->get_record('user', array('id' => $downloadexam->requestedby));
        // Copy file from temp folder to Moodle's filesystem.
        $filerecord = array('contextid' => $context->id, 'component' => 'mod_emarking', 'filearea' => 'examstoprint', 'itemid' => $downloadexam->emarking, 'filepath' => '/', 'filename' => $examfilename . '.pdf', 'timecreated' => time(), 'timemodified' => time(), 'userid' => $requestedby->id, 'author' => $requestedby->firstname . ' ' . $requestedby->lastname, 'license' => 'allrightsreserved');
        // Filesystem.
        $fs = get_file_storage();
        // If the file already exists we delete it.
        if ($fs->file_exists($context->id, 'mod_emarking', 'examstoprint', $downloadexam->emarking, '/', $examfilename . '.pdf')) {
            $previousfile = $fs->get_file($context->id, 'mod_emarking', 'examstoprint', $downloadexam->emarking, '/', $examfilename . '.pdf');
            $previousfile->delete();
        }
        // Info for the new file.
        $fileinfo = $fs->create_file_from_pathname($filerecord, $filedir . '/' . $examfilename . '.pdf');
        // Notify everyone that the exam was downloaded.
        emarking_send_examgenerated_notification($downloadexam, $course, $requestedby);
        $downloadexam->status = EMARKING_EXAM_SENT_TO_PRINT;
        $downloadexam->printdate = time();
        $downloadexam->filetoprint = $fileinfo->get_id();
        $DB->update_record('emarking_exams', $downloadexam);
        // Add to Moodle log so some auditing can be done.
        \mod_emarking\event\exam_downloaded::create_from_exam($downloadexam, $context)->trigger();
        return true;
    } else {
        // Notify everyone that the exam was downloaded.
        emarking_send_examdownloaded_notification($downloadexam, $course, $USER);
        $downloadexam->status = EMARKING_EXAM_SENT_TO_PRINT;
        $downloadexam->printdate = time();
        $DB->update_record('emarking_exams', $downloadexam);
        // Add to Moodle log so some auditing can be done.
        \mod_emarking\event\exam_downloaded::create_from_exam($downloadexam, $context)->trigger();
        $pdf->Output($examfilename . '.pdf', 'D');
    }
}
Beispiel #3
0
// A token was sent to validate download it will have 5 digits, otherwise it should be 0.
if ($token > 9999 && $_SESSION[$USER->sesskey . "smstoken"] === $token) {
    $now = new DateTime();
    $tokendate = new DateTime();
    $tokendate->setTimestamp($_SESSION[$USER->sesskey . "smsdate"]);
    $diff = $now->diff($tokendate);
    if ($diff->i > 5 && false) {
        echo $OUTPUT->header();
        echo $OUTPUT->notification(get_string("tokenexpired", "mod_emarking"), "notifyproblem");
        $buttonurl = $incourse ? $courseurl : $coursecategoryurl;
        echo $OUTPUT->single_button($buttonurl, get_string("back"), "get");
        echo $OUTPUT->footer();
        die;
    }
    // Add to Moodle log so some auditing can be done.
    \mod_emarking\event\exam_downloaded::create_from_exam($exam, $contextcourse)->trigger();
    // Get all the files uploaded as forms for this exam.
    $fs = get_file_storage();
    $files = $fs->get_area_files($contextcourse->id, 'mod_emarking', 'examstoprint', $exam->emarking);
    // We filter only the PDFs.
    $pdffilename = NULL;
    foreach ($files as $filepdf) {
        if ($filepdf->get_mimetype() === 'application/pdf') {
            $pdffilename = $filepdf->get_filename();
        }
    }
    // Verify that at least we have a PDF.
    if (!$pdffilename) {
        throw new Exception(get_string("examhasnopdf", "mod_emarking"));
    }
    redirect($CFG->wwwroot . '/pluginfile.php/' . $contextcourse->id . '/mod_emarking/examstoprint/' . $exam->emarking . '/' . $pdffilename . '?token=' . $token);