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.

Differences Between: [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 functions for assign_plugin abstract class
  19   *
  20   *
  21   * @package   mod_assign
  22   * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
  23   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  /**
  29   * Abstract class for assign_plugin (submission/feedback).
  30   *
  31   * @package   mod_assign
  32   * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
  33   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  34   */
  35  abstract class assign_plugin {
  36  
  37      /** @var assign $assignment the assignment record that contains the global
  38       *              settings for this assign instance
  39       */
  40      protected $assignment;
  41      /** @var string $type assignment plugin type */
  42      private $type = '';
  43      /** @var string $error error message */
  44      private $error = '';
  45      /** @var boolean|null $enabledcache Cached lookup of the is_enabled function */
  46      private $enabledcache = null;
  47      /** @var boolean|null $enabledcache Cached lookup of the is_visible function */
  48      private $visiblecache = null;
  49  
  50      /**
  51       * Constructor for the abstract plugin type class
  52       *
  53       * @param assign $assignment
  54       * @param string $type
  55       */
  56      public final function __construct(assign $assignment, $type) {
  57          $this->assignment = $assignment;
  58          $this->type = $type;
  59      }
  60  
  61      /**
  62       * Is this the first plugin in the list?
  63       *
  64       * @return bool
  65       */
  66      public final function is_first() {
  67          $order = get_config($this->get_subtype() . '_' . $this->get_type(), 'sortorder');
  68  
  69          if ($order == 0) {
  70              return true;
  71          }
  72          return false;
  73      }
  74  
  75      /**
  76       * Is this the last plugin in the list?
  77       *
  78       * @return bool
  79       */
  80      public final function is_last() {
  81          $lastindex = count(core_component::get_plugin_list($this->get_subtype()))-1;
  82          $currentindex = get_config($this->get_subtype() . '_' . $this->get_type(), 'sortorder');
  83          if ($lastindex == $currentindex) {
  84              return true;
  85          }
  86  
  87          return false;
  88      }
  89  
  90      /**
  91       * This function should be overridden to provide an array of elements that can be added to a moodle
  92       * form for display in the settings page for the assignment.
  93       * @param MoodleQuickForm $mform The form to add the elements to
  94       * @return $array
  95       */
  96      public function get_settings(MoodleQuickForm $mform) {
  97          return;
  98      }
  99  
 100      /**
 101       * Allows the plugin to update the defaultvalues passed in to
 102       * the settings form (needed to set up draft areas for editor
 103       * and filemanager elements)
 104       * @param array $defaultvalues
 105       */
 106      public function data_preprocessing(&$defaultvalues) {
 107          return;
 108      }
 109  
 110      /**
 111       * The assignment subtype is responsible for saving it's own settings as the database table for the
 112       * standard type cannot be modified.
 113       *
 114       * @param stdClass $formdata - the data submitted from the form
 115       * @return bool - on error the subtype should call set_error and return false.
 116       */
 117      public function save_settings(stdClass $formdata) {
 118          return true;
 119      }
 120  
 121      /**
 122       * Save the error message from the last error
 123       *
 124       * @param string $msg - the error description
 125       */
 126      protected final function set_error($msg) {
 127          $this->error = $msg;
 128      }
 129  
 130      /**
 131       * What was the last error?
 132       *
 133       * @return string
 134       */
 135      public final function get_error() {
 136          return $this->error;
 137      }
 138  
 139      /**
 140       * Should return the name of this plugin type.
 141       *
 142       * @return string - the name
 143       */
 144      public abstract function get_name();
 145  
 146      /**
 147       * Should return the subtype of this plugin.
 148       *
 149       * @return string - either 'assignsubmission' or 'feedback'
 150       */
 151      public abstract function get_subtype();
 152  
 153      /**
 154       * Should return the type of this plugin.
 155       *
 156       * @return string - the type
 157       */
 158      public final function get_type() {
 159          return $this->type;
 160      }
 161  
 162      /**
 163       * Get the installed version of this plugin
 164       *
 165       * @return string
 166       */
 167      public final function get_version() {
 168          $version = get_config($this->get_subtype() . '_' . $this->get_type(), 'version');
 169          if ($version) {
 170              return $version;
 171          } else {
 172              return '';
 173          }
 174      }
 175  
 176      /**
 177       * Get the required moodle version for this plugin
 178       *
 179       * @return string
 180       */
 181      public final function get_requires() {
 182          $requires = get_config($this->get_subtype() . '_' . $this->get_type(), 'requires');
 183          if ($requires) {
 184              return $requires;
 185          } else {
 186              return '';
 187          }
 188      }
 189  
 190      /**
 191       * Save any custom data for this form submission
 192       *
 193       * @param stdClass $submissionorgrade - assign_submission or assign_grade.
 194       *              For submission plugins this is the submission data,
 195       *              for feedback plugins it is the grade data
 196       * @param stdClass $data - the data submitted from the form
 197       * @return bool - on error the subtype should call set_error and return false.
 198       */
 199      public function save(stdClass $submissionorgrade, stdClass $data) {
 200          return true;
 201      }
 202  
 203      /**
 204       * Set this plugin to enabled
 205       *
 206       * @return bool
 207       */
 208      public final function enable() {
 209          $this->enabledcache = true;
 210          return $this->set_config('enabled', 1);
 211      }
 212  
 213      /**
 214       * Set this plugin to disabled
 215       *
 216       * @return bool
 217       */
 218      public final function disable() {
 219          $this->enabledcache = false;
 220          return $this->set_config('enabled', 0);
 221      }
 222  
 223      /**
 224       * Allows hiding this plugin from the submission/feedback screen if it is not enabled.
 225       *
 226       * @return bool - if false - this plugin will not accept submissions / feedback
 227       */
 228      public function is_enabled() {
 229          if ($this->enabledcache === null) {
 230              $this->enabledcache = $this->get_config('enabled');
 231          }
 232          return $this->enabledcache;
 233      }
 234  
 235  
 236      /**
 237       * Get any additional fields for the submission/grading form for this assignment.
 238       *
 239       * @param mixed $submissionorgrade submission|grade - For submission plugins this is the submission data,
 240       *                                                    for feedback plugins it is the grade data
 241       * @param MoodleQuickForm $mform - This is the form
 242       * @param stdClass $data - This is the form data that can be modified for example by a filemanager element
 243       * @param int $userid - This is the userid for the current submission.
 244       *                      This is passed separately as there may not yet be a submission or grade.
 245       * @return boolean - true if we added anything to the form
 246       */
 247      public function get_form_elements_for_user($submissionorgrade, MoodleQuickForm $mform, stdClass $data, $userid) {
 248          return $this->get_form_elements($submissionorgrade, $mform, $data);
 249      }
 250  
 251      /**
 252       * Get any additional fields for the submission/grading form for this assignment.
 253       * This function is retained for backwards compatibility - new plugins should override {@link get_form_elements_for_user()}.
 254       *
 255       * @param mixed $submissionorgrade submission|grade - For submission plugins this is the submission data,
 256       *                                                    for feedback plugins it is the grade data
 257       * @param MoodleQuickForm $mform - This is the form
 258       * @param stdClass $data - This is the form data that can be modified for example by a filemanager element
 259       * @return boolean - true if we added anything to the form
 260       */
 261      public function get_form_elements($submissionorgrade, MoodleQuickForm $mform, stdClass $data) {
 262          return false;
 263      }
 264  
 265      /**
 266       * Should not output anything - return the result as a string so it can be consumed by webservices.
 267       *
 268       * @param stdClass $submissionorgrade assign_submission or assign_grade
 269       *                 For submission plugins this is the submission data,
 270       *                 for feedback plugins it is the grade data
 271       * @return string - return a string representation of the submission in full
 272       */
 273      public function view(stdClass $submissionorgrade) {
 274          return '';
 275      }
 276  
 277      /**
 278       * Get the numerical sort order for this plugin
 279       *
 280       * @return int
 281       */
 282      public final function get_sort_order() {
 283          $order = get_config($this->get_subtype() . '_' . $this->get_type(), 'sortorder');
 284          return $order?$order:0;
 285      }
 286  
 287      /**
 288       * Is this plugin enaled?
 289       *
 290       * @return bool
 291       */
 292      public final function is_visible() {
 293          if ($this->visiblecache === null) {
 294              $disabled = get_config($this->get_subtype() . '_' . $this->get_type(), 'disabled');
 295              $this->visiblecache = !$disabled;
 296          }
 297          return $this->visiblecache;
 298      }
 299  
 300  
 301      /**
 302       * Has this plugin got a custom settings.php file?
 303       *
 304       * @return bool
 305       */
 306      public final function has_admin_settings() {
 307          global $CFG;
 308  
 309          $pluginroot = $CFG->dirroot . '/mod/assign/' . substr($this->get_subtype(), strlen('assign')) . '/' . $this->get_type();
 310          $settingsfile = $pluginroot . '/settings.php';
 311          return file_exists($settingsfile);
 312      }
 313  
 314      /**
 315       * Set a configuration value for this plugin
 316       *
 317       * @param string $name The config key
 318       * @param string $value The config value
 319       * @return bool
 320       */
 321      public final function set_config($name, $value) {
 322          global $DB;
 323  
 324          $dbparams = array('assignment'=>$this->assignment->get_instance()->id,
 325                            'subtype'=>$this->get_subtype(),
 326                            'plugin'=>$this->get_type(),
 327                            'name'=>$name);
 328          $current = $DB->get_record('assign_plugin_config', $dbparams, '*', IGNORE_MISSING);
 329  
 330          if ($current) {
 331              $current->value = $value;
 332              return $DB->update_record('assign_plugin_config', $current);
 333          } else {
 334              $setting = new stdClass();
 335              $setting->assignment = $this->assignment->get_instance()->id;
 336              $setting->subtype = $this->get_subtype();
 337              $setting->plugin = $this->get_type();
 338              $setting->name = $name;
 339              $setting->value = $value;
 340  
 341              return $DB->insert_record('assign_plugin_config', $setting) > 0;
 342          }
 343      }
 344  
 345      /**
 346       * Get a configuration value for this plugin
 347       *
 348       * @param mixed $setting The config key (string) or null
 349       * @return mixed string | false
 350       */
 351      public final function get_config($setting = null) {
 352          global $DB;
 353  
 354          if ($setting) {
 355              if (!$this->assignment->has_instance()) {
 356                  return false;
 357              }
 358              $assignment = $this->assignment->get_instance();
 359              if ($assignment) {
 360                  $dbparams = array('assignment'=>$assignment->id,
 361                                    'subtype'=>$this->get_subtype(),
 362                                    'plugin'=>$this->get_type(),
 363                                    'name'=>$setting);
 364                  $result = $DB->get_record('assign_plugin_config', $dbparams, '*', IGNORE_MISSING);
 365                  if ($result) {
 366                      return $result->value;
 367                  }
 368              }
 369              return false;
 370          }
 371          $dbparams = array('assignment'=>$this->assignment->get_instance()->id,
 372                            'subtype'=>$this->get_subtype(),
 373                             'plugin'=>$this->get_type());
 374          $results = $DB->get_records('assign_plugin_config', $dbparams);
 375  
 376          $config = new stdClass();
 377          if (is_array($results)) {
 378              foreach ($results as $setting) {
 379                  $name = $setting->name;
 380                  $config->$name = $setting->value;
 381              }
 382          }
 383          return $config;
 384      }
 385  
 386      /**
 387       * Get a list of file areas associated with the plugin configuration.
 388       * This is used for backup/restore.
 389       *
 390       * @return array names of the fileareas, can be an empty array
 391       */
 392      public function get_config_file_areas() {
 393          return array();
 394      }
 395  
 396      /**
 397       * Should not output anything - return the result as a string so it can be consumed by webservices.
 398       *
 399       * @param stdClass $submissionorgrade assign_submission or assign_grade
 400       *                 For submission plugins this is the submission data, for feedback plugins it is the grade data
 401       * @param bool $showviewlink Modifed to return whether or not to show a link to the full submission/feedback
 402       * @return string - return a string representation of the submission in full
 403       */
 404      public function view_summary(stdClass $submissionorgrade, & $showviewlink) {
 405          return '';
 406      }
 407  
 408      /**
 409       * Given a field name and value should update the text for this field in the plugins submission or grade
 410       *
 411       * @param string $name Name of the field.
 412       * @param string $value Updated text
 413       * @param int $submissionorgradeid The id of the submission or grade
 414       * @return bool - true if the value was updated
 415       */
 416      public function set_editor_text($name, $value, $submissionorgradeid) {
 417          return false;
 418      }
 419  
 420      /**
 421       * Given a field name and value should update the format for this field in the plugins submission or grade
 422       *
 423       * @param string $name Name of the field.
 424       * @param int $format Updated format.
 425       * @param int $submissionorgradeid The id of the submission or grade.
 426       * @return bool - true if the value was updated
 427       */
 428      public function set_editor_format($name, $format, $submissionorgradeid) {
 429          return false;
 430      }
 431  
 432      /**
 433       * Return a list of the fields that can be exported or imported via text.
 434       *
 435       * @return array - The list of field names (strings) and descriptions. ($name => $description)
 436       */
 437      public function get_editor_fields() {
 438          return array();
 439      }
 440  
 441      /**
 442       * Given a field name, should return the text of an editor field that is part of
 443       * this plugin. This is used when exporting to portfolio.
 444       *
 445       * @param string $name Name of the field.
 446       * @param int $submissionorgradeid The id of the submission or grade
 447       * @return string - The text for the editor field
 448       */
 449      public function get_editor_text($name, $submissionorgradeid) {
 450          return '';
 451      }
 452  
 453      /**
 454       * Produce a list of files suitable for export that represent this feedback or submission
 455       *
 456       * @param stdClass $submissionorgrade assign_submission or assign_grade
 457       *                 For submission plugins this is the submission data, for feedback plugins it is the grade data
 458       * @param stdClass $user The user record for the current submission.
 459       *                         Needed for url rewriting if this is a group submission.
 460       * @return array - return an array of files indexed by filename
 461       */
 462      public function get_files(stdClass $submissionorgrade, stdClass $user) {
 463          return array();
 464      }
 465  
 466      /**
 467       * Given a field name, should return the format of an editor field that is part of
 468       * this plugin. This is used when exporting to portfolio.
 469       *
 470       * @param string $name Name of the field.
 471       * @param int $submissionid The id of the submission
 472       * @return int - The format for the editor field
 473       */
 474      public function get_editor_format($name, $submissionid) {
 475          return 0;
 476      }
 477  
 478      /**
 479       * Return true if this plugin can upgrade an old Moodle 2.2 assignment of this type
 480       * and version.
 481       *
 482       * @param string $type The old assignment subtype
 483       * @param int $version The old assignment version
 484       * @return bool True if upgrade is possible
 485       */
 486      public function can_upgrade($type, $version) {
 487          return false;
 488      }
 489  
 490      /**
 491       * Upgrade the settings from the old assignment to the new one
 492       *
 493       * @param context $oldcontext The context for the old assignment module
 494       * @param stdClass $oldassignment The data record for the old assignment
 495       * @param string $log Record upgrade messages in the log
 496       * @return bool true or false - false will trigger a rollback
 497       */
 498      public function upgrade_settings(context $oldcontext, stdClass $oldassignment, & $log) {
 499          $params = array('type'=>$this->type, 'subtype'=>$this->get_subtype());
 500          $log .= ' ' . get_string('upgradenotimplemented', 'mod_assign', $params);
 501          return false;
 502      }
 503  
 504      /**
 505       * Upgrade the submission from the old assignment to the new one
 506       *
 507       * @param context $oldcontext The data record for the old context
 508       * @param stdClass $oldassignment The data record for the old assignment
 509       * @param stdClass $oldsubmissionorgrade The data record for the old submission
 510       * @param stdClass $submissionorgrade assign_submission or assign_grade The new submission or grade
 511       * @param string $log Record upgrade messages in the log
 512       * @return boolean true or false - false will trigger a rollback
 513       */
 514      public function upgrade(context $oldcontext,
 515                              stdClass $oldassignment,
 516                              stdClass $oldsubmissionorgrade,
 517                              stdClass $submissionorgrade,
 518                              & $log) {
 519          $params = array('type'=>$this->type, 'subtype'=>$this->get_subtype());
 520          $log = $log . ' ' . get_string('upgradenotimplemented', 'mod_assign', $params);
 521          return false;
 522      }
 523  
 524      /**
 525       * Formatting for log info
 526       *
 527       * @param stdClass $submissionorgrade assign_submission or assign_grade The new submission or grade
 528       * @return string
 529       */
 530      public function format_for_log(stdClass $submissionorgrade) {
 531          // Format the info for each submission plugin add_to_log.
 532          return '';
 533      }
 534  
 535      /**
 536       * The assignment has been deleted - remove the plugin specific data
 537       *
 538       * @return bool
 539       */
 540      public function delete_instance() {
 541          return true;
 542      }
 543  
 544      /**
 545       * Run cron for this plugin
 546       */
 547      public static function cron() {
 548      }
 549  
 550      /**
 551       * Is this assignment plugin empty? (ie no submission or feedback)
 552       * @param stdClass $submissionorgrade assign_submission or assign_grade
 553       * @return bool
 554       */
 555      public function is_empty(stdClass $submissionorgrade) {
 556          return true;
 557      }
 558  
 559      /**
 560       * Get file areas returns a list of areas this plugin stores files
 561       * @return array - An array of fileareas (keys) and descriptions (values)
 562       */
 563      public function get_file_areas() {
 564          return array();
 565      }
 566  
 567  
 568      /**
 569       * Default implementation of file_get_info for plugins.
 570       * This is used by the filebrowser to browse a plugins file areas.
 571       *
 572       * This implementation should work for most plugins but can be overridden if required.
 573       * @param file_browser $browser
 574       * @param string $filearea
 575       * @param int $itemid
 576       * @param string $filepath
 577       * @param string $filename
 578       * @return file_info_stored
 579       */
 580      public function get_file_info($browser, $filearea, $itemid, $filepath, $filename) {
 581          global $CFG, $DB, $USER;
 582          $urlbase = $CFG->wwwroot.'/pluginfile.php';
 583          $writeaccess = false;
 584          // Permission check on the itemid.
 585          $assignment = $this->assignment;
 586  
 587          if ($this->get_subtype() == 'assignsubmission') {
 588              if ($itemid) {
 589                  $record = $DB->get_record('assign_submission', array('id' => $itemid), 'userid,groupid', IGNORE_MISSING);
 590                  if (!$record) {
 591                      return null;
 592                  }
 593                  if (!empty($record->userid)) {
 594                      if (!$assignment->can_view_submission($record->userid)) {
 595                          return null;
 596                      }
 597  
 598                      // We only report write access for teachers.
 599                      $writeaccess = $assignment->can_grade() && $assignment->can_edit_submission($record->userid);
 600                  } else {
 601                      // Must be a team submission with a group.
 602                      if (!$assignment->can_view_group_submission($record->groupid)) {
 603                          return null;
 604                      }
 605                      // We only report write access for teachers.
 606                      $writeaccess = $assignment->can_grade() && $assignment->can_edit_group_submission($record->groupid);
 607                  }
 608              }
 609          } else {
 610              // Not supported for feedback plugins.
 611              return null;
 612          }
 613  
 614          $fs = get_file_storage();
 615          $filepath = is_null($filepath) ? '/' : $filepath;
 616          $filename = is_null($filename) ? '.' : $filename;
 617          if (!($storedfile = $fs->get_file($assignment->get_context()->id,
 618                                            $this->get_subtype() . '_' . $this->get_type(),
 619                                            $filearea,
 620                                            $itemid,
 621                                            $filepath,
 622                                            $filename))) {
 623              return null;
 624          }
 625  
 626          return new file_info_stored($browser,
 627                                      $assignment->get_context(),
 628                                      $storedfile,
 629                                      $urlbase,
 630                                      $filearea,
 631                                      $itemid,
 632                                      true,
 633                                      $writeaccess,
 634                                      false);
 635      }
 636  
 637      /**
 638       * This allows a plugin to render a page in the context of the assignment
 639       *
 640       * If the plugin creates a link to the assignment view.php page with
 641       * The following required parameters:
 642       *      id=coursemoduleid
 643       *      plugin=type
 644       *      pluginsubtype=assignfeedback|assignsubmission
 645       *      pluginaction=customaction
 646       *
 647       * Then this function will be called to display the page with the pluginaction passed as action
 648       * @param string $action The plugin specified action
 649       * @return string
 650       */
 651      public function view_page($action) {
 652          return '';
 653      }
 654  
 655      /**
 656       * This allows a plugin to render an introductory section which is displayed
 657       * right below the activity's "intro" section on the main assignment page.
 658       *
 659       * @return string
 660       */
 661      public function view_header() {
 662          return '';
 663      }
 664  
 665      /**
 666       * If this plugin should not include a column in the grading table or a row on the summary page
 667       * then return false
 668       *
 669       * @return bool
 670       */
 671      public function has_user_summary() {
 672          return true;
 673      }
 674  
 675      /**
 676       * If this plugin can participate in a webservice (save_submission or save_grade),
 677       * return a list of external_params to be included in the definition of that webservice.
 678       *
 679       * @return external_description|null
 680       */
 681      public function get_external_parameters() {
 682          return null;
 683      }
 684  
 685      /**
 686       * If true, the plugin will appear on the module settings page and can be
 687       * enabled/disabled per assignment instance.
 688       *
 689       * @return bool
 690       */
 691      public function is_configurable() {
 692          return true;
 693      }
 694  
 695      /**
 696       * Return the plugin configs for external functions,
 697       * in some cases the configs will need formatting or be returned only if the current user has some capabilities enabled.
 698       *
 699       * @return array the list of settings
 700       * @since Moodle 3.2
 701       */
 702      public function get_config_for_external() {
 703          return array();
 704      }
 705  }