Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403]

   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 editor class 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   * This class performs crud operations on comments and annotations from a page of a response.
  29   *
  30   * No capability checks are done - they should be done by the calling class.
  31   *
  32   * @package   assignfeedback_editpdf
  33   * @copyright 2012 Davo Smith
  34   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  class page_editor {
  37  
  38      /**
  39       * Get all comments for a page.
  40       * @param int $gradeid
  41       * @param int $pageno
  42       * @param bool $draft
  43       * @return comment[]
  44       */
  45      public static function get_comments($gradeid, $pageno, $draft) {
  46          global $DB;
  47  
  48          $comments = array();
  49          $params = array('gradeid'=>$gradeid, 'pageno'=>$pageno, 'draft'=>1);
  50          if (!$draft) {
  51              $params['draft'] = 0;
  52          }
  53          // Fetch comments ordered by position on the page.
  54          $records = $DB->get_records('assignfeedback_editpdf_cmnt', $params, 'y, x');
  55          foreach ($records as $record) {
  56              array_push($comments, new comment($record));
  57          }
  58  
  59          return $comments;
  60      }
  61  
  62      /**
  63       * Set all comments for a page.
  64       * @param int $gradeid
  65       * @param int $pageno
  66       * @param comment[] $comments
  67       * @return int - the number of comments.
  68       */
  69      public static function set_comments($gradeid, $pageno, $comments) {
  70          global $DB;
  71  
  72          $DB->delete_records('assignfeedback_editpdf_cmnt', array('gradeid'=>$gradeid, 'pageno'=>$pageno, 'draft'=>1));
  73  
  74          $added = 0;
  75          foreach ($comments as $record) {
  76              // Force these.
  77              if (!($record instanceof comment)) {
  78                  $comment = new comment($record);
  79              } else {
  80                  $comment = $record;
  81              }
  82              if (trim($comment->rawtext) === '') {
  83                  continue;
  84              }
  85              $comment->gradeid = $gradeid;
  86              $comment->pageno = $pageno;
  87              $comment->draft = 1;
  88              if (self::add_comment($comment)) {
  89                  $added++;
  90              }
  91          }
  92  
  93          return $added;
  94      }
  95  
  96      /**
  97       * Get a single comment by id.
  98       * @param int $commentid
  99       * @return comment or false
 100       */
 101      public static function get_comment($commentid) {
 102          $record = $DB->get_record('assignfeedback_editpdf_cmnt', array('id'=>$commentid), '*', IGNORE_MISSING);
 103          if ($record) {
 104              return new comment($record);
 105          }
 106          return false;
 107      }
 108  
 109      /**
 110       * Add a comment to a page.
 111       * @param comment $comment
 112       * @return bool
 113       */
 114      public static function add_comment(comment $comment) {
 115          global $DB;
 116          $comment->id = null;
 117          return $DB->insert_record('assignfeedback_editpdf_cmnt', $comment);
 118      }
 119  
 120      /**
 121       * Remove a comment from a page.
 122       * @param int $commentid
 123       * @return bool
 124       */
 125      public static function remove_comment($commentid) {
 126          global $DB;
 127          return $DB->delete_records('assignfeedback_editpdf_cmnt', array('id'=>$commentid));
 128      }
 129  
 130      /**
 131       * Get all annotations for a page.
 132       * @param int $gradeid
 133       * @param int $pageno
 134       * @param bool $draft
 135       * @return annotation[]
 136       */
 137      public static function get_annotations($gradeid, $pageno, $draft) {
 138          global $DB;
 139  
 140          $params = array('gradeid'=>$gradeid, 'pageno'=>$pageno, 'draft'=>1);
 141          if (!$draft) {
 142              $params['draft'] = 0;
 143          }
 144          $annotations = array();
 145          $records = $DB->get_records('assignfeedback_editpdf_annot', $params);
 146          foreach ($records as $record) {
 147              array_push($annotations, new annotation($record));
 148          }
 149  
 150          return $annotations;
 151      }
 152  
 153      /**
 154       * Set all annotations for a page.
 155       * @param int $gradeid
 156       * @param int $pageno
 157       * @param annotation[] $annotations
 158       * @return int - the number of annotations.
 159       */
 160      public static function set_annotations($gradeid, $pageno, $annotations) {
 161          global $DB;
 162  
 163          $DB->delete_records('assignfeedback_editpdf_annot', array('gradeid' => $gradeid, 'pageno' => $pageno, 'draft' => 1));
 164          $added = 0;
 165          foreach ($annotations as $record) {
 166              // Force these.
 167              if (!($record instanceof annotation)) {
 168                  $annotation = new annotation($record);
 169              } else {
 170                  $annotation = $record;
 171              }
 172              $annotation->gradeid = $gradeid;
 173              $annotation->pageno = $pageno;
 174              $annotation->draft = 1;
 175              if (self::add_annotation($annotation)) {
 176                  $added++;
 177              }
 178          }
 179  
 180          return $added;
 181      }
 182  
 183      /**
 184       * Get a single annotation by id.
 185       * @param int $annotationid
 186       * @return annotation or false
 187       */
 188      public static function get_annotation($annotationid) {
 189          global $DB;
 190  
 191          $record = $DB->get_record('assignfeedback_editpdf_annot', array('id'=>$annotationid), '*', IGNORE_MISSING);
 192          if ($record) {
 193              return new annotation($record);
 194          }
 195          return false;
 196      }
 197  
 198      /**
 199       * Unrelease drafts
 200       * @param int $gradeid
 201       * @return bool
 202       */
 203      public static function unrelease_drafts($gradeid) {
 204          global $DB;
 205  
 206          // Delete the non-draft annotations and comments.
 207          $result = $DB->delete_records('assignfeedback_editpdf_cmnt', array('gradeid'=>$gradeid, 'draft'=>0));
 208          $result = $DB->delete_records('assignfeedback_editpdf_annot', array('gradeid'=>$gradeid, 'draft'=>0)) && $result;
 209          return $result;
 210      }
 211  
 212      /**
 213       * Release the draft comments and annotations to students.
 214       * @param int $gradeid
 215       * @return bool
 216       */
 217      public static function release_drafts($gradeid) {
 218          global $DB;
 219  
 220          // Delete the previous non-draft annotations and comments.
 221          $DB->delete_records('assignfeedback_editpdf_cmnt', array('gradeid'=>$gradeid, 'draft'=>0));
 222          $DB->delete_records('assignfeedback_editpdf_annot', array('gradeid'=>$gradeid, 'draft'=>0));
 223  
 224          // Copy all the draft annotations and comments to non-drafts.
 225          $records = $DB->get_records('assignfeedback_editpdf_annot', array('gradeid'=>$gradeid, 'draft'=>1));
 226          foreach ($records as $record) {
 227              unset($record->id);
 228              $record->draft = 0;
 229              $DB->insert_record('assignfeedback_editpdf_annot', $record);
 230          }
 231          $records = $DB->get_records('assignfeedback_editpdf_cmnt', array('gradeid'=>$gradeid, 'draft'=>1));
 232          foreach ($records as $record) {
 233              unset($record->id);
 234              $record->draft = 0;
 235              $DB->insert_record('assignfeedback_editpdf_cmnt', $record);
 236          }
 237  
 238          return true;
 239      }
 240  
 241      /**
 242       * Has annotations or comments.
 243       * @param int $gradeid
 244       * @return bool
 245       */
 246      public static function has_annotations_or_comments($gradeid, $includedraft) {
 247          global $DB;
 248          $params = array('gradeid'=>$gradeid);
 249          if (!$includedraft) {
 250              $params['draft'] = 0;
 251          }
 252          if ($DB->count_records('assignfeedback_editpdf_cmnt', $params)) {
 253              return true;
 254          }
 255          if ($DB->count_records('assignfeedback_editpdf_annot', $params)) {
 256              return true;
 257          }
 258          return false;
 259      }
 260  
 261      /**
 262       * Aborts all draft annotations and reverts to the last version released to students.
 263       * @param int $gradeid
 264       * @return bool
 265       */
 266      public static function revert_drafts($gradeid) {
 267          global $DB;
 268  
 269          // Delete the previous non-draft annotations and comments.
 270          $DB->delete_records('assignfeedback_editpdf_cmnt', array('gradeid'=>$gradeid, 'draft'=>1));
 271          $DB->delete_records('assignfeedback_editpdf_annot', array('gradeid'=>$gradeid, 'draft'=>1));
 272  
 273          // Copy all the draft annotations and comments to non-drafts.
 274          $records = $DB->get_records('assignfeedback_editpdf_annot', array('gradeid'=>$gradeid, 'draft'=>0));
 275          foreach ($records as $record) {
 276              unset($record->id);
 277              $record->draft = 0;
 278              $DB->insert_record('assignfeedback_editpdf_annot', $record);
 279          }
 280          $records = $DB->get_records('assignfeedback_editpdf_cmnt', array('gradeid'=>$gradeid, 'draft'=>0));
 281          foreach ($records as $record) {
 282              unset($record->id);
 283              $record->draft = 0;
 284              $DB->insert_record('assignfeedback_editpdf_annot', $record);
 285          }
 286  
 287          return true;
 288      }
 289  
 290      /**
 291       * Add a annotation to a page.
 292       * @param annotation $annotation
 293       * @return bool
 294       */
 295      public static function add_annotation(annotation $annotation) {
 296          global $DB;
 297  
 298          $annotation->id = null;
 299          return $DB->insert_record('assignfeedback_editpdf_annot', $annotation);
 300      }
 301  
 302      /**
 303       * Remove a annotation from a page.
 304       * @param int $annotationid
 305       * @return bool
 306       */
 307      public static function remove_annotation($annotationid) {
 308          global $DB;
 309  
 310          return $DB->delete_records('assignfeedback_editpdf_annot', array('id'=>$annotationid));
 311      }
 312  
 313      /**
 314       * Copy annotations, comments, pages, and other required content from the source user to the current group member
 315       * being procssed when using applytoall.
 316       *
 317       * @param int|\assign $assignment
 318       * @param \stdClass $grade
 319       * @param int $sourceuserid
 320       * @return bool
 321       */
 322      public static function copy_drafts_from_to($assignment, $grade, $sourceuserid) {
 323          global $DB;
 324  
 325          // Delete any existing annotations and comments from current user.
 326          $DB->delete_records('assignfeedback_editpdf_annot', array('gradeid' => $grade->id));
 327          $DB->delete_records('assignfeedback_editpdf_cmnt', array('gradeid' => $grade->id));
 328          // Get gradeid, annotations and comments from sourceuserid.
 329          $sourceusergrade = $assignment->get_user_grade($sourceuserid, true, $grade->attemptnumber);
 330          $annotations = $DB->get_records('assignfeedback_editpdf_annot', array('gradeid' => $sourceusergrade->id, 'draft' => 1));
 331          $comments = $DB->get_records('assignfeedback_editpdf_cmnt', array('gradeid' => $sourceusergrade->id, 'draft' => 1));
 332          $contextid = $assignment->get_context()->id;
 333          $sourceitemid = $sourceusergrade->id;
 334  
 335          // Add annotations and comments to current user to generate feedback file.
 336          foreach ($annotations as $annotation) {
 337              $annotation->gradeid = $grade->id;
 338              $DB->insert_record('assignfeedback_editpdf_annot', $annotation);
 339          }
 340          foreach ($comments as $comment) {
 341              $comment->gradeid = $grade->id;
 342              $DB->insert_record('assignfeedback_editpdf_cmnt', $comment);
 343          }
 344  
 345          $fs = get_file_storage();
 346  
 347          // Copy the stamp files.
 348          self::replace_files_from_to($fs, $contextid, $sourceitemid, $grade->id, document_services::STAMPS_FILEAREA, true);
 349  
 350          // Copy the PAGE_IMAGE_FILEAREA files.
 351          self::replace_files_from_to($fs, $contextid, $sourceitemid, $grade->id, document_services::PAGE_IMAGE_FILEAREA);
 352  
 353          return true;
 354      }
 355  
 356      /**
 357       * Replace the area files in the specified area with those in the source item id.
 358       *
 359       * @param \file_storage $fs The file storage class
 360       * @param int $contextid The ID of the context for the assignment.
 361       * @param int $sourceitemid The itemid to copy from - typically the source grade id.
 362       * @param int $itemid The itemid to copy to - typically the target grade id.
 363       * @param string $area The file storage area.
 364       * @param bool $includesubdirs Whether to copy the content of sub-directories too.
 365       */
 366      public static function replace_files_from_to($fs, $contextid, $sourceitemid, $itemid, $area, $includesubdirs = false) {
 367          $component = 'assignfeedback_editpdf';
 368          // Remove the existing files within this area.
 369          $fs->delete_area_files($contextid, $component, $area, $itemid);
 370  
 371          // Copy the files from the source area.
 372          if ($files = $fs->get_area_files($contextid, $component, $area, $sourceitemid,
 373                                           "filename", $includesubdirs)) {
 374              foreach ($files as $file) {
 375                  $newrecord = new \stdClass();
 376                  $newrecord->contextid = $contextid;
 377                  $newrecord->itemid = $itemid;
 378                  $fs->create_file_from_storedfile($newrecord, $file);
 379              }
 380          }
 381      }
 382  
 383      /**
 384       * Delete the draft annotations and comments.
 385       *
 386       * This is intended to be used when the version of the PDF has changed and the annotations
 387       * might not be relevant any more, therefore we should delete them.
 388       *
 389       * @param int $gradeid The grade ID.
 390       * @return bool
 391       */
 392      public static function delete_draft_content($gradeid) {
 393          global $DB;
 394          $conditions = array('gradeid' => $gradeid, 'draft' => 1);
 395          $result = $DB->delete_records('assignfeedback_editpdf_annot', $conditions);
 396          $result = $result && $DB->delete_records('assignfeedback_editpdf_cmnt', $conditions);
 397          return $result;
 398      }
 399  
 400      /**
 401       * Set page rotation value.
 402       * @param int $gradeid grade id.
 403       * @param int $pageno page number.
 404       * @param bool $isrotated whether the page is rotated or not.
 405       * @param string $pathnamehash path name hash
 406       * @param int $degree rotation degree.
 407       * @throws \dml_exception
 408       */
 409      public static function set_page_rotation($gradeid, $pageno, $isrotated, $pathnamehash, $degree = 0) {
 410          global $DB;
 411          $oldrecord = self::get_page_rotation($gradeid, $pageno);
 412          if ($oldrecord == null) {
 413              $record = new \stdClass();
 414              $record->gradeid = $gradeid;
 415              $record->pageno = $pageno;
 416              $record->isrotated = $isrotated;
 417              $record->pathnamehash = $pathnamehash;
 418              $record->degree = $degree;
 419              $DB->insert_record('assignfeedback_editpdf_rot', $record, false);
 420          } else {
 421              $oldrecord->isrotated = $isrotated;
 422              $oldrecord->pathnamehash = $pathnamehash;
 423              $oldrecord->degree = $degree;
 424              $DB->update_record('assignfeedback_editpdf_rot', $oldrecord, false);
 425          }
 426      }
 427  
 428      /**
 429       * Get Page Rotation Value.
 430       * @param int $gradeid grade id.
 431       * @param int $pageno page number.
 432       * @return mixed
 433       * @throws \dml_exception
 434       */
 435      public static function get_page_rotation($gradeid, $pageno) {
 436          global $DB;
 437          $result = $DB->get_record('assignfeedback_editpdf_rot', array('gradeid' => $gradeid, 'pageno' => $pageno));
 438          return $result;
 439      }
 440  
 441  }