Search moodle.org's
Developer Documentation

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.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  /**
      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  }