/** * This function returns a list of the page images from a pdf. * * The readonly version is different than the normal one. The readonly version contains a copy * of the pages in the state they were when the PDF was annotated, by doing so we prevent the * the pages that are displayed to change as soon as the submission changes. * * Though there is an edge case, if the PDF was annotated before MDL-45580, then it is possible * that we do not find any readonly version of the pages. In that case, we will get the normal * pages and copy them to the readonly area. This ensures that the pages will remain in that * state until the submission is updated. When the normal files do not exist, we throw an exception * because the readonly pages should only ever be displayed after a teacher has annotated the PDF, * they would not exist until they do. * * @param int|\assign $assignment * @param int $userid * @param int $attemptnumber (-1 means latest attempt) * @param bool $readonly If true, then we are requesting the readonly version. * @return array(stored_file) */ public static function get_page_images_for_attempt($assignment, $userid, $attemptnumber, $readonly = false) { $assignment = self::get_assignment_from_param($assignment); if (!$assignment->can_view_submission($userid)) { \print_error('nopermission'); } if ($assignment->get_instance()->teamsubmission) { $submission = $assignment->get_group_submission($userid, 0, false, $attemptnumber); } else { $submission = $assignment->get_user_submission($userid, false, $attemptnumber); } $grade = $assignment->get_user_grade($userid, true, $attemptnumber); $contextid = $assignment->get_context()->id; $component = 'assignfeedback_editpdf'; $itemid = $grade->id; $filepath = '/'; $filearea = self::PAGE_IMAGE_FILEAREA; $fs = \get_file_storage(); // If we are after the readonly pages... if ($readonly) { $filearea = self::PAGE_IMAGE_READONLY_FILEAREA; if ($fs->is_area_empty($contextid, $component, $filearea, $itemid)) { // We have a problem here, we were supposed to find the files. // Attempt to re-generate the pages from the combined images. self::generate_page_images_for_attempt($assignment, $userid, $attemptnumber); self::copy_pages_to_readonly_area($assignment, $grade); } } $files = $fs->get_directory_files($contextid, $component, $filearea, $itemid, $filepath); $pages = array(); if (!empty($files)) { $first = reset($files); if (!$readonly && $first->get_timemodified() < $submission->timemodified) { // Image files are stale, we need to regenerate them, except in readonly mode. // We also need to remove the draft annotations and comments associated with this attempt. $fs->delete_area_files($contextid, $component, $filearea, $itemid); page_editor::delete_draft_content($itemid); $files = array(); } else { // Need to reorder the files following their name. // because get_directory_files() return a different order than generate_page_images_for_attempt(). foreach ($files as $file) { // Extract the page number from the file name image_pageXXXX.png. preg_match('/page([\\d]+)\\./', $file->get_filename(), $matches); if (empty($matches) or !is_numeric($matches[1])) { throw new \coding_exception("'" . $file->get_filename() . "' file hasn't the expected format filename: image_pageXXXX.png."); } $pagenumber = (int) $matches[1]; // Save the page in the ordered array. $pages[$pagenumber] = $file; } ksort($pages); } } if (empty($pages)) { if ($readonly) { // This should never happen, there should be a version of the pages available // whenever we are requesting the readonly version. throw new \moodle_exception('Could not find readonly pages for grade ' . $grade->id); } $pages = self::generate_page_images_for_attempt($assignment, $userid, $attemptnumber); } return $pages; }