Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   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  namespace assignfeedback_editpdf\task;
  18  
  19  use core\task\adhoc_task;
  20  use core\task\manager;
  21  use assignfeedback_editpdf\document_services;
  22  use assignfeedback_editpdf\combined_document;
  23  use context_module;
  24  use assign;
  25  
  26  /**
  27   * An adhoc task to convert submissions to pdf in the background.
  28   *
  29   * @copyright  2022 Mikhail Golenkov <mikhailgolenkov@catalyst-au.net>
  30   * @package    assignfeedback_editpdf
  31   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  32   */
  33  class convert_submission extends adhoc_task {
  34  
  35      /**
  36       * Run the task.
  37       */
  38      public function execute() {
  39          global $CFG, $DB;
  40          require_once($CFG->dirroot . '/mod/assign/locallib.php');
  41  
  42          $data = $this->get_custom_data();
  43  
  44          $submission = $DB->get_record('assign_submission', ['id' => $data->submissionid], '*', IGNORE_MISSING);
  45          if (!$submission) {
  46              mtrace('Submission no longer exists');
  47              return;
  48          }
  49  
  50          $cm = get_coursemodule_from_instance('assign', $submission->assignment, 0, false, MUST_EXIST);
  51          $context = context_module::instance($cm->id);
  52          $assign = new assign($context, null, null);
  53  
  54          if ($submission->userid) {
  55              $users = [$submission->userid];
  56          } else {
  57              $users = [];
  58              $members = $assign->get_submission_group_members($submission->groupid, true);
  59              foreach ($members as $member) {
  60                  $users[] = $member->id;
  61              }
  62          }
  63  
  64          $conversionrequirespolling = false;
  65          foreach ($users as $userid) {
  66              mtrace('Converting submission for user id ' . $userid);
  67  
  68              // If the assignment is not vieweable, we should not try to convert the documents
  69              // for this submission, as it will cause the adhoc task to fail with a permission
  70              // error.
  71              //
  72              // Comments on MDL-56810 indicate that submission conversion should not be attempted
  73              // if the submission is not viewable due to the user not being enrolled.
  74              if (!$assign->can_view_submission($userid)) {
  75                  continue;
  76              }
  77              // Note: Before MDL-71468, the scheduled task version of this
  78              // task would stop attempting to poll the conversion after a
  79              // configured number of attempts were made to poll it, see:
  80              //
  81              // mod/assign/feedback/editpdf/classes/task/convert_submissions.php@MOODLE_400_STABLE
  82              //
  83              // This means that currently this adhoc task, if it fails, will retry forever. But
  84              // the fail-delay mechanism will ensure that it eventually only tries once per day.
  85              //
  86              // See MDL-75457 for details on re-implementing the conversionattemptlimit.
  87              //
  88              // Also note: This code must not be in a try/catch - an exception needs to be thrown to
  89              // allow the task API to mark the task as failed and update its faildelay. Using
  90              // manager::adhoc_task_failed in the catch block will not work, as the task API
  91              // will later assume the task completed successfully (as no exception was thrown) and
  92              // complete it (removing it from the adhoc task queue).
  93              $combineddocument = document_services::get_combined_pdf_for_attempt($assign, $userid, $data->submissionattempt);
  94              switch ($combineddocument->get_status()) {
  95                  case combined_document::STATUS_READY:
  96                  case combined_document::STATUS_READY_PARTIAL:
  97                  case combined_document::STATUS_PENDING_INPUT:
  98                      // The document has not been converted yet or is somehow still ready.
  99                      $conversionrequirespolling = true;
 100                      continue 2;
 101                  case combined_document::STATUS_FAILED:
 102                      // Although STATUS_FAILED indicates a "permanent error" it should be possible
 103                      // in some cases to fix the underlying problem, allowing the conversion to
 104                      // complete. So we throw an exception here, allowing the adhoc task to retry.
 105                      //
 106                      // Currently this can result in the task trying indefinitely (although it will
 107                      // settle on trying once per day due to the faildelay exponential backoff)
 108                      // however once the conversionattepmtlimit is re-implemented in MDL-75457 the
 109                      // task will eventually get dropped.
 110                      throw new \moodle_exception('documentcombinationfailed');
 111              }
 112  
 113              document_services::get_page_images_for_attempt($assign, $userid, $data->submissionattempt, false);
 114              document_services::get_page_images_for_attempt($assign, $userid, $data->submissionattempt, true);
 115          }
 116  
 117          if ($conversionrequirespolling) {
 118              mtrace('Conversion still in progress. Requeueing self to check again.');
 119              $task = new self;
 120              $task->set_custom_data($data);
 121              $task->set_next_run_time(time() + MINSECS);
 122              manager::queue_adhoc_task($task);
 123          } else {
 124              mtrace('The document has been successfully converted');
 125          }
 126      }
 127  }