Exemplo n.º 1
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)
{
    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"));
    }
    // Contexto del curso para verificar permisos
    $context = context_course::instance($downloadexam->course);
    if (!has_capability('mod/emarking:downloadexam', $context)) {
        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) {
        // 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_SENT_TO_PRINT;
        $downloadexam->printdate = time();
        $DB->update_record('emarking_exams', $downloadexam);
        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);
        $downloadexam->status = EMARKING_EXAM_SENT_TO_PRINT;
        $downloadexam->printdate = time();
        $DB->update_record('emarking_exams', $downloadexam);
        // Read zip file from disk and send to the browser
        $file_name = 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);
    }
    // Notify everyone that the exam was downloaded
    emarking_send_examdownloaded_notification($downloadexam, $course);
    $downloadexam->status = EMARKING_EXAM_SENT_TO_PRINT;
    $downloadexam->printdate = time();
    $DB->update_record('emarking_exams', $downloadexam);
    $pdf->Output($examfilename . '.pdf', 'D');
}
Exemplo n.º 2
0
/**
 * Crea un archivo PDF a partir de un quiz, agregando una hoja de respuestas de opción múltiple
 * 
 * @param unknown $cm
 * @param string $debug
 * @param string $context
 * @param string $course
 * @param string $logofilepath
 * @param boolean $answersheetsonly
 * @return void|NULL
 */
