[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/mod/assign/feedback/editpdf/classes/ -> document_services.php (source)

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * This file contains the ingest manager for the assignfeedback_editpdf plugin
  19   *
  20   * @package   assignfeedback_editpdf
  21   * @copyright 2012 Davo Smith
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace assignfeedback_editpdf;
  26  
  27  /**
  28   * Functions for generating the annotated pdf.
  29   *
  30   * This class controls the ingest of student submission files to a normalised
  31   * PDF 1.4 document with all submission files concatinated together. It also
  32   * provides the functions to generate a downloadable pdf with all comments and
  33   * annotations embedded.
  34   * @copyright 2012 Davo Smith
  35   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  36   */
  37  class document_services {
  38  
  39      /** File area for generated pdf */
  40      const FINAL_PDF_FILEAREA = 'download';
  41      /** File area for combined pdf */
  42      const COMBINED_PDF_FILEAREA = 'combined';
  43      /** File area for page images */
  44      const PAGE_IMAGE_FILEAREA = 'pages';
  45      /** File area for readonly page images */
  46      const PAGE_IMAGE_READONLY_FILEAREA = 'readonlypages';
  47      /** Filename for combined pdf */
  48      const COMBINED_PDF_FILENAME = 'combined.pdf';
  49  
  50      /**
  51       * This function will take an int or an assignment instance and
  52       * return an assignment instance. It is just for convenience.
  53       * @param int|\assign $assignment
  54       * @return assign
  55       */
  56      private static function get_assignment_from_param($assignment) {
  57          global $CFG;
  58  
  59          require_once($CFG->dirroot . '/mod/assign/locallib.php');
  60  
  61          if (!is_object($assignment)) {
  62              $cm = \get_coursemodule_from_instance('assign', $assignment, 0, false, MUST_EXIST);
  63              $context = \context_module::instance($cm->id);
  64  
  65              $assignment = new \assign($context, null, null);
  66          }
  67          return $assignment;
  68      }
  69  
  70      /**
  71       * Get a hash that will be unique and can be used in a path name.
  72       * @param int|\assign $assignment
  73       * @param int $userid
  74       * @param int $attemptnumber (-1 means latest attempt)
  75       */
  76      private static function hash($assignment, $userid, $attemptnumber) {
  77          if (is_object($assignment)) {
  78              $assignmentid = $assignment->get_instance()->id;
  79          } else {
  80              $assignmentid = $assignment;
  81          }
  82          return sha1($assignmentid . '_' . $userid . '_' . $attemptnumber);
  83      }
  84  
  85      /**
  86       * This function will search for all files that can be converted
  87       * and concatinated into a PDF (1.4) - for any submission plugin
  88       * for this students attempt.
  89       * @param int|\assign $assignment
  90       * @param int $userid
  91       * @param int $attemptnumber (-1 means latest attempt)
  92       * @return array(stored_file)
  93       */
  94      public static function list_compatible_submission_files_for_attempt($assignment, $userid, $attemptnumber) {
  95          global $USER, $DB;
  96  
  97          $assignment = self::get_assignment_from_param($assignment);
  98  
  99          // Capability checks.
 100          if (!$assignment->can_view_submission($userid)) {
 101              \print_error('nopermission');
 102          }
 103  
 104          $files = array();
 105  
 106          if ($assignment->get_instance()->teamsubmission) {
 107              $submission = $assignment->get_group_submission($userid, 0, false);
 108          } else {
 109              $submission = $assignment->get_user_submission($userid, false);
 110          }
 111          $user = $DB->get_record('user', array('id' => $userid));
 112  
 113          // User has not submitted anything yet.
 114          if (!$submission) {
 115              return $files;
 116          }
 117          // Ask each plugin for it's list of files.
 118          foreach ($assignment->get_submission_plugins() as $plugin) {
 119              if ($plugin->is_enabled() && $plugin->is_visible()) {
 120                  $pluginfiles = $plugin->get_files($submission, $user);
 121                  foreach ($pluginfiles as $filename => $file) {
 122                      if (($file instanceof \stored_file) && ($file->get_mimetype() === 'application/pdf')) {
 123                          $files[$filename] = $file;
 124                      }
 125                  }
 126              }
 127          }
 128          return $files;
 129      }
 130  
 131      /**
 132       * This function return the combined pdf for all valid submission files.
 133       * @param int|\assign $assignment
 134       * @param int $userid
 135       * @param int $attemptnumber (-1 means latest attempt)
 136       * @return stored_file
 137       */
 138      public static function get_combined_pdf_for_attempt($assignment, $userid, $attemptnumber) {
 139  
 140          global $USER, $DB;
 141  
 142          $assignment = self::get_assignment_from_param($assignment);
 143  
 144          // Capability checks.
 145          if (!$assignment->can_view_submission($userid)) {
 146              \print_error('nopermission');
 147          }
 148  
 149          $grade = $assignment->get_user_grade($userid, true, $attemptnumber);
 150          if ($assignment->get_instance()->teamsubmission) {
 151              $submission = $assignment->get_group_submission($userid, 0, false);
 152          } else {
 153              $submission = $assignment->get_user_submission($userid, false);
 154          }
 155  
 156          $contextid = $assignment->get_context()->id;
 157          $component = 'assignfeedback_editpdf';
 158          $filearea = self::COMBINED_PDF_FILEAREA;
 159          $itemid = $grade->id;
 160          $filepath = '/';
 161          $filename = self::COMBINED_PDF_FILENAME;
 162          $fs = \get_file_storage();
 163  
 164          $combinedpdf = $fs->get_file($contextid, $component, $filearea, $itemid, $filepath, $filename);
 165          if (!$combinedpdf ||
 166                  ($submission && ($combinedpdf->get_timemodified() < $submission->timemodified))) {
 167              return self::generate_combined_pdf_for_attempt($assignment, $userid, $attemptnumber);
 168          }
 169          return $combinedpdf;
 170      }
 171  
 172      /**
 173       * This function will take all of the compatible files for a submission
 174       * and combine them into one PDF.
 175       * @param int|\assign $assignment
 176       * @param int $userid
 177       * @param int $attemptnumber (-1 means latest attempt)
 178       * @return stored_file
 179       */
 180      public static function generate_combined_pdf_for_attempt($assignment, $userid, $attemptnumber) {
 181          global $CFG;
 182  
 183          require_once($CFG->libdir . '/pdflib.php');
 184  
 185          $assignment = self::get_assignment_from_param($assignment);
 186  
 187          if (!$assignment->can_view_submission($userid)) {
 188              \print_error('nopermission');
 189          }
 190  
 191          $files = self::list_compatible_submission_files_for_attempt($assignment, $userid, $attemptnumber);
 192  
 193          $pdf = new pdf();
 194          if (!$files) {
 195              // No valid submission files - create an empty pdf.
 196              $pdf->AddPage();
 197          } else {
 198  
 199              // Create a mega joined PDF.
 200              $compatiblepdfs = array();
 201              foreach ($files as $file) {
 202                  $compatiblepdf = pdf::ensure_pdf_compatible($file);
 203                  if ($compatiblepdf) {
 204                      array_push($compatiblepdfs, $compatiblepdf);
 205                  }
 206              }
 207  
 208              $tmpdir = \make_temp_directory('assignfeedback_editpdf/combined/' . self::hash($assignment, $userid, $attemptnumber));
 209              $tmpfile = $tmpdir . '/' . self::COMBINED_PDF_FILENAME;
 210  
 211              @unlink($tmpfile);
 212              try {
 213                  $pagecount = $pdf->combine_pdfs($compatiblepdfs, $tmpfile);
 214              } catch (\Exception $e) {
 215                  debugging('TCPDF could not process the pdf files:' . $e->getMessage(), DEBUG_DEVELOPER);
 216                  // TCPDF does not recover from errors so we need to re-initialise the class.
 217                  $pagecount = 0;
 218              }
 219              if ($pagecount == 0) {
 220                  // We at least want a single blank page.
 221                  debugging('TCPDF did not produce a valid pdf:' . $tmpfile . '. Replacing with a blank pdf.', DEBUG_DEVELOPER);
 222                  $pdf = new pdf();
 223                  $pdf->AddPage();
 224                  @unlink($tmpfile);
 225                  $files = false;
 226              }
 227          }
 228  
 229          $grade = $assignment->get_user_grade($userid, true, $attemptnumber);
 230          $record = new \stdClass();
 231  
 232          $record->contextid = $assignment->get_context()->id;
 233          $record->component = 'assignfeedback_editpdf';
 234          $record->filearea = self::COMBINED_PDF_FILEAREA;
 235          $record->itemid = $grade->id;
 236          $record->filepath = '/';
 237          $record->filename = self::COMBINED_PDF_FILENAME;
 238          $fs = \get_file_storage();
 239  
 240          $fs->delete_area_files($record->contextid, $record->component, $record->filearea, $record->itemid);
 241  
 242          // Detect corrupt generated pdfs and replace with a blank one.
 243          if ($files) {
 244              $pagecount = $pdf->load_pdf($tmpfile);
 245              if ($pagecount <= 0) {
 246                  $files = false;
 247              }
 248          }
 249  
 250          if (!$files) {
 251              // This was a blank pdf.
 252              unset($pdf);
 253              $pdf = new pdf();
 254              $content = $pdf->Output(self::COMBINED_PDF_FILENAME, 'S');
 255              $file = $fs->create_file_from_string($record, $content);
 256          } else {
 257              // This was a combined pdf.
 258              $file = $fs->create_file_from_pathname($record, $tmpfile);
 259              @unlink($tmpfile);
 260  
 261              // Test the generated file for correctness.
 262              $compatiblepdf = pdf::ensure_pdf_compatible($file);
 263          }
 264  
 265          return $file;
 266      }
 267  
 268      /**
 269       * This function will return the number of pages of a pdf.
 270       * @param int|\assign $assignment
 271       * @param int $userid
 272       * @param int $attemptnumber (-1 means latest attempt)
 273       * @param bool $readonly When true we get the number of pages for the readonly version.
 274       * @return int number of pages
 275       */
 276      public static function page_number_for_attempt($assignment, $userid, $attemptnumber, $readonly = false) {
 277          global $CFG;
 278  
 279          require_once($CFG->libdir . '/pdflib.php');
 280  
 281          $assignment = self::get_assignment_from_param($assignment);
 282  
 283          if (!$assignment->can_view_submission($userid)) {
 284              \print_error('nopermission');
 285          }
 286  
 287          // When in readonly we can return the number of images in the DB because they should already exist,
 288          // if for some reason they do not, then we proceed as for the normal version.
 289          if ($readonly) {
 290              $grade = $assignment->get_user_grade($userid, true, $attemptnumber);
 291              $fs = get_file_storage();
 292              $files = $fs->get_directory_files($assignment->get_context()->id, 'assignfeedback_editpdf',
 293                  self::PAGE_IMAGE_READONLY_FILEAREA, $grade->id, '/');
 294              $pagecount = count($files);
 295              if ($pagecount > 0) {
 296                  return $pagecount;
 297              }
 298          }
 299  
 300          // Get a combined pdf file from all submitted pdf files.
 301          $file = self::get_combined_pdf_for_attempt($assignment, $userid, $attemptnumber);
 302          if (!$file) {
 303              \print_error('Could not generate combined pdf.');
 304          }
 305  
 306          // Store the combined pdf file somewhere to be opened by tcpdf.
 307          $tmpdir = \make_temp_directory('assignfeedback_editpdf/pagetotal/'
 308              . self::hash($assignment, $userid, $attemptnumber));
 309          $combined = $tmpdir . '/' . self::COMBINED_PDF_FILENAME;
 310          $file->copy_content_to($combined); // Copy the file.
 311  
 312          // Get the total number of pages.
 313          $pdf = new pdf();
 314          $pagecount = $pdf->set_pdf($combined);
 315  
 316          // Delete temporary folders and files.
 317          @unlink($combined);
 318          @rmdir($tmpdir);
 319  
 320          return $pagecount;
 321      }
 322  
 323      /**
 324       * This function will generate and return a list of the page images from a pdf.
 325       * @param int|\assign $assignment
 326       * @param int $userid
 327       * @param int $attemptnumber (-1 means latest attempt)
 328       * @return array(stored_file)
 329       */
 330      public static function generate_page_images_for_attempt($assignment, $userid, $attemptnumber) {
 331          global $CFG;
 332  
 333          require_once($CFG->libdir . '/pdflib.php');
 334  
 335          $assignment = self::get_assignment_from_param($assignment);
 336  
 337          if (!$assignment->can_view_submission($userid)) {
 338              \print_error('nopermission');
 339          }
 340  
 341          // Need to generate the page images - first get a combined pdf.
 342          $file = self::get_combined_pdf_for_attempt($assignment, $userid, $attemptnumber);
 343          if (!$file) {
 344              throw new \moodle_exception('Could not generate combined pdf.');
 345          }
 346  
 347          $tmpdir = \make_temp_directory('assignfeedback_editpdf/pageimages/' . self::hash($assignment, $userid, $attemptnumber));
 348          $combined = $tmpdir . '/' . self::COMBINED_PDF_FILENAME;
 349          $file->copy_content_to($combined); // Copy the file.
 350  
 351          $pdf = new pdf();
 352  
 353          $pdf->set_image_folder($tmpdir);
 354          $pagecount = $pdf->set_pdf($combined);
 355  
 356          $grade = $assignment->get_user_grade($userid, true, $attemptnumber);
 357  
 358          $record = new \stdClass();
 359          $record->contextid = $assignment->get_context()->id;
 360          $record->component = 'assignfeedback_editpdf';
 361          $record->filearea = self::PAGE_IMAGE_FILEAREA;
 362          $record->itemid = $grade->id;
 363          $record->filepath = '/';
 364          $fs = \get_file_storage();
 365  
 366          $files = array();
 367          for ($i = 0; $i < $pagecount; $i++) {
 368              $image = $pdf->get_image($i);
 369              $record->filename = basename($image);
 370              $files[$i] = $fs->create_file_from_pathname($record, $tmpdir . '/' . $image);
 371              @unlink($tmpdir . '/' . $image);
 372          }
 373  
 374          @unlink($combined);
 375          @rmdir($tmpdir);
 376  
 377          return $files;
 378      }
 379  
 380      /**
 381       * This function returns a list of the page images from a pdf.
 382       *
 383       * The readonly version is different than the normal one. The readonly version contains a copy
 384       * of the pages in the state they were when the PDF was annotated, by doing so we prevent the
 385       * the pages that are displayed to change as soon as the submission changes.
 386       *
 387       * Though there is an edge case, if the PDF was annotated before MDL-45580, then it is possible
 388       * that we do not find any readonly version of the pages. In that case, we will get the normal
 389       * pages and copy them to the readonly area. This ensures that the pages will remain in that
 390       * state until the submission is updated. When the normal files do not exist, we throw an exception
 391       * because the readonly pages should only ever be displayed after a teacher has annotated the PDF,
 392       * they would not exist until they do.
 393       *
 394       * @param int|\assign $assignment
 395       * @param int $userid
 396       * @param int $attemptnumber (-1 means latest attempt)
 397       * @param bool $readonly If true, then we are requesting the readonly version.
 398       * @return array(stored_file)
 399       */
 400      public static function get_page_images_for_attempt($assignment, $userid, $attemptnumber, $readonly = false) {
 401  
 402          $assignment = self::get_assignment_from_param($assignment);
 403  
 404          if (!$assignment->can_view_submission($userid)) {
 405              \print_error('nopermission');
 406          }
 407  
 408          if ($assignment->get_instance()->teamsubmission) {
 409              $submission = $assignment->get_group_submission($userid, 0, false);
 410          } else {
 411              $submission = $assignment->get_user_submission($userid, false);
 412          }
 413          $grade = $assignment->get_user_grade($userid, true, $attemptnumber);
 414  
 415          $contextid = $assignment->get_context()->id;
 416          $component = 'assignfeedback_editpdf';
 417          $itemid = $grade->id;
 418          $filepath = '/';
 419          $filearea = self::PAGE_IMAGE_FILEAREA;
 420  
 421          $fs = \get_file_storage();
 422  
 423          // If we are after the readonly pages...
 424          $copytoreadonly = false;
 425          if ($readonly) {
 426              $filearea = self::PAGE_IMAGE_READONLY_FILEAREA;
 427              if ($fs->is_area_empty($contextid, $component, $filearea, $itemid)) {
 428                  // We have a problem here, we were supposed to find the files...
 429                  // let's fallback on the other area, and copy the files to the readonly area.
 430                  $copytoreadonly = true;
 431                  $filearea = self::PAGE_IMAGE_FILEAREA;
 432              }
 433          }
 434  
 435          $files = $fs->get_directory_files($contextid, $component, $filearea, $itemid, $filepath);
 436  
 437          $pages = array();
 438          if (!empty($files)) {
 439              $first = reset($files);
 440              if (!$readonly && $first->get_timemodified() < $submission->timemodified) {
 441                  // Image files are stale, we need to regenerate them, except in readonly mode.
 442                  // We also need to remove the draft annotations and comments associated with this attempt.
 443                  $fs->delete_area_files($contextid, $component, $filearea, $itemid);
 444                  page_editor::delete_draft_content($itemid);
 445                  $files = array();
 446              } else {
 447  
 448                  // Need to reorder the files following their name.
 449                  // because get_directory_files() return a different order than generate_page_images_for_attempt().
 450                  foreach($files as $file) {
 451                      // Extract the page number from the file name image_pageXXXX.png.
 452                      preg_match('/page([\d]+)\./', $file->get_filename(), $matches);
 453                      if (empty($matches) or !is_numeric($matches[1])) {
 454                          throw new \coding_exception("'" . $file->get_filename()
 455                              . "' file hasn't the expected format filename: image_pageXXXX.png.");
 456                      }
 457                      $pagenumber = (int)$matches[1];
 458  
 459                      // Save the page in the ordered array.
 460                      $pages[$pagenumber] = $file;
 461                  }
 462                  ksort($pages);
 463  
 464                  if ($copytoreadonly) {
 465                      self::copy_pages_to_readonly_area($assignment, $grade);
 466                  }
 467              }
 468          }
 469  
 470          if (empty($pages)) {
 471              if ($readonly) {
 472                  // This should never happen, there should be a version of the pages available
 473                  // whenever we are requesting the readonly version.
 474                  throw new \moodle_exception('Could not find readonly pages for grade ' . $grade->id);
 475              }
 476              $pages = self::generate_page_images_for_attempt($assignment, $userid, $attemptnumber);
 477          }
 478  
 479          return $pages;
 480      }
 481  
 482      /**
 483       * This function returns sensible filename for a feedback file.
 484       * @param int|\assign $assignment
 485       * @param int $userid
 486       * @param int $attemptnumber (-1 means latest attempt)
 487       * @return string
 488       */
 489      protected static function get_downloadable_feedback_filename($assignment, $userid, $attemptnumber) {
 490          global $DB;
 491  
 492          $assignment = self::get_assignment_from_param($assignment);
 493  
 494          $groupmode = groups_get_activity_groupmode($assignment->get_course_module());
 495          $groupname = '';
 496          if ($groupmode) {
 497              $groupid = groups_get_activity_group($assignment->get_course_module(), true);
 498              $groupname = groups_get_group_name($groupid).'-';
 499          }
 500          if ($groupname == '-') {
 501              $groupname = '';
 502          }
 503          $grade = $assignment->get_user_grade($userid, true, $attemptnumber);
 504          $user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
 505  
 506          if ($assignment->is_blind_marking()) {
 507              $prefix = $groupname . get_string('participant', 'assign');
 508              $prefix = str_replace('_', ' ', $prefix);
 509              $prefix = clean_filename($prefix . '_' . $assignment->get_uniqueid_for_user($userid) . '_');
 510          } else {
 511              $prefix = $groupname . fullname($user);
 512              $prefix = str_replace('_', ' ', $prefix);
 513              $prefix = clean_filename($prefix . '_' . $assignment->get_uniqueid_for_user($userid) . '_');
 514          }
 515          $prefix .= $grade->attemptnumber;
 516  
 517          return $prefix . '.pdf';
 518      }
 519  
 520      /**
 521       * This function takes the combined pdf and embeds all the comments and annotations.
 522       *
 523       * This also moves the annotations and comments from drafts to not drafts. And it will
 524       * copy all the images stored to the readonly area, so that they can be viewed online, and
 525       * not be overwritten when a new submission is sent.
 526       *
 527       * @param int|\assign $assignment
 528       * @param int $userid
 529       * @param int $attemptnumber (-1 means latest attempt)
 530       * @return stored_file
 531       */
 532      public static function generate_feedback_document($assignment, $userid, $attemptnumber) {
 533  
 534          $assignment = self::get_assignment_from_param($assignment);
 535  
 536          if (!$assignment->can_view_submission($userid)) {
 537              \print_error('nopermission');
 538          }
 539          if (!$assignment->can_grade()) {
 540              \print_error('nopermission');
 541          }
 542  
 543          // Need to generate the page images - first get a combined pdf.
 544          $file = self::get_combined_pdf_for_attempt($assignment, $userid, $attemptnumber);
 545          if (!$file) {
 546              throw new \moodle_exception('Could not generate combined pdf.');
 547          }
 548  
 549          $tmpdir = \make_temp_directory('assignfeedback_editpdf/final/' . self::hash($assignment, $userid, $attemptnumber));
 550          $combined = $tmpdir . '/' . self::COMBINED_PDF_FILENAME;
 551          $file->copy_content_to($combined); // Copy the file.
 552  
 553          $pdf = new pdf();
 554  
 555          $fs = \get_file_storage();
 556          $stamptmpdir = \make_temp_directory('assignfeedback_editpdf/stamps/' . self::hash($assignment, $userid, $attemptnumber));
 557          $grade = $assignment->get_user_grade($userid, true, $attemptnumber);
 558          // Copy any new stamps to this instance.
 559          if ($files = $fs->get_area_files($assignment->get_context()->id,
 560                                           'assignfeedback_editpdf',
 561                                           'stamps',
 562                                           $grade->id,
 563                                           "filename",
 564                                           false)) {
 565              foreach ($files as $file) {
 566                  $filename = $stamptmpdir . '/' . $file->get_filename();
 567                  $file->copy_content_to($filename); // Copy the file.
 568              }
 569          }
 570  
 571          $pagecount = $pdf->set_pdf($combined);
 572          $grade = $assignment->get_user_grade($userid, true, $attemptnumber);
 573          page_editor::release_drafts($grade->id);
 574  
 575          for ($i = 0; $i < $pagecount; $i++) {
 576              $pdf->copy_page();
 577              $comments = page_editor::get_comments($grade->id, $i, false);
 578              $annotations = page_editor::get_annotations($grade->id, $i, false);
 579  
 580              foreach ($comments as $comment) {
 581                  $pdf->add_comment($comment->rawtext,
 582                                    $comment->x,
 583                                    $comment->y,
 584                                    $comment->width,
 585                                    $comment->colour);
 586              }
 587  
 588              foreach ($annotations as $annotation) {
 589                  $pdf->add_annotation($annotation->x,
 590                                       $annotation->y,
 591                                       $annotation->endx,
 592                                       $annotation->endy,
 593                                       $annotation->colour,
 594                                       $annotation->type,
 595                                       $annotation->path,
 596                                       $stamptmpdir);
 597              }
 598          }
 599  
 600          fulldelete($stamptmpdir);
 601  
 602          $filename = self::get_downloadable_feedback_filename($assignment, $userid, $attemptnumber);
 603          $filename = clean_param($filename, PARAM_FILE);
 604  
 605          $generatedpdf = $tmpdir . '/' . $filename;
 606          $pdf->save_pdf($generatedpdf);
 607  
 608  
 609          $record = new \stdClass();
 610  
 611          $record->contextid = $assignment->get_context()->id;
 612          $record->component = 'assignfeedback_editpdf';
 613          $record->filearea = self::FINAL_PDF_FILEAREA;
 614          $record->itemid = $grade->id;
 615          $record->filepath = '/';
 616          $record->filename = $filename;
 617  
 618  
 619          // Only keep one current version of the generated pdf.
 620          $fs->delete_area_files($record->contextid, $record->component, $record->filearea, $record->itemid);
 621  
 622          $file = $fs->create_file_from_pathname($record, $generatedpdf);
 623  
 624          // Cleanup.
 625          @unlink($generatedpdf);
 626          @unlink($combined);
 627          @rmdir($tmpdir);
 628  
 629          self::copy_pages_to_readonly_area($assignment, $grade);
 630  
 631          return $file;
 632      }
 633  
 634      /**
 635       * Copy the pages image to the readonly area.
 636       *
 637       * @param int|\assign $assignment The assignment.
 638       * @param \stdClass $grade The grade record.
 639       * @return void
 640       */
 641      public static function copy_pages_to_readonly_area($assignment, $grade) {
 642          $fs = get_file_storage();
 643          $assignment = self::get_assignment_from_param($assignment);
 644          $contextid = $assignment->get_context()->id;
 645          $component = 'assignfeedback_editpdf';
 646          $itemid = $grade->id;
 647  
 648          // Get all the pages.
 649          $originalfiles = $fs->get_area_files($contextid, $component, self::PAGE_IMAGE_FILEAREA, $itemid);
 650          if (empty($originalfiles)) {
 651              // Nothing to do here...
 652              return;
 653          }
 654  
 655          // Delete the old readonly files.
 656          $fs->delete_area_files($contextid, $component, self::PAGE_IMAGE_READONLY_FILEAREA, $itemid);
 657  
 658          // Do the copying.
 659          foreach ($originalfiles as $originalfile) {
 660              $fs->create_file_from_storedfile(array('filearea' => self::PAGE_IMAGE_READONLY_FILEAREA), $originalfile);
 661          }
 662      }
 663  
 664      /**
 665       * This function returns the generated pdf (if it exists).
 666       * @param int|\assign $assignment
 667       * @param int $userid
 668       * @param int $attemptnumber (-1 means latest attempt)
 669       * @return stored_file
 670       */
 671      public static function get_feedback_document($assignment, $userid, $attemptnumber) {
 672  
 673          $assignment = self::get_assignment_from_param($assignment);
 674  
 675          if (!$assignment->can_view_submission($userid)) {
 676              \print_error('nopermission');
 677          }
 678  
 679          $grade = $assignment->get_user_grade($userid, true, $attemptnumber);
 680  
 681          $contextid = $assignment->get_context()->id;
 682          $component = 'assignfeedback_editpdf';
 683          $filearea = self::FINAL_PDF_FILEAREA;
 684          $itemid = $grade->id;
 685          $filepath = '/';
 686  
 687          $fs = \get_file_storage();
 688          $files = $fs->get_area_files($contextid,
 689                                       $component,
 690                                       $filearea,
 691                                       $itemid,
 692                                       "itemid, filepath, filename",
 693                                       false);
 694          if ($files) {
 695              return reset($files);
 696          }
 697          return false;
 698      }
 699  
 700      /**
 701       * This function deletes the generated pdf for a student.
 702       * @param int|\assign $assignment
 703       * @param int $userid
 704       * @param int $attemptnumber (-1 means latest attempt)
 705       * @return bool
 706       */
 707      public static function delete_feedback_document($assignment, $userid, $attemptnumber) {
 708  
 709          $assignment = self::get_assignment_from_param($assignment);
 710  
 711          if (!$assignment->can_view_submission($userid)) {
 712              \print_error('nopermission');
 713          }
 714          if (!$assignment->can_grade()) {
 715              \print_error('nopermission');
 716          }
 717  
 718          $grade = $assignment->get_user_grade($userid, true, $attemptnumber);
 719  
 720          $contextid = $assignment->get_context()->id;
 721          $component = 'assignfeedback_editpdf';
 722          $filearea = self::FINAL_PDF_FILEAREA;
 723          $itemid = $grade->id;
 724  
 725          $fs = \get_file_storage();
 726          return $fs->delete_area_files($contextid, $component, $filearea, $itemid);
 727      }
 728  
 729  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1