function emarking_create_quiz_pdf($cm, $debug = false, $context = null, $course = null, $answersheetsonly = false, $pbar = false)
{
    global $DB, $CFG, $OUTPUT;
    // Inclusión de librerías
    require_once $CFG->dirroot . '/mod/assign/feedback/editpdf/fpdi/fpdi2tcpdf_bridge.php';
    require_once $CFG->dirroot . '/mod/assign/feedback/editpdf/fpdi/fpdi.php';
    require_once $CFG->libdir . '/pdflib.php';
    require_once $CFG->dirroot . '/mod/quiz/locallib.php';
    require_once $CFG->dirroot . '/mod/emarking/print/locallib.php';
    $filedir = $CFG->dataroot . "/temp/emarking/{$context->id}";
    emarking_initialize_directory($filedir, true);
    $fileimg = $CFG->dataroot . "/temp/emarking/{$context->id}/qr";
    emarking_initialize_directory($fileimg, true);
    $userimgdir = $CFG->dataroot . "/temp/emarking/{$context->id}/u";
    emarking_initialize_directory($userimgdir, true);
    $logofile = emarking_get_logo_file();
    $logofilepath = $logofile ? emarking_get_path_from_hash($filedir, $logofile->get_pathnamehash()) : null;
    $fullhtml = array();
    $numanswers = array();
    $attemptids = array();
    $images = array();
    $imageshtml = array();
    $users = emarking_get_enroled_students($course->id);
    if ($pbar) {
        echo $OUTPUT->heading(get_string('loadingquestions', 'mod_emarking'), 3);
        $progressbar = new progress_bar();
        $progressbar->create();
        $progressbar->update(0, count($users), get_string('processing', 'mod_emarking'));
    }
    $current = 0;
    foreach ($users as $user) {
        $current++;
        if ($pbar) {
            $progressbar->update($current, count($users), "{$user->firstname}, {$user->lastname}");
        }
        // Get the quiz object
        $quizobj = quiz::create($cm->instance, $user->id);
        // Create the new attempt and initialize the question sessions
        $attemptnumber = 1;
        $lastattempt = null;
        $timenow = time();
        // Update time now, in case the server is running really slowly.
        $attempts = quiz_get_user_attempts($quizobj->get_quizid(), $user->id, 'all');
        $numattempts = count($attempts);
        foreach ($attempts as $attempt) {
            $attemptobj = quiz_attempt::create($attempt->id);
            $slots = $attemptobj->get_slots();
            foreach ($slots as $slot) {
                $qattempt = $attemptobj->get_question_attempt($slot);
                $question = $qattempt->get_question();
                if ($question->get_type_name() === 'multianswer') {
                    $q = $question->subquestions[1];
                    $numanswers[$user->id][] = count($q->answers);
                } else {
                    if ($question->get_type_name() === 'multichoice') {
                        $numanswers[$user->id][] = count($question->answers);
                    }
                }
                $attemptids[$user->id] = $attempt->id;
                $qhtml = $attemptobj->render_question($slot, false);
                $qhtml = emarking_clean_question_html($qhtml);
                $currentimages = emarking_extract_images_url($qhtml);
                $idx = 0;
                foreach ($currentimages[1] as $imageurl) {
                    if (!array_search($imageurl, $images)) {
                        $images[] = $imageurl;
                        $imageshtml[] = $currentimages[0][$idx];
                    }
                    $idx++;
                }
                $fullhtml[$user->id][] = $qhtml;
            }
            // One attempt per user
            break;
        }
    }
    $save_to = $CFG->tempdir . '/emarking/printquiz/' . $cm->id . '/';
    emarking_initialize_directory($save_to, true);
    // Bajar las imágenes del HTML a dibujar
    $search = array();
    $replace = array();
    $replaceweb = array();
    $imagesize = array();
    $idx = 0;
    if ($pbar) {
        $progressbar->update_full(100, get_string('finished', 'mod_emarking'));
        echo $OUTPUT->heading(get_string('downloadingimages', 'mod_emarking'), 3);
        $progressbar = new progress_bar();
        $progressbar->create();
        $progressbar->update(0, count($images), get_string('processing', 'mod_emarking'));
    }
    foreach ($images as $image) {
        if ($pbar) {
            $imagefilename = explode("/", $image);
            $progressbar->update($idx + 1, count($images), $imagefilename[count($imagefilename) - 1]);
        }
        // Si solamente incluiremos hojas de respuesta terminamos el ciclo
        if ($answersheetsonly) {
            break;
        }
        if (!(list($filename, $imageinfo) = emarking_get_file_from_url($image, $save_to))) {
            echo "Problem downloading file {$image} <hr>";
        } else {
            // Buscamos el src de la imagen
            $search[] = 'src="' . $image . '"';
            $replacehtml = ' src="' . $filename . '"';
            $replacehtmlxweb = ' src="' . $image . '"';
            // Si el html de la misma contiene ancho o alto, se deja tal cual
            $imghtml = $imageshtml[$idx];
            if (substr_count($imghtml, "width") + substr_count($imghtml, "height") == 0) {
                $width = $imageinfo[0];
                $height = $imageinfo[1];
                $ratio = floatval(10) / floatval($height);
                $height = 10;
                $width = (int) ($ratio * floatval($width));
                $sizehtml = 'width="' . $width . '" height="' . $height . '"';
                $replacehtml = $sizehtml . ' ' . $replacehtml;
                $replacehtmlxweb = $sizehtml . ' ' . $replacehtmlxweb;
            }
            $replace[] = $replacehtml;
            $replaceweb[] = $replacehtmlxweb;
            $imagesize[] = $imageinfo;
        }
        $idx++;
    }
    if ($debug) {
        foreach ($fullhtml as $uid => $questions) {
            $index = 0;
            foreach ($questions as $question) {
                echo str_replace($search, $replaceweb, $fullhtml[$uid][$index]);
                $index++;
            }
        }
        return;
    }
    // Now we create the pdf file with the modified html
    $doc = new FPDI();
    $doc->setPrintHeader(false);
    $doc->setPrintFooter(false);
    $doc->SetFont('times', '', 12);
    // set margins
    $doc->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
    $doc->SetHeaderMargin(250);
    $doc->SetFooterMargin(PDF_MARGIN_FOOTER);
    if ($pbar) {
        $progressbar->update_full(100, get_string('finished', 'mod_emarking'));
        echo $OUTPUT->heading(get_string('creatingpdffile', 'mod_emarking'), 3);
        $progressbar = new progress_bar();
        $progressbar->create();
    }
    $current = 0;
    foreach ($fullhtml as $uid => $questions) {
        $current++;
        $stinfo = $DB->get_record('user', array('id' => $uid));
        $stinfo->name = $stinfo->firstname . ' ' . $stinfo->lastname;
        $stinfo->picture = emarking_get_student_picture($stinfo, $userimgdir);
        $stinfo->idnumber = $uid . '-' . $attemptids[$uid];
        if ($pbar) {
            $progressbar->update($current, count($fullhtml), $stinfo->name);
        }
        $groups = groups_get_user_groups($course->id, $uid);
        if ($groups && isset($groups[0][0]) && ($group = $DB->get_record('groups', array('id' => $groups[0][0])))) {
            $stinfo->group = $group->name;
        } else {
            $stinfo->group = '';
        }
        emarking_add_answer_sheet($doc, $filedir, $stinfo, $logofilepath, null, $fileimg, $course, $quizobj->get_quiz_name(), $numanswers[$uid], $attemptids[$uid]);
        // Una vez agregada la página de respuestas, si es todo lo que hay que hacer saltar al siguiente
        if ($answersheetsonly) {
            continue;
        }
        $doc->AddPage();
        emarking_draw_header($doc, $stinfo, $quizobj->get_quiz_name(), 2, $fileimg, $logofilepath, $course, null, false, 0);
        $doc->SetFont('times', '', 12);
        $doc->SetAutoPageBreak(true);
        $doc->SetXY(PDF_MARGIN_LEFT, 40);
        $index = 0;
        foreach ($questions as $question) {
            $prevy = $doc->getY();
            $fullhtml[$uid][$index] = str_replace($search, $replace, $fullhtml[$uid][$index]);
            $doc->writeHTML($fullhtml[$uid][$index]);
            $y = $doc->getY();
            $fmargin = $doc->getFooterMargin();
            $height = $doc->getPageHeight();
            $spaceleft = $height - $fmargin - $y;
            $questionsize = $y - $prevy;
            if ($spaceleft < 70) {
                $doc->AddPage();
            }
            $index++;
        }
    }
    if ($pbar) {
        $progressbar->update_full(100, get_string('finished', 'mod_emarking'));
    }
    $qid = $quizobj->get_quizid();
    $pdfquizfilename = 'quiz-' . $qid . '-' . random_string() . '.pdf';
    $fs = get_file_storage();
    $filerecord = array('component' => 'mod_emarking', 'filearea' => 'pdfquiz', 'contextid' => $context->id, 'itemid' => $quizobj->get_quizid(), 'filepath' => '/', 'filename' => $pdfquizfilename);
    $doc->Output($filedir . '/' . $pdfquizfilename, 'F');
    $file = $fs->create_file_from_pathname($filerecord, $filedir . '/' . $pdfquizfilename);
    $downloadurl = moodle_url::make_file_url("{$CFG->wwwroot}/pluginfile.php", "/{$context->id}/mod_emarking/pdfquiz/{$qid}/{$pdfquizfilename}", null, true);
    return $downloadurl;
